From fdd4346891a5337aad88554faf2dfaa67c9c161c Mon Sep 17 00:00:00 2001 From: Martin Aeschlimann Date: Thu, 10 Jun 2021 20:21:11 +0200 Subject: [PATCH] support custom data. For microsoft/monaco-editor#2284 --- monaco.d.ts | 88 ++++++++++++++++++++++++- package-lock.json | 18 ++--- package.json | 6 +- src/cssWorker.ts | 23 +++++-- src/monaco.contribution.ts | 131 ++++++++++++++++++++++++++++++++----- src/workerManager.ts | 2 +- 6 files changed, 232 insertions(+), 36 deletions(-) diff --git a/monaco.d.ts b/monaco.d.ts index 1f7668ee..15b256bf 100644 --- a/monaco.d.ts +++ b/monaco.d.ts @@ -6,7 +6,7 @@ /// declare namespace monaco.languages.css { - export interface DiagnosticsOptions { + export interface Options { readonly validate?: boolean; readonly lint?: { readonly compatibleVendorPrefixes?: 'ignore' | 'warning' | 'error'; @@ -28,6 +28,10 @@ declare namespace monaco.languages.css { readonly float?: 'ignore' | 'warning' | 'error'; readonly idSelector?: 'ignore' | 'warning' | 'error'; }; + /** + * Configures the CSS data types known by the langauge service. + */ + readonly data?: CSSDataConfiguration; } export interface ModeConfiguration { /** @@ -78,12 +82,90 @@ declare namespace monaco.languages.css { export interface LanguageServiceDefaults { readonly languageId: string; readonly onDidChange: IEvent; - readonly diagnosticsOptions: DiagnosticsOptions; readonly modeConfiguration: ModeConfiguration; - setDiagnosticsOptions(options: DiagnosticsOptions): void; + readonly options: Options; + setOptions(options: Options): void; setModeConfiguration(modeConfiguration: ModeConfiguration): void; + /** @deprecated Use options instead */ + readonly diagnosticsOptions: DiagnosticsOptions; + /** @deprecated Use setOptions instead */ + setDiagnosticsOptions(options: DiagnosticsOptions): void; } + /** @deprecated Use Options instead */ + export type DiagnosticsOptions = Options; export const cssDefaults: LanguageServiceDefaults; export const scssDefaults: LanguageServiceDefaults; export const lessDefaults: LanguageServiceDefaults; + export interface CSSDataConfiguration { + /** + * Defines whether the standard CSS properties, at-directives, pseudoClasses and pseudoElements are shown. + */ + useDefaultDataProvider?: boolean; + /** + * Provides a set of custom data providers. + */ + dataProviders?: { + [providerId: string]: CSSDataV1; + }; + } + /** + * Custom CSS properties, at-directives, pseudoClasses and pseudoElements + * https://github.com/microsoft/vscode-css-languageservice/blob/main/docs/customData.md + */ + export interface CSSDataV1 { + version: 1 | 1.1; + properties?: IPropertyData[]; + atDirectives?: IAtDirectiveData[]; + pseudoClasses?: IPseudoClassData[]; + pseudoElements?: IPseudoElementData[]; + } + export type EntryStatus = 'standard' | 'experimental' | 'nonstandard' | 'obsolete'; + export interface IReference { + name: string; + url: string; + } + export interface IPropertyData { + name: string; + description?: string | MarkupContent; + browsers?: string[]; + restrictions?: string[]; + status?: EntryStatus; + syntax?: string; + values?: IValueData[]; + references?: IReference[]; + relevance?: number; + } + export interface IAtDirectiveData { + name: string; + description?: string | MarkupContent; + browsers?: string[]; + status?: EntryStatus; + references?: IReference[]; + } + export interface IPseudoClassData { + name: string; + description?: string | MarkupContent; + browsers?: string[]; + status?: EntryStatus; + references?: IReference[]; + } + export interface IPseudoElementData { + name: string; + description?: string | MarkupContent; + browsers?: string[]; + status?: EntryStatus; + references?: IReference[]; + } + export interface IValueData { + name: string; + description?: string | MarkupContent; + browsers?: string[]; + status?: EntryStatus; + references?: IReference[]; + } + export interface MarkupContent { + kind: MarkupKind; + value: string; + } + export type MarkupKind = 'plaintext' | 'markdown'; } diff --git a/package-lock.json b/package-lock.json index 89a2045f..ead62a3b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -426,9 +426,9 @@ } }, "terser": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.6.0.tgz", - "integrity": "sha512-vyqLMoqadC1uR0vywqOZzriDYzgEkNJFK4q9GeyOBHIbiECHiWLKcWfbQWAUaPfxkjDhapSlZB9f7fkMrvkVjA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.7.0.tgz", + "integrity": "sha512-HP5/9hp2UaZt5fYkuhNBR8YyRcT8juw8+uFbAme53iN9hblvKnLUTKkmwJG6ocWpIKf8UK4DoeWG4ty0J6S6/g==", "dev": true, "requires": { "commander": "^2.20.0", @@ -437,15 +437,15 @@ } }, "typescript": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz", - "integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz", + "integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==", "dev": true }, "vscode-css-languageservice": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-5.1.0.tgz", - "integrity": "sha512-iLHd/WjRKgaZBXMNeUooHG+r0qlhJBkXa+3MpQQR6Rpm928cis/3OV2Mp1R80yAQevIMeDL32RIJfHoJCT/RRg==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-5.1.3.tgz", + "integrity": "sha512-c8xiUhrDBNG6iS92FEE+K3IWOHAqVvzsqjjLSaXHyF5Qdn/6VhUweGNjtZ2CBSfs+Vkmz7pJzLQ7Io1x5deumA==", "dev": true, "requires": { "vscode-languageserver-textdocument": "^1.0.1", diff --git a/package.json b/package.json index 0cc092a7..8089ba40 100644 --- a/package.json +++ b/package.json @@ -29,9 +29,9 @@ "prettier": "^2.2.1", "pretty-quick": "^3.1.0", "requirejs": "^2.3.6", - "typescript": "4.2.3", - "terser": "^5.6.0", - "vscode-css-languageservice": "5.1.0", + "typescript": "4.3.2", + "terser": "^5.7.0", + "vscode-css-languageservice": "5.1.3", "vscode-languageserver-types": "3.16.0", "vscode-languageserver-textdocument": "^1.0.1" }, diff --git a/src/cssWorker.ts b/src/cssWorker.ts index 34cc57c6..31fff0a1 100644 --- a/src/cssWorker.ts +++ b/src/cssWorker.ts @@ -5,6 +5,7 @@ import type { worker } from './fillers/monaco-editor-core'; import * as cssService from 'vscode-css-languageservice'; +import { Options } from './monaco.contribution'; export class CSSWorker { // --- model sync ----------------------- @@ -16,17 +17,29 @@ export class CSSWorker { constructor(ctx: worker.IWorkerContext, createData: ICreateData) { this._ctx = ctx; - this._languageSettings = createData.languageSettings; + this._languageSettings = createData.options; this._languageId = createData.languageId; + + const data = createData.options.data; + + const useDefaultDataProvider = data?.useDefaultDataProvider; + const customDataProviders: cssService.ICSSDataProvider[] = []; + if (data?.dataProviders) { + for (const id in data.dataProviders) { + customDataProviders.push(cssService.newCSSDataProvider(data.dataProviders[id])); + } + } + const lsOptions: cssService.LanguageServiceOptions = { customDataProviders, useDefaultDataProvider }; + switch (this._languageId) { case 'css': - this._languageService = cssService.getCSSLanguageService(); + this._languageService = cssService.getCSSLanguageService(lsOptions); break; case 'less': - this._languageService = cssService.getLESSLanguageService(); + this._languageService = cssService.getLESSLanguageService(lsOptions); break; case 'scss': - this._languageService = cssService.getSCSSLanguageService(); + this._languageService = cssService.getSCSSLanguageService(lsOptions); break; default: throw new Error('Invalid language id: ' + this._languageId); @@ -160,7 +173,7 @@ export class CSSWorker { export interface ICreateData { languageId: string; - languageSettings: cssService.LanguageSettings; + options: Options } export function create(ctx: worker.IWorkerContext, createData: ICreateData): CSSWorker { diff --git a/src/monaco.contribution.ts b/src/monaco.contribution.ts index 6b75b37f..b9e05bc4 100644 --- a/src/monaco.contribution.ts +++ b/src/monaco.contribution.ts @@ -6,7 +6,7 @@ import * as mode from './cssMode'; import { languages, Emitter, IEvent } from './fillers/monaco-editor-core'; -export interface DiagnosticsOptions { +export interface Options { readonly validate?: boolean; readonly lint?: { readonly compatibleVendorPrefixes?: 'ignore' | 'warning' | 'error'; @@ -28,6 +28,10 @@ export interface DiagnosticsOptions { readonly float?: 'ignore' | 'warning' | 'error'; readonly idSelector?: 'ignore' | 'warning' | 'error'; }; + /** + * Configures the CSS data types known by the langauge service. + */ + readonly data?: CSSDataConfiguration; } export interface ModeConfiguration { @@ -90,27 +94,36 @@ export interface ModeConfiguration { export interface LanguageServiceDefaults { readonly languageId: string; readonly onDidChange: IEvent; - readonly diagnosticsOptions: DiagnosticsOptions; + readonly modeConfiguration: ModeConfiguration; - setDiagnosticsOptions(options: DiagnosticsOptions): void; + readonly options: Options; + setOptions(options: Options): void; setModeConfiguration(modeConfiguration: ModeConfiguration): void; + + /** @deprecated Use options instead */ + readonly diagnosticsOptions: DiagnosticsOptions; + /** @deprecated Use setOptions instead */ + setDiagnosticsOptions(options: DiagnosticsOptions): void; } +/** @deprecated Use Options instead */ +export type DiagnosticsOptions = Options; + // --- CSS configuration and defaults --------- class LanguageServiceDefaultsImpl implements LanguageServiceDefaults { private _onDidChange = new Emitter(); - private _diagnosticsOptions: DiagnosticsOptions; + private _options: Options; private _modeConfiguration: ModeConfiguration; private _languageId: string; constructor( languageId: string, - diagnosticsOptions: DiagnosticsOptions, + options: Options, modeConfiguration: ModeConfiguration ) { this._languageId = languageId; - this.setDiagnosticsOptions(diagnosticsOptions); + this.setOptions(options); this.setModeConfiguration(modeConfiguration); } @@ -126,22 +139,30 @@ class LanguageServiceDefaultsImpl implements LanguageServiceDefaults { return this._modeConfiguration; } - get diagnosticsOptions(): DiagnosticsOptions { - return this._diagnosticsOptions; + get diagnosticsOptions(): Options { + return this.options; } - setDiagnosticsOptions(options: DiagnosticsOptions): void { - this._diagnosticsOptions = options || Object.create(null); + get options(): Options { + return this._options; + } + + setOptions(options: Options): void { + this._options = options || Object.create(null); this._onDidChange.fire(this); } + setDiagnosticsOptions(options: Options): void { + this.setOptions(options); + } + setModeConfiguration(modeConfiguration: ModeConfiguration): void { this._modeConfiguration = modeConfiguration || Object.create(null); this._onDidChange.fire(this); } } -const diagnosticDefault: Required = { +const optionsDefault: Required = { validate: true, lint: { compatibleVendorPrefixes: 'ignore', @@ -162,7 +183,8 @@ const diagnosticDefault: Required = { important: 'ignore', float: 'ignore', idSelector: 'ignore' - } + }, + data: { useDefaultDataProvider: true } }; const modeConfigurationDefault: Required = { @@ -181,17 +203,17 @@ const modeConfigurationDefault: Required = { export const cssDefaults: LanguageServiceDefaults = new LanguageServiceDefaultsImpl( 'css', - diagnosticDefault, + optionsDefault, modeConfigurationDefault ); export const scssDefaults: LanguageServiceDefaults = new LanguageServiceDefaultsImpl( 'scss', - diagnosticDefault, + optionsDefault, modeConfigurationDefault ); export const lessDefaults: LanguageServiceDefaults = new LanguageServiceDefaultsImpl( 'less', - diagnosticDefault, + optionsDefault, modeConfigurationDefault ); @@ -215,3 +237,82 @@ languages.onLanguage('scss', () => { languages.onLanguage('css', () => { getMode().then((mode) => mode.setupMode(cssDefaults)); }); + + +// CSS Data + +export interface CSSDataConfiguration { + /** + * Defines whether the standard CSS properties, at-directives, pseudoClasses and pseudoElements are shown. + */ + useDefaultDataProvider?: boolean; + /** + * Provides a set of custom data providers. + */ + dataProviders?: { [providerId: string]: CSSDataV1 }; +} + +/** + * Custom CSS properties, at-directives, pseudoClasses and pseudoElements + * https://github.com/microsoft/vscode-css-languageservice/blob/main/docs/customData.md + */ +export interface CSSDataV1 { + version: 1 | 1.1; + properties?: IPropertyData[]; + atDirectives?: IAtDirectiveData[]; + pseudoClasses?: IPseudoClassData[]; + pseudoElements?: IPseudoElementData[]; +} + +export type EntryStatus = 'standard' | 'experimental' | 'nonstandard' | 'obsolete'; + +export interface IReference { + name: string; + url: string; +} + +export interface IPropertyData { + name: string; + description?: string | MarkupContent; + browsers?: string[]; + restrictions?: string[]; + status?: EntryStatus; + syntax?: string; + values?: IValueData[]; + references?: IReference[]; + relevance?: number; +} +export interface IAtDirectiveData { + name: string; + description?: string | MarkupContent; + browsers?: string[]; + status?: EntryStatus; + references?: IReference[]; +} +export interface IPseudoClassData { + name: string; + description?: string | MarkupContent; + browsers?: string[]; + status?: EntryStatus; + references?: IReference[]; +} +export interface IPseudoElementData { + name: string; + description?: string | MarkupContent; + browsers?: string[]; + status?: EntryStatus; + references?: IReference[]; +} + +export interface IValueData { + name: string; + description?: string | MarkupContent; + browsers?: string[]; + status?: EntryStatus; + references?: IReference[]; +} +export interface MarkupContent { + kind: MarkupKind; + value: string; +} +export declare type MarkupKind = 'plaintext' | 'markdown'; diff --git a/src/workerManager.ts b/src/workerManager.ts index 774e7c72..335396d5 100644 --- a/src/workerManager.ts +++ b/src/workerManager.ts @@ -62,7 +62,7 @@ export class WorkerManager { // passed in to the create() method createData: { - languageSettings: this._defaults.diagnosticsOptions, + options: this._defaults.options, languageId: this._defaults.languageId } });