From 7f4101de5f3328d5bd561aa6648d16ef2a2d0243 Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Tue, 9 Jan 2024 12:33:39 +0100 Subject: [PATCH] feat: enable opening external URLs in editor (#1524) --- src/renderer/components/editor.tsx | 48 +++++++++++++++++++++++------- src/renderer/components/output.tsx | 48 +++++++++++++++++++++++------- 2 files changed, 76 insertions(+), 20 deletions(-) diff --git a/src/renderer/components/editor.tsx b/src/renderer/components/editor.tsx index 219fae8f91..8e527c9eb7 100644 --- a/src/renderer/components/editor.tsx +++ b/src/renderer/components/editor.tsx @@ -82,16 +82,22 @@ export class Editor extends React.Component { const { fontFamily, fontSize } = appState; if (ref) { - this.editor = monaco.editor.create(ref, { - automaticLayout: true, - language: this.language, - theme: 'main', - fontFamily, - fontSize, - contextmenu: false, - model: null, - ...monacoOptions, - }); + this.editor = monaco.editor.create( + ref, + { + automaticLayout: true, + language: this.language, + theme: 'main', + fontFamily, + fontSize, + contextmenu: false, + model: null, + ...monacoOptions, + }, + { + openerService: this.openerService(), + }, + ); // mark this editor as focused whenever it is this.editor.onDidFocusEditorText(() => { @@ -113,6 +119,28 @@ export class Editor extends React.Component { } } + /** + * Implements external url handling for Monaco. + * + * @returns {MonacoType.editor.IOpenerService} + */ + private openerService() { + const { appState } = this.props; + + return { + open: (url: string) => { + appState + .showConfirmDialog({ + label: `Open ${url} in external browser?`, + ok: 'Open', + }) + .then((open) => { + if (open) window.open(url); + }); + }, + }; + } + public render() { return
; } diff --git a/src/renderer/components/output.tsx b/src/renderer/components/output.tsx index 497a40ee0c..a90e965301 100644 --- a/src/renderer/components/output.tsx +++ b/src/renderer/components/output.tsx @@ -78,16 +78,22 @@ export const Output = observer( const ref = this.outputRef.current; if (ref) { this.setupCustomOutputEditorLanguage(monaco); - this.editor = monaco.editor.create(ref, { - language: this.language, - theme: 'main', - readOnly: true, - contextmenu: false, - automaticLayout: true, - model: this.model, - ...monacoOptions, - wordWrap: 'on', - }); + this.editor = monaco.editor.create( + ref, + { + language: this.language, + theme: 'main', + readOnly: true, + contextmenu: false, + automaticLayout: true, + model: this.model, + ...monacoOptions, + wordWrap: 'on', + }, + { + openerService: this.openerService(), + }, + ); } } @@ -193,6 +199,28 @@ export const Output = observer( return lines; } + /** + * Implements external url handling for Monaco. + * + * @returns {MonacoType.editor.IOpenerService} + */ + private openerService() { + const { appState } = this.props; + + return { + open: (url: string) => { + appState + .showConfirmDialog({ + label: `Open ${url} in external browser?`, + ok: 'Open', + }) + .then((open) => { + if (open) window.open(url); + }); + }, + }; + } + public render(): JSX.Element | null { const { isConsoleShowing } = this.props.appState;