From 380ec6676c45a1e3843c38af719607318eb05488 Mon Sep 17 00:00:00 2001 From: Erick Zhao Date: Tue, 18 Nov 2025 00:01:06 -0800 Subject: [PATCH 1/9] uhhh --- package.json | 4 +-- src/renderer/components/editors.tsx | 9 +++++-- src/renderer/editor-mosaic.ts | 40 +++++++++++++++++++++++++++-- yarn.lock | 22 ++++++++-------- 4 files changed, 58 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index 8f254ab737..74a8bf0413 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "getos": "^3.2.1", "mobx": "^6.5.0", "mobx-react": "^7.3.0", - "monaco-editor": "^0.21.3", + "monaco-editor": "^0.22.0", "namor": "^2.0.2", "node-watch": "^0.7.3", "p-debounce": "^2.0.0", @@ -134,7 +134,7 @@ "log-symbols": "^6.0.0", "markdownlint-cli2": "^0.18.0", "mini-css-extract-plugin": "^2.6.1", - "monaco-editor-webpack-plugin": "2.1.0", + "monaco-editor-webpack-plugin": "^3.0.0", "npm-run-all2": "^7.0.1", "postcss": "^8.4.25", "postcss-less": "^6.0.0", diff --git a/src/renderer/components/editors.tsx b/src/renderer/components/editors.tsx index 24f498cacd..39f9161219 100644 --- a/src/renderer/components/editors.tsx +++ b/src/renderer/components/editors.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; +import { toJS } from 'mobx'; import { observer } from 'mobx-react'; import type * as MonacoType from 'monaco-editor'; import { @@ -185,7 +186,7 @@ export const Editors = observer( } /** - * Renders the little tool bar on top of each panel + * Renders the little toolbar on top of each panel */ public renderToolbar( { title }: MosaicWindowProps, @@ -197,7 +198,9 @@ export const Editors = observer(
{/* Left */}
-
{title}
+
+ {title} (${appState.editorMosaic.erick.get(id)}) +
{/* Middle */}
@@ -252,6 +255,8 @@ export const Editors = observer( public render() { const { editorMosaic } = this.props.appState; + console.log(toJS(editorMosaic.erick)); + return ( className={`focused__${this.state.focused}`} diff --git a/src/renderer/editor-mosaic.ts b/src/renderer/editor-mosaic.ts index 652a7c2ddb..551f709631 100644 --- a/src/renderer/editor-mosaic.ts +++ b/src/renderer/editor-mosaic.ts @@ -1,4 +1,11 @@ -import { action, computed, makeObservable, observable, reaction } from 'mobx'; +import { + action, + computed, + makeObservable, + observable, + reaction, + runInAction, +} from 'mobx'; import type * as MonacoType from 'monaco-editor'; import { MosaicDirection, MosaicNode, getLeaves } from 'react-mosaic-component'; @@ -104,6 +111,25 @@ export class EditorMosaic { } }, ); + + window.monaco.editor.onDidChangeMarkers(() => { + runInAction(() => { + for (const id of this.getAllEditorIds()) { + const markers = window.monaco.editor.getModelMarkers({ + resource: window.monaco.Uri.parse(`inmemory://fiddle/${id}`), + }); + + const maxSeverity: MonacoType.MarkerSeverity = markers.reduce( + (max, marker) => { + return Math.max(max, marker.severity); + }, + window.monaco.MarkerSeverity.Hint, + ); + + this.erick.set(id, maxSeverity); + } + }); + }); } /** File is visible, focus file content */ @@ -160,7 +186,10 @@ export class EditorMosaic { // create a monaco model with the file's contents const { monaco } = window; const language = monacoLanguage(id); - const model = monaco.editor.createModel(value, language); + + // set a URI for each editor for stable identification for monaco features + const uri = monaco.Uri.parse(`inmemory://fiddle/${id}`); + const model = monaco.editor.createModel(value, language, uri); // if we have an editor available, use the monaco model now. // otherwise, save the file in `this.backups` for future use. @@ -263,6 +292,7 @@ export class EditorMosaic { this.backups.delete(id); this.editors.set(id, editor); + this.erick.set(id, window.monaco.MarkerSeverity.Hint); this.setEditorFromBackup(editor, backup); } @@ -342,6 +372,10 @@ export class EditorMosaic { } }; + public getAllEditorIds(): EditorId[] { + return [...this.editors.keys()]; + } + public getAllEditors(): Editor[] { return [...this.editors.values()]; } @@ -380,4 +414,6 @@ export class EditorMosaic { disposable.dispose(); }); } + + public erick = observable.map(); } diff --git a/yarn.lock b/yarn.lock index 16e4fb8dba..99443a33c6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6189,8 +6189,8 @@ __metadata: mini-css-extract-plugin: "npm:^2.6.1" mobx: "npm:^6.5.0" mobx-react: "npm:^7.3.0" - monaco-editor: "npm:^0.21.3" - monaco-editor-webpack-plugin: "npm:2.1.0" + monaco-editor: "npm:^0.22.0" + monaco-editor-webpack-plugin: "npm:^3.0.0" namor: "npm:^2.0.2" node-watch: "npm:^0.7.3" npm-run-all2: "npm:^7.0.1" @@ -10883,22 +10883,22 @@ __metadata: languageName: node linkType: hard -"monaco-editor-webpack-plugin@npm:2.1.0": - version: 2.1.0 - resolution: "monaco-editor-webpack-plugin@npm:2.1.0" +"monaco-editor-webpack-plugin@npm:^3.0.0": + version: 3.1.0 + resolution: "monaco-editor-webpack-plugin@npm:3.1.0" dependencies: loader-utils: "npm:^2.0.0" peerDependencies: - monaco-editor: 0.21.x + monaco-editor: 0.22.x || 0.23.x || 0.24.x webpack: ^4.5.0 || 5.x - checksum: 10c0/47d891383b46c0fcbcdf6732b0d5e8886bbe28c4ad2054f9a45750efafd8267c3116e6adfb66bf8996c26eeb8b1609cbb6f9dbb3d741a15cbd03a909f8ec20f9 + checksum: 10c0/c8e094968eeb63a02c764e60bc38e56e1fbad9be9551785bff291da65196bc0061e13ff507c3f786bde92bf270a0cdfc653a99fc88034305a7b6ceeebcb6e20f languageName: node linkType: hard -"monaco-editor@npm:^0.21.3": - version: 0.21.3 - resolution: "monaco-editor@npm:0.21.3" - checksum: 10c0/846a5007fee92eb64bbbe162fc2d06ea908caac9a9072da6903724c3e3959a3c9f8c15eedff2b9f98ce8a11bf7781305b16ad8125bcfe39a13a6aecc1ad9c0d3 +"monaco-editor@npm:^0.22.0": + version: 0.22.3 + resolution: "monaco-editor@npm:0.22.3" + checksum: 10c0/a95f82f7788617d1f418e42d478b278ba83adfb3a4659cc813378867ad0d6b7a7dc8e1395afac5ec00b2064cef083b1fe75f77b4edd7aae57de5ed6fa49bc9a4 languageName: node linkType: hard From 04907853939218677b30680db6202000f3cda89c Mon Sep 17 00:00:00 2001 From: Erick Zhao Date: Tue, 18 Nov 2025 18:21:29 -0800 Subject: [PATCH 2/9] fixes --- src/renderer/app.tsx | 1 + src/renderer/editor-mosaic.ts | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/renderer/app.tsx b/src/renderer/app.tsx index f5e077b82b..bf0e45ba80 100644 --- a/src/renderer/app.tsx +++ b/src/renderer/app.tsx @@ -68,6 +68,7 @@ export class App { } this.state.editorMosaic.set(editorValues); + this.state.editorMosaic.erick.clear(); this.state.gistId = gistId || ''; this.state.localPath = localFiddle?.filePath; diff --git a/src/renderer/editor-mosaic.ts b/src/renderer/editor-mosaic.ts index 551f709631..7c943a9f58 100644 --- a/src/renderer/editor-mosaic.ts +++ b/src/renderer/editor-mosaic.ts @@ -189,7 +189,8 @@ export class EditorMosaic { // set a URI for each editor for stable identification for monaco features const uri = monaco.Uri.parse(`inmemory://fiddle/${id}`); - const model = monaco.editor.createModel(value, language, uri); + const maybeModel = monaco.editor.getModel(uri); + const model = maybeModel ?? monaco.editor.createModel(value, language, uri); // if we have an editor available, use the monaco model now. // otherwise, save the file in `this.backups` for future use. From 3ed8329dd9cfc6c9fcbc897987c15440ca739a5f Mon Sep 17 00:00:00 2001 From: Erick Zhao Date: Tue, 18 Nov 2025 19:14:14 -0800 Subject: [PATCH 3/9] add css --- src/less/components/editors.less | 14 ++++ src/renderer/components/editors.tsx | 102 ++++++++++++++-------------- src/renderer/editor-mosaic.ts | 1 + 3 files changed, 65 insertions(+), 52 deletions(-) diff --git a/src/less/components/editors.less b/src/less/components/editors.less index fba46ab238..40a430549a 100644 --- a/src/less/components/editors.less +++ b/src/less/components/editors.less @@ -24,6 +24,20 @@ } } +// Set the toolbar text colour based on the mosaic's +// current severity level. +// Hint=1, +// Info=2, +// Warning=4, +// Error=8 +.mosaic-toolbar-severity-level-8 { + color: @red4; +} + +.mosaic-toolbar-severity-level-4 { + color: @orange4; +} + // TODO: support new file // update if list of Editor ID changes @editor-ids: main\.js, renderer\.js, index\.html, preload\.js, styles\.css; diff --git a/src/renderer/components/editors.tsx b/src/renderer/components/editors.tsx index 39f9161219..635a59621c 100644 --- a/src/renderer/components/editors.tsx +++ b/src/renderer/components/editors.tsx @@ -44,7 +44,6 @@ export const Editors = observer( this.onChange = this.onChange.bind(this); this.renderEditor = this.renderEditor.bind(this); - this.renderTile = this.renderTile.bind(this); this.setFocused = this.setFocused.bind(this); this.state = { @@ -185,55 +184,6 @@ export const Editors = observer( } } - /** - * Renders the little toolbar on top of each panel - */ - public renderToolbar( - { title }: MosaicWindowProps, - id: EditorId, - ): JSX.Element { - const { appState } = this.props; - - return ( -
- {/* Left */} -
-
- {title} (${appState.editorMosaic.erick.get(id)}) -
-
- {/* Middle */} -
- {/* Right */} -
- - -
-
- ); - } - - /** - * Renders a Mosaic tile - */ - public renderTile(id: EditorId, path: Array): JSX.Element { - const content = this.renderEditor(id); - const title = getEditorTitle(id as EditorId); - - return ( - - className={id} - path={path} - title={title} - renderToolbar={(props: MosaicWindowProps) => - this.renderToolbar(props, id) - } - > - {content} - - ); - } - /** * Render an editor */ @@ -254,8 +204,56 @@ export const Editors = observer( public render() { const { editorMosaic } = this.props.appState; + const erickMap = toJS(editorMosaic.erick); + /** + * Renders the little toolbar on top of each panel + */ + const renderToolbar = ( + { title }: MosaicWindowProps, + id: EditorId, + ) => { + const { appState } = this.props; + return ( +
+ {/* Left */} +
+
+ {title} +
+
+ {/* Middle */} +
+ {/* Right */} +
+ + +
+
+ ); + }; - console.log(toJS(editorMosaic.erick)); + /** + * Renders a Mosaic tile + */ + const renderTile = (id: EditorId, path: Array) => { + const content = this.renderEditor(id); + const title = getEditorTitle(id as EditorId); + + return ( + + className={id} + path={path} + title={title} + renderToolbar={(props: MosaicWindowProps) => + renderToolbar(props, id) + } + > + {content} + + ); + }; return ( @@ -263,7 +261,7 @@ export const Editors = observer( onChange={this.onChange} value={editorMosaic.mosaic} zeroStateView={} - renderTile={this.renderTile} + renderTile={renderTile} /> ); } diff --git a/src/renderer/editor-mosaic.ts b/src/renderer/editor-mosaic.ts index 7c943a9f58..4b60b4df96 100644 --- a/src/renderer/editor-mosaic.ts +++ b/src/renderer/editor-mosaic.ts @@ -91,6 +91,7 @@ export class EditorMosaic { setEditorFromBackup: action, addNewFile: action, renameFile: action, + erick: observable, }); // whenever the mosaics are changed, From 4c6df61b440f9910f96dd398a9380e5de61900e5 Mon Sep 17 00:00:00 2001 From: Erick Zhao Date: Tue, 18 Nov 2025 19:30:33 -0800 Subject: [PATCH 4/9] bepp boop --- src/renderer/app.tsx | 2 +- src/renderer/components/editors.tsx | 40 +++++++++++++--------------- src/renderer/editor-mosaic.ts | 12 +++++---- tests/mocks/monaco.ts | 12 +++++++++ tests/renderer/editor-mosaic-spec.ts | 1 + tests/setup.ts | 4 +-- 6 files changed, 41 insertions(+), 30 deletions(-) diff --git a/src/renderer/app.tsx b/src/renderer/app.tsx index bf0e45ba80..0674c616b2 100644 --- a/src/renderer/app.tsx +++ b/src/renderer/app.tsx @@ -68,7 +68,7 @@ export class App { } this.state.editorMosaic.set(editorValues); - this.state.editorMosaic.erick.clear(); + this.state.editorMosaic.editorSeverityMap.clear(); this.state.gistId = gistId || ''; this.state.localPath = localFiddle?.filePath; diff --git a/src/renderer/components/editors.tsx b/src/renderer/components/editors.tsx index 635a59621c..3479b36e6a 100644 --- a/src/renderer/components/editors.tsx +++ b/src/renderer/components/editors.tsx @@ -43,7 +43,6 @@ export const Editors = observer( super(props); this.onChange = this.onChange.bind(this); - this.renderEditor = this.renderEditor.bind(this); this.setFocused = this.setFocused.bind(this); this.state = { @@ -184,27 +183,9 @@ export const Editors = observer( } } - /** - * Render an editor - */ - public renderEditor(id: EditorId): JSX.Element | null { - const { appState } = this.props; - const { monaco } = this.state; - - return ( - - ); - } - public render() { const { editorMosaic } = this.props.appState; - const erickMap = toJS(editorMosaic.erick); + const severityLevel = toJS(editorMosaic.editorSeverityMap); /** * Renders the little toolbar on top of each panel */ @@ -218,7 +199,7 @@ export const Editors = observer( {/* Left */}
{title}
@@ -238,7 +219,7 @@ export const Editors = observer( * Renders a Mosaic tile */ const renderTile = (id: EditorId, path: Array) => { - const content = this.renderEditor(id); + const content = renderEditor(id); const title = getEditorTitle(id as EditorId); return ( @@ -255,6 +236,21 @@ export const Editors = observer( ); }; + const renderEditor = (id: EditorId) => { + const { appState } = this.props; + const { monaco } = this.state; + + return ( + + ); + }; + return ( className={`focused__${this.state.focused}`} diff --git a/src/renderer/editor-mosaic.ts b/src/renderer/editor-mosaic.ts index 4b60b4df96..c7b31a9bbd 100644 --- a/src/renderer/editor-mosaic.ts +++ b/src/renderer/editor-mosaic.ts @@ -91,7 +91,7 @@ export class EditorMosaic { setEditorFromBackup: action, addNewFile: action, renameFile: action, - erick: observable, + editorSeverityMap: observable, }); // whenever the mosaics are changed, @@ -112,7 +112,6 @@ export class EditorMosaic { } }, ); - window.monaco.editor.onDidChangeMarkers(() => { runInAction(() => { for (const id of this.getAllEditorIds()) { @@ -127,7 +126,7 @@ export class EditorMosaic { window.monaco.MarkerSeverity.Hint, ); - this.erick.set(id, maxSeverity); + this.editorSeverityMap.set(id, maxSeverity); } }); }); @@ -294,7 +293,7 @@ export class EditorMosaic { this.backups.delete(id); this.editors.set(id, editor); - this.erick.set(id, window.monaco.MarkerSeverity.Hint); + this.editorSeverityMap.set(id, window.monaco.MarkerSeverity.Hint); this.setEditorFromBackup(editor, backup); } @@ -417,5 +416,8 @@ export class EditorMosaic { }); } - public erick = observable.map(); + public editorSeverityMap = observable.map< + EditorId, + MonacoType.MarkerSeverity + >(); } diff --git a/tests/mocks/monaco.ts b/tests/mocks/monaco.ts index 00334e5d90..61cf69c3bd 100644 --- a/tests/mocks/monaco.ts +++ b/tests/mocks/monaco.ts @@ -26,6 +26,7 @@ export class MonacoMock { public latestModel: any; public editor = { create: vi.fn(() => (this.latestEditor = new MonacoEditorMock())), + getModel: vi.fn(), createModel: vi.fn((value: string, language: string) => { const model = new MonacoModelMock(value, language); this.latestModel = model; @@ -35,6 +36,8 @@ export class MonacoMock { onDidFocusEditorText: vi.fn(), revealLine: vi.fn(), setTheme: vi.fn(), + onDidChangeMarkers: vi.fn(() => ({ dispose: vi.fn() })), + getModelMarkers: vi.fn(() => []), }; public languages = { register: vi.fn(), @@ -46,6 +49,15 @@ export class MonacoMock { }, }, }; + public Uri = { + parse: vi.fn((uri: string) => ({ toString: () => uri })), + }; + public MarkerSeverity = { + Hint: 1, + Info: 2, + Warning: 4, + Error: 8, + }; public KeyMod = { CtrlCmd: vi.fn(), }; diff --git a/tests/renderer/editor-mosaic-spec.ts b/tests/renderer/editor-mosaic-spec.ts index 53a8e3bf81..b3f77abfa6 100644 --- a/tests/renderer/editor-mosaic-spec.ts +++ b/tests/renderer/editor-mosaic-spec.ts @@ -101,6 +101,7 @@ describe('EditorMosaic', () => { expect(monaco.editor.createModel).toHaveBeenCalledWith( content, expect.anything(), + expect.anything(), ); }); }); diff --git a/tests/setup.ts b/tests/setup.ts index a8dea90ca8..1fb6653141 100644 --- a/tests/setup.ts +++ b/tests/setup.ts @@ -95,8 +95,8 @@ window.navigator = window.navigator ?? {}; * code called in individual tests. */ (window.ElectronFiddle as any) = new ElectronFiddleMock(); -(window.app as any) = new AppMock(); (window.monaco as any) = new MonacoMock(); +(window.app as any) = new AppMock(); window.localStorage.setItem = vi.fn(); window.localStorage.getItem = vi.fn(); window.localStorage.removeItem = vi.fn(); @@ -115,8 +115,8 @@ beforeEach(() => { document.body.innerHTML = '
'; (window.ElectronFiddle as any) = new ElectronFiddleMock(); - (window.app as any) = new AppMock(); (window.monaco as any) = new MonacoMock(); + (window.app as any) = new AppMock(); vi.mocked(window.localStorage.setItem).mockReset(); vi.mocked(window.localStorage.getItem).mockReset(); vi.mocked(window.localStorage.removeItem).mockReset(); From 44576babf489b8cd46a2375885dc3da64c729027 Mon Sep 17 00:00:00 2001 From: Erick Zhao Date: Tue, 18 Nov 2025 20:08:26 -0800 Subject: [PATCH 5/9] hmm? --- tests/mocks/monaco.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/mocks/monaco.ts b/tests/mocks/monaco.ts index 61cf69c3bd..7bb8e216f4 100644 --- a/tests/mocks/monaco.ts +++ b/tests/mocks/monaco.ts @@ -36,7 +36,7 @@ export class MonacoMock { onDidFocusEditorText: vi.fn(), revealLine: vi.fn(), setTheme: vi.fn(), - onDidChangeMarkers: vi.fn(() => ({ dispose: vi.fn() })), + onDidChangeMarkers: vi.fn(), getModelMarkers: vi.fn(() => []), }; public languages = { From df5c9efbca8b4e128f4e66d22f7d3d8f6135e0fb Mon Sep 17 00:00:00 2001 From: Erick Zhao Date: Tue, 18 Nov 2025 20:21:52 -0800 Subject: [PATCH 6/9] add a few tests --- src/renderer/editor-mosaic.ts | 38 +++++++++++----------- tests/renderer/editor-mosaic-spec.ts | 48 ++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 18 deletions(-) diff --git a/src/renderer/editor-mosaic.ts b/src/renderer/editor-mosaic.ts index c7b31a9bbd..06ccc949f0 100644 --- a/src/renderer/editor-mosaic.ts +++ b/src/renderer/editor-mosaic.ts @@ -112,24 +112,7 @@ export class EditorMosaic { } }, ); - window.monaco.editor.onDidChangeMarkers(() => { - runInAction(() => { - for (const id of this.getAllEditorIds()) { - const markers = window.monaco.editor.getModelMarkers({ - resource: window.monaco.Uri.parse(`inmemory://fiddle/${id}`), - }); - - const maxSeverity: MonacoType.MarkerSeverity = markers.reduce( - (max, marker) => { - return Math.max(max, marker.severity); - }, - window.monaco.MarkerSeverity.Hint, - ); - - this.editorSeverityMap.set(id, maxSeverity); - } - }); - }); + window.monaco.editor.onDidChangeMarkers(this.setSeverityLevels.bind(this)); } /** File is visible, focus file content */ @@ -420,4 +403,23 @@ export class EditorMosaic { EditorId, MonacoType.MarkerSeverity >(); + + public setSeverityLevels() { + runInAction(() => { + for (const id of this.getAllEditorIds()) { + const markers = window.monaco.editor.getModelMarkers({ + resource: window.monaco.Uri.parse(`inmemory://fiddle/${id}`), + }); + + const maxSeverity: MonacoType.MarkerSeverity = markers.reduce( + (max, marker) => { + return Math.max(max, marker.severity); + }, + window.monaco.MarkerSeverity.Hint, + ); + + this.editorSeverityMap.set(id, maxSeverity); + } + }); + } } diff --git a/tests/renderer/editor-mosaic-spec.ts b/tests/renderer/editor-mosaic-spec.ts index b3f77abfa6..9d67ee94db 100644 --- a/tests/renderer/editor-mosaic-spec.ts +++ b/tests/renderer/editor-mosaic-spec.ts @@ -542,4 +542,52 @@ describe('EditorMosaic', () => { dispose(); }); }); + + describe('setSeverityLevels', () => { + it.each([ + { + markers: [ + { + severity: monaco.MarkerSeverity.Error, + message: 'Error message', + }, + { + severity: monaco.MarkerSeverity.Warning, + message: 'Warning message', + }, + ], + expectedSeverity: monaco.MarkerSeverity.Error, + }, + { + markers: [ + { + severity: monaco.MarkerSeverity.Warning, + message: 'Warning message', + }, + ], + expectedSeverity: monaco.MarkerSeverity.Warning, + }, + { + markers: [], + expectedSeverity: monaco.MarkerSeverity.Info, + }, + ])( + 'updates severity levels based on Monaco markers', + ({ markers, expectedSeverity }) => { + const id = MAIN_JS; + const editor = new MonacoEditorMock() as unknown as Editor; + editorMosaic.set({ [id]: '// content' }); + editorMosaic.addEditor(id, editor); + + vi.mocked(monaco.editor.getModelMarkers).mockReturnValueOnce( + markers as any, + ); + + editorMosaic.setSeverityLevels(); + + const severityLevels = editorMosaic.editorSeverityMap; + expect(severityLevels.get(id)).toBe(expectedSeverity); + }, + ); + }); }); From 6b2a4910a340be5c0889e01d13af4c7da45e4836 Mon Sep 17 00:00:00 2001 From: Erick Zhao Date: Tue, 18 Nov 2025 20:34:01 -0800 Subject: [PATCH 7/9] fix my tests --- tests/renderer/editor-mosaic-spec.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/renderer/editor-mosaic-spec.ts b/tests/renderer/editor-mosaic-spec.ts index 9d67ee94db..07a235f38a 100644 --- a/tests/renderer/editor-mosaic-spec.ts +++ b/tests/renderer/editor-mosaic-spec.ts @@ -548,28 +548,28 @@ describe('EditorMosaic', () => { { markers: [ { - severity: monaco.MarkerSeverity.Error, + severity: window.monaco.MarkerSeverity.Error, message: 'Error message', }, { - severity: monaco.MarkerSeverity.Warning, + severity: window.monaco.MarkerSeverity.Warning, message: 'Warning message', }, ], - expectedSeverity: monaco.MarkerSeverity.Error, + expectedSeverity: window.monaco.MarkerSeverity.Error, }, { markers: [ { - severity: monaco.MarkerSeverity.Warning, + severity: window.monaco.MarkerSeverity.Warning, message: 'Warning message', }, ], - expectedSeverity: monaco.MarkerSeverity.Warning, + expectedSeverity: window.monaco.MarkerSeverity.Warning, }, { markers: [], - expectedSeverity: monaco.MarkerSeverity.Info, + expectedSeverity: window.monaco.MarkerSeverity.Hint, }, ])( 'updates severity levels based on Monaco markers', From ba71f348f6ffa5e316d6340ff8c9f7c1ae64d49d Mon Sep 17 00:00:00 2001 From: Erick Zhao Date: Thu, 20 Nov 2025 11:45:48 -0800 Subject: [PATCH 8/9] fix: update content when recycling editor --- src/renderer/components/editors.tsx | 1 + src/renderer/editor-mosaic.ts | 9 +++++++-- tests/renderer/editor-mosaic-spec.ts | 9 +++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/renderer/components/editors.tsx b/src/renderer/components/editors.tsx index 3479b36e6a..3310a1bc35 100644 --- a/src/renderer/components/editors.tsx +++ b/src/renderer/components/editors.tsx @@ -185,6 +185,7 @@ export const Editors = observer( public render() { const { editorMosaic } = this.props.appState; + // HACK: we use this to force re-renders of the toolbar when severity changes const severityLevel = toJS(editorMosaic.editorSeverityMap); /** * Renders the little toolbar on top of each panel diff --git a/src/renderer/editor-mosaic.ts b/src/renderer/editor-mosaic.ts index 06ccc949f0..bee3922bd6 100644 --- a/src/renderer/editor-mosaic.ts +++ b/src/renderer/editor-mosaic.ts @@ -172,9 +172,14 @@ export class EditorMosaic { // set a URI for each editor for stable identification for monaco features const uri = monaco.Uri.parse(`inmemory://fiddle/${id}`); + let model: MonacoType.editor.ITextModel; const maybeModel = monaco.editor.getModel(uri); - const model = maybeModel ?? monaco.editor.createModel(value, language, uri); - + if (maybeModel) { + model = maybeModel; + model.setValue(value); + } else { + model = monaco.editor.createModel(value, language, uri); + } // if we have an editor available, use the monaco model now. // otherwise, save the file in `this.backups` for future use. const backup: EditorBackup = { model }; diff --git a/tests/renderer/editor-mosaic-spec.ts b/tests/renderer/editor-mosaic-spec.ts index 07a235f38a..5ac191b889 100644 --- a/tests/renderer/editor-mosaic-spec.ts +++ b/tests/renderer/editor-mosaic-spec.ts @@ -304,6 +304,9 @@ describe('EditorMosaic', () => { // now call set again, same filename DIFFERENT content content = '// second content'; + vi.mocked(monaco.editor.getModel).mockReturnValueOnce( + monaco.latestModel, + ); editorMosaic.set({ [id]: content }); // test that editorMosaic set the editor to the new content expect(editor.getValue()).toBe(content); @@ -311,6 +314,9 @@ describe('EditorMosaic', () => { // test that the editor still responds to edits content = '// third content'; + vi.mocked(monaco.editor.getModel).mockReturnValueOnce( + monaco.latestModel, + ); editor.setValue(content); expect(editorMosaic.isEdited).toBe(true); @@ -320,6 +326,9 @@ describe('EditorMosaic', () => { // test that the editor still responds to edits content = '// fourth content'; + vi.mocked(monaco.editor.getModel).mockReturnValueOnce( + monaco.latestModel, + ); editor.setValue(content); expect(editorMosaic.isEdited).toBe(true); }); From 53131eafd27d1cc4e0852751afc23eccc69de73b Mon Sep 17 00:00:00 2001 From: Erick Zhao Date: Thu, 20 Nov 2025 11:49:35 -0800 Subject: [PATCH 9/9] chore: add comment for destructor --- src/renderer/editor-mosaic.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/renderer/editor-mosaic.ts b/src/renderer/editor-mosaic.ts index bee3922bd6..ac7e9f4005 100644 --- a/src/renderer/editor-mosaic.ts +++ b/src/renderer/editor-mosaic.ts @@ -112,6 +112,8 @@ export class EditorMosaic { } }, ); + // TODO: evaluate if we need to dispose of the listener when this class is + // destroyed via FinalizationRegistry window.monaco.editor.onDidChangeMarkers(this.setSeverityLevels.bind(this)); }