Feat: updates to docs, extension

This commit is contained in:
Jonathan Kelley committed 2021-01-29 11:57:52 -05:00
1 parent 2e626aea51
commit a2406b33d6
25 files changed
+917 -508

No files matched your search

+385 -351
View File
@@ -3,413 +3,447 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { TextDocument, Position, Range } from 'vscode-languageclient';
import { LanguageService, TokenType } from 'vscode-html-languageservice';
import { TextDocument } from "vscode-languageserver-textdocument";
import { Position, Range } from "vscode-languageclient";
import { LanguageService, TokenType } from "vscode-html-languageservice";
export interface LanguageRange extends Range {
languageId: string | undefined;
attributeValue?: boolean;
languageId: string | undefined;
attributeValue?: boolean;
}
export interface HTMLDocumentRegions {
getEmbeddedDocument(languageId: string, ignoreAttributeValues?: boolean): TextDocument;
getLanguageRanges(range: Range): LanguageRange[];
getLanguageAtPosition(position: Position): string | undefined;
getLanguagesInDocument(): string[];
getImportedScripts(): string[];
getEmbeddedDocument(
languageId: string,
ignoreAttributeValues?: boolean
): TextDocument;
getLanguageRanges(range: Range): LanguageRange[];
getLanguageAtPosition(position: Position): string | undefined;
getLanguagesInDocument(): string[];
getImportedScripts(): string[];
}
export const CSS_STYLE_RULE = '__';
export const CSS_STYLE_RULE = "__";
interface EmbeddedRegion {
languageId: string | undefined;
start: number;
end: number;
attributeValue?: boolean;
languageId: string | undefined;
start: number;
end: number;
attributeValue?: boolean;
}
// Check if the request is coming from inside a special region
export function isInsideStyleRegion(
languageService: LanguageService,
documentText: string,
offset: number
languageService: LanguageService,
documentText: string,
offset: number
) {
let scanner = languageService.createScanner(documentText);
let scanner = languageService.createScanner(documentText);
let token = scanner.scan();
while (token !== TokenType.EOS) {
switch (token) {
case TokenType.Styles:
if (offset >= scanner.getTokenOffset() && offset <= scanner.getTokenEnd()) {
return true;
}
}
token = scanner.scan();
}
return false;
let token = scanner.scan();
while (token !== TokenType.EOS) {
switch (token) {
case TokenType.Styles:
if (
offset >= scanner.getTokenOffset() &&
offset <= scanner.getTokenEnd()
) {
return true;
}
}
token = scanner.scan();
}
return false;
}
export function getCSSVirtualContent(
languageService: LanguageService,
documentText: string
languageService: LanguageService,
documentText: string
): string {
let regions: EmbeddedRegion[] = [];
let scanner = languageService.createScanner(documentText);
let lastTagName: string = '';
let lastAttributeName: string | null = null;
let languageIdFromType: string | undefined = undefined;
let importedScripts: string[] = [];
let regions: EmbeddedRegion[] = [];
let scanner = languageService.createScanner(documentText);
let lastTagName: string = "";
let lastAttributeName: string | null = null;
let languageIdFromType: string | undefined = undefined;
let importedScripts: string[] = [];
let token = scanner.scan();
while (token !== TokenType.EOS) {
switch (token) {
case TokenType.StartTag:
lastTagName = scanner.getTokenText();
lastAttributeName = null;
languageIdFromType = 'javascript';
break;
case TokenType.Styles:
regions.push({
languageId: 'css',
start: scanner.getTokenOffset(),
end: scanner.getTokenEnd()
});
break;
case TokenType.Script:
regions.push({
languageId: languageIdFromType,
start: scanner.getTokenOffset(),
end: scanner.getTokenEnd()
});
break;
case TokenType.AttributeName:
lastAttributeName = scanner.getTokenText();
break;
case TokenType.AttributeValue:
if (lastAttributeName === 'src' && lastTagName.toLowerCase() === 'script') {
let value = scanner.getTokenText();
if (value[0] === "'" || value[0] === '"') {
value = value.substr(1, value.length - 1);
}
importedScripts.push(value);
} else if (lastAttributeName === 'type' && lastTagName.toLowerCase() === 'script') {
if (
/["'](module|(text|application)\/(java|ecma)script|text\/babel)["']/.test(
scanner.getTokenText()
)
) {
languageIdFromType = 'javascript';
} else if (/["']text\/typescript["']/.test(scanner.getTokenText())) {
languageIdFromType = 'typescript';
} else {
languageIdFromType = undefined;
}
} else {
let attributeLanguageId = getAttributeLanguage(lastAttributeName!);
if (attributeLanguageId) {
let start = scanner.getTokenOffset();
let end = scanner.getTokenEnd();
let firstChar = documentText[start];
if (firstChar === "'" || firstChar === '"') {
start++;
end--;
}
regions.push({
languageId: attributeLanguageId,
start,
end,
attributeValue: true
});
}
}
lastAttributeName = null;
break;
}
token = scanner.scan();
}
let token = scanner.scan();
while (token !== TokenType.EOS) {
switch (token) {
case TokenType.StartTag:
lastTagName = scanner.getTokenText();
lastAttributeName = null;
languageIdFromType = "javascript";
break;
case TokenType.Styles:
regions.push({
languageId: "css",
start: scanner.getTokenOffset(),
end: scanner.getTokenEnd(),
});
break;
case TokenType.Script:
regions.push({
languageId: languageIdFromType,
start: scanner.getTokenOffset(),
end: scanner.getTokenEnd(),
});
break;
case TokenType.AttributeName:
lastAttributeName = scanner.getTokenText();
break;
case TokenType.AttributeValue:
if (
lastAttributeName === "src" &&
lastTagName.toLowerCase() === "script"
) {
let value = scanner.getTokenText();
if (value[0] === "'" || value[0] === '"') {
value = value.substr(1, value.length - 1);
}
importedScripts.push(value);
} else if (
lastAttributeName === "type" &&
lastTagName.toLowerCase() === "script"
) {
if (
/["'](module|(text|application)\/(java|ecma)script|text\/babel)["']/.test(
scanner.getTokenText()
)
) {
languageIdFromType = "javascript";
} else if (/["']text\/typescript["']/.test(scanner.getTokenText())) {
languageIdFromType = "typescript";
} else {
languageIdFromType = undefined;
}
} else {
let attributeLanguageId = getAttributeLanguage(lastAttributeName!);
if (attributeLanguageId) {
let start = scanner.getTokenOffset();
let end = scanner.getTokenEnd();
let firstChar = documentText[start];
if (firstChar === "'" || firstChar === '"') {
start++;
end--;
}
regions.push({
languageId: attributeLanguageId,
start,
end,
attributeValue: true,
});
}
}
lastAttributeName = null;
break;
}
token = scanner.scan();
}
let content = documentText
.split('\n')
.map(line => {
return ' '.repeat(line.length);
}).join('\n');
let content = documentText
.split("\n")
.map((line) => {
return " ".repeat(line.length);
})
.join("\n");
regions.forEach(r => {
if (r.languageId === 'css') {
content = content.slice(0, r.start) + documentText.slice(r.start, r.end) + content.slice(r.end);
}
});
regions.forEach((r) => {
if (r.languageId === "css") {
content =
content.slice(0, r.start) +
documentText.slice(r.start, r.end) +
content.slice(r.end);
}
});
return content;
return content;
}
export function getDocumentRegions(
languageService: LanguageService,
document: TextDocument
languageService: LanguageService,
document: TextDocument
): HTMLDocumentRegions {
let regions: EmbeddedRegion[] = [];
let scanner = languageService.createScanner(document.getText());
let lastTagName: string = '';
let lastAttributeName: string | null = null;
let languageIdFromType: string | undefined = undefined;
let importedScripts: string[] = [];
let regions: EmbeddedRegion[] = [];
let scanner = languageService.createScanner(document.getText());
let lastTagName: string = "";
let lastAttributeName: string | null = null;
let languageIdFromType: string | undefined = undefined;
let importedScripts: string[] = [];
let token = scanner.scan();
while (token !== TokenType.EOS) {
switch (token) {
case TokenType.StartTag:
lastTagName = scanner.getTokenText();
lastAttributeName = null;
languageIdFromType = 'javascript';
break;
case TokenType.Styles:
regions.push({
languageId: 'css',
start: scanner.getTokenOffset(),
end: scanner.getTokenEnd()
});
break;
case TokenType.Script:
regions.push({
languageId: languageIdFromType,
start: scanner.getTokenOffset(),
end: scanner.getTokenEnd()
});
break;
case TokenType.AttributeName:
lastAttributeName = scanner.getTokenText();
break;
case TokenType.AttributeValue:
if (lastAttributeName === 'src' && lastTagName.toLowerCase() === 'script') {
let value = scanner.getTokenText();
if (value[0] === "'" || value[0] === '"') {
value = value.substr(1, value.length - 1);
}
importedScripts.push(value);
} else if (lastAttributeName === 'type' && lastTagName.toLowerCase() === 'script') {
if (
/["'](module|(text|application)\/(java|ecma)script|text\/babel)["']/.test(
scanner.getTokenText()
)
) {
languageIdFromType = 'javascript';
} else if (/["']text\/typescript["']/.test(scanner.getTokenText())) {
languageIdFromType = 'typescript';
} else {
languageIdFromType = undefined;
}
} else {
let attributeLanguageId = getAttributeLanguage(lastAttributeName!);
if (attributeLanguageId) {
let start = scanner.getTokenOffset();
let end = scanner.getTokenEnd();
let firstChar = document.getText()[start];
if (firstChar === "'" || firstChar === '"') {
start++;
end--;
}
regions.push({
languageId: attributeLanguageId,
start,
end,
attributeValue: true
});
}
}
lastAttributeName = null;
break;
}
token = scanner.scan();
}
return {
getLanguageRanges: (range: Range) => getLanguageRanges(document, regions, range),
getEmbeddedDocument: (languageId: string, ignoreAttributeValues: boolean) =>
getEmbeddedDocument(document, regions, languageId, ignoreAttributeValues),
getLanguageAtPosition: (position: Position) =>
getLanguageAtPosition(document, regions, position),
getLanguagesInDocument: () => getLanguagesInDocument(document, regions),
getImportedScripts: () => importedScripts
};
let token = scanner.scan();
while (token !== TokenType.EOS) {
switch (token) {
case TokenType.StartTag:
lastTagName = scanner.getTokenText();
lastAttributeName = null;
languageIdFromType = "javascript";
break;
case TokenType.Styles:
regions.push({
languageId: "css",
start: scanner.getTokenOffset(),
end: scanner.getTokenEnd(),
});
break;
case TokenType.Script:
regions.push({
languageId: languageIdFromType,
start: scanner.getTokenOffset(),
end: scanner.getTokenEnd(),
});
break;
case TokenType.AttributeName:
lastAttributeName = scanner.getTokenText();
break;
case TokenType.AttributeValue:
if (
lastAttributeName === "src" &&
lastTagName.toLowerCase() === "script"
) {
let value = scanner.getTokenText();
if (value[0] === "'" || value[0] === '"') {
value = value.substr(1, value.length - 1);
}
importedScripts.push(value);
} else if (
lastAttributeName === "type" &&
lastTagName.toLowerCase() === "script"
) {
if (
/["'](module|(text|application)\/(java|ecma)script|text\/babel)["']/.test(
scanner.getTokenText()
)
) {
languageIdFromType = "javascript";
} else if (/["']text\/typescript["']/.test(scanner.getTokenText())) {
languageIdFromType = "typescript";
} else {
languageIdFromType = undefined;
}
} else {
let attributeLanguageId = getAttributeLanguage(lastAttributeName!);
if (attributeLanguageId) {
let start = scanner.getTokenOffset();
let end = scanner.getTokenEnd();
let firstChar = document.getText()[start];
if (firstChar === "'" || firstChar === '"') {
start++;
end--;
}
regions.push({
languageId: attributeLanguageId,
start,
end,
attributeValue: true,
});
}
}
lastAttributeName = null;
break;
}
token = scanner.scan();
}
return {
getLanguageRanges: (range: Range) =>
getLanguageRanges(document, regions, range),
getEmbeddedDocument: (languageId: string, ignoreAttributeValues: boolean) =>
getEmbeddedDocument(document, regions, languageId, ignoreAttributeValues),
getLanguageAtPosition: (position: Position) =>
getLanguageAtPosition(document, regions, position),
getLanguagesInDocument: () => getLanguagesInDocument(document, regions),
getImportedScripts: () => importedScripts,
};
}
function getLanguageRanges(
document: TextDocument,
regions: EmbeddedRegion[],
range: Range
document: TextDocument,
regions: EmbeddedRegion[],
range: Range
): LanguageRange[] {
let result: LanguageRange[] = [];
let currentPos = range ? range.start : Position.create(0, 0);
let currentOffset = range ? document.offsetAt(range.start) : 0;
let endOffset = range ? document.offsetAt(range.end) : document.getText().length;
for (let region of regions) {
if (region.end > currentOffset && region.start < endOffset) {
let start = Math.max(region.start, currentOffset);
let startPos = document.positionAt(start);
if (currentOffset < region.start) {
result.push({
start: currentPos,
end: startPos,
languageId: 'html'
});
}
let end = Math.min(region.end, endOffset);
let endPos = document.positionAt(end);
if (end > region.start) {
result.push({
start: startPos,
end: endPos,
languageId: region.languageId,
attributeValue: region.attributeValue
});
}
currentOffset = end;
currentPos = endPos;
}
}
if (currentOffset < endOffset) {
let endPos = range ? range.end : document.positionAt(endOffset);
result.push({
start: currentPos,
end: endPos,
languageId: 'html'
});
}
return result;
let result: LanguageRange[] = [];
let currentPos = range ? range.start : Position.create(0, 0);
let currentOffset = range ? document.offsetAt(range.start) : 0;
let endOffset = range
? document.offsetAt(range.end)
: document.getText().length;
for (let region of regions) {
if (region.end > currentOffset && region.start < endOffset) {
let start = Math.max(region.start, currentOffset);
let startPos = document.positionAt(start);
if (currentOffset < region.start) {
result.push({
start: currentPos,
end: startPos,
languageId: "html",
});
}
let end = Math.min(region.end, endOffset);
let endPos = document.positionAt(end);
if (end > region.start) {
result.push({
start: startPos,
end: endPos,
languageId: region.languageId,
attributeValue: region.attributeValue,
});
}
currentOffset = end;
currentPos = endPos;
}
}
if (currentOffset < endOffset) {
let endPos = range ? range.end : document.positionAt(endOffset);
result.push({
start: currentPos,
end: endPos,
languageId: "html",
});
}
return result;
}
function getLanguagesInDocument(
_document: TextDocument,
regions: EmbeddedRegion[]
_document: TextDocument,
regions: EmbeddedRegion[]
): string[] {
let result = [];
for (let region of regions) {
if (region.languageId && result.indexOf(region.languageId) === -1) {
result.push(region.languageId);
if (result.length === 3) {
return result;
}
}
}
result.push('html');
return result;
let result = [];
for (let region of regions) {
if (region.languageId && result.indexOf(region.languageId) === -1) {
result.push(region.languageId);
if (result.length === 3) {
return result;
}
}
}
result.push("html");
return result;
}
function getLanguageAtPosition(
document: TextDocument,
regions: EmbeddedRegion[],
position: Position
document: TextDocument,
regions: EmbeddedRegion[],
position: Position
): string | undefined {
let offset = document.offsetAt(position);
for (let region of regions) {
if (region.start <= offset) {
if (offset <= region.end) {
return region.languageId;
}
} else {
break;
}
}
return 'html';
let offset = document.offsetAt(position);
for (let region of regions) {
if (region.start <= offset) {
if (offset <= region.end) {
return region.languageId;
}
} else {
break;
}
}
return "html";
}
function getEmbeddedDocument(
document: TextDocument,
contents: EmbeddedRegion[],
languageId: string,
ignoreAttributeValues: boolean
document: TextDocument,
contents: EmbeddedRegion[],
languageId: string,
ignoreAttributeValues: boolean
): TextDocument {
let currentPos = 0;
let oldContent = document.getText();
let result = '';
let lastSuffix = '';
for (let c of contents) {
if (c.languageId === languageId && (!ignoreAttributeValues || !c.attributeValue)) {
result = substituteWithWhitespace(
result,
currentPos,
c.start,
oldContent,
lastSuffix,
getPrefix(c)
);
result += oldContent.substring(c.start, c.end);
currentPos = c.end;
lastSuffix = getSuffix(c);
}
}
result = substituteWithWhitespace(
result,
currentPos,
oldContent.length,
oldContent,
lastSuffix,
''
);
return TextDocument.create(document.uri, languageId, document.version, result);
let currentPos = 0;
let oldContent = document.getText();
let result = "";
let lastSuffix = "";
for (let c of contents) {
if (
c.languageId === languageId &&
(!ignoreAttributeValues || !c.attributeValue)
) {
result = substituteWithWhitespace(
result,
currentPos,
c.start,
oldContent,
lastSuffix,
getPrefix(c)
);
result += oldContent.substring(c.start, c.end);
currentPos = c.end;
lastSuffix = getSuffix(c);
}
}
result = substituteWithWhitespace(
result,
currentPos,
oldContent.length,
oldContent,
lastSuffix,
""
);
return TextDocument.create(
document.uri,
languageId,
document.version,
result
);
}
function getPrefix(c: EmbeddedRegion) {
if (c.attributeValue) {
switch (c.languageId) {
case 'css':
return CSS_STYLE_RULE + '{';
}
}
return '';
if (c.attributeValue) {
switch (c.languageId) {
case "css":
return CSS_STYLE_RULE + "{";
}
}
return "";
}
function getSuffix(c: EmbeddedRegion) {
if (c.attributeValue) {
switch (c.languageId) {
case 'css':
return '}';
case 'javascript':
return ';';
}
}
return '';
if (c.attributeValue) {
switch (c.languageId) {
case "css":
return "}";
case "javascript":
return ";";
}
}
return "";
}
function substituteWithWhitespace(
result: string,
start: number,
end: number,
oldContent: string,
before: string,
after: string
result: string,
start: number,
end: number,
oldContent: string,
before: string,
after: string
) {
let accumulatedWS = 0;
result += before;
for (let i = start + before.length; i < end; i++) {
let ch = oldContent[i];
if (ch === '\n' || ch === '\r') {
// only write new lines, skip the whitespace
accumulatedWS = 0;
result += ch;
} else {
accumulatedWS++;
}
}
result = append(result, ' ', accumulatedWS - after.length);
result += after;
return result;
let accumulatedWS = 0;
result += before;
for (let i = start + before.length; i < end; i++) {
let ch = oldContent[i];
if (ch === "\n" || ch === "\r") {
// only write new lines, skip the whitespace
accumulatedWS = 0;
result += ch;
} else {
accumulatedWS++;
}
}
result = append(result, " ", accumulatedWS - after.length);
result += after;
return result;
}
function append(result: string, str: string, n: number): string {
while (n > 0) {
if (n & 1) {
result += str;
}
n >>= 1;
str += str;
}
return result;
while (n > 0) {
if (n & 1) {
result += str;
}
n >>= 1;
str += str;
}
return result;
}
function getAttributeLanguage(attributeName: string): string | null {
let match = attributeName.match(/^(style)$|^(on\w+)$/i);
if (!match) {
return null;
}
return match[1] ? 'css' : 'javascript';
let match = attributeName.match(/^(style)$|^(on\w+)$/i);
if (!match) {
return null;
}
return match[1] ? "css" : "javascript";
}
+124 -64
View File
@@ -3,85 +3,145 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
* ------------------------------------------------------------------------------------------ */
import * as path from 'path';
import { commands, CompletionList, ExtensionContext, Uri, workspace } from 'vscode';
import { getLanguageService } from 'vscode-html-languageservice';
import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind } from 'vscode-languageclient';
import { getCSSVirtualContent, isInsideStyleRegion } from './embeddedSupport';
import * as path from "path";
import {
commands,
CompletionList,
ExtensionContext,
Uri,
workspace,
} from "vscode";
import { getLanguageService } from "vscode-html-languageservice";
import {
LanguageClient,
LanguageClientOptions,
ServerOptions,
TransportKind,
} from "vscode-languageclient";
import { isInsideHtmlMacro } from "./rustSupport";
// import { getCSSVirtualContent, isInsideStyleRegion } from "./embeddedSupport";
let client: LanguageClient;
const htmlLanguageService = getLanguageService();
export function activate(context: ExtensionContext) {
// The server is implemented in node
let serverModule = context.asAbsolutePath(path.join('server', 'out', 'server.js'));
// The debug options for the server
// --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging
let debugOptions = { execArgv: ['--nolazy', '--inspect=6009'] };
// The server is implemented in node
let serverModule = context.asAbsolutePath(
path.join("server", "out", "server.js")
);
// The debug options for the server
// --inspect=6009: runs the server in Node's Inspector mode so VS Code can attach to the server for debugging
let debugOptions = { execArgv: ["--nolazy", "--inspect=6009"] };
// If the extension is launched in debug mode then the debug server options are used
// Otherwise the run options are used
let serverOptions: ServerOptions = {
run: { module: serverModule, transport: TransportKind.ipc },
debug: {
module: serverModule,
transport: TransportKind.ipc,
options: debugOptions
}
};
// If the extension is launched in debug mode then the debug server options are used
// Otherwise the run options are used
let serverOptions: ServerOptions = {
run: { module: serverModule, transport: TransportKind.ipc },
debug: {
module: serverModule,
transport: TransportKind.ipc,
options: debugOptions,
},
};
const virtualDocumentContents = new Map<string, string>();
const virtualDocumentContents = new Map<string, string>();
workspace.registerTextDocumentContentProvider('embedded-content', {
provideTextDocumentContent: uri => {
const originalUri = uri.path.slice(1).slice(0, -4);
const decodedUri = decodeURIComponent(originalUri);
return virtualDocumentContents.get(decodedUri);
}
});
workspace.registerTextDocumentContentProvider("embedded-content", {
provideTextDocumentContent: (uri) => {
const originalUri = uri.path.slice(1).slice(0, -4);
console.error(originalUri);
const decodedUri = decodeURIComponent(originalUri);
return virtualDocumentContents.get(decodedUri);
},
});
let clientOptions: LanguageClientOptions = {
documentSelector: [{ scheme: 'file', language: 'html1' }],
middleware: {
provideCompletionItem: async (document, position, context, token, next) => {
// If not in `<style>`, do not perform request forwarding
if (!isInsideStyleRegion(htmlLanguageService, document.getText(), document.offsetAt(position))) {
return await next(document, position, context, token);
}
let clientOptions: LanguageClientOptions = {
documentSelector: [{ scheme: "file", language: "rust" }],
middleware: {
provideCompletionItem: async (
document,
position,
context,
token,
next
) => {
/*
1: Find the occurences of the html! macro using regex
2: Check if any of the occurences match the cursor offset
3: If so, direct the captured block to the html to the rsx language service
*/
const docSrc = document.getText();
const offset = document.offsetAt(position);
const matches = docSrc.matchAll(macroRegex);
const originalUri = document.uri.toString();
virtualDocumentContents.set(originalUri, getCSSVirtualContent(htmlLanguageService, document.getText()));
// Lazily loop through matches, abort early if the cursor is after the match
// let start = 0;
// let end = 0;
let matchBody: string | undefined = undefined;
const vdocUriString = `embedded-content://css/${encodeURIComponent(
originalUri
)}.css`;
const vdocUri = Uri.parse(vdocUriString);
return await commands.executeCommand<CompletionList>(
'vscode.executeCompletionItemProvider',
vdocUri,
position,
context.triggerCharacter
);
}
}
};
for (const match of matches) {
// // Check if the cursor is inbetween the previous end and the new start
// // This means the cursor is between html! invocations and we should bail early
// if (offset > end && offset < match.index) {
// // Ensure the match
// // defer to the "next?" symbol
// return await next(document, position, context, token);
// }
// Create the language client and start the client.
client = new LanguageClient(
'languageServerExample',
'Language Server Example',
serverOptions,
clientOptions
);
// Otherwise, move the counters forward
const start = match.index;
const end = start + match.length;
// Start the client. This will also launch the server
client.start();
// Ensure the cursor is within the match
// Break if so
if (offset >= start && offset <= end) {
matchBody = match[1];
break;
}
}
// If we looped through all the matches and the match wasn't defined, then bail
if (matchBody === undefined) {
return await next(document, position, context, token);
}
// If we're inside the style region, then provide CSS completions with the CSS provider
const originalUri = document.uri.toString();
virtualDocumentContents.set(originalUri, matchBody);
// getCSSVirtualContent(htmlLanguageService, document.getText())
const vdocUriString = `embedded-content://html/${encodeURIComponent(
originalUri
)}.html`;
const vdocUri = Uri.parse(vdocUriString);
return await commands.executeCommand<CompletionList>(
"vscode.executeCompletionItemProvider",
vdocUri,
position,
context.triggerCharacter
);
},
},
};
// Create the language client and start the client.
client = new LanguageClient(
"languageServerExample",
"Language Server Example",
serverOptions,
clientOptions
);
// Start the client. This will also launch the server
client.start();
}
export function deactivate(): Thenable<void> | undefined {
if (!client) {
return undefined;
}
return client.stop();
if (!client) {
return undefined;
}
return client.stop();
}
const macroRegex = /html! {([\s\S]*?)}/g;
@@ -0,0 +1,8 @@
const macroRegex = /html! {([\s\S]*?)}/g;
export function isInsideHtmlMacro(
match: RegExpMatchArray,
cursor: number
): boolean {
return false;
}