[html] add css support to html extension as library

This commit is contained in:
Martin Aeschlimann
2016-11-14 11:34:33 +01:00
parent 332fd57d3f
commit 8a85fc0399
17 changed files with 357 additions and 492 deletions

View File

@@ -16,14 +16,14 @@ export function getEmbeddedLanguageAtPosition(languageService: LanguageService,
return embeddedContent.languageId;
}
}
return null;
return 'html';
}
export function hasEmbeddedContent(languageService: LanguageService, document: TextDocument, htmlDocument: HTMLDocument, embeddedLanguages: { [languageId: string]: boolean }): string[] {
export function hasEmbeddedContent(languageService: LanguageService, document: TextDocument, htmlDocument: HTMLDocument): string[] {
let embeddedLanguageIds: { [languageId: string]: boolean } = {};
function collectEmbeddedLanguages(node: Node): void {
let c = getEmbeddedContentForNode(languageService, document, node);
if (c && embeddedLanguages[c.languageId] && !isWhitespace(document.getText().substring(c.start, c.end))) {
if (c && !isWhitespace(document.getText().substring(c.start, c.end))) {
embeddedLanguageIds[c.languageId] = true;
}
node.children.forEach(collectEmbeddedLanguages);
@@ -33,7 +33,7 @@ export function hasEmbeddedContent(languageService: LanguageService, document: T
return Object.keys(embeddedLanguageIds);
}
export function getEmbeddedContent(languageService: LanguageService, document: TextDocument, htmlDocument: HTMLDocument, languageId: string): string {
export function getEmbeddedDocument(languageService: LanguageService, document: TextDocument, htmlDocument: HTMLDocument, languageId: string): TextDocument {
let contents = [];
function collectEmbeddedNodes(node: Node): void {
let c = getEmbeddedContentForNode(languageService, document, node);
@@ -54,7 +54,7 @@ export function getEmbeddedContent(languageService: LanguageService, document: T
currentPos = c.end;
}
result = substituteWithWhitespace(result, currentPos, oldContent.length, oldContent);
return result;
return TextDocument.create(document.uri, languageId, document.version, result);
}
function substituteWithWhitespace(result, start, end, oldContent) {

View File

@@ -4,14 +4,10 @@
*--------------------------------------------------------------------------------------------*/
'use strict';
import {
createConnection, IConnection, TextDocuments, InitializeParams, InitializeResult, FormattingOptions, RequestType, NotificationType,
CompletionList, Position, Hover
} from 'vscode-languageserver';
import { createConnection, IConnection, TextDocuments, InitializeParams, InitializeResult, RequestType } from 'vscode-languageserver';
import { DocumentContext, TextDocument, Diagnostic, DocumentLink, Range } from 'vscode-html-languageservice';
import { getLanguageModes } from './languageModes';
import { HTMLDocument, getLanguageService, CompletionConfiguration, HTMLFormatConfiguration, DocumentContext, TextDocument } from 'vscode-html-languageservice';
import { getLanguageModelCache } from './languageModelCache';
import { getEmbeddedContent, getEmbeddedLanguageAtPosition, hasEmbeddedContent } from './embeddedSupport';
import * as url from 'url';
import * as path from 'path';
import uri from 'vscode-uri';
@@ -19,50 +15,8 @@ import uri from 'vscode-uri';
import * as nls from 'vscode-nls';
nls.config(process.env['VSCODE_NLS_CONFIG']);
interface EmbeddedCompletionParams {
uri: string;
version: number;
embeddedLanguageId: string;
position: Position;
}
namespace EmbeddedCompletionRequest {
export const type: RequestType<EmbeddedCompletionParams, CompletionList, any> = { get method() { return 'embedded/completion'; } };
}
interface EmbeddedHoverParams {
uri: string;
version: number;
embeddedLanguageId: string;
position: Position;
}
namespace EmbeddedHoverRequest {
export const type: RequestType<EmbeddedCompletionParams, Hover, any> = { get method() { return 'embedded/hover'; } };
}
interface EmbeddedContentParams {
uri: string;
embeddedLanguageId: string;
}
interface EmbeddedContent {
content: string;
version: number;
}
namespace EmbeddedContentRequest {
export const type: RequestType<EmbeddedContentParams, EmbeddedContent, any> = { get method() { return 'embedded/content'; } };
}
interface EmbeddedContentChangedParams {
uri: string;
version: number;
embeddedLanguageIds: string[];
}
namespace EmbeddedContentChangedNotification {
export const type: NotificationType<EmbeddedContentChangedParams> = { get method() { return 'embedded/contentchanged'; } };
namespace ColorSymbolRequest {
export const type: RequestType<string, Range[], any> = { get method() { return 'css/colorSymbols'; } };
}
// Create a connection for the server
@@ -78,22 +32,22 @@ let documents: TextDocuments = new TextDocuments();
// for open, change and close text document events
documents.listen(connection);
let htmlDocuments = getLanguageModelCache<HTMLDocument>(10, 60, document => getLanguageService().parseHTMLDocument(document));
let languageModes = getLanguageModes({ 'css': true });
documents.onDidClose(e => {
htmlDocuments.onDocumentRemoved(e.document);
languageModes.getAllModes().forEach(m => m.onDocumentRemoved(e.document));
});
connection.onShutdown(() => {
htmlDocuments.dispose();
languageModes.getAllModes().forEach(m => m.dispose());
});
let workspacePath: string;
let embeddedLanguages: { [languageId: string]: boolean };
// After the server has started the client sends an initilize request. The server receives
// in the passed params the rootPath of the workspace plus the client capabilites
connection.onInitialize((params: InitializeParams): InitializeResult => {
workspacePath = params.rootPath;
embeddedLanguages = params.initializationOptions.embeddedLanguages;
return {
capabilities: {
// Tell the client that the server works in FULL text document sync mode
@@ -107,25 +61,10 @@ connection.onInitialize((params: InitializeParams): InitializeResult => {
};
});
// create the JSON language service
var languageService = getLanguageService();
// The settings interface describes the server relevant settings part
interface Settings {
html: LanguageSettings;
}
interface LanguageSettings {
suggest: CompletionConfiguration;
format: HTMLFormatConfiguration;
}
let languageSettings: LanguageSettings;
// The settings have changed. Is send on server activation as well.
connection.onDidChangeConfiguration((change) => {
var settings = <Settings>change.settings;
languageSettings = settings.html;
languageModes.configure(change.settings);
});
let pendingValidationRequests: { [uri: string]: NodeJS.Timer } = {};
@@ -140,10 +79,7 @@ documents.onDidChangeContent(change => {
// a document has closed: clear all diagnostics
documents.onDidClose(event => {
cleanPendingValidation(event.document);
//connection.sendDiagnostics({ uri: event.document.uri, diagnostics: [] });
if (embeddedLanguages) {
connection.sendNotification(EmbeddedContentChangedNotification.type, { uri: event.document.uri, version: event.document.version, embeddedLanguageIds: [] });
}
connection.sendDiagnostics({ uri: event.document.uri, diagnostics: [] });
});
function cleanPendingValidation(textDocument: TextDocument): void {
@@ -163,79 +99,50 @@ function triggerValidation(textDocument: TextDocument): void {
}
function validateTextDocument(textDocument: TextDocument): void {
let htmlDocument = htmlDocuments.get(textDocument);
//let diagnostics = languageService.doValidation(textDocument, htmlDocument);
// Send the computed diagnostics to VSCode.
//connection.sendDiagnostics({ uri: textDocument.uri, diagnostics });
if (embeddedLanguages) {
let embeddedLanguageIds = hasEmbeddedContent(languageService, textDocument, htmlDocument, embeddedLanguages);
let p = { uri: textDocument.uri, version: textDocument.version, embeddedLanguageIds };
connection.sendNotification(EmbeddedContentChangedNotification.type, p);
}
let diagnostics: Diagnostic[] = [];
languageModes.getAllModesInDocument(textDocument).forEach(mode => {
if (mode.doValidation) {
diagnostics = diagnostics.concat(mode.doValidation(textDocument));
}
});
connection.sendDiagnostics({ uri: textDocument.uri, diagnostics });
}
connection.onCompletion(textDocumentPosition => {
let document = documents.get(textDocumentPosition.textDocument.uri);
let htmlDocument = htmlDocuments.get(document);
let options = languageSettings && languageSettings.suggest;
let list = languageService.doComplete(document, textDocumentPosition.position, htmlDocument, options);
if (list.items.length === 0 && embeddedLanguages) {
let embeddedLanguageId = getEmbeddedLanguageAtPosition(languageService, document, htmlDocument, textDocumentPosition.position);
if (embeddedLanguageId && embeddedLanguages[embeddedLanguageId]) {
return connection.sendRequest(EmbeddedCompletionRequest.type, { uri: document.uri, version: document.version, embeddedLanguageId, position: textDocumentPosition.position });
}
let mode = languageModes.getModeAtPosition(document, textDocumentPosition.position);
if (mode && mode.doComplete) {
return mode.doComplete(document, textDocumentPosition.position);
}
return list;
return { isIncomplete: true, items: [] };
});
connection.onHover(textDocumentPosition => {
let document = documents.get(textDocumentPosition.textDocument.uri);
let htmlDocument = htmlDocuments.get(document);
let hover = languageService.doHover(document, textDocumentPosition.position, htmlDocument);
if (!hover && embeddedLanguages) {
let embeddedLanguageId = getEmbeddedLanguageAtPosition(languageService, document, htmlDocument, textDocumentPosition.position);
if (embeddedLanguageId && embeddedLanguages[embeddedLanguageId]) {
return connection.sendRequest(EmbeddedHoverRequest.type, { uri: document.uri, version: document.version, embeddedLanguageId, position: textDocumentPosition.position });
}
let mode = languageModes.getModeAtPosition(document, textDocumentPosition.position);
if (mode && mode.doHover) {
return mode.doHover(document, textDocumentPosition.position);
}
return hover;
});
connection.onRequest(EmbeddedContentRequest.type, parms => {
let document = documents.get(parms.uri);
if (document) {
let htmlDocument = htmlDocuments.get(document);
return { content: getEmbeddedContent(languageService, document, htmlDocument, parms.embeddedLanguageId), version: document.version };
}
return void 0;
return null;
});
connection.onDocumentHighlight(documentHighlightParams => {
let document = documents.get(documentHighlightParams.textDocument.uri);
let htmlDocument = htmlDocuments.get(document);
return languageService.findDocumentHighlights(document, documentHighlightParams.position, htmlDocument);
let mode = languageModes.getModeAtPosition(document, documentHighlightParams.position);
if (mode && mode.findDocumentHighlight) {
return mode.findDocumentHighlight(document, documentHighlightParams.position);
}
return [];
});
function merge(src: any, dst: any): any {
for (var key in src) {
if (src.hasOwnProperty(key)) {
dst[key] = src[key];
}
}
return dst;
}
function getFormattingOptions(formatParams: FormattingOptions) {
let formatSettings = languageSettings && languageSettings.format;
if (!formatSettings) {
return formatParams;
}
return merge(formatParams, merge(formatSettings, {}));
}
connection.onDocumentRangeFormatting(formatParams => {
let document = documents.get(formatParams.textDocument.uri);
return languageService.format(document, formatParams.range, getFormattingOptions(formatParams.options));
let startMode = languageModes.getModeAtPosition(document, formatParams.range.start);
let endMode = languageModes.getModeAtPosition(document, formatParams.range.end);
if (startMode && startMode === endMode && startMode.format) {
return startMode.format(document, formatParams.range, formatParams.options);
}
return null;
});
connection.onDocumentLinks(documentLinkParam => {
@@ -248,9 +155,27 @@ connection.onDocumentLinks(documentLinkParam => {
return url.resolve(document.uri, ref);
}
};
return languageService.findDocumentLinks(document, documentContext);
let links: DocumentLink[] = [];
languageModes.getAllModesInDocument(document).forEach(m => {
if (m.findDocumentLinks) {
links = links.concat(m.findDocumentLinks(document, documentContext));
}
});
return links;
});
connection.onRequest(ColorSymbolRequest.type, uri => {
let ranges: Range[] = [];
let document = documents.get(uri);
if (document) {
languageModes.getAllModesInDocument(document).forEach(m => {
if (m.findColorSymbols) {
ranges = ranges.concat(m.findColorSymbols(document));
}
});
}
return ranges;
});
// Listen on the connection
connection.listen();

View File

@@ -0,0 +1,164 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import {
TextDocument, Position, HTMLDocument, Diagnostic, CompletionList, Hover, getLanguageService as getHTMLLanguageService,
DocumentHighlight, DocumentLink, DocumentContext, Range, TextEdit, FormattingOptions, CompletionConfiguration, HTMLFormatConfiguration
} from 'vscode-html-languageservice';
import { getCSSLanguageService, Stylesheet } from 'vscode-css-languageservice';
import { getLanguageModelCache } from './languageModelCache';
import { getEmbeddedDocument, getEmbeddedLanguageAtPosition, hasEmbeddedContent } from './embeddedSupport';
export interface LanguageMode {
doValidation?: (document: TextDocument) => Diagnostic[];
doComplete?: (document: TextDocument, position: Position) => CompletionList;
doHover?: (document: TextDocument, position: Position) => Hover;
findDocumentHighlight?: (document: TextDocument, position: Position) => DocumentHighlight[];
findDocumentLinks?: (document: TextDocument, documentContext: DocumentContext) => DocumentLink[];
format?: (document: TextDocument, range: Range, options: FormattingOptions) => TextEdit[];
findColorSymbols?: (document: TextDocument) => Range[];
onDocumentRemoved(document: TextDocument): void;
dispose(): void;
}
// The settings interface describes the server relevant settings part
export interface Settings {
html: HTMLLanguageSettings;
css: any;
}
export interface HTMLLanguageSettings {
suggest: CompletionConfiguration;
format: HTMLFormatConfiguration;
}
export interface LanguageModes {
getModeAtPosition(document: TextDocument, position: Position): LanguageMode;
getAllModesInDocument(document: TextDocument): LanguageMode[];
getAllModes(): LanguageMode[];
getMode(languageId: string): LanguageMode;
configure(options: Settings): void;
}
export function getLanguageModes(supportedLanguages: { [languageId: string]: boolean; }): LanguageModes {
var htmlLanguageService = getHTMLLanguageService();
let htmlDocuments = getLanguageModelCache<HTMLDocument>(10, 60, document => htmlLanguageService.parseHTMLDocument(document));
let modes: { [id: string]: LanguageMode } = {};
let settings: any = {};
supportedLanguages['html'] = true;
modes['html'] = {
doComplete(document: TextDocument, position: Position) {
let options = settings && settings.html && settings.html.suggest;
return htmlLanguageService.doComplete(document, position, htmlDocuments.get(document), options);
},
doHover(document: TextDocument, position: Position) {
return htmlLanguageService.doHover(document, position, htmlDocuments.get(document));
},
findDocumentHighlight(document: TextDocument, position: Position) {
return htmlLanguageService.findDocumentHighlights(document, position, htmlDocuments.get(document));
},
findDocumentLinks(document: TextDocument, documentContext: DocumentContext) {
return htmlLanguageService.findDocumentLinks(document, documentContext);
},
format(document: TextDocument, range: Range, formatParams: FormattingOptions) {
let formatSettings = settings && settings.html && settings.html.format;
if (!formatSettings) {
formatSettings = formatParams;
} else {
formatSettings = merge(formatParams, merge(formatSettings, {}));
}
return htmlLanguageService.format(document, range, formatSettings);
},
onDocumentRemoved(document: TextDocument) {
htmlDocuments.onDocumentRemoved(document);
},
dispose() {
htmlDocuments.dispose();
}
};
if (supportedLanguages['css']) {
let cssLanguageService = getCSSLanguageService();
let cssStylesheets = getLanguageModelCache<Stylesheet>(10, 60, document => cssLanguageService.parseStylesheet(document));
let getEmbeddedCSSDocument = (document: TextDocument) => getEmbeddedDocument(htmlLanguageService, document, htmlDocuments.get(document), 'css');
modes['css'] = {
doValidation(document: TextDocument) {
let embedded = getEmbeddedCSSDocument(document);
return cssLanguageService.doValidation(embedded, cssStylesheets.get(embedded));
},
doComplete(document: TextDocument, position: Position) {
let embedded = getEmbeddedCSSDocument(document);
return cssLanguageService.doComplete(embedded, position, cssStylesheets.get(embedded));
},
doHover(document: TextDocument, position: Position) {
let embedded = getEmbeddedCSSDocument(document);
return cssLanguageService.doHover(embedded, position, cssStylesheets.get(embedded));
},
findDocumentHighlight(document: TextDocument, position: Position) {
let embedded = getEmbeddedCSSDocument(document);
return cssLanguageService.findDocumentHighlights(embedded, position, cssStylesheets.get(embedded));
},
findColorSymbols(document: TextDocument) {
let embedded = getEmbeddedCSSDocument(document);
return cssLanguageService.findColorSymbols(embedded, cssStylesheets.get(embedded));
},
onDocumentRemoved(document: TextDocument) {
cssStylesheets.onDocumentRemoved(document);
},
dispose() {
cssStylesheets.dispose();
}
};
};
return {
getModeAtPosition(document: TextDocument, position: Position): LanguageMode {
let languageId = getEmbeddedLanguageAtPosition(htmlLanguageService, document, htmlDocuments.get(document), position);
if (supportedLanguages[languageId]) {
return modes[languageId];
}
return null;
},
getAllModesInDocument(document: TextDocument): LanguageMode[] {
let result = [modes['html']];
let embeddedLanguageIds = hasEmbeddedContent(htmlLanguageService, document, htmlDocuments.get(document));
for (let languageId of embeddedLanguageIds) {
if (supportedLanguages[languageId]) {
result.push(modes[languageId]);
}
}
return result;
},
getAllModes(): LanguageMode[] {
let result = [];
for (let languageId in modes) {
if (supportedLanguages[languageId]) {
result.push(modes[languageId]);
}
}
return result;
},
getMode(languageId: string): LanguageMode {
return modes[languageId];
},
configure(options: any): void {
settings = options;
}
};
}
function merge(src: any, dst: any): any {
for (var key in src) {
if (src.hasOwnProperty(key)) {
dst[key] = src[key];
}
}
return dst;
}

View File

@@ -7,11 +7,11 @@
import * as assert from 'assert';
import * as embeddedSupport from '../embeddedSupport';
import {TextDocument} from 'vscode-languageserver-types';
import { getLanguageService } from 'vscode-html-languageservice';
import { getLanguageService} from 'vscode-html-languageservice';
suite('HTML Embedded Support', () => {
var htmlLanguageService = getLanguageService();
function assertEmbeddedLanguageId(value: string, expectedLanguageId: string): void {
let offset = value.indexOf('|');
@@ -23,7 +23,7 @@ suite('HTML Embedded Support', () => {
let ls = getLanguageService();
let htmlDoc = ls.parseHTMLDocument(document);
let languageId = embeddedSupport.getEmbeddedLanguageAtPosition(ls, document, htmlDoc, position);
let languageId = embeddedSupport.getEmbeddedLanguageAtPosition(htmlLanguageService, document, htmlDoc, position);
assert.equal(languageId, expectedLanguageId);
}
@@ -34,18 +34,18 @@ suite('HTML Embedded Support', () => {
let ls = getLanguageService();
let htmlDoc = ls.parseHTMLDocument(document);
let content = embeddedSupport.getEmbeddedContent(ls, document, htmlDoc, languageId);
assert.equal(content, expectedContent);
let content = embeddedSupport.getEmbeddedDocument(ls, document, htmlDoc, languageId);
assert.equal(content.getText(), expectedContent);
}
test('Styles', function (): any {
assertEmbeddedLanguageId('|<html><style>foo { }</style></html>', void 0);
assertEmbeddedLanguageId('<html|><style>foo { }</style></html>', void 0);
assertEmbeddedLanguageId('<html><st|yle>foo { }</style></html>', void 0);
assertEmbeddedLanguageId('|<html><style>foo { }</style></html>', 'html');
assertEmbeddedLanguageId('<html|><style>foo { }</style></html>', 'html');
assertEmbeddedLanguageId('<html><st|yle>foo { }</style></html>', 'html');
assertEmbeddedLanguageId('<html><style>|foo { }</style></html>', 'css');
assertEmbeddedLanguageId('<html><style>foo| { }</style></html>', 'css');
assertEmbeddedLanguageId('<html><style>foo { }|</style></html>', 'css');
assertEmbeddedLanguageId('<html><style>foo { }</sty|le></html>', void 0);
assertEmbeddedLanguageId('<html><style>foo { }</sty|le></html>', 'html');
});
test('Style content', function (): any {
@@ -57,19 +57,19 @@ suite('HTML Embedded Support', () => {
});
test('Scripts', function (): any {
assertEmbeddedLanguageId('|<html><script>var i = 0;</script></html>', void 0);
assertEmbeddedLanguageId('<html|><script>var i = 0;</script></html>', void 0);
assertEmbeddedLanguageId('<html><scr|ipt>var i = 0;</script></html>', void 0);
assertEmbeddedLanguageId('|<html><script>var i = 0;</script></html>', 'html');
assertEmbeddedLanguageId('<html|><script>var i = 0;</script></html>', 'html');
assertEmbeddedLanguageId('<html><scr|ipt>var i = 0;</script></html>', 'html');
assertEmbeddedLanguageId('<html><script>|var i = 0;</script></html>', 'javascript');
assertEmbeddedLanguageId('<html><script>var| i = 0;</script></html>', 'javascript');
assertEmbeddedLanguageId('<html><script>var i = 0;|</script></html>', 'javascript');
assertEmbeddedLanguageId('<html><script>var i = 0;</scr|ipt></html>', void 0);
assertEmbeddedLanguageId('<html><script>var i = 0;</scr|ipt></html>', 'html');
assertEmbeddedLanguageId('<script type="text/javascript">var| i = 0;</script>', 'javascript');
assertEmbeddedLanguageId('<script type="text/ecmascript">var| i = 0;</script>', 'javascript');
assertEmbeddedLanguageId('<script type="application/javascript">var| i = 0;</script>', 'javascript');
assertEmbeddedLanguageId('<script type="application/ecmascript">var| i = 0;</script>', 'javascript');
assertEmbeddedLanguageId('<script type="application/typescript">var| i = 0;</script>', void 0);
assertEmbeddedLanguageId('<script type="application/typescript">var| i = 0;</script>', 'html');
assertEmbeddedLanguageId('<script type=\'text/javascript\'>var| i = 0;</script>', 'javascript');
});

View File

@@ -1,27 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import * as assert from 'assert';
import {getEmbeddedContentUri, getEmbeddedLanguageId, getHostDocumentUri, isEmbeddedContentUri} from './embeddedContentUri';
suite('Embedded URI', () => {
test('URI', function (): any {
let resourceUri1 = 'file:///c%3A/workspaces/samples/foo.html';
let resourceUri2 = 'file://Users/joe/samples/foo.html';
let uri = getEmbeddedContentUri(resourceUri1, 'css');
assert(isEmbeddedContentUri(uri));
assert.equal(getEmbeddedLanguageId(uri), 'css');
assert.equal(getHostDocumentUri(uri), resourceUri1);
let uri2 = getEmbeddedContentUri(resourceUri2, 'css');
assert(isEmbeddedContentUri(uri2));
assert.equal(getEmbeddedLanguageId(uri2), 'css');
assert.equal(getHostDocumentUri(uri2), resourceUri2);
});
});

View File

@@ -1,27 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
'use strict';
import Uri from 'vscode-uri';
export const EMBEDDED_CONTENT_SCHEME = 'embedded-content';
export function isEmbeddedContentUri(virtualDocumentUri: Uri): boolean {
return virtualDocumentUri.scheme === EMBEDDED_CONTENT_SCHEME;
}
export function getEmbeddedContentUri(parentDocumentUri: string, embeddedLanguageId: string): Uri {
return Uri.from({ scheme: EMBEDDED_CONTENT_SCHEME, authority: embeddedLanguageId, path: '/' + encodeURIComponent(parentDocumentUri) + '.' + embeddedLanguageId });
};
export function getHostDocumentUri(virtualDocumentUri: Uri): string {
let languageId = virtualDocumentUri.authority;
let path = virtualDocumentUri.path.substring(1, virtualDocumentUri.path.length - languageId.length - 1); // remove leading '/' and new file extension
return decodeURIComponent(path);
};
export function getEmbeddedLanguageId(virtualDocumentUri: Uri): string {
return virtualDocumentUri.authority;
}