diff --git a/ivette/package.json b/ivette/package.json index 5916f2832104af4dc270adf23249704bce3ee5b4..4accc25c115927804617213092dd1a8ebf2aead9 100644 --- a/ivette/package.json +++ b/ivette/package.json @@ -55,6 +55,7 @@ "dependencies": { "@babel/runtime": "^7.9.2", "@fortawesome/fontawesome-free": "^5.13.1", + "@types/diff": "^4.0.2", "@types/react-window": "^1.8.2", "codemirror": "^5.52.2", "cytoscape": "^3.15.1", @@ -65,6 +66,7 @@ "cytoscape-klay": "^3.1.3", "cytoscape-panzoom": "^2.5.3", "cytoscape-popper": "^1.0.7", + "diff": "^5.0.0", "immutable": "^4.0.0-rc.12", "lodash": "^4.17.15", "react": "^16.8", diff --git a/ivette/src/frama-c/eva/diffed.tsx b/ivette/src/frama-c/eva/diffed.tsx new file mode 100644 index 0000000000000000000000000000000000000000..27f4e6819430a9ba5bc57b9cb64862f7b467a282 --- /dev/null +++ b/ivette/src/frama-c/eva/diffed.tsx @@ -0,0 +1,67 @@ +// -------------------------------------------------------------------------- +// --- Diff Text Rendering +// -------------------------------------------------------------------------- + +import React from 'react'; +import { Change, diffChars } from 'diff'; + +export class DiffBuffer { + + private readonly contents: React.ReactNode[] = []; + private added = false; + private removed = false; + private value = ''; + + constructor() { + this.push = this.push.bind(this); + } + + push(c: Change) { + if (!c.added && !c.removed) this.flush(); + if (c.added) this.added = true; + if (c.removed) this.removed = true; + if (!c.added) this.value += c.value; + } + + flush(): React.ReactNode[] { + const { value, added, removed, contents } = this; + if (value) { + if (added && removed) { + contents.push(<span className='eva-diff-modified'>{value}</span>); + } else if (removed) { + contents.push(<span className='eva-diff-removed'>{value}</span>); + } else if (added) { + contents.push(<span className='eva-diff-added' />); + } else { + contents.push(value); + } + this.value = ''; + this.added = false; + this.removed = false; + } + return this.contents; + } + +} + +/* --------------------------------------------------------------------------*/ +/* --- Component with memoized diff ---*/ +/* --------------------------------------------------------------------------*/ + +export interface DiffedProps { + original?: string; + modified?: string; +} + +export function Diffed(props: DiffedProps) { + const { original = '', modified = '' } = props; + const contents = React.useMemo(() => { + if (original === modified) return original; + const buffer = new DiffBuffer(); + diffChars(original, modified).forEach(buffer.push); + return buffer.flush(); + }, [original, modified]); + return <>{contents}</>; +} + +// -------------------------------------------------------------------------- diff --git a/ivette/yarn.lock b/ivette/yarn.lock index 1b2c21e55881c5a5a6630ade9f9dd6f6499ff8ec..d1b9cd89c54e0e40fff49ff63ea303bc37d47555 100644 --- a/ivette/yarn.lock +++ b/ivette/yarn.lock @@ -1022,6 +1022,11 @@ resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.5.tgz#b14efa8852b7768d898906613c23f688713e02cd" integrity sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ== +"@types/diff@^4.0.2": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/diff/-/diff-4.0.2.tgz#2e9bb89f9acc3ab0108f0f3dc4dbdcf2fff8a99c" + integrity sha512-mIenTfsIe586/yzsyfql69KRnA75S8SVXQbTLpDejRrjH0QSJcpu3AUOi/Vjnt9IOsXKxPhJfGpQUNMueIU1fQ== + "@types/eslint-visitor-keys@^1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" @@ -3240,6 +3245,11 @@ detect-node@^2.0.4: resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw== +diff@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875"