mirror of
https://github.com/Microsoft/vscode
synced 2024-10-02 17:32:41 +00:00
Contribute to html language server with a custom language. (#146731)
* Contribute to html language server with a custom language. Fixes #146730 Signed-off-by: azerr <azerr@redhat.com> * refactor out LanguageParticipants * restart client on language selector change * htmlLanguage -> htmlLanguageParticipants * tune autoInsert wording * tune autoInsert description Co-authored-by: azerr <azerr@redhat.com> Co-authored-by: Martin Aeschlimann <martinae@microsoft.com>
This commit is contained in:
parent
6cad4b9494
commit
cef02dae8d
|
@ -36,6 +36,12 @@
|
||||||
"scopeName": "text.html.handlebars",
|
"scopeName": "text.html.handlebars",
|
||||||
"path": "./syntaxes/Handlebars.tmLanguage.json"
|
"path": "./syntaxes/Handlebars.tmLanguage.json"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"htmlLanguageParticipants": [
|
||||||
|
{
|
||||||
|
"languageId": "handlebars",
|
||||||
|
"autoInsert": true
|
||||||
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|
|
@ -5,8 +5,9 @@
|
||||||
|
|
||||||
import { window, workspace, Disposable, TextDocument, Position, SnippetString, TextDocumentChangeEvent, TextDocumentChangeReason, TextDocumentContentChangeEvent } from 'vscode';
|
import { window, workspace, Disposable, TextDocument, Position, SnippetString, TextDocumentChangeEvent, TextDocumentChangeReason, TextDocumentContentChangeEvent } from 'vscode';
|
||||||
import { Runtime } from './htmlClient';
|
import { Runtime } from './htmlClient';
|
||||||
|
import { LanguageParticipants } from './languageParticipants';
|
||||||
|
|
||||||
export function activateAutoInsertion(provider: (kind: 'autoQuote' | 'autoClose', document: TextDocument, position: Position) => Thenable<string>, supportedLanguages: { [id: string]: boolean }, runtime: Runtime): Disposable {
|
export function activateAutoInsertion(provider: (kind: 'autoQuote' | 'autoClose', document: TextDocument, position: Position) => Thenable<string>, languageParticipants: LanguageParticipants, runtime: Runtime): Disposable {
|
||||||
const disposables: Disposable[] = [];
|
const disposables: Disposable[] = [];
|
||||||
workspace.onDidChangeTextDocument(onDidChangeTextDocument, null, disposables);
|
workspace.onDidChangeTextDocument(onDidChangeTextDocument, null, disposables);
|
||||||
|
|
||||||
|
@ -33,7 +34,7 @@ export function activateAutoInsertion(provider: (kind: 'autoQuote' | 'autoClose'
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const document = editor.document;
|
const document = editor.document;
|
||||||
if (!supportedLanguages[document.languageId]) {
|
if (!languageParticipants.useAutoInsert(document.languageId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const configurations = workspace.getConfiguration(undefined, document.uri);
|
const configurations = workspace.getConfiguration(undefined, document.uri);
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import { Disposable, ExtensionContext, Uri } from 'vscode';
|
import { Disposable, ExtensionContext, Uri } from 'vscode';
|
||||||
import { BaseLanguageClient, LanguageClientOptions } from 'vscode-languageclient';
|
import { LanguageClientOptions } from 'vscode-languageclient';
|
||||||
import { startClient, LanguageClientConstructor } from '../htmlClient';
|
import { startClient, LanguageClientConstructor, AsyncDisposable } from '../htmlClient';
|
||||||
import { LanguageClient } from 'vscode-languageclient/browser';
|
import { LanguageClient } from 'vscode-languageclient/browser';
|
||||||
|
|
||||||
declare const Worker: {
|
declare const Worker: {
|
||||||
|
@ -15,7 +15,7 @@ declare const TextDecoder: {
|
||||||
new(encoding?: string): { decode(buffer: ArrayBuffer): string };
|
new(encoding?: string): { decode(buffer: ArrayBuffer): string };
|
||||||
};
|
};
|
||||||
|
|
||||||
let client: BaseLanguageClient | undefined;
|
let client: AsyncDisposable | undefined;
|
||||||
|
|
||||||
// this method is called when vs code is activated
|
// this method is called when vs code is activated
|
||||||
export async function activate(context: ExtensionContext) {
|
export async function activate(context: ExtensionContext) {
|
||||||
|
@ -42,7 +42,7 @@ export async function activate(context: ExtensionContext) {
|
||||||
|
|
||||||
export async function deactivate(): Promise<void> {
|
export async function deactivate(): Promise<void> {
|
||||||
if (client) {
|
if (client) {
|
||||||
await client.stop();
|
await client.dispose();
|
||||||
client = undefined;
|
client = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,7 +125,7 @@ function collectInWorkspaces(workspaceUris: Set<string>): Set<string> {
|
||||||
}
|
}
|
||||||
|
|
||||||
function collectInExtensions(localExtensionUris: Set<string>, externalUris: Set<string>): void {
|
function collectInExtensions(localExtensionUris: Set<string>, externalUris: Set<string>): void {
|
||||||
for (const extension of extensions.all) {
|
for (const extension of extensions.allAcrossExtensionHosts) {
|
||||||
const customData = extension.packageJSON?.contributes?.html?.customData;
|
const customData = extension.packageJSON?.contributes?.html?.customData;
|
||||||
if (Array.isArray(customData)) {
|
if (Array.isArray(customData)) {
|
||||||
for (const uriOrPath of customData) {
|
for (const uriOrPath of customData) {
|
||||||
|
|
|
@ -9,7 +9,7 @@ const localize = nls.loadMessageBundle();
|
||||||
import {
|
import {
|
||||||
languages, ExtensionContext, Position, TextDocument, Range, CompletionItem, CompletionItemKind, SnippetString, workspace, extensions,
|
languages, ExtensionContext, Position, TextDocument, Range, CompletionItem, CompletionItemKind, SnippetString, workspace, extensions,
|
||||||
Disposable, FormattingOptions, CancellationToken, ProviderResult, TextEdit, CompletionContext, CompletionList, SemanticTokensLegend,
|
Disposable, FormattingOptions, CancellationToken, ProviderResult, TextEdit, CompletionContext, CompletionList, SemanticTokensLegend,
|
||||||
DocumentSemanticTokensProvider, DocumentRangeSemanticTokensProvider, SemanticTokens, window, commands
|
DocumentSemanticTokensProvider, DocumentRangeSemanticTokensProvider, SemanticTokens, window, commands, OutputChannel
|
||||||
} from 'vscode';
|
} from 'vscode';
|
||||||
import {
|
import {
|
||||||
LanguageClientOptions, RequestType, DocumentRangeFormattingParams,
|
LanguageClientOptions, RequestType, DocumentRangeFormattingParams,
|
||||||
|
@ -18,6 +18,7 @@ import {
|
||||||
import { FileSystemProvider, serveFileSystemRequests } from './requests';
|
import { FileSystemProvider, serveFileSystemRequests } from './requests';
|
||||||
import { getCustomDataSource } from './customData';
|
import { getCustomDataSource } from './customData';
|
||||||
import { activateAutoInsertion } from './autoInsertion';
|
import { activateAutoInsertion } from './autoInsertion';
|
||||||
|
import { getLanguageParticipants, LanguageParticipants } from './languageParticipants';
|
||||||
|
|
||||||
namespace CustomDataChangedNotification {
|
namespace CustomDataChangedNotification {
|
||||||
export const type: NotificationType<string[]> = new NotificationType('html/customDataChanged');
|
export const type: NotificationType<string[]> = new NotificationType('html/customDataChanged');
|
||||||
|
@ -74,6 +75,8 @@ export interface TelemetryReporter {
|
||||||
|
|
||||||
export type LanguageClientConstructor = (name: string, description: string, clientOptions: LanguageClientOptions) => BaseLanguageClient;
|
export type LanguageClientConstructor = (name: string, description: string, clientOptions: LanguageClientOptions) => BaseLanguageClient;
|
||||||
|
|
||||||
|
export const languageServerDescription = localize('htmlserver.name', 'HTML Language Server');
|
||||||
|
|
||||||
export interface Runtime {
|
export interface Runtime {
|
||||||
TextDecoder: { new(encoding?: string): { decode(buffer: ArrayBuffer): string } };
|
TextDecoder: { new(encoding?: string): { decode(buffer: ArrayBuffer): string } };
|
||||||
fileFs?: FileSystemProvider;
|
fileFs?: FileSystemProvider;
|
||||||
|
@ -83,11 +86,69 @@ export interface Runtime {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function startClient(context: ExtensionContext, newLanguageClient: LanguageClientConstructor, runtime: Runtime): Promise<BaseLanguageClient> {
|
export interface AsyncDisposable {
|
||||||
|
dispose(): Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
const toDispose = context.subscriptions;
|
export async function startClient(context: ExtensionContext, newLanguageClient: LanguageClientConstructor, runtime: Runtime): Promise<AsyncDisposable> {
|
||||||
|
|
||||||
const documentSelector = ['html', 'handlebars'];
|
const outputChannel = window.createOutputChannel(languageServerDescription);
|
||||||
|
|
||||||
|
const languageParticipants = getLanguageParticipants();
|
||||||
|
context.subscriptions.push(languageParticipants);
|
||||||
|
|
||||||
|
let client: Disposable | undefined = await startClientWithParticipants(languageParticipants, newLanguageClient, outputChannel, runtime);
|
||||||
|
|
||||||
|
const promptForLinkedEditingKey = 'html.promptForLinkedEditing';
|
||||||
|
if (extensions.getExtension('formulahendry.auto-rename-tag') !== undefined && (context.globalState.get(promptForLinkedEditingKey) !== false)) {
|
||||||
|
const config = workspace.getConfiguration('editor', { languageId: 'html' });
|
||||||
|
if (!config.get('linkedEditing') && !config.get('renameOnType')) {
|
||||||
|
const activeEditorListener = window.onDidChangeActiveTextEditor(async e => {
|
||||||
|
if (e && languageParticipants.hasLanguage(e.document.languageId)) {
|
||||||
|
context.globalState.update(promptForLinkedEditingKey, false);
|
||||||
|
activeEditorListener.dispose();
|
||||||
|
const configure = localize('configureButton', 'Configure');
|
||||||
|
const res = await window.showInformationMessage(localize('linkedEditingQuestion', 'VS Code now has built-in support for auto-renaming tags. Do you want to enable it?'), configure);
|
||||||
|
if (res === configure) {
|
||||||
|
commands.executeCommand('workbench.action.openSettings', SettingIds.linkedEditing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
context.subscriptions.push(activeEditorListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let restartTrigger: Disposable | undefined;
|
||||||
|
languageParticipants.onDidChange(() => {
|
||||||
|
if (restartTrigger) {
|
||||||
|
restartTrigger.dispose();
|
||||||
|
}
|
||||||
|
restartTrigger = runtime.timer.setTimeout(async () => {
|
||||||
|
if (client) {
|
||||||
|
outputChannel.appendLine('Extensions have changed, restarting HTML server...');
|
||||||
|
outputChannel.appendLine('');
|
||||||
|
const oldClient = client;
|
||||||
|
client = undefined;
|
||||||
|
await oldClient.dispose();
|
||||||
|
client = await startClientWithParticipants(languageParticipants, newLanguageClient, outputChannel, runtime);
|
||||||
|
}
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
dispose: async () => {
|
||||||
|
restartTrigger?.dispose();
|
||||||
|
await client?.dispose();
|
||||||
|
outputChannel.dispose();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function startClientWithParticipants(languageParticipants: LanguageParticipants, newLanguageClient: LanguageClientConstructor, outputChannel: OutputChannel, runtime: Runtime): Promise<AsyncDisposable> {
|
||||||
|
|
||||||
|
const toDispose: Disposable[] = [];
|
||||||
|
|
||||||
|
const documentSelector = languageParticipants.documentSelector;
|
||||||
const embeddedLanguages = { css: true, javascript: true };
|
const embeddedLanguages = { css: true, javascript: true };
|
||||||
|
|
||||||
let rangeFormatting: Disposable | undefined = undefined;
|
let rangeFormatting: Disposable | undefined = undefined;
|
||||||
|
@ -129,22 +190,23 @@ export async function startClient(context: ExtensionContext, newLanguageClient:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
clientOptions.outputChannel = outputChannel;
|
||||||
|
|
||||||
// Create the language client and start the client.
|
// Create the language client and start the client.
|
||||||
const client = newLanguageClient('html', localize('htmlserver.name', 'HTML Language Server'), clientOptions);
|
const client = newLanguageClient('html', languageServerDescription, clientOptions);
|
||||||
client.registerProposedFeatures();
|
client.registerProposedFeatures();
|
||||||
|
|
||||||
await client.start();
|
await client.start();
|
||||||
|
|
||||||
toDispose.push(serveFileSystemRequests(client, runtime));
|
toDispose.push(serveFileSystemRequests(client, runtime));
|
||||||
|
|
||||||
const customDataSource = getCustomDataSource(runtime, context.subscriptions);
|
const customDataSource = getCustomDataSource(runtime, toDispose);
|
||||||
|
|
||||||
client.sendNotification(CustomDataChangedNotification.type, customDataSource.uris);
|
client.sendNotification(CustomDataChangedNotification.type, customDataSource.uris);
|
||||||
customDataSource.onDidChange(() => {
|
customDataSource.onDidChange(() => {
|
||||||
client.sendNotification(CustomDataChangedNotification.type, customDataSource.uris);
|
client.sendNotification(CustomDataChangedNotification.type, customDataSource.uris);
|
||||||
});
|
}, undefined, toDispose);
|
||||||
client.onRequest(CustomDataContent.type, customDataSource.getContent);
|
toDispose.push(client.onRequest(CustomDataContent.type, customDataSource.getContent));
|
||||||
|
|
||||||
|
|
||||||
const insertRequestor = (kind: 'autoQuote' | 'autoClose', document: TextDocument, position: Position): Promise<string> => {
|
const insertRequestor = (kind: 'autoQuote' | 'autoClose', document: TextDocument, position: Position): Promise<string> => {
|
||||||
|
@ -155,7 +217,8 @@ export async function startClient(context: ExtensionContext, newLanguageClient:
|
||||||
};
|
};
|
||||||
return client.sendRequest(AutoInsertRequest.type, param);
|
return client.sendRequest(AutoInsertRequest.type, param);
|
||||||
};
|
};
|
||||||
const disposable = activateAutoInsertion(insertRequestor, { html: true, handlebars: true }, runtime);
|
|
||||||
|
const disposable = activateAutoInsertion(insertRequestor, languageParticipants, runtime);
|
||||||
toDispose.push(disposable);
|
toDispose.push(disposable);
|
||||||
|
|
||||||
const disposable2 = client.onTelemetry(e => {
|
const disposable2 = client.onTelemetry(e => {
|
||||||
|
@ -193,7 +256,6 @@ export async function startClient(context: ExtensionContext, newLanguageClient:
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
function updateFormatterRegistration() {
|
function updateFormatterRegistration() {
|
||||||
const formatEnabled = workspace.getConfiguration().get(SettingIds.formatEnable);
|
const formatEnabled = workspace.getConfiguration().get(SettingIds.formatEnable);
|
||||||
if (!formatEnabled && rangeFormatting) {
|
if (!formatEnabled && rangeFormatting) {
|
||||||
|
@ -278,25 +340,12 @@ export async function startClient(context: ExtensionContext, newLanguageClient:
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const promptForLinkedEditingKey = 'html.promptForLinkedEditing';
|
return {
|
||||||
if (extensions.getExtension('formulahendry.auto-rename-tag') !== undefined && (context.globalState.get(promptForLinkedEditingKey) !== false)) {
|
dispose: async () => {
|
||||||
const config = workspace.getConfiguration('editor', { languageId: 'html' });
|
await client.stop();
|
||||||
if (!config.get('linkedEditing') && !config.get('renameOnType')) {
|
toDispose.forEach(d => d.dispose());
|
||||||
const activeEditorListener = window.onDidChangeActiveTextEditor(async e => {
|
rangeFormatting?.dispose();
|
||||||
if (e && documentSelector.indexOf(e.document.languageId) !== -1) {
|
|
||||||
context.globalState.update(promptForLinkedEditingKey, false);
|
|
||||||
activeEditorListener.dispose();
|
|
||||||
const configure = localize('configureButton', 'Configure');
|
|
||||||
const res = await window.showInformationMessage(localize('linkedEditingQuestion', 'VS Code now has built-in support for auto-renaming tags. Do you want to enable it?'), configure);
|
|
||||||
if (res === configure) {
|
|
||||||
commands.executeCommand('workbench.action.openSettings', SettingIds.linkedEditing);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
toDispose.push(activeEditorListener);
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
return client;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { DocumentSelector } from 'vscode-languageclient';
|
||||||
|
import { Event, EventEmitter, extensions } from 'vscode';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HTML language participant contribution.
|
||||||
|
*/
|
||||||
|
interface LanguageParticipantContribution {
|
||||||
|
/**
|
||||||
|
* The id of the language which participates with the HTML language server.
|
||||||
|
*/
|
||||||
|
languageId: string;
|
||||||
|
/**
|
||||||
|
* true if the language activates the auto insertion and false otherwise.
|
||||||
|
*/
|
||||||
|
autoInsert?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LanguageParticipants {
|
||||||
|
readonly onDidChange: Event<void>;
|
||||||
|
readonly documentSelector: DocumentSelector;
|
||||||
|
hasLanguage(languageId: string): boolean;
|
||||||
|
useAutoInsert(languageId: string): boolean;
|
||||||
|
dispose(): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getLanguageParticipants(): LanguageParticipants {
|
||||||
|
const onDidChangeEmmiter = new EventEmitter<void>();
|
||||||
|
let languages = new Set<string>();
|
||||||
|
let autoInsert = new Set<string>();
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
const oldLanguages = languages, oldAutoInsert = autoInsert;
|
||||||
|
|
||||||
|
languages = new Set();
|
||||||
|
languages.add('html');
|
||||||
|
autoInsert = new Set();
|
||||||
|
autoInsert.add('html');
|
||||||
|
|
||||||
|
for (const extension of extensions.allAcrossExtensionHosts) {
|
||||||
|
const htmlLanguageParticipants = extension.packageJSON?.contributes?.htmlLanguageParticipants as LanguageParticipantContribution[];
|
||||||
|
if (Array.isArray(htmlLanguageParticipants)) {
|
||||||
|
for (const htmlLanguageParticipant of htmlLanguageParticipants) {
|
||||||
|
const languageId = htmlLanguageParticipant.languageId;
|
||||||
|
if (typeof languageId === 'string') {
|
||||||
|
languages.add(languageId);
|
||||||
|
if (htmlLanguageParticipant.autoInsert !== false) {
|
||||||
|
autoInsert.add(languageId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return !isEqualSet(languages, oldLanguages) || !isEqualSet(oldLanguages, oldAutoInsert);
|
||||||
|
}
|
||||||
|
update();
|
||||||
|
|
||||||
|
const changeListener = extensions.onDidChange(_ => {
|
||||||
|
if (update()) {
|
||||||
|
onDidChangeEmmiter.fire();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
onDidChange: onDidChangeEmmiter.event,
|
||||||
|
get documentSelector() { return Array.from(languages); },
|
||||||
|
hasLanguage(languageId: string) { return languages.has(languageId); },
|
||||||
|
useAutoInsert(languageId: string) { return autoInsert.has(languageId); },
|
||||||
|
dispose: () => changeListener.dispose()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function isEqualSet<T>(s1: Set<T>, s2: Set<T>) {
|
||||||
|
if (s1.size !== s2.size) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (const e of s1) {
|
||||||
|
if (!s2.has(e)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -5,15 +5,15 @@
|
||||||
|
|
||||||
import { getNodeFileFS } from './nodeFs';
|
import { getNodeFileFS } from './nodeFs';
|
||||||
import { Disposable, ExtensionContext } from 'vscode';
|
import { Disposable, ExtensionContext } from 'vscode';
|
||||||
import { startClient, LanguageClientConstructor } from '../htmlClient';
|
import { startClient, LanguageClientConstructor, AsyncDisposable } from '../htmlClient';
|
||||||
import { ServerOptions, TransportKind, LanguageClientOptions, LanguageClient, BaseLanguageClient } from 'vscode-languageclient/node';
|
import { ServerOptions, TransportKind, LanguageClientOptions, LanguageClient } from 'vscode-languageclient/node';
|
||||||
import { TextDecoder } from 'util';
|
import { TextDecoder } from 'util';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import TelemetryReporter from '@vscode/extension-telemetry';
|
import TelemetryReporter from '@vscode/extension-telemetry';
|
||||||
|
|
||||||
|
|
||||||
let telemetry: TelemetryReporter | undefined;
|
let telemetry: TelemetryReporter | undefined;
|
||||||
let client: BaseLanguageClient | undefined;
|
let client: AsyncDisposable | undefined;
|
||||||
|
|
||||||
// this method is called when vs code is activated
|
// this method is called when vs code is activated
|
||||||
export async function activate(context: ExtensionContext) {
|
export async function activate(context: ExtensionContext) {
|
||||||
|
@ -50,7 +50,7 @@ export async function activate(context: ExtensionContext) {
|
||||||
|
|
||||||
export async function deactivate(): Promise<void> {
|
export async function deactivate(): Promise<void> {
|
||||||
if (client) {
|
if (client) {
|
||||||
await client.stop();
|
await client.dispose();
|
||||||
client = undefined;
|
client = undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src/**/*",
|
"src/**/*",
|
||||||
"../../../src/vscode-dts/vscode.d.ts"
|
"../../../src/vscode-dts/vscode.d.ts",
|
||||||
|
"../../../src/vscode-dts/vscode.proposed.extensionsAny.d.ts"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
"onLanguage:html",
|
"onLanguage:html",
|
||||||
"onLanguage:handlebars"
|
"onLanguage:handlebars"
|
||||||
],
|
],
|
||||||
|
"enabledApiProposals": [
|
||||||
|
"extensionsAny"
|
||||||
|
],
|
||||||
"main": "./client/out/node/htmlClientMain",
|
"main": "./client/out/node/htmlClientMain",
|
||||||
"browser": "./client/dist/browser/htmlClientMain",
|
"browser": "./client/dist/browser/htmlClientMain",
|
||||||
"capabilities": {
|
"capabilities": {
|
||||||
|
|
|
@ -13,6 +13,23 @@
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Relative path to a HTML custom data file"
|
"description": "Relative path to a HTML custom data file"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"htmlLanguageParticipants": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "A list of languages that participate with the HTML language server.",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"languageId": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The id of the language that participates with HTML language server."
|
||||||
|
},
|
||||||
|
"autoInsert": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether the language participates with HTML auto insertions. If not specified, defaults to <code>true</code>."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue