import { CodeBlockStyle, CodeHighlightStyle, CopyButtonStyle, LineCountStyle } from './styles'; import React from 'react'; import copy from 'copy-to-clipboard'; import { trackCopyClicks } from '../../utils/track'; const COPY = 'copy'; const COPIED = 'copied'; const FAILED = 'failed to copy'; const CONSOLE = 'console'; type CopyMessageType = typeof COPY | typeof COPIED | typeof FAILED; type CodeBlockProps = { lineCount: string; language: string; children: React.ReactElement[]; }; type CodeBlockState = { copyMessage: CopyMessageType; }; class CodeBlock extends React.Component { element?: HTMLDivElement; constructor(props) { super(props); this.state = { copyMessage: COPY }; } lineNumbers = () => { const lineCount = parseInt(this.props.lineCount); if (lineCount > 1 && this.props.language !== CONSOLE) { return (
{new Array(lineCount).fill(null).map((_, i) => ( {String(i + 1)} ))}
); } }; setElement = (ref: HTMLDivElement | undefined) => { if (ref !== null) { this.element = ref; } }; copyToClipboard = () => { if (this.element && this.element.textContent) { if ( this.element?.firstElementChild?.classList.contains( 'highlight-source-diff' ) ) { const textContent = this.element.textContent; let copyLines = textContent.split('\n'); let copyText = copyLines .filter((line) => { return !line.startsWith('-'); }) .map((line) => { if (line.startsWith('+')) { return line.replace('+', ' '); } else { return line; } }) .join('\n'); copy(copyText); trackCopyClicks(copyText); } else { copy(this.element.textContent); trackCopyClicks(this.element.textContent); } this.setState({ copyMessage: COPIED }); } else { this.setState({ copyMessage: FAILED }); } setTimeout(() => { this.setState({ copyMessage: COPY }); }, 1500); }; copyButton = () => { if (this.props.language !== CONSOLE) { return ( {this.state.copyMessage} ); } }; render() { if (this.props.children === undefined) return
; const oneLine = this.props.lineCount === '1' || this.props.language === CONSOLE; return ( {this.lineNumbers()} {this.props.children} {this.copyButton()} ); } } export default CodeBlock;