import React, {Component, type ReactNode} from 'react'; import ReactTooltip from 'react-tooltip'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import { faClipboard } from '@fortawesome/free-solid-svg-icons' import styles from './styles.module.css'; interface Props { children: ReactNode; command: string; output: string; } export default function Terminal({ children, command, output, }: Props): JSX.Element { let decodedOutput = atob(output); const outputParts = decodedOutput.split('\n') let sections : Array = [] let section = new TerminalSection() let appendNext = false; let allCommands = ""; for(let i = 0; i < outputParts.length; i++) { let currentLine = outputParts[i] if(!appendNext) { if(currentLine.startsWith('$ ')) { section = new TerminalSection() sections.push(section) currentLine = currentLine.substring(2) } if(section.processLine(currentLine)) { allCommands = `${allCommands}\n${currentLine}` } } } const handler = () => { navigator.clipboard.writeText(`${allCommands}\n`) } return (
{ sections.map(element => { return element.render() })}
); } class TerminalSection { protected contexts: Array = []; private context : TerminalContext; private commandContext : TerminalCommand; private inHeredoc = false; private commandString : string = ""; private inCommand = true; constructor() { this.context = this.commandContext = new TerminalCommand(); this.contexts.push(this.context) } switchContext(context: TerminalContext) { this.contexts.push(context) this.context = context; } addLine(line: string) { this.context.addLine(line) } processLine(currentLine: string) : boolean { let processed = false; this.context.addLine(currentLine); if(this.inCommand) { this.commandString += currentLine; processed = true; } if(currentLine.indexOf('< -1) { this.inHeredoc = true } else if(this.inHeredoc) { if(currentLine.indexOf('EOF') > -1) { this.inHeredoc = false } } if(!currentLine.endsWith('\\') && !this.inHeredoc) { this.context = new TerminalOutput() this.contexts.push(this.context) this.inCommand = false; } return processed; } render() { const commandString = this.commandContext.getCommand() const handler = () => { navigator.clipboard.writeText(commandString) } return (
{this.contexts.map(element => { return (element.render()) })}
) } } class TerminalContext { protected lines: Array = []; addLine(line: string) { this.lines.push(line) } render() { return (
) } hasLines() { return this.lines.length > 0 } } class TerminalCommand extends TerminalContext { private isMultiLine = false; addLine(line: string) { super.addLine(line) } getCommand() { return this.lines.join('\n') } render() { return (
~ $ {this.renderCommand(this.lines[0], false)}
{ this.lines.slice(1).map(element => { return (
{this.renderCommand(element, true)}
) }) }
) } renderCommand(command: string, indent: boolean) { let output = command; return ({output}) } } class TerminalOutput extends TerminalContext { render() { return (
        { this.lines.join('\n')}
      
) } }