From 9c4bff5b6e5b57d7cf0cee08b096b03a93ece279 Mon Sep 17 00:00:00 2001 From: Kai Salmen Date: Sat, 7 Oct 2023 19:18:49 +0200 Subject: [PATCH] Properly separate classic and extended app (code and terminology) --- .../langium/config/wrapperLangiumClassic.ts | 5 -- ...iumVscode.ts => wrapperLangiumExtended.ts} | 4 +- .../config/wrapperStatemachineConfig.ts | 2 +- .../examples/src/langium/wrapperLangium.ts | 8 +-- packages/examples/src/reactPython.tsx | 2 +- packages/examples/src/wrapperTs.ts | 2 +- packages/examples/src/wrapperWs.ts | 2 +- packages/examples/wrapper_langium.html | 2 +- packages/monaco-editor-wrapper/README.md | 61 +++++++++++----- .../src/editorAppBase.ts | 47 ++++++------- .../src/editorAppClassic.ts | 70 +++++++------------ ...orAppVscodeApi.ts => editorAppExtended.ts} | 28 +++++--- packages/monaco-editor-wrapper/src/index.ts | 20 +++--- packages/monaco-editor-wrapper/src/wrapper.ts | 16 ++--- .../test/editorAppBase.test.ts | 26 +++---- .../test/editorAppClassic.test.ts | 6 +- ...eApi.test.ts => editorAppExtended.test.ts} | 4 +- 17 files changed, 151 insertions(+), 154 deletions(-) rename packages/examples/src/langium/config/{wrapperLangiumVscode.ts => wrapperLangiumExtended.ts} (96%) rename packages/monaco-editor-wrapper/src/{editorAppVscodeApi.ts => editorAppExtended.ts} (83%) rename packages/monaco-editor-wrapper/test/{editorAppVscodeApi.test.ts => editorAppExtended.test.ts} (83%) diff --git a/packages/examples/src/langium/config/wrapperLangiumClassic.ts b/packages/examples/src/langium/config/wrapperLangiumClassic.ts index 49ad413..ff6bd77 100644 --- a/packages/examples/src/langium/config/wrapperLangiumClassic.ts +++ b/packages/examples/src/langium/config/wrapperLangiumClassic.ts @@ -32,16 +32,11 @@ export const setupLangiumClientClassic = async (): Promise => { code: code, useDiffEditor: false, theme: 'vs-dark', - // configure it like this or in the userConfiguration editorOptions: { 'semanticHighlighting.enabled': true }, languageExtensionConfig: { id: 'langium' }, languageDef: LangiumMonarchContent, - userConfiguration: { - // or configure the semantic highlighting like this: - // `{ json: "editor.semanticHighlighting.enabled": true }` - } } }, languageClientConfig: { diff --git a/packages/examples/src/langium/config/wrapperLangiumVscode.ts b/packages/examples/src/langium/config/wrapperLangiumExtended.ts similarity index 96% rename from packages/examples/src/langium/config/wrapperLangiumVscode.ts rename to packages/examples/src/langium/config/wrapperLangiumExtended.ts index cc6fa5f..cbd0ada 100644 --- a/packages/examples/src/langium/config/wrapperLangiumVscode.ts +++ b/packages/examples/src/langium/config/wrapperLangiumExtended.ts @@ -5,7 +5,7 @@ import { UserConfig } from 'monaco-editor-wrapper'; import { getTextContent } from '../../common.js'; import { loadLangiumWorker } from '../wrapperLangium.js'; -export const setupLangiumClientVscodeApi = async (): Promise => { +export const setupLangiumClientExtended = async (): Promise => { const code = await getTextContent(new URL('./src/langium/content/example.langium', window.location.href)); const extensionFilesOrContents = new Map(); @@ -26,7 +26,7 @@ export const setupLangiumClientVscodeApi = async (): Promise => { debugLogging: true }, editorAppConfig: { - $type: 'vscodeApi', + $type: 'extended', languageId: 'langium', code: code, useDiffEditor: false, diff --git a/packages/examples/src/langium/config/wrapperStatemachineConfig.ts b/packages/examples/src/langium/config/wrapperStatemachineConfig.ts index 6b77498..f779376 100644 --- a/packages/examples/src/langium/config/wrapperStatemachineConfig.ts +++ b/packages/examples/src/langium/config/wrapperStatemachineConfig.ts @@ -26,7 +26,7 @@ export const createLangiumGlobalConfig = async (): Promise => { debugLogging: true }, editorAppConfig: { - $type: 'vscodeApi', + $type: 'extended', languageId: 'statemachine', code: code, useDiffEditor: false, diff --git a/packages/examples/src/langium/wrapperLangium.ts b/packages/examples/src/langium/wrapperLangium.ts index dc9efe3..e813d71 100644 --- a/packages/examples/src/langium/wrapperLangium.ts +++ b/packages/examples/src/langium/wrapperLangium.ts @@ -4,7 +4,7 @@ * ------------------------------------------------------------------------------------------ */ import { MonacoEditorLanguageClientWrapper } from 'monaco-editor-wrapper'; -import { setupLangiumClientVscodeApi } from './config/wrapperLangiumVscode.js'; +import { setupLangiumClientExtended } from './config/wrapperLangiumExtended.js'; import { setupLangiumClientClassic } from './config/wrapperLangiumClassic.js'; import { buildWorkerDefinition } from 'monaco-editor-workers'; @@ -16,17 +16,17 @@ const htmlElement = document.getElementById('monaco-editor-root'); export const run = async () => { try { document.querySelector('#button-start-classic')?.addEventListener('click', startLangiumClientClassic); - document.querySelector('#button-start-vscode-api')?.addEventListener('click', startLangiumClientVscodeApi); + document.querySelector('#button-start-extended')?.addEventListener('click', startLangiumClientExtended); document.querySelector('#button-dispose')?.addEventListener('click', disposeEditor); } catch (e) { console.error(e); } }; -export const startLangiumClientVscodeApi = async () => { +export const startLangiumClientExtended = async () => { try { if (checkStarted()) return; - const config = await setupLangiumClientVscodeApi(); + const config = await setupLangiumClientExtended(); wrapper = new MonacoEditorLanguageClientWrapper(); wrapper.start(config, htmlElement); } catch (e) { diff --git a/packages/examples/src/reactPython.tsx b/packages/examples/src/reactPython.tsx index 7f8115e..7bb848e 100644 --- a/packages/examples/src/reactPython.tsx +++ b/packages/examples/src/reactPython.tsx @@ -57,7 +57,7 @@ const userConfig: UserConfig = { debugLogging: true }, editorAppConfig: { - $type: 'vscodeApi', + $type: 'extended', languageId: 'python', codeUri: '/workspace/python.py', awaitExtensionReadiness: [whenReadyPython], diff --git a/packages/examples/src/wrapperTs.ts b/packages/examples/src/wrapperTs.ts index 30571e8..2efce35 100644 --- a/packages/examples/src/wrapperTs.ts +++ b/packages/examples/src/wrapperTs.ts @@ -41,7 +41,7 @@ const userConfig: UserConfig = { editorAppConfig: { $type: 'classic', languageId: 'typescript', - code: code, + code, codeUri: codeUri, codeOriginal: codeOriginal, useDiffEditor: false, diff --git a/packages/examples/src/wrapperWs.ts b/packages/examples/src/wrapperWs.ts index cb18f90..068bcc9 100644 --- a/packages/examples/src/wrapperWs.ts +++ b/packages/examples/src/wrapperWs.ts @@ -25,7 +25,7 @@ const userConfig: UserConfig = { debugLogging: true }, editorAppConfig: { - $type: 'vscodeApi', + $type: 'extended', languageId: languageId, code: codeMain, useDiffEditor: false, diff --git a/packages/examples/wrapper_langium.html b/packages/examples/wrapper_langium.html index 81fbdb9..4993470 100644 --- a/packages/examples/wrapper_langium.html +++ b/packages/examples/wrapper_langium.html @@ -11,7 +11,7 @@

Langium Grammar DSL Language Client & Server (Worker)

- +
diff --git a/packages/monaco-editor-wrapper/README.md b/packages/monaco-editor-wrapper/README.md index 5d03bf9..019cf82 100644 --- a/packages/monaco-editor-wrapper/README.md +++ b/packages/monaco-editor-wrapper/README.md @@ -16,18 +16,44 @@ npm run build This will clean, compile and build a bundle of the `monaco-editor-wrapper`, which you can reference in your own projects. For examples, you can see the top-level [README](../../README.md#getting-started) with details on running a local dev instance. ## Configuration -s -With release 2.0.0, the configuration approach is completely revised. -The `UserConfig` now contains everything and is passed to the `start` function of the wrapper. Because [monaco-vscode-api](https://github.com/CodinGame/monaco-vscode-api) uses a VS Code extension like configuration approach, the `UserConfig` allows to configure monaco-editor the [classical way](./src/editorAppClassic.ts) or to use [monaco-vscode-api way](./src/editorAppVscodeApi.ts). Additionally, [monaco-vscode-api](https://github.com/CodinGame/monaco-vscode-api) brings VS Code services to monaco-editor it usually does not have (Textmate Support, VS Code Theme Support, Keybindings, etc.). The wrapper initializes the following services from monaco-vscode-api independent of the editor mode: *model*, *editor* and *configuration*. +With release >2.0.0, the configuration approach is completely revised. + +The `UserConfig` now contains everything and is passed to the `start` function of the wrapper along with the HTML element `monaco-editor` is bound to. + +[@codingame/monaco-vscode-api](https://github.com/CodinGame/monaco-vscode-api) implements the VSCode api and redirects calls to `monaco-editor`. It allows to add serivccs that are usually only available in VSCode and not with pure `monaco-editor`. + `UserConfig` allows two possible configuration modes: + +- **Classical**: Configure `monaco-editor` as you would when using it directly, [see](./src/editorAppClassic.ts) +- **Extended**: Configure `monaco-editor` like a VSCode extension, [see](./src/editorAppExtended.ts) + +[This](https://github.com/CodinGame/monaco-vscode-api#monaco-standalone-services) is the list of services defined by [@codingame/monaco-vscode-api](https://github.com/CodinGame/monaco-vscode-api). +The following services are enabled by default in both editor modes: + +- layout +- environment +- extension +- files +- quickAccess +- languages +- model +- configuration + +**Extended** mode adds the following: + +- theme +- textmate + +If you want any further services than the ones initialized by default, you should use the **extended** mode as some service (like *theme* and *textmate*) are incompatible with the **classic** mode. + +Monarch grammars and themes can only be used in **classical** mode and textmate grammars and themes can only be used in **extended** mode. ## Usage -Monaco Editor with TypeScript language support in web worker and relying on regular monaco-editor configuration: +Monaco Editor with TypeScript language support in web worker and relying on classic mode: -```typescript +```ts import { MonacoEditorLanguageClientWrapper, UserConfig } from 'monaco-editor-wrapper'; - import 'monaco-editor/esm/vs/basic-languages/typescript/typescript.contribution.js'; import 'monaco-editor/esm/vs/language/typescript/monaco.contribution.js'; @@ -38,21 +64,22 @@ buildWorkerDefinition('./node_modules/monaco-editor-workers/dist/workers', impor // no top-level await const run = async () => { const wrapper = new MonacoEditorLanguageClientWrapper(); + const code: `function sayHello(): string { + return "Hello"; +};`, const userConfig = { - htmlElement: document.getElementById('monaco-editor-root') as HTMLElement, - // rely on regular monaco-editor configuration wrapperConfig: { editorAppConfig: { $type: 'classic', languageId: 'typescript', - code: `function sayHello(): string { - return "Hello"; -};`, + code, useDiffEditor: false, } } }; - await wrapper.start(userConfig); + + const htmlElement = document.getElementById('monaco-editor-root'); + await wrapper.start(userConfig, htmlElement); } ``` @@ -60,8 +87,8 @@ const run = async () => { These are the examples specifically for `monaco-editor-wrapper` you find in the repository: -- TypeScript editor worker using classical configuration, [see](../examples/wrapper_ts.html) -- Language client & web socket language server example using vscode-api configuration [see](../examples/wrapper_ws.html) It requires the json language server to run. Use `start:server:json` from [here](../examples/package.json) -- Multiple editors using classical configuration [see](../examples/wrapper_adv.html) -- Langium statemachine language client and web worker based language server using vscode-api configuration [see](../examples/wrapper_statemachine.html) -- Langium grammar language client and web worker based language server using vscode-api configuration [see](../examples/wrapper_langium.html) +- TypeScript editor worker using classical mode, [see](../examples/wrapper_ts.html) +- Language client & web socket language server example using extended mode [see](../examples/wrapper_ws.html) It requires the json language server to run. Use `start:server:json` from [here](../examples/package.json) +- Multiple editors using classical mode [see](../examples/wrapper_adv.html) +- Langium statemachine language client and web worker based language server using extended mode [see](../examples/wrapper_statemachine.html) +- Langium grammar language client and web worker based language server allowing to choose classical or extended mode [see](../examples/wrapper_langium.html) diff --git a/packages/monaco-editor-wrapper/src/editorAppBase.ts b/packages/monaco-editor-wrapper/src/editorAppBase.ts index d4fcab6..03af636 100644 --- a/packages/monaco-editor-wrapper/src/editorAppBase.ts +++ b/packages/monaco-editor-wrapper/src/editorAppBase.ts @@ -1,10 +1,10 @@ import { editor, Uri } from 'monaco-editor'; import { createConfiguredEditor, createConfiguredDiffEditor, createModelReference, ITextFileEditorModel } from 'vscode/monaco'; import { IReference } from 'vscode/service-override/editor'; -import { UserConfig, WrapperConfig } from './wrapper.js'; +import { WrapperConfig } from './wrapper.js'; import { updateUserConfiguration as vscodeUpdateUserConfiguration } from 'vscode/service-override/configuration'; import { EditorAppConfigClassic } from './editorAppClassic.js'; -import { EditorAppConfigVscodeApi } from './editorAppVscodeApi.js'; +import { EditorAppConfigExtended } from './editorAppExtended.js'; export type ModelUpdate = { languageId: string; @@ -18,20 +18,15 @@ export type EditorAppBaseConfig = ModelUpdate & { useDiffEditor: boolean; domReadOnly?: boolean; readOnly?: boolean; - awaitExtensionReadiness?: Array<() => Promise> - userConfiguration?: UserConfiguration; + awaitExtensionReadiness?: Array<() => Promise>; } -export type EditorAppType = 'vscodeApi' | 'classic'; - -export type UserConfiguration = { - json?: string; -} +export type EditorAppType = 'extended' | 'classic'; /** * This is the base class for both Monaco Ediotor Apps: * - EditorAppClassic - * - EditorAppVscodeApi + * - EditorAppExtended * * It provides the generic functionality for both implementations. */ @@ -49,8 +44,7 @@ export abstract class EditorAppBase { this.id = id; } - protected buildConfig(userConfig: UserConfig): EditorAppBaseConfig { - const userAppConfig = userConfig.wrapperConfig.editorAppConfig; + protected buildConfig(userAppConfig: EditorAppConfigExtended | EditorAppConfigClassic): EditorAppBaseConfig { return { languageId: userAppConfig.languageId, code: userAppConfig.code ?? '', @@ -60,7 +54,6 @@ export abstract class EditorAppBase { codeOriginalUri: userAppConfig.codeOriginalUri ?? undefined, readOnly: userAppConfig.readOnly ?? false, domReadOnly: userAppConfig.domReadOnly ?? false, - userConfiguration: userAppConfig.userConfiguration ?? undefined, awaitExtensionReadiness: userAppConfig.awaitExtensionReadiness ?? undefined }; } @@ -221,9 +214,9 @@ export abstract class EditorAppBase { return Promise.resolve(); } - async updateUserConfiguration(config?: UserConfiguration) { - if (config?.json) { - return vscodeUpdateUserConfiguration(config.json); + protected async updateUserConfiguration(json?: string) { + if (json) { + return vscodeUpdateUserConfiguration(json); } return Promise.resolve(); } @@ -232,12 +225,12 @@ export abstract class EditorAppBase { abstract init(): Promise; abstract specifyService(): editor.IEditorOverrideServices; abstract createEditors(container: HTMLElement): Promise; - abstract getConfig(): EditorAppConfigClassic | EditorAppConfigVscodeApi; + abstract getConfig(): EditorAppConfigClassic | EditorAppConfigExtended; abstract disposeApp(): void; } -export const isVscodeApiEditorApp = (wrapperConfig: WrapperConfig) => { - return wrapperConfig.editorAppConfig?.$type === 'vscodeApi'; +export const isExtendedEditorApp = (wrapperConfig: WrapperConfig) => { + return wrapperConfig.editorAppConfig?.$type === 'extended'; }; export const isCodeUpdateRequired = (config: EditorAppBaseConfig, modelUpdate: ModelUpdate) => { @@ -263,14 +256,14 @@ export enum ModelUpdateType { model } -export const isAppConfigDifferent = (orgConfig: EditorAppConfigClassic | EditorAppConfigVscodeApi, - config: EditorAppConfigClassic | EditorAppConfigVscodeApi, includeModelData: boolean, includeEditorOptions: boolean): boolean => { +export const isAppConfigDifferent = (orgConfig: EditorAppConfigClassic | EditorAppConfigExtended, + config: EditorAppConfigClassic | EditorAppConfigExtended, includeModelData: boolean, includeEditorOptions: boolean): boolean => { let different = includeModelData ? isModelUpdateRequired(orgConfig, config) !== ModelUpdateType.none : false; if (orgConfig.$type === config.$type) { type ClassicKeys = keyof typeof orgConfig; - const propsClassic = ['useDiffEditor', 'readOnly', 'domReadOnly', 'awaitExtensionReadiness', 'userConfiguration', 'automaticLayout', 'languageDef', 'languageExtensionConfig', 'theme', 'themeData']; + const propsClassic = ['useDiffEditor', 'readOnly', 'domReadOnly', 'awaitExtensionReadiness', 'automaticLayout', 'languageDef', 'languageExtensionConfig', 'theme', 'themeData']; const propsClassicEditorOptions = ['editorOptions', 'diffEditorOptions']; const propCompareClassic = (name: string) => { @@ -278,9 +271,9 @@ export const isAppConfigDifferent = (orgConfig: EditorAppConfigClassic | EditorA }; const propsVscode = ['useDiffEditor', 'readOnly', 'domReadOnly', 'awaitExtensionReadiness', 'userConfiguration', 'extensions']; - type VscodeApiKeys = keyof typeof orgConfig; - const propCompareVscodeApi = (name: string) => { - return orgConfig[name as VscodeApiKeys] !== config[name as VscodeApiKeys]; + type ExtendedKeys = keyof typeof orgConfig; + const propCompareExtended = (name: string) => { + return orgConfig[name as ExtendedKeys] !== config[name as ExtendedKeys]; }; if (orgConfig.$type === 'classic' && config.$type === 'classic') { @@ -288,8 +281,8 @@ export const isAppConfigDifferent = (orgConfig: EditorAppConfigClassic | EditorA if (includeEditorOptions) { different = different || propsClassicEditorOptions.some(propCompareClassic); } - } else if (orgConfig.$type === 'vscodeApi' && config.$type === 'vscodeApi') { - different = different || propsVscode.some(propCompareVscodeApi); + } else if (orgConfig.$type === 'extended' && config.$type === 'extended') { + different = different || propsVscode.some(propCompareExtended); } } else { throw new Error('Provided configurations are not of the same type.'); diff --git a/packages/monaco-editor-wrapper/src/editorAppClassic.ts b/packages/monaco-editor-wrapper/src/editorAppClassic.ts index 0063a09..18c9d22 100644 --- a/packages/monaco-editor-wrapper/src/editorAppClassic.ts +++ b/packages/monaco-editor-wrapper/src/editorAppClassic.ts @@ -2,19 +2,6 @@ import { editor, languages } from 'monaco-editor'; import { EditorAppBase, EditorAppBaseConfig, EditorAppType } from './editorAppBase.js'; import { UserConfig } from './wrapper.js'; import { Logger } from './logger.js'; -/** - * This is derived from: - * https://microsoft.github.io/monaco-editor/api/interfaces/monaco.languages.ILanguageExtensionPoint.html - */ -export type MonacoLanguageExtensionConfig = { - id: string; - extensions?: string[]; - filenames?: string[]; - filenamePatterns?: string[]; - firstLine?: string; - aliases?: string[]; - mimetypes?: string[]; -} export type EditorAppConfigClassic = EditorAppBaseConfig & { $type: 'classic'; @@ -22,7 +9,7 @@ export type EditorAppConfigClassic = EditorAppBaseConfig & { theme?: editor.BuiltinTheme | string; editorOptions?: editor.IStandaloneEditorConstructionOptions; diffEditorOptions?: editor.IStandaloneDiffEditorConstructionOptions; - languageExtensionConfig?: MonacoLanguageExtensionConfig; + languageExtensionConfig?: languages.ILanguageExtensionPoint; languageDef?: languages.IMonarchLanguage; themeData?: editor.IStandaloneThemeData; }; @@ -32,40 +19,28 @@ export type EditorAppConfigClassic = EditorAppBaseConfig & { */ export class EditorAppClassic extends EditorAppBase { - private editorOptions: editor.IStandaloneEditorConstructionOptions; - private diffEditorOptions: editor.IStandaloneDiffEditorConstructionOptions; private config: EditorAppConfigClassic; private logger: Logger | undefined; constructor(id: string, userConfig: UserConfig, logger?: Logger) { super(id); this.logger = logger; - this.config = this.buildConfig(userConfig) as EditorAppConfigClassic; - const userInput = userConfig.wrapperConfig.editorAppConfig as EditorAppConfigClassic; + const userAppConfig = userConfig.wrapperConfig.editorAppConfig as EditorAppConfigClassic; + this.config = this.buildConfig(userAppConfig) as EditorAppConfigClassic; // default to vs-light - this.config.theme = userInput.theme ?? 'vs-light'; + this.config.theme = userAppConfig.theme ?? 'vs-light'; // default to true - this.config.automaticLayout = userInput.automaticLayout ?? true; - - this.editorOptions = userInput.editorOptions ?? {}; - this.editorOptions.automaticLayout = userInput.automaticLayout ?? true; - - this.diffEditorOptions = userInput.diffEditorOptions ?? {}; - this.diffEditorOptions.automaticLayout = userInput.automaticLayout ?? true; - - this.config.languageExtensionConfig = userInput.languageExtensionConfig ?? undefined; - this.config.languageDef = userInput.languageDef ?? undefined; - this.config.themeData = userInput.themeData ?? undefined; - - // buildConfig ensures userConfiguration is available - if (userInput.editorOptions?.['semanticHighlighting.enabled'] !== undefined) { - if (this.config.userConfiguration === undefined) { - this.config.userConfiguration = {}; - } - const parsedUserConfig = JSON.parse(this.config.userConfiguration.json ?? '{}'); - parsedUserConfig['editor.semanticHighlighting.enabled'] = userInput.editorOptions?.['semanticHighlighting.enabled']; - this.config.userConfiguration.json = JSON.stringify(parsedUserConfig); - } + this.config.automaticLayout = userAppConfig.automaticLayout ?? true; + + this.config.editorOptions = userAppConfig.editorOptions ?? {}; + this.config.editorOptions.automaticLayout = userAppConfig.automaticLayout ?? true; + + this.config.diffEditorOptions = userAppConfig.diffEditorOptions ?? {}; + this.config.diffEditorOptions.automaticLayout = userAppConfig.automaticLayout ?? true; + + this.config.languageExtensionConfig = userAppConfig.languageExtensionConfig ?? undefined; + this.config.languageDef = userAppConfig.languageDef ?? undefined; + this.config.themeData = userAppConfig.themeData ?? undefined; } getAppType(): EditorAppType { @@ -82,9 +57,9 @@ export class EditorAppClassic extends EditorAppBase { async createEditors(container: HTMLElement): Promise { if (this.config.useDiffEditor) { - await this.createDiffEditor(container, this.diffEditorOptions); + await this.createDiffEditor(container, this.config.diffEditorOptions); } else { - await this.createEditor(container, this.editorOptions); + await this.createEditor(container, this.config.editorOptions); } } @@ -117,9 +92,14 @@ export class EditorAppClassic extends EditorAppBase { } editor.setTheme(this.config.theme!); - // buildConfig ensures userConfiguration is available - await this.updateUserConfiguration(this.config.userConfiguration); - this.logger?.info('Init of MonacoConfig was completed.'); + if (this.config.editorOptions?.['semanticHighlighting.enabled'] !== undefined) { + // use updateConfiguration here as otherwise semantic highlighting will not work + const json = JSON.stringify({ + 'editor.semanticHighlighting.enabled': this.config.editorOptions['semanticHighlighting.enabled'] + }); + await this.updateUserConfiguration(json); + } + this.logger?.info('Init of Classic App was completed.'); } updateMonacoEditorOptions(options: editor.IEditorOptions & editor.IGlobalEditorOptions) { diff --git a/packages/monaco-editor-wrapper/src/editorAppVscodeApi.ts b/packages/monaco-editor-wrapper/src/editorAppExtended.ts similarity index 83% rename from packages/monaco-editor-wrapper/src/editorAppVscodeApi.ts rename to packages/monaco-editor-wrapper/src/editorAppExtended.ts index cb05fd9..edbe37f 100644 --- a/packages/monaco-editor-wrapper/src/editorAppVscodeApi.ts +++ b/packages/monaco-editor-wrapper/src/editorAppExtended.ts @@ -14,9 +14,14 @@ export type ExtensionConfig = { filesOrContents?: Map; }; -export type EditorAppConfigVscodeApi = EditorAppBaseConfig & { - $type: 'vscodeApi'; +export type UserConfiguration = { + json?: string; +} + +export type EditorAppConfigExtended = EditorAppBaseConfig & { + $type: 'extended'; extensions?: ExtensionConfig[]; + userConfiguration?: UserConfiguration; }; export type RegisterExtensionResult = { @@ -37,25 +42,26 @@ export type RegisterLocalProcessExtensionResult = RegisterLocalExtensionResult & /** * The vscode-apo monaco-editor app uses vscode user and extension configuration for monaco-editor. */ -export class EditorAppVscodeApi extends EditorAppBase { +export class EditorAppExtended extends EditorAppBase { - private config: EditorAppConfigVscodeApi; + private config: EditorAppConfigExtended; private extensionRegisterResults: Map = new Map(); private logger: Logger | undefined; constructor(id: string, userConfig: UserConfig, logger?: Logger) { super(id); this.logger = logger; - this.config = this.buildConfig(userConfig) as EditorAppConfigVscodeApi; - const userInput = userConfig.wrapperConfig.editorAppConfig as EditorAppConfigVscodeApi; - this.config.extensions = userInput.extensions ?? undefined; + const userAppConfig = userConfig.wrapperConfig.editorAppConfig as EditorAppConfigExtended; + this.config = this.buildConfig(userAppConfig) as EditorAppConfigExtended; + this.config.extensions = userAppConfig.extensions ?? undefined; + this.config.userConfiguration = userAppConfig.userConfiguration ?? undefined; } getAppType(): EditorAppType { - return 'vscodeApi'; + return 'extended'; } - getConfig(): EditorAppConfigVscodeApi { + getConfig(): EditorAppConfigExtended { return this.config; } @@ -101,8 +107,8 @@ export class EditorAppVscodeApi extends EditorAppBase { } // buildConfig ensures userConfiguration is available - await this.updateUserConfiguration(this.config.userConfiguration); - this.logger?.info('Init of VscodeApiConfig was completed.'); + await this.updateUserConfiguration(this.config.userConfiguration?.json); + this.logger?.info('Init of Extended App was completed.'); } disposeApp(): void { diff --git a/packages/monaco-editor-wrapper/src/index.ts b/packages/monaco-editor-wrapper/src/index.ts index 73f07fd..0297234 100644 --- a/packages/monaco-editor-wrapper/src/index.ts +++ b/packages/monaco-editor-wrapper/src/index.ts @@ -1,6 +1,6 @@ import { EditorAppBase, - isVscodeApiEditorApp, + isExtendedEditorApp, isCodeUpdateRequired, isModelUpdateRequired, isAppConfigDifferent, @@ -10,8 +10,7 @@ import { import type { EditorAppBaseConfig, EditorAppType, - ModelUpdate, - UserConfiguration, + ModelUpdate } from './editorAppBase.js'; import type { @@ -24,14 +23,15 @@ import { import type { ExtensionConfig, - EditorAppConfigVscodeApi, + EditorAppConfigExtended, RegisterExtensionResult, RegisterLocalProcessExtensionResult, -} from './editorAppVscodeApi.js'; + UserConfiguration +} from './editorAppExtended.js'; import { - EditorAppVscodeApi -} from './editorAppVscodeApi.js'; + EditorAppExtended +} from './editorAppExtended.js'; import type { WebSocketCallOptions, @@ -71,7 +71,7 @@ export type { EditorAppType, EditorAppConfigClassic, ExtensionConfig, - EditorAppConfigVscodeApi, + EditorAppConfigExtended, RegisterExtensionResult, RegisterLocalProcessExtensionResult, UserConfiguration, @@ -92,13 +92,13 @@ export { MonacoEditorLanguageClientWrapper, LanguageClientWrapper, EditorAppBase, - isVscodeApiEditorApp, + isExtendedEditorApp, isCodeUpdateRequired, isModelUpdateRequired, isAppConfigDifferent, ModelUpdateType, EditorAppClassic, - EditorAppVscodeApi, + EditorAppExtended, Logger }; diff --git a/packages/monaco-editor-wrapper/src/wrapper.ts b/packages/monaco-editor-wrapper/src/wrapper.ts index ae1e02c..8e1a3d1 100644 --- a/packages/monaco-editor-wrapper/src/wrapper.ts +++ b/packages/monaco-editor-wrapper/src/wrapper.ts @@ -1,15 +1,15 @@ import { editor, Uri } from 'monaco-editor'; import getConfigurationServiceOverride from '@codingame/monaco-vscode-configuration-service-override'; import { initServices, wasVscodeApiInitialized, InitializeServiceConfig, MonacoLanguageClient, mergeServices } from 'monaco-languageclient'; -import { EditorAppVscodeApi, EditorAppConfigVscodeApi } from './editorAppVscodeApi.js'; +import { EditorAppExtended, EditorAppConfigExtended } from './editorAppExtended.js'; import { EditorAppClassic, EditorAppConfigClassic } from './editorAppClassic.js'; -import { ModelUpdate, UserConfiguration, isVscodeApiEditorApp } from './editorAppBase.js'; +import { ModelUpdate, isExtendedEditorApp } from './editorAppBase.js'; import { LanguageClientConfig, LanguageClientWrapper } from './languageClientWrapper.js'; import { Logger, LoggerConfig } from './logger.js'; export type WrapperConfig = { serviceConfig?: InitializeServiceConfig; - editorAppConfig: EditorAppConfigVscodeApi | EditorAppConfigClassic; + editorAppConfig: EditorAppConfigExtended | EditorAppConfigClassic; }; export type UserConfig = { @@ -28,7 +28,7 @@ export class MonacoEditorLanguageClientWrapper { private id: string; - private editorApp: EditorAppClassic | EditorAppVscodeApi | undefined; + private editorApp: EditorAppClassic | EditorAppExtended | undefined; private languageClientWrapper: LanguageClientWrapper; private serviceConfig: InitializeServiceConfig; private logger: Logger; @@ -76,8 +76,8 @@ export class MonacoEditorLanguageClientWrapper { this.init(userConfig); - if (isVscodeApiEditorApp(userConfig.wrapperConfig)) { - this.editorApp = new EditorAppVscodeApi(this.id, userConfig, this.logger); + if (isExtendedEditorApp(userConfig.wrapperConfig)) { + this.editorApp = new EditorAppExtended(this.id, userConfig, this.logger); } else { this.editorApp = new EditorAppClassic(this.id, userConfig, this.logger); } @@ -139,10 +139,6 @@ export class MonacoEditorLanguageClientWrapper { await this.editorApp?.updateDiffModel(modelUpdate); } - updateUserConfiguration(config: UserConfiguration) { - return this.editorApp?.updateUserConfiguration(config); - } - public reportStatus() { const status: string[] = []; status.push('Wrapper status:'); diff --git a/packages/monaco-editor-wrapper/test/editorAppBase.test.ts b/packages/monaco-editor-wrapper/test/editorAppBase.test.ts index c9d223e..128f43e 100644 --- a/packages/monaco-editor-wrapper/test/editorAppBase.test.ts +++ b/packages/monaco-editor-wrapper/test/editorAppBase.test.ts @@ -1,17 +1,17 @@ import { describe, expect, test } from 'vitest'; -import { isAppConfigDifferent, isVscodeApiEditorApp, isModelUpdateRequired, EditorAppClassic, ModelUpdateType, EditorAppConfigVscodeApi } from 'monaco-editor-wrapper'; +import { isAppConfigDifferent, isExtendedEditorApp, isModelUpdateRequired, EditorAppClassic, ModelUpdateType, EditorAppConfigExtended, EditorAppExtended } from 'monaco-editor-wrapper'; import { createBaseConfig, createEditorAppConfig, createWrapperConfig } from './helper.js'; describe('Test EditorAppBase', () => { - test('isVscodeApiEditorApp: empty EditorAppConfigClassic', () => { + test('isExtendedEditorApp: empty EditorAppConfigClassic', () => { const wrapperConfig = createWrapperConfig('classic'); - expect(isVscodeApiEditorApp(wrapperConfig)).toBeFalsy(); + expect(isExtendedEditorApp(wrapperConfig)).toBeFalsy(); }); - test('isVscodeApiEditorApp: empty EditorAppConfigVscodeApi', () => { - const wrapperConfig = createWrapperConfig('vscodeApi'); - expect(isVscodeApiEditorApp(wrapperConfig)).toBeTruthy(); + test('isExtendedEditorApp: empty EditorAppConfigExtended', () => { + const wrapperConfig = createWrapperConfig('extended'); + expect(isExtendedEditorApp(wrapperConfig)).toBeTruthy(); }); test('config defaults', () => { @@ -25,15 +25,15 @@ describe('Test EditorAppBase', () => { expect(app.getConfig().codeOriginalUri).toBeUndefined(); expect(app.getConfig().readOnly).toBeFalsy(); expect(app.getConfig().domReadOnly).toBeFalsy(); - expect(app.getConfig().userConfiguration?.json).toBeUndefined(); }); test('config userConfiguration', () => { - const config = createBaseConfig('classic'); - config.wrapperConfig.editorAppConfig.userConfiguration = { + const config = createBaseConfig('extended'); + const appConfig = config.wrapperConfig.editorAppConfig as EditorAppConfigExtended; + appConfig.userConfiguration = { json: '{ "editor.semanticHighlighting.enabled": true }' }; - const app = new EditorAppClassic('config defaults', config); + const app = new EditorAppExtended('config defaults', config); expect(app.getConfig().userConfiguration?.json).toEqual('{ "editor.semanticHighlighting.enabled": true }'); }); @@ -66,9 +66,9 @@ describe('Test EditorAppBase', () => { expect(isAppConfigDifferent(orgConfig, config, false, false)).toBeTruthy(); }); - test('isAppConfigDifferent: vscodeApi', () => { - const orgConfig = createEditorAppConfig('vscodeApi') as EditorAppConfigVscodeApi; - const config = createEditorAppConfig('vscodeApi') as EditorAppConfigVscodeApi; + test('isAppConfigDifferent: vscode', () => { + const orgConfig = createEditorAppConfig('extended') as EditorAppConfigExtended; + const config = createEditorAppConfig('extended') as EditorAppConfigExtended; expect(isAppConfigDifferent(orgConfig, config, false, true)).toBeFalsy(); config.code = 'test'; diff --git a/packages/monaco-editor-wrapper/test/editorAppClassic.test.ts b/packages/monaco-editor-wrapper/test/editorAppClassic.test.ts index 7dac7fc..b9539ea 100644 --- a/packages/monaco-editor-wrapper/test/editorAppClassic.test.ts +++ b/packages/monaco-editor-wrapper/test/editorAppClassic.test.ts @@ -17,7 +17,7 @@ describe('Test EditorAppClassic', () => { const app = new EditorAppClassic('config defaults', config); expect(configclassic.$type).toEqual('classic'); - expect(app.getConfig().userConfiguration?.json).toEqual('{"editor.semanticHighlighting.enabled":true}'); + expect(app.getConfig().editorOptions?.['semanticHighlighting.enabled']).toEqual(true); }); test('editorOptions: semanticHighlighting=false', () => { @@ -26,7 +26,7 @@ describe('Test EditorAppClassic', () => { configclassic.editorOptions!['semanticHighlighting.enabled'] = false; const app = new EditorAppClassic('config defaults', config); - expect(app.getConfig().userConfiguration?.json).toEqual('{"editor.semanticHighlighting.enabled":false}'); + expect(app.getConfig().editorOptions?.['semanticHighlighting.enabled']).toEqual(false); }); test('editorOptions: semanticHighlighting="configuredByTheme"', () => { @@ -35,6 +35,6 @@ describe('Test EditorAppClassic', () => { configclassic.editorOptions!['semanticHighlighting.enabled'] = 'configuredByTheme'; const app = new EditorAppClassic('config defaults', config); - expect(app.getConfig().userConfiguration?.json).toEqual('{"editor.semanticHighlighting.enabled":"configuredByTheme"}'); + expect(app.getConfig().editorOptions?.['semanticHighlighting.enabled']).toEqual('configuredByTheme'); }); }); diff --git a/packages/monaco-editor-wrapper/test/editorAppVscodeApi.test.ts b/packages/monaco-editor-wrapper/test/editorAppExtended.test.ts similarity index 83% rename from packages/monaco-editor-wrapper/test/editorAppVscodeApi.test.ts rename to packages/monaco-editor-wrapper/test/editorAppExtended.test.ts index 6abb5e2..eb2bb31 100644 --- a/packages/monaco-editor-wrapper/test/editorAppVscodeApi.test.ts +++ b/packages/monaco-editor-wrapper/test/editorAppExtended.test.ts @@ -1,10 +1,10 @@ import { describe, expect, test } from 'vitest'; import { verifyUrlorCreateDataUrl } from 'monaco-editor-wrapper'; -describe('Test EditorAppVscodeApi', () => { +describe('Test EditorAppExtended', () => { test('verifyUrlorCreateDataUrl: url', () => { - const url = new URL('./editorVscodeApi.test.ts', import.meta.url); + const url = new URL('./editorAppExtended.test.ts', import.meta.url); expect(verifyUrlorCreateDataUrl(url)).toBe(url.href); });