diff --git a/extensions/html-language-features/client/src/customData.ts b/extensions/html-language-features/client/src/customData.ts index 5e7c1c99c16..fb89f811769 100644 --- a/extensions/html-language-features/client/src/customData.ts +++ b/extensions/html-language-features/client/src/customData.ts @@ -8,21 +8,17 @@ import { workspace, WorkspaceFolder } from 'vscode'; interface ExperimentalConfig { experimental?: { - custom?: { - tags?: string[]; - attributes?: string[]; - } + customData?: string[]; }; } export function getCustomDataPathsInAllWorkspaces(workspaceFolders: WorkspaceFolder[] | undefined) { - const tagPaths: string[] = []; - const attributePaths: string[] = []; + const dataPaths: string[] = []; + if (!workspaceFolders) { return { - tagPaths, - attributePaths + dataPaths }; } @@ -33,24 +29,17 @@ export function getCustomDataPathsInAllWorkspaces(workspaceFolders: WorkspaceFol if ( wfHtmlConfig && wfHtmlConfig.workspaceFolderValue && - wfHtmlConfig.workspaceFolderValue.experimental && - wfHtmlConfig.workspaceFolderValue.experimental.custom + wfHtmlConfig.workspaceFolderValue.experimental ) { - if (wfHtmlConfig.workspaceFolderValue.experimental.custom.tags) { - wfHtmlConfig.workspaceFolderValue.experimental.custom.tags.forEach(t => { - tagPaths.push(path.resolve(wf.uri.fsPath, t)); - }); - } - if (wfHtmlConfig.workspaceFolderValue.experimental.custom.attributes) { - wfHtmlConfig.workspaceFolderValue.experimental.custom.attributes.forEach(a => { - attributePaths.push(path.resolve(wf.uri.fsPath, a)); + if (wfHtmlConfig.workspaceFolderValue.experimental.customData) { + wfHtmlConfig.workspaceFolderValue.experimental.customData.forEach(t => { + dataPaths.push(path.resolve(wf.uri.fsPath, t)); }); } } }); return { - tagPaths, - attributePaths + dataPaths }; } diff --git a/extensions/html-language-features/client/src/htmlMain.ts b/extensions/html-language-features/client/src/htmlMain.ts index 0b4a33b776b..a95a8a7fc25 100644 --- a/extensions/html-language-features/client/src/htmlMain.ts +++ b/extensions/html-language-features/client/src/htmlMain.ts @@ -50,7 +50,7 @@ export function activate(context: ExtensionContext) { let documentSelector = ['html', 'handlebars', 'razor']; let embeddedLanguages = { css: true, javascript: true }; - let { tagPaths, attributePaths } = getCustomDataPathsInAllWorkspaces(workspace.workspaceFolders); + let { dataPaths } = getCustomDataPathsInAllWorkspaces(workspace.workspaceFolders); // Options to control the language client let clientOptions: LanguageClientOptions = { @@ -60,8 +60,7 @@ export function activate(context: ExtensionContext) { }, initializationOptions: { embeddedLanguages, - tagPaths, - attributePaths + dataPaths } }; diff --git a/extensions/html-language-features/package.json b/extensions/html-language-features/package.json index ca3320124e5..812b6104c1b 100644 --- a/extensions/html-language-features/package.json +++ b/extensions/html-language-features/package.json @@ -31,13 +31,9 @@ "type": "object", "title": "HTML", "properties": { - "html.experimental.custom.tags": { + "html.experimental.customData": { "type": "array", - "description": "A list of JSON file paths that define custom tags. Only workspace folder setting will be read." - }, - "html.experimental.custom.attributes": { - "type": "array", - "description": "A list of JSON file paths that define custom attributes. Only workspace folder setting will be read." + "description": "A list of JSON file paths that define custom tags, properties and other HTML syntax constructs. Only workspace folder setting will be read." }, "html.format.enable": { "type": "boolean", diff --git a/extensions/html-language-features/server/src/htmlServerMain.ts b/extensions/html-language-features/server/src/htmlServerMain.ts index 1b32205c2e3..cec1d1da31e 100644 --- a/extensions/html-language-features/server/src/htmlServerMain.ts +++ b/extensions/html-language-features/server/src/htmlServerMain.ts @@ -20,8 +20,8 @@ import uri from 'vscode-uri'; import { formatError, runSafe, runSafeAsync } from './utils/runner'; import { getFoldingRanges } from './modes/htmlFolding'; -import { parseTagSet, parseAttributes } from './utils/tagDefinitions'; -import { ITagSet, IAttributeSet } from 'vscode-html-languageservice'; +import { parseHTMLData } from './utils/tagDefinitions'; +import { HTMLData } from 'vscode-html-languageservice'; namespace TagCloseRequest { export const type: RequestType = new RequestType('html/tag'); @@ -91,18 +91,24 @@ connection.onInitialize((params: InitializeParams): InitializeResult => { } } - const tagPaths: string[] = params.initializationOptions.tagPaths; - const attributePaths: string[] = params.initializationOptions.attributePaths; - const htmlTags: ITagSet = {}; - const htmlAttributes: IAttributeSet = {}; + const dataPaths: string[] = params.initializationOptions.dataPaths; - if (tagPaths) { - tagPaths.forEach(path => { + let allHtmlData: HTMLData = { + tags: [], + globalAttributes: [], + valueSetMap: {} + }; + + if (dataPaths) { + dataPaths.forEach(path => { try { if (fs.existsSync(path)) { - const tagSet = parseTagSet(fs.readFileSync(path, 'utf-8')); - for (let tag in tagSet) { - htmlTags[tag] = tagSet[tag]; + const htmlData = parseHTMLData(fs.readFileSync(path, 'utf-8')); + if (htmlData.tags) { + allHtmlData.tags = allHtmlData.tags!.concat(htmlData.tags); + } + if (htmlData.globalAttributes) { + allHtmlData.globalAttributes = allHtmlData.globalAttributes!.concat(htmlData.globalAttributes); } } } catch (err) { @@ -110,27 +116,13 @@ connection.onInitialize((params: InitializeParams): InitializeResult => { } }); } - if (htmlAttributes) { - attributePaths.forEach(path => { - try { - if (fs.existsSync(path)) { - const attributeSet = parseAttributes(fs.readFileSync(path, 'utf-8')); - for (let ga in attributeSet) { - htmlAttributes[ga] = attributeSet[ga]; - } - } - } catch (err) { - console.log(`Failed to load attributes from ${path}`); - } - }); - } const workspace = { get settings() { return globalSettings; }, get folders() { return workspaceFolders; } }; - languageModes = getLanguageModes(initializationOptions ? initializationOptions.embeddedLanguages : { css: true, javascript: true }, workspace, htmlTags, htmlAttributes); + languageModes = getLanguageModes(initializationOptions ? initializationOptions.embeddedLanguages : { css: true, javascript: true }, workspace, allHtmlData); documents.onDidClose(e => { languageModes.onDocumentRemoved(e.document); diff --git a/extensions/html-language-features/server/src/modes/languageModes.ts b/extensions/html-language-features/server/src/modes/languageModes.ts index 28b90a4cd0c..b398dc5b364 100644 --- a/extensions/html-language-features/server/src/modes/languageModes.ts +++ b/extensions/html-language-features/server/src/modes/languageModes.ts @@ -3,7 +3,7 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { getLanguageService as getHTMLLanguageService, DocumentContext, ITagSet, IAttributeSet } from 'vscode-html-languageservice'; +import { getLanguageService as getHTMLLanguageService, DocumentContext, HTMLData } from 'vscode-html-languageservice'; import { CompletionItem, Location, SignatureHelp, Definition, TextEdit, TextDocument, Diagnostic, DocumentLink, Range, Hover, DocumentHighlight, CompletionList, Position, FormattingOptions, SymbolInformation, FoldingRange @@ -65,11 +65,10 @@ export interface LanguageModeRange extends Range { attributeValue?: boolean; } -export function getLanguageModes(supportedLanguages: { [languageId: string]: boolean; }, workspace: Workspace, customTags?: ITagSet, customAttributes?: IAttributeSet): LanguageModes { +export function getLanguageModes(supportedLanguages: { [languageId: string]: boolean; }, workspace: Workspace, customData?: HTMLData): LanguageModes { const htmlLanguageService = getHTMLLanguageService({ - customTags, - customAttributes + customData }); let documentRegions = getLanguageModelCache(10, 60, document => getDocumentRegions(htmlLanguageService, document)); diff --git a/extensions/html-language-features/server/src/utils/tagDefinitions.ts b/extensions/html-language-features/server/src/utils/tagDefinitions.ts index 84bb3395c2b..110a2acc5d7 100644 --- a/extensions/html-language-features/server/src/utils/tagDefinitions.ts +++ b/extensions/html-language-features/server/src/utils/tagDefinitions.ts @@ -3,56 +3,8 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { ITagSet, IAttributeSet, HTMLTagSpecification } from 'vscode-html-languageservice'; +import { HTMLData } from 'vscode-html-languageservice'; -interface Tag { - label: string; - description: string; - attributes: Attribute[]; -} -interface Attribute { - label: string; - description: string; -} -interface RawTagSet { - tags: Tag[]; -} -interface RawAttributeSet { - attributes: Attribute[]; -} - -export function parseTagSet(source: string): ITagSet { - const tagSet: ITagSet = {}; - - let rawTagSet: RawTagSet; - try { - rawTagSet = JSON.parse(source); - } catch (err) { - return {}; - } - - rawTagSet.tags.forEach(c => { - tagSet[c.label] = new HTMLTagSpecification(c.description, c.attributes.map(a => a.label)); - }); - - return tagSet; -} - -export function parseAttributes(source: string): IAttributeSet { - const attributeSet: IAttributeSet = {}; - - let rawAttributeSet: RawAttributeSet; - try { - rawAttributeSet = JSON.parse(source); - } catch (err) { - return {}; - } - - rawAttributeSet.attributes.forEach(ag => { - attributeSet[ag.label] = { - ...ag - }; - }); - - return attributeSet; +export function parseHTMLData(source: string): HTMLData { + return JSON.parse(source); } \ No newline at end of file