From 4a564eca9bba54c22d0d3e320107e1689da1936c Mon Sep 17 00:00:00 2001 From: Henning Dieterichs Date: Sat, 29 Aug 2020 12:45:27 +0200 Subject: [PATCH] Adds diff visualizer. --- playground/src/demo.editable.json | 5 + visualization-bundle/src/visualizers/index.ts | 1 + .../MonacoEditor.tsx | 117 ++++++++++++++++++ .../monaco-text-diff-visualizer/index.tsx | 53 ++++++++ .../monaco-text-diff-visualizer/style.scss | 22 ++++ 5 files changed, 198 insertions(+) create mode 100644 visualization-bundle/src/visualizers/monaco-text-diff-visualizer/MonacoEditor.tsx create mode 100644 visualization-bundle/src/visualizers/monaco-text-diff-visualizer/index.tsx create mode 100644 visualization-bundle/src/visualizers/monaco-text-diff-visualizer/style.scss diff --git a/playground/src/demo.editable.json b/playground/src/demo.editable.json index 46c5925..08ac1c8 100644 --- a/playground/src/demo.editable.json +++ b/playground/src/demo.editable.json @@ -46,6 +46,11 @@ "name": "Monaco Text Visualizer", "preferredVisualizationId": "monaco-text" }, + { + "dataSrc": "{\r\n \"kind\": { \"text\": true },\r\n \"text\": \"class Test {\\n}\",\r\n \"otherText\": \"class test {\\n}\",\r\n \"fileName\": \"foo.ts\"\r\n}", + "name": "Monaco Text Diff Visualizer", + "preferredVisualizationId": "monaco-text" + }, { "dataSrc": "{\r\n \"kind\": { \"text\": true },\r\n \"text\": \"class Test {\\n}\",\r\n \"fileName\": \"foo.ts\"\r\n}", "name": "Simple Text Visualizer", diff --git a/visualization-bundle/src/visualizers/index.ts b/visualization-bundle/src/visualizers/index.ts index a2873b4..676e2be 100644 --- a/visualization-bundle/src/visualizers/index.ts +++ b/visualization-bundle/src/visualizers/index.ts @@ -3,6 +3,7 @@ export * from "./graph"; export * from "./grid-visualizer"; export * from "./image-visualizer"; export * from "./monaco-text-visualizer"; +export * from "./monaco-text-diff-visualizer"; export * from "./perspective-table-visualizer"; export * from "./plotly-visualizer"; export * from "./simple-text-visualizer"; diff --git a/visualization-bundle/src/visualizers/monaco-text-diff-visualizer/MonacoEditor.tsx b/visualization-bundle/src/visualizers/monaco-text-diff-visualizer/MonacoEditor.tsx new file mode 100644 index 0000000..892b00f --- /dev/null +++ b/visualization-bundle/src/visualizers/monaco-text-diff-visualizer/MonacoEditor.tsx @@ -0,0 +1,117 @@ +import * as React from "react"; +import { observer, disposeOnUnmount } from "mobx-react"; +import { observable, autorun } from "mobx"; +import * as monacoTypes from "monaco-editor"; +import { Theme } from "@hediet/visualization-core"; +import { getLoadedMonaco } from "@hediet/monaco-editor-react"; + +export function getLanguageId(fileName: string): string { + const l = getLoadedMonaco().languages.getLanguages(); + const result = l.find(l => { + if (l.filenamePatterns) { + for (const p of l.filenamePatterns) { + if (new RegExp(p).test(fileName)) { + return true; + } + } + } + if (l.extensions) { + for (const p of l.extensions) { + if (fileName.endsWith(p)) { + return true; + } + } + } + + return false; + }); + + if (result) { + return result.id; + } + return "text"; +} + +@observer +export class MonacoEditor extends React.Component<{ + originalText: string; + modifiedText: string; + languageId: string; + theme: Theme; +}> { + @observable private editor: + | monacoTypes.editor.IStandaloneDiffEditor + | undefined; + + componentWillUnmount() { + if (this.editor) { + this.editor.dispose(); + } + } + + private originalModel: + | monacoTypes.editor.ITextModel + | undefined = undefined; + private modifiedModel: + | monacoTypes.editor.ITextModel + | undefined = undefined; + + @disposeOnUnmount + private _updateText = autorun(() => { + if (this.editor) { + const originalModel = getLoadedMonaco().editor.createModel( + this.props.originalText, + this.props.languageId, + undefined + ); + const modifiedModel = getLoadedMonaco().editor.createModel( + this.props.modifiedText, + this.props.languageId, + undefined + ); + + this.editor.setModel({ + original: originalModel, + modified: modifiedModel, + }); + + if (this.originalModel) { + this.originalModel.dispose(); + } + this.originalModel = originalModel; + + if (this.modifiedModel) { + this.modifiedModel.dispose(); + } + this.modifiedModel = modifiedModel; + } + }); + + private readonly setEditorDiv = (editorDiv: HTMLDivElement) => { + if (!editorDiv) { + return; + } + this.editor = getLoadedMonaco().editor.createDiffEditor(editorDiv, { + automaticLayout: true, + scrollBeyondLastLine: false, + minimap: { enabled: false }, + fixedOverflowWidgets: true, + readOnly: true, + theme: this.props.theme.kind === "dark" ? "vs-dark" : "vs", + }); + if (this.originalModel && this.modifiedModel) { + this.editor.setModel({ + original: this.originalModel!, + modified: this.modifiedModel!, + }); + } + }; + + render() { + return ( +
+
+
+ ); + } +} diff --git a/visualization-bundle/src/visualizers/monaco-text-diff-visualizer/index.tsx b/visualization-bundle/src/visualizers/monaco-text-diff-visualizer/index.tsx new file mode 100644 index 0000000..3206962 --- /dev/null +++ b/visualization-bundle/src/visualizers/monaco-text-diff-visualizer/index.tsx @@ -0,0 +1,53 @@ +import { + sOpenObject, + sLiteral, + sString, + sOptionalProp, + sProp, +} from "@hediet/semantic-json"; +import * as React from "react"; +import { + getLanguageId, + MonacoEditor as MonacoDiffEditor, +} from "./MonacoEditor"; +import { + createVisualizer, + ReactVisualization, + globalVisualizationFactory, +} from "@hediet/visualization-core"; +import { visualizationNs } from "../../consts"; + +export const monacoTextDiffVisualizer = createVisualizer({ + id: "monaco-text-diff", + name: "Text Diff", + serializer: sOpenObject({ + kind: sOpenObject({ + text: sLiteral(true), + }), + text: sProp(sString(), { description: "The text to show" }), + otherText: sProp(sString(), { + description: "The text to compare against", + }), + fileName: sOptionalProp(sString(), { + description: + "An optional filename that might be used for chosing a syntax highlighter", + }), + }).defineAs(visualizationNs("MonacoTextDiffVisualizationData")), + getVisualization: (data, self) => + new ReactVisualization(self, { priority: 500 }, theme => { + let id = "text"; + if (data.fileName) { + id = getLanguageId(data.fileName); + } + return ( + + ); + }), +}); + +globalVisualizationFactory.addVisualizer(monacoTextDiffVisualizer); diff --git a/visualization-bundle/src/visualizers/monaco-text-diff-visualizer/style.scss b/visualization-bundle/src/visualizers/monaco-text-diff-visualizer/style.scss new file mode 100644 index 0000000..1269846 --- /dev/null +++ b/visualization-bundle/src/visualizers/monaco-text-diff-visualizer/style.scss @@ -0,0 +1,22 @@ +.component-monaco-editor { + width: 100%; + height: 100%; + min-width: 0; + box-sizing: border-box; + display: flex; + padding: 2px; + border: 0.5px solid gray; + + .part-editor { + min-width: 0; + min-height: 0; + flex: 1; + + .current-line { + border: none !important; + } + .selectionHighlight { + background: transparent !important; + } + } +}