@samitouri / QOS-React-2 / commits / e8650951ea

[playground] Add diff view toggle

Quick hack to show a diff view comparing previous pass to current. Default is the output view ![Screenshot 2023-01-31 at 5 37 09 PM](https://user-images.githubusercontent.com/1390709/215899637-672d578a-6fb9-4580-ae87-ae0be0878a59.png) ![Screenshot 2023-01-31 at 5 37 12 PM](https://user-images.githubusercontent.com/1390709/215899640-7aff3c06-fc67-476a-82f9-59d65b4f9ac4.png)

Lauren Tan committed Jan 31, 2023 at 17:37 UTC e8650951ea652e26979319ba5eb56a7daa05f682
2 files changed +100 -21
compiler/forget/packages/playground/components/Editor/Output.tsx
+99 -20
@@ -7,7 +7,7 @@
7
8 import generate from "@babel/generator";
9 import * as t from "@babel/types";
10 -import MonacoEditor from "@monaco-editor/react";
10 +import MonacoEditor, { DiffEditor } from "@monaco-editor/react";
11 import { type CompilerError } from "babel-plugin-react-forget";
12 import prettier from "prettier";
13 import prettierParserBabel from "prettier/parser-babel";
@@ -15,6 +15,12 @@ import { memo, useMemo, useState } from "react";
15 import { type Store } from "../../lib/stores";
16 import TabbedWindow from "../TabbedWindow";
17 import { monacoOptions } from "./monacoOptions";
18 +import {
19 + CodeIcon,
20 + DocumentAddIcon,
21 + InformationCircleIcon,
22 +} from "@heroicons/react/outline";
23 +
24 const MemoizedOutput = memo(Output);
25
26 export default MemoizedOutput;
@@ -86,8 +92,17 @@ function tabify(source: string, compilerOutput: CompilerOutput) {
92 }
93 }
94 }
95 + let lastPassOutput: string | null = null;
96 for (const [passName, text] of concattedResults) {
90 - tabs.set(passName, <TextTabContent output={text}></TextTabContent>);
97 + tabs.set(
98 + passName,
99 + <TextTabContent
100 + output={text}
101 + diff={lastPassOutput ?? null}
102 + showInfoPanel={true}
103 + ></TextTabContent>
104 + );
105 + lastPassOutput = text;
106 }
107 // Ensure that JS and the JS source map come first
108 if (topLevelFnDecls.length > 0) {
@@ -95,7 +110,14 @@ function tabify(source: string, compilerOutput: CompilerOutput) {
110 // FunctionDeclarations
111 const ast = t.program(topLevelFnDecls);
112 const { code, sourceMapUrl } = codegen(ast, source);
98 - reorderedTabs.set("JS", <TextTabContent output={code}></TextTabContent>);
113 + reorderedTabs.set(
114 + "JS",
115 + <TextTabContent
116 + output={code}
117 + diff={null}
118 + showInfoPanel={false}
119 + ></TextTabContent>
120 + );
121 if (sourceMapUrl) {
122 reorderedTabs.set(
123 "SourceMap",
@@ -164,13 +186,16 @@ function Output({ store, compilerOutput }: Props) {
186 tabs={tabs}
187 />
188 {compilerOutput.kind === "err" ? (
167 - <div className="flex flex-wrap w-full absolute bottom-0 bg-white grow w-screen border-y border-grey-200 transition-all ease-in">
189 + <div
190 + className="flex flex-wrap absolute bottom-0 bg-white grow border-y border-grey-200 transition-all ease-in"
191 + style={{ width: "calc(100vw - 650px)" }}
192 + >
193 <div className="w-full p-4 basis-full border-b">
194 <h2>COMPILER ERRORS</h2>
195 </div>
196 <pre
172 - className="p-4 basis-full text-red-600"
173 - style={{ maxHeight: "20vh", overflowY: "scroll" }}
197 + className="p-4 basis-full text-red-600 overflow-x-hidden"
198 + style={{ maxHeight: "20vh" }}
199 >
200 {compilerOutput.error.toString()}
201 </pre>
@@ -180,24 +205,78 @@ function Output({ store, compilerOutput }: Props) {
205 );
206 }
207
183 -function TextTabContent({ output }: { output: string }) {
208 +function TextTabContent({
209 + output,
210 + diff,
211 + showInfoPanel,
212 +}: {
213 + output: string;
214 + diff: string | null;
215 + showInfoPanel: boolean;
216 +}) {
217 + const [value, setValue] = useState(output);
218 return (
219 // Restrict MonacoEditor's height, since the config autoLayout:true
220 // will grow the editor to fit within parent element
221 <div className="w-full h-monaco_small sm:h-monaco">
188 - <MonacoEditor
189 - defaultLanguage="javascript"
190 - value={output}
191 - options={{
192 - ...monacoOptions,
193 - readOnly: true,
194 - lineNumbers: "off",
195 - glyphMargin: false,
196 - // Undocumented see https://github.com/Microsoft/vscode/issues/30795#issuecomment-410998882
197 - lineDecorationsWidth: 0,
198 - lineNumbersMinChars: 0,
199 - }}
200 - />
222 + {showInfoPanel ? (
223 + <div className="flex items-center gap-1 bg-amber-50 p-2">
224 + {diff != null && output !== diff ? (
225 + <button
226 + className="flex items-center gap-1 transition-colors duration-150 ease-in text-secondary hover:text-link"
227 + onClick={() =>
228 + value === output ? setValue(diff) : setValue(output)
229 + }
230 + >
231 + {value === output ? (
232 + <>
233 + <DocumentAddIcon className="w-5 h-5" /> Show Diff
234 + </>
235 + ) : (
236 + <>
237 + <CodeIcon className="w-5 h-5" /> Show Output
238 + </>
239 + )}
240 + </button>
241 + ) : (
242 + <>
243 + <span className="flex items-center gap-1">
244 + <InformationCircleIcon className="w-5 h-5" /> No changes from
245 + previous pass
246 + </span>
247 + </>
248 + )}
249 + </div>
250 + ) : null}
251 + {diff != null && value !== output ? (
252 + <DiffEditor
253 + original={diff}
254 + modified={output}
255 + options={{
256 + ...monacoOptions,
257 + readOnly: true,
258 + lineNumbers: "off",
259 + glyphMargin: false,
260 + // Undocumented see https://github.com/Microsoft/vscode/issues/30795#issuecomment-410998882
261 + lineDecorationsWidth: 0,
262 + lineNumbersMinChars: 0,
263 + }}
264 + />
265 + ) : (
266 + <MonacoEditor
267 + defaultLanguage="javascript"
268 + value={output}
269 + options={{
270 + ...monacoOptions,
271 + readOnly: true,
272 + lineNumbers: "off",
273 + glyphMargin: false,
274 + // Undocumented see https://github.com/Microsoft/vscode/issues/30795#issuecomment-410998882
275 + lineDecorationsWidth: 0,
276 + lineNumbersMinChars: 0,
277 + }}
278 + />
279 + )}
280 </div>
281 );
282 }
compiler/forget/packages/playground/components/TabbedWindow.tsx
+1 -1
@@ -68,7 +68,7 @@ function TabbedWindowItem({
68 return (
69 <div key={name} className="flex flex-row">
70 {isShow ? (
71 - <div style={{ minWidth: 550, overflow: "hidden" }}>
71 + <div className="border-r" style={{ minWidth: 550, overflow: "hidden" }}>
72 <h2
73 onClick={toggleTabs}
74 className="p-4 duration-150 ease-in border-b cursor-pointer border-grey-200 text-secondary hover:text-link"