import * as diff from 'diff' import * as Prism from 'prismjs' import * as q from '../../../../../backend/src/Model' import * as React from 'react' import DiffCount from './DiffCount' import Gutters from './Gutters' import { isPlottable, lineChangeStyle, trimNewlineRight } from './util' import { JsonPropertyLocation, literalsMappedByLines } from '../../../../../backend/src/JsonAstParser' import { selectTextWithCtrlA } from '../../../utils/handleTextSelectWithCtrlA' import { style } from './style' import { withStyles } from '@material-ui/core' import 'prismjs/components/prism-json' interface Props { treeNode: q.TreeNode previous: string current: string nameOfCompareMessage: string language?: 'json' classes: any } interface State {} class CodeDiff extends React.Component { private handleCtrlA = selectTextWithCtrlA({ targetSelector: 'pre ~ pre' }) constructor(props: Props) { super(props) this.state = {} } private isValidJson(str: string) { try { JSON.parse(str) return true } catch (error) { return false } } private plottableLiteralsIndexedWithLineNumbers() { const allLiterals = this.isValidJson(this.props.current) ? literalsMappedByLines(this.props.current) || [] : [] return allLiterals.map((l: JsonPropertyLocation) => (isPlottable(l.value) ? l : undefined)) as Array< JsonPropertyLocation > } private renderStyledCodeLines(changes: Array) { const styledLines = Prism.highlight(this.props.current, Prism.languages.json, 'json').split('\n') let lineNumber = 0 return changes .map((change, key) => { const hasStyledCode = change.removed !== true const changedLines = change.count || 0 if (hasStyledCode && this.props.language === 'json') { const currentLines = styledLines.slice(lineNumber, lineNumber + changedLines) const lines = currentLines.map((html: string, idx: number) => { return (
) }) lineNumber += changedLines return [
{lines}
] } return trimNewlineRight(change.value) .split('\n') .map((line, idx) => { return (
{line}
) }) }) .reduce((a, b) => a.concat(b), []) } public render() { const changes = diff.diffLines(this.props.previous, this.props.current) const literalPositions = this.plottableLiteralsIndexedWithLineNumbers() const code = this.renderStyledCodeLines(changes) return (
{code}
) } } export default withStyles(style)(CodeDiff)