Updates dockerfile
All checks were successful
Build and Push / build (push) Successful in 55s

This commit is contained in:
2026-02-16 15:09:37 -05:00
parent 8346776f2a
commit d181f77fb2
14943 changed files with 2078509 additions and 16 deletions

21
node_modules/volar-service-emmet/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022-present Johnson Chu
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

25
node_modules/volar-service-emmet/README.md generated vendored Normal file
View File

@@ -0,0 +1,25 @@
# volar-service-emmet
Volar plugin for [`@vscode/emmet-helper`](https://github.com/microsoft/vscode-emmet-helper).
## Installation
```sh
npm install volar-service-emmet
```
## Usage
`volar.config.js`
```js
module.exports = {
services: [
require('volar-service-emmet').create(),
],
};
```
## License
[MIT](LICENSE) © [Johnson Chu](https://github.com/johnsoncodehk)

3
node_modules/volar-service-emmet/empty.d.ts generated vendored Normal file
View File

@@ -0,0 +1,3 @@
import type { LanguageServicePlugin } from '@volar/language-service';
export declare function create(): LanguageServicePlugin;
//# sourceMappingURL=empty.d.ts.map

14
node_modules/volar-service-emmet/empty.js generated vendored Normal file
View File

@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.create = create;
console.warn('[volar-service-emmet] this module is not yet supported for web.');
function create() {
return {
name: 'emmet (stub)',
capabilities: {},
create() {
return {};
},
};
}
//# sourceMappingURL=empty.js.map

5
node_modules/volar-service-emmet/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,5 @@
import type * as vscode from '@volar/language-service';
export declare function create({ mappedLanguages, }?: {
mappedLanguages?: Record<string, string>;
}): vscode.LanguageServicePlugin;
//# sourceMappingURL=index.d.ts.map

196
node_modules/volar-service-emmet/index.js generated vendored Normal file
View File

@@ -0,0 +1,196 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.create = create;
const vscode_uri_1 = require("vscode-uri");
const abbreviationActions_1 = require("./lib/abbreviationActions");
const parseDocument_1 = require("./lib/parseDocument");
const util_1 = require("./lib/util");
function create({ mappedLanguages = {}, } = {}) {
return {
name: 'emmet',
capabilities: {
completionProvider: {
// https://docs.emmet.io/abbreviations/syntax/
triggerCharacters: '>+^*()#.[]$@-{}'.split(''),
},
},
create(context) {
let lastCompletionType;
return {
isAdditionalCompletion: true,
provideCompletionItems(document, position, completionContext) {
const completionResult = provideCompletionItemsInternal(document, position, completionContext);
if (!completionResult) {
lastCompletionType = undefined;
return;
}
return completionResult.then(completionList => {
if (!completionList || !completionList.items.length) {
lastCompletionType = undefined;
return completionList;
}
const item = completionList.items[0];
const expandedText = item.documentation ? item.documentation.toString() : '';
if (expandedText.startsWith('<')) {
lastCompletionType = 'html';
}
else if (expandedText.indexOf(':') > 0 && expandedText.endsWith(';')) {
lastCompletionType = 'css';
}
else {
lastCompletionType = undefined;
}
return completionList;
});
},
};
async function provideCompletionItemsInternal(document, position, completionContext) {
const emmetConfig = await context.env.getConfiguration?.('emmet') ?? {};
const excludedLanguages = emmetConfig['excludeLanguages'] ?? [];
if (excludedLanguages.includes(document.languageId)) {
return;
}
const isSyntaxMapped = mappedLanguages[document.languageId] ? true : false;
const emmetMode = (0, util_1.getEmmetMode)(mappedLanguages[document.languageId] ?? document.languageId, mappedLanguages, excludedLanguages);
if (!emmetMode
|| emmetConfig['showExpandedAbbreviation'] === 'never'
|| ((isSyntaxMapped || emmetMode === 'jsx') && emmetConfig['showExpandedAbbreviation'] !== 'always')) {
return;
}
let syntax = emmetMode;
let validateLocation = syntax === 'html' || syntax === 'jsx' || syntax === 'xml';
let rootNode;
let currentNode;
// Don't show completions if there's a comment at the beginning of the line
const lineRange = {
start: { line: position.line, character: 0 },
end: position,
};
if (document.getText(lineRange).trimStart().startsWith('//')) {
return;
}
const helper = (0, util_1.getEmmetHelper)();
if (syntax === 'html') {
if (completionContext.triggerKind === 3) {
switch (lastCompletionType) {
case 'html':
validateLocation = false;
break;
case 'css':
validateLocation = false;
syntax = 'css';
break;
default:
break;
}
}
if (validateLocation) {
const positionOffset = document.offsetAt(position);
const emmetRootNode = (0, parseDocument_1.getRootNode)(document, true);
const foundNode = (0, util_1.getHtmlFlatNode)(document.getText(), emmetRootNode, positionOffset, false);
if (foundNode) {
if (foundNode.name === 'script') {
const typeNode = foundNode.attributes.find(attr => attr.name.toString() === 'type');
if (typeNode) {
const typeAttrValue = typeNode.value.toString();
if (typeAttrValue === 'application/javascript' || typeAttrValue === 'text/javascript') {
if (!await (0, abbreviationActions_1.getSyntaxFromArgs)(context, { language: 'javascript' })) {
return;
}
else {
validateLocation = false;
}
}
else if (util_1.allowedMimeTypesInScriptTag.includes(typeAttrValue)) {
validateLocation = false;
}
}
else {
return;
}
}
else if (foundNode.name === 'style') {
syntax = 'css';
validateLocation = false;
}
else {
const styleNode = foundNode.attributes.find(attr => attr.name.toString() === 'style');
if (styleNode && styleNode.value.start <= positionOffset && positionOffset <= styleNode.value.end) {
syntax = 'css';
validateLocation = false;
}
}
}
}
}
const expandOptions = (0, util_1.isStyleSheet)(syntax) ?
{ lookAhead: false, syntax: 'stylesheet' } :
{ lookAhead: true, syntax: 'markup' };
const extractAbbreviationResults = helper.extractAbbreviation(document, position, expandOptions);
if (!extractAbbreviationResults || !helper.isAbbreviationValid(syntax, extractAbbreviationResults.abbreviation)) {
return;
}
const offset = document.offsetAt(position);
if ((0, util_1.isStyleSheet)(document.languageId) && completionContext.triggerKind !== 3) {
validateLocation = true;
const usePartialParsing = await context.env.getConfiguration?.('emmet.optimizeStylesheetParsing') === true;
rootNode = usePartialParsing && document.lineCount > 1000 ? (0, util_1.parsePartialStylesheet)(document, position) : (0, parseDocument_1.getRootNode)(document, true);
if (!rootNode) {
return;
}
currentNode = (0, util_1.getFlatNode)(rootNode, offset, true);
}
// Fix for https://github.com/microsoft/vscode/issues/107578
// Validate location if syntax is of styleSheet type to ensure that location is valid for emmet abbreviation.
// For an html document containing a <style> node, compute the embeddedCssNode and fetch the flattened node as currentNode.
if (!(0, util_1.isStyleSheet)(document.languageId) && (0, util_1.isStyleSheet)(syntax) && completionContext.triggerKind !== 3) {
validateLocation = true;
rootNode = (0, parseDocument_1.getRootNode)(document, true);
if (!rootNode) {
return;
}
const flatNode = (0, util_1.getFlatNode)(rootNode, offset, true);
const embeddedCssNode = (0, util_1.getEmbeddedCssNodeIfAny)(document, flatNode, position);
currentNode = (0, util_1.getFlatNode)(embeddedCssNode, offset, true);
}
if (validateLocation && !await (0, abbreviationActions_1.isValidLocationForEmmetAbbreviation)(context, document, rootNode, currentNode, syntax, offset, extractAbbreviationResults.abbreviationRange)) {
return;
}
let isNoisePromise = Promise.resolve(false);
// Fix for https://github.com/microsoft/vscode/issues/32647
// Check for document symbols in js/ts/jsx/tsx and avoid triggering emmet for abbreviations of the form symbolName.sometext
// Presence of > or * or + in the abbreviation denotes valid abbreviation that should trigger emmet
if (!(0, util_1.isStyleSheet)(syntax) && (document.languageId === 'javascript' || document.languageId === 'javascriptreact' || document.languageId === 'typescript' || document.languageId === 'typescriptreact')) {
const abbreviation = extractAbbreviationResults.abbreviation;
// For the second condition, we don't want abbreviations that have [] characters but not ='s in them to expand
// In turn, users must explicitly expand abbreviations of the form Component[attr1 attr2], but it means we don't try to expand a[i].
if (abbreviation.startsWith('this.') || /\[[^\]=]*\]/.test(abbreviation)) {
isNoisePromise = Promise.resolve(true);
}
else {
const uri = vscode_uri_1.URI.parse(document.uri);
const documentUri = context.decodeEmbeddedDocumentUri(uri)?.[0] ?? uri;
isNoisePromise = context.getLanguageService().getDocumentSymbols(documentUri).then(symbols => {
return !!symbols && symbols.some(x => abbreviation === x.name || (abbreviation.startsWith(x.name + '.') && !/>|\*|\+/.test(abbreviation)));
});
}
}
return isNoisePromise.then(async (isNoise) => {
if (isNoise) {
return undefined;
}
const config = await (0, util_1.getEmmetConfiguration)(context, syntax);
const result = helper.doComplete(document, position, syntax, config);
// https://github.com/microsoft/vscode/issues/86941
if (result && result.items && result.items.length === 1) {
if (result.items[0].label === 'widows: ;') {
return undefined;
}
}
return result;
});
}
},
};
}
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1,17 @@
import type * as vscode from '@volar/language-service';
import type { Node } from 'EmmetFlatNode';
/**
* Checks if given position is a valid location to expand emmet abbreviation.
* Works only on html and css/less/scss syntax
* @param document current Text Document
* @param rootNode parsed document
* @param currentNode current node in the parsed document
* @param syntax syntax of the abbreviation
* @param position position to validate
* @param abbreviationRange The range of the abbreviation for which given position is being validated
*/
export declare function isValidLocationForEmmetAbbreviation(context: vscode.LanguageServiceContext, document: vscode.TextDocument, rootNode: Node | undefined, currentNode: Node | undefined, syntax: string, offset: number, abbreviationRange: vscode.Range): Promise<boolean>;
export declare function getSyntaxFromArgs(context: vscode.LanguageServiceContext, args: {
[x: string]: string;
}): Promise<string | undefined>;
//# sourceMappingURL=abbreviationActions.d.ts.map

View File

@@ -0,0 +1,199 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.isValidLocationForEmmetAbbreviation = isValidLocationForEmmetAbbreviation;
exports.getSyntaxFromArgs = getSyntaxFromArgs;
const util_1 = require("./util");
const hexColorRegex = /^#[\da-fA-F]{0,6}$/;
/**
* Checks if given position is a valid location to expand emmet abbreviation.
* Works only on html and css/less/scss syntax
* @param document current Text Document
* @param rootNode parsed document
* @param currentNode current node in the parsed document
* @param syntax syntax of the abbreviation
* @param position position to validate
* @param abbreviationRange The range of the abbreviation for which given position is being validated
*/
async function isValidLocationForEmmetAbbreviation(context, document, rootNode, currentNode, syntax, offset, abbreviationRange) {
if ((0, util_1.isStyleSheet)(syntax)) {
const stylesheet = rootNode;
if (stylesheet && (stylesheet.comments || []).some(x => offset >= x.start && offset <= x.end)) {
return false;
}
// Continue validation only if the file was parse-able and the currentNode has been found
if (!currentNode) {
return true;
}
// Get the abbreviation right now
// Fixes https://github.com/microsoft/vscode/issues/74505
// Stylesheet abbreviations starting with @ should bring up suggestions
// even at outer-most level
const abbreviation = document.getText(abbreviationRange);
if (abbreviation.startsWith('@')) {
return true;
}
// Fix for https://github.com/microsoft/vscode/issues/34162
// Other than sass, stylus, we can make use of the terminator tokens to validate position
if (syntax !== 'sass' && syntax !== 'stylus' && currentNode.type === 'property') {
// Fix for upstream issue https://github.com/emmetio/css-parser/issues/3
if (currentNode.parent
&& currentNode.parent.type !== 'rule'
&& currentNode.parent.type !== 'at-rule') {
return false;
}
const propertyNode = currentNode;
if (propertyNode.terminatorToken
&& propertyNode.separator
&& offset >= propertyNode.separatorToken.end
&& offset <= propertyNode.terminatorToken.start
&& !abbreviation.includes(':')) {
return hexColorRegex.test(abbreviation) || abbreviation === '!';
}
if (!propertyNode.terminatorToken
&& propertyNode.separator
&& offset >= propertyNode.separatorToken.end
&& !abbreviation.includes(':')) {
return hexColorRegex.test(abbreviation) || abbreviation === '!';
}
if (hexColorRegex.test(abbreviation) || abbreviation === '!') {
return false;
}
}
// If current node is a rule or at-rule, then perform additional checks to ensure
// emmet suggestions are not provided in the rule selector
if (currentNode.type !== 'rule' && currentNode.type !== 'at-rule') {
return true;
}
const currentCssNode = currentNode;
// Position is valid if it occurs after the `{` that marks beginning of rule contents
if (offset > currentCssNode.contentStartToken.end) {
return true;
}
// Workaround for https://github.com/microsoft/vscode/30188
// The line above the rule selector is considered as part of the selector by the css-parser
// But we should assume it is a valid location for css properties under the parent rule
if (currentCssNode.parent
&& (currentCssNode.parent.type === 'rule' || currentCssNode.parent.type === 'at-rule')
&& currentCssNode.selectorToken) {
const position = document.positionAt(offset);
const tokenStartPos = document.positionAt(currentCssNode.selectorToken.start);
const tokenEndPos = document.positionAt(currentCssNode.selectorToken.end);
if (position.line !== tokenEndPos.line
&& tokenStartPos.character === abbreviationRange.start.character
&& tokenStartPos.line === abbreviationRange.start.line) {
return true;
}
}
return false;
}
const startAngle = '<';
const endAngle = '>';
const escape = '\\';
const question = '?';
const currentHtmlNode = currentNode;
let start = 0;
if (currentHtmlNode) {
if (currentHtmlNode.name === 'script') {
const typeAttribute = (currentHtmlNode.attributes || []).filter(x => x.name.toString() === 'type')[0];
const typeValue = typeAttribute ? typeAttribute.value.toString() : '';
if (util_1.allowedMimeTypesInScriptTag.includes(typeValue)) {
return true;
}
const isScriptJavascriptType = !typeValue || typeValue === 'application/javascript' || typeValue === 'text/javascript';
if (isScriptJavascriptType) {
return !!await getSyntaxFromArgs(context, { language: 'javascript' });
}
return false;
}
// Fix for https://github.com/microsoft/vscode/issues/28829
if (!currentHtmlNode.open || !currentHtmlNode.close ||
!(currentHtmlNode.open.end <= offset && offset <= currentHtmlNode.close.start)) {
return false;
}
// Fix for https://github.com/microsoft/vscode/issues/35128
// Find the position up till where we will backtrack looking for unescaped < or >
// to decide if current position is valid for emmet expansion
start = currentHtmlNode.open.end;
let lastChildBeforePosition = currentHtmlNode.firstChild;
while (lastChildBeforePosition) {
if (lastChildBeforePosition.end > offset) {
break;
}
start = lastChildBeforePosition.end;
lastChildBeforePosition = lastChildBeforePosition.nextSibling;
}
}
const startPos = document.positionAt(start);
let textToBackTrack = document.getText({ start: startPos, end: abbreviationRange.start });
// Worse case scenario is when cursor is inside a big chunk of text which needs to backtracked
// Backtrack only 500 offsets to ensure we dont waste time doing this
if (textToBackTrack.length > 500) {
textToBackTrack = textToBackTrack.substr(textToBackTrack.length - 500);
}
if (!textToBackTrack.trim()) {
return true;
}
let valid = true;
let foundSpace = false; // If < is found before finding whitespace, then its valid abbreviation. E.g.: <div|
let i = textToBackTrack.length - 1;
if (textToBackTrack[i] === startAngle) {
return false;
}
while (i >= 0) {
const char = textToBackTrack[i];
i--;
if (!foundSpace && /\s/.test(char)) {
foundSpace = true;
continue;
}
if (char === question && textToBackTrack[i] === startAngle) {
i--;
continue;
}
// Fix for https://github.com/microsoft/vscode/issues/55411
// A space is not a valid character right after < in a tag name.
if (/\s/.test(char) && textToBackTrack[i] === startAngle) {
i--;
continue;
}
if (char !== startAngle && char !== endAngle) {
continue;
}
if (i >= 0 && textToBackTrack[i] === escape) {
i--;
continue;
}
if (char === endAngle) {
if (i >= 0 && textToBackTrack[i] === '=') {
continue; // False alarm of cases like =>
}
else {
break;
}
}
if (char === startAngle) {
valid = !foundSpace;
break;
}
}
return valid;
}
async function getSyntaxFromArgs(context, args) {
const mappedModes = await (0, util_1.getMappingForIncludedLanguages)(context);
const language = args['language'];
const parentMode = args['parentMode'];
const excludedLanguages = await context.env.getConfiguration?.('emmet.excludeLanguages') ?? [];
if (excludedLanguages.includes(language)) {
return;
}
let syntax = (0, util_1.getEmmetMode)(mappedModes[language] ?? language, mappedModes, excludedLanguages);
if (!syntax) {
syntax = (0, util_1.getEmmetMode)(mappedModes[parentMode] ?? parentMode, mappedModes, excludedLanguages);
}
return syntax;
}
//# sourceMappingURL=abbreviationActions.js.map

66
node_modules/volar-service-emmet/lib/bufferStream.d.ts generated vendored Normal file
View File

@@ -0,0 +1,66 @@
import type { TextDocument } from '@volar/language-service';
/**
* A stream reader for VSCode's `TextDocument`
* Based on @emmetio/stream-reader and @emmetio/atom-plugin
*/
export declare class DocumentStreamReader {
private document;
private start;
private _eof;
private _sof;
pos: number;
constructor(document: TextDocument, pos?: number, limit?: [number, number]);
/**
* Returns true only if the stream is at the start of the file.
*/
sof(): boolean;
/**
* Returns true only if the stream is at the end of the file.
*/
eof(): boolean;
/**
* Creates a new stream instance which is limited to given range for given document
*/
limit(start: number, end: number): DocumentStreamReader;
/**
* Returns the next character code in the stream without advancing it.
* Will return NaN at the end of the file.
*/
peek(): number;
/**
* Returns the next character in the stream and advances it.
* Also returns NaN when no more characters are available.
*/
next(): number;
/**
* Backs up the stream n characters. Backing it up further than the
* start of the current token will cause things to break, so be careful.
*/
backUp(n: number): number;
/**
* Get the string between the start of the current token and the
* current stream position.
*/
current(): string;
/**
* Returns contents for given range
*/
substring(from: number, to: number): string;
/**
* Creates error object with current stream state
*/
error(message: string): Error;
/**
* `match` can be a character code or a function that takes a character code
* and returns a boolean. If the next character in the stream 'matches'
* the given argument, it is consumed and returned.
* Otherwise, `false` is returned.
*/
eat(match: number | Function): boolean;
/**
* Repeatedly calls <code>eat</code> with the given argument, until it
* fails. Returns <code>true</code> if any characters were eaten.
*/
eatWhile(match: number | Function): boolean;
}
//# sourceMappingURL=bufferStream.d.ts.map

119
node_modules/volar-service-emmet/lib/bufferStream.js generated vendored Normal file
View File

@@ -0,0 +1,119 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.DocumentStreamReader = void 0;
/**
* A stream reader for VSCode's `TextDocument`
* Based on @emmetio/stream-reader and @emmetio/atom-plugin
*/
class DocumentStreamReader {
constructor(document, pos, limit) {
this.document = document;
this.start = this.pos = pos ? pos : 0;
this._sof = limit ? limit[0] : 0;
this._eof = limit ? limit[1] : document.getText().length;
}
/**
* Returns true only if the stream is at the start of the file.
*/
sof() {
return this.pos <= this._sof;
}
/**
* Returns true only if the stream is at the end of the file.
*/
eof() {
return this.pos >= this._eof;
}
/**
* Creates a new stream instance which is limited to given range for given document
*/
limit(start, end) {
return new DocumentStreamReader(this.document, start, [start, end]);
}
/**
* Returns the next character code in the stream without advancing it.
* Will return NaN at the end of the file.
*/
peek() {
if (this.eof()) {
return NaN;
}
return this.document.getText().charCodeAt(this.pos);
}
/**
* Returns the next character in the stream and advances it.
* Also returns NaN when no more characters are available.
*/
next() {
if (this.eof()) {
return NaN;
}
const code = this.document.getText().charCodeAt(this.pos);
this.pos++;
if (this.eof()) {
// restrict pos to eof, if in case it got moved beyond eof
this.pos = this._eof;
}
return code;
}
/**
* Backs up the stream n characters. Backing it up further than the
* start of the current token will cause things to break, so be careful.
*/
backUp(n) {
this.pos -= n;
if (this.pos < 0) {
this.pos = 0;
}
return this.peek();
}
/**
* Get the string between the start of the current token and the
* current stream position.
*/
current() {
return this.substring(this.start, this.pos);
}
/**
* Returns contents for given range
*/
substring(from, to) {
return this.document.getText().substring(from, to);
}
/**
* Creates error object with current stream state
*/
error(message) {
const err = new Error(`${message} at offset ${this.pos}`);
return err;
}
/**
* `match` can be a character code or a function that takes a character code
* and returns a boolean. If the next character in the stream 'matches'
* the given argument, it is consumed and returned.
* Otherwise, `false` is returned.
*/
eat(match) {
const ch = this.peek();
const ok = typeof match === 'function' ? match(ch) : ch === match;
if (ok) {
this.next();
}
return ok;
}
/**
* Repeatedly calls <code>eat</code> with the given argument, until it
* fails. Returns <code>true</code> if any characters were eaten.
*/
eatWhile(match) {
const start = this.pos;
while (!this.eof() && this.eat(match)) { }
return this.pos !== start;
}
}
exports.DocumentStreamReader = DocumentStreamReader;
//# sourceMappingURL=bufferStream.js.map

View File

@@ -0,0 +1,4 @@
import type { TextDocument } from '@volar/language-service';
import type { Node as FlatNode } from 'EmmetFlatNode';
export declare function getRootNode(document: TextDocument, useCache: boolean): FlatNode;
//# sourceMappingURL=parseDocument.d.ts.map

29
node_modules/volar-service-emmet/lib/parseDocument.js generated vendored Normal file
View File

@@ -0,0 +1,29 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.getRootNode = getRootNode;
const html_matcher_1 = require("@emmetio/html-matcher");
const css_parser_1 = require("@emmetio/css-parser");
const util_1 = require("./util");
// Map(filename, Pair(fileVersion, rootNodeOfParsedContent))
const _parseCache = new Map();
function getRootNode(document, useCache) {
const key = document.uri.toString();
const result = _parseCache.get(key);
const documentVersion = document.version;
if (useCache && result) {
if (documentVersion === result.key) {
return result.value;
}
}
const parseContent = (0, util_1.isStyleSheet)(document.languageId) ? css_parser_1.default : html_matcher_1.default;
const rootNode = parseContent(document.getText());
if (useCache) {
_parseCache.set(key, { key: documentVersion, value: rootNode });
}
return rootNode;
}
//# sourceMappingURL=parseDocument.js.map

View File

@@ -0,0 +1,89 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
declare module 'EmmetFlatNode' {
export interface Node {
start: number;
end: number;
type: string;
parent: Node | undefined;
firstChild: Node | undefined;
nextSibling: Node | undefined;
previousSibling: Node | undefined;
children: Node[];
}
export interface Token {
start: number;
end: number;
stream: BufferStream;
toString(): string;
}
export interface CssToken extends Token {
size: number;
item(number: number): any;
type: string;
}
export interface HtmlToken extends Token {
value: string;
}
export interface Attribute extends Token {
name: Token;
value: Token;
}
export interface HtmlNode extends Node {
name: string;
open: Token | undefined;
close: Token | undefined;
parent: HtmlNode | undefined;
firstChild: HtmlNode | undefined;
nextSibling: HtmlNode | undefined;
previousSibling: HtmlNode | undefined;
children: HtmlNode[];
attributes: Attribute[];
}
export interface CssNode extends Node {
name: string;
parent: CssNode | undefined;
firstChild: CssNode | undefined;
nextSibling: CssNode | undefined;
previousSibling: CssNode | undefined;
children: CssNode[];
}
export interface Rule extends CssNode {
selectorToken: Token;
contentStartToken: Token;
contentEndToken: Token;
}
export interface Property extends CssNode {
valueToken: Token;
separator: string;
parent: Rule;
terminatorToken: Token;
separatorToken: Token;
value: string;
}
export interface Stylesheet extends Node {
comments: Token[];
}
export interface BufferStream {
peek(): number;
next(): number;
backUp(n: number): number;
current(): string;
substring(from: number, to: number): string;
eat(match: any): boolean;
eatWhile(match: any): boolean;
}
}

View File

@@ -0,0 +1,91 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
declare module 'EmmetNode' {
import { Position } from 'vscode';
export interface Node {
start: Position;
end: Position;
type: string;
parent: Node;
firstChild: Node;
nextSibling: Node;
previousSibling: Node;
children: Node[];
}
export interface Token {
start: Position;
end: Position;
stream: BufferStream;
toString(): string;
}
export interface CssToken extends Token {
size: number;
item(number: number): any;
type: string;
}
export interface HtmlToken extends Token {
value: string;
}
export interface Attribute extends Token {
name: Token;
value: Token;
}
export interface HtmlNode extends Node {
name: string;
open: Token;
close: Token;
parent: HtmlNode;
firstChild: HtmlNode;
nextSibling: HtmlNode;
previousSibling: HtmlNode;
children: HtmlNode[];
attributes: Attribute[];
}
export interface CssNode extends Node {
name: string;
parent: CssNode;
firstChild: CssNode;
nextSibling: CssNode;
previousSibling: CssNode;
children: CssNode[];
}
export interface Rule extends CssNode {
selectorToken: Token;
contentStartToken: Token;
contentEndToken: Token;
}
export interface Property extends CssNode {
valueToken: Token;
separator: string;
parent: Rule;
terminatorToken: Token;
separatorToken: Token;
value: string;
}
export interface Stylesheet extends Node {
comments: Token[];
}
export interface BufferStream {
peek(): number;
next(): number;
backUp(n: number): number;
current(): string;
substring(from: Position, to: Position): string;
eat(match: any): boolean;
eatWhile(match: any): boolean;
}
}

View File

@@ -0,0 +1,14 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
declare module '@emmetio/css-parser' {
import { BufferStream, Stylesheet } from 'EmmetNode';
import { Stylesheet as FlatStylesheet } from 'EmmetFlatNode';
function parseStylesheet(stream: BufferStream): Stylesheet;
function parseStylesheet(stream: string): FlatStylesheet;
export default parseStylesheet;
}

View File

@@ -0,0 +1,14 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
declare module '@emmetio/html-matcher' {
import { BufferStream, HtmlNode } from 'EmmetNode';
import { HtmlNode as HtmlFlatNode } from 'EmmetFlatNode';
function parse(stream: BufferStream): HtmlNode;
function parse(stream: string): HtmlFlatNode;
export default parse;
}

View File

@@ -0,0 +1,6 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
/// <reference types='@types/node'/>

43
node_modules/volar-service-emmet/lib/util.d.ts generated vendored Normal file
View File

@@ -0,0 +1,43 @@
import type * as vscode from '@volar/language-service';
import type * as EmmetHelper from '@vscode/emmet-helper';
import type { Node as FlatNode, Stylesheet as FlatStylesheet, HtmlNode as HtmlFlatNode } from 'EmmetFlatNode';
export declare function getEmmetHelper(): typeof EmmetHelper;
export declare function isStyleSheet(syntax: string): boolean;
export declare function getMappingForIncludedLanguages(context: vscode.LanguageServiceContext): Promise<Record<string, string>>;
/**
* Get the corresponding emmet mode for given vscode language mode
* E.g.: jsx for typescriptreact/javascriptreact or pug for jade
* If the language is not supported by emmet or has been excluded via `excludeLanguages` setting,
* then nothing is returned
*
* @param excludedLanguages Array of language ids that user has chosen to exclude for emmet
*/
export declare function getEmmetMode(language: string, mappedModes: Record<string, string>, excludedLanguages: string[]): string | undefined;
/**
* Traverse the given document backward & forward from given position
* to find a complete ruleset, then parse just that to return a Stylesheet
* @param document TextDocument
* @param position vscode.Position
*/
export declare function parsePartialStylesheet(document: vscode.TextDocument, position: vscode.Position): FlatStylesheet | undefined;
/**
* Returns node corresponding to given position in the given root node
*/
export declare function getFlatNode(root: FlatNode | undefined, offset: number, includeNodeBoundary: boolean): FlatNode | undefined;
export declare const allowedMimeTypesInScriptTag: string[];
/**
* Finds the HTML node within an HTML document at a given position
* If position is inside a script tag of type template, then it will be parsed to find the inner HTML node as well
*/
export declare function getHtmlFlatNode(documentText: string, root: FlatNode | undefined, offset: number, includeNodeBoundary: boolean): HtmlFlatNode | undefined;
export declare function getEmmetConfiguration(context: vscode.LanguageServiceContext, syntax: string): Promise<{
preferences: any;
showExpandedAbbreviation: any;
showAbbreviationSuggestions: any;
syntaxProfiles: any;
variables: any;
excludeLanguages: any;
showSuggestionsAsSnippets: any;
}>;
export declare function getEmbeddedCssNodeIfAny(document: vscode.TextDocument, currentNode: FlatNode | undefined, position: vscode.Position): FlatNode | undefined;
//# sourceMappingURL=util.d.ts.map

403
node_modules/volar-service-emmet/lib/util.js generated vendored Normal file
View File

@@ -0,0 +1,403 @@
"use strict";
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.allowedMimeTypesInScriptTag = void 0;
exports.getEmmetHelper = getEmmetHelper;
exports.isStyleSheet = isStyleSheet;
exports.getMappingForIncludedLanguages = getMappingForIncludedLanguages;
exports.getEmmetMode = getEmmetMode;
exports.parsePartialStylesheet = parsePartialStylesheet;
exports.getFlatNode = getFlatNode;
exports.getHtmlFlatNode = getHtmlFlatNode;
exports.getEmmetConfiguration = getEmmetConfiguration;
exports.getEmbeddedCssNodeIfAny = getEmbeddedCssNodeIfAny;
const css_parser_1 = require("@emmetio/css-parser");
const html_matcher_1 = require("@emmetio/html-matcher");
const bufferStream_1 = require("./bufferStream");
let _emmetHelper;
function getEmmetHelper() {
// Lazy load vscode-emmet-helper instead of importing it
// directly to reduce the start-up time of the extension
if (!_emmetHelper) {
_emmetHelper = require('@vscode/emmet-helper');
}
return _emmetHelper;
}
/**
* Mapping between languages that support Emmet and completion trigger characters
*/
const LANGUAGE_MODES = {
'html': ['!', '.', '}', ':', '*', '$', ']', '/', '>', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'jade': ['!', '.', '}', ':', '*', '$', ']', '/', '>', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'slim': ['!', '.', '}', ':', '*', '$', ']', '/', '>', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'haml': ['!', '.', '}', ':', '*', '$', ']', '/', '>', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'xml': ['.', '}', '*', '$', ']', '/', '>', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'xsl': ['!', '.', '}', '*', '$', '/', ']', '>', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'css': [':', '!', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'scss': [':', '!', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'sass': [':', '!', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'less': [':', '!', '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'stylus': [':', '!', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'javascriptreact': ['!', '.', '}', '*', '$', ']', '/', '>', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'],
'typescriptreact': ['!', '.', '}', '*', '$', ']', '/', '>', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
};
function isStyleSheet(syntax) {
const stylesheetSyntaxes = ['css', 'scss', 'sass', 'less', 'stylus'];
return stylesheetSyntaxes.includes(syntax);
}
async function getMappingForIncludedLanguages(context) {
// Explicitly map languages that have built-in grammar in VS Code to their parent language
// to get emmet completion support
// For other languages, users will have to use `emmet.includeLanguages` or
// language specific extensions can provide emmet completion support
const MAPPED_MODES = {
'handlebars': 'html',
'php': 'html'
};
const finalMappedModes = {};
const includeLanguagesConfig = await context.env.getConfiguration?.('emmet.includeLanguages');
const includeLanguages = Object.assign({}, MAPPED_MODES, includeLanguagesConfig ?? {});
Object.keys(includeLanguages).forEach(syntax => {
if (typeof includeLanguages[syntax] === 'string' && LANGUAGE_MODES[includeLanguages[syntax]]) {
finalMappedModes[syntax] = includeLanguages[syntax];
}
});
return finalMappedModes;
}
/**
* Get the corresponding emmet mode for given vscode language mode
* E.g.: jsx for typescriptreact/javascriptreact or pug for jade
* If the language is not supported by emmet or has been excluded via `excludeLanguages` setting,
* then nothing is returned
*
* @param excludedLanguages Array of language ids that user has chosen to exclude for emmet
*/
function getEmmetMode(language, mappedModes, excludedLanguages) {
if (!language || excludedLanguages.includes(language)) {
return;
}
if (language === 'jsx-tags') {
language = 'javascriptreact';
}
if (mappedModes[language]) {
language = mappedModes[language];
}
if (/\b(typescriptreact|javascriptreact|jsx-tags)\b/.test(language)) { // treat tsx like jsx
language = 'jsx';
}
else if (language === 'sass-indented') { // map sass-indented to sass
language = 'sass';
}
else if (language === 'jade' || language === 'pug') {
language = 'pug';
}
const syntaxes = getSyntaxes();
if (syntaxes.markup.includes(language) || syntaxes.stylesheet.includes(language)) {
return language;
}
return;
}
const closeBrace = 125;
const openBrace = 123;
const slash = 47;
const star = 42;
/**
* Traverse the given document backward & forward from given position
* to find a complete ruleset, then parse just that to return a Stylesheet
* @param document TextDocument
* @param position vscode.Position
*/
function parsePartialStylesheet(document, position) {
const isCSS = document.languageId === 'css';
const positionOffset = document.offsetAt(position);
let startOffset = 0;
let endOffset = document.getText().length;
const limitCharacter = positionOffset - 5000;
const limitOffset = limitCharacter > 0 ? limitCharacter : startOffset;
const stream = new bufferStream_1.DocumentStreamReader(document, positionOffset);
function findOpeningCommentBeforePosition(pos) {
const text = document.getText().substring(0, pos);
const offset = text.lastIndexOf('/*');
if (offset === -1) {
return;
}
return offset;
}
function findClosingCommentAfterPosition(pos) {
const text = document.getText().substring(pos);
let offset = text.indexOf('*/');
if (offset === -1) {
return;
}
offset += 2 + pos;
return offset;
}
function consumeLineCommentBackwards() {
const posLineNumber = document.positionAt(stream.pos).line;
if (!isCSS && currentLine !== posLineNumber) {
currentLine = posLineNumber;
const startLineComment = document.getText({
start: { line: currentLine, character: 0 },
end: { line: currentLine + 1, character: 0 },
}).indexOf('//');
if (startLineComment > -1) {
stream.pos = document.offsetAt({ line: currentLine, character: startLineComment });
}
}
}
function consumeBlockCommentBackwards() {
if (!stream.sof() && stream.peek() === slash) {
if (stream.backUp(1) === star) {
stream.pos = findOpeningCommentBeforePosition(stream.pos) ?? startOffset;
}
else {
stream.next();
}
}
}
function consumeCommentForwards() {
if (stream.eat(slash)) {
if (stream.eat(slash) && !isCSS) {
const posLineNumber = document.positionAt(stream.pos).line;
stream.pos = document.offsetAt({ line: posLineNumber + 1, character: 0 });
}
else if (stream.eat(star)) {
stream.pos = findClosingCommentAfterPosition(stream.pos) ?? endOffset;
}
}
}
// Go forward until we find a closing brace.
while (!stream.eof() && !stream.eat(closeBrace)) {
if (stream.peek() === slash) {
consumeCommentForwards();
}
else {
stream.next();
}
}
if (!stream.eof()) {
endOffset = stream.pos;
}
stream.pos = positionOffset;
let openBracesToFind = 1;
let currentLine = position.line;
let exit = false;
// Go back until we found an opening brace. If we find a closing one, consume its pair and continue.
while (!exit && openBracesToFind > 0 && !stream.sof()) {
consumeLineCommentBackwards();
switch (stream.backUp(1)) {
case openBrace:
openBracesToFind--;
break;
case closeBrace:
if (isCSS) {
stream.next();
startOffset = stream.pos;
exit = true;
}
else {
openBracesToFind++;
}
break;
case slash:
consumeBlockCommentBackwards();
break;
default:
break;
}
if (position.line - document.positionAt(stream.pos).line > 100
|| stream.pos <= limitOffset) {
exit = true;
}
}
// We are at an opening brace. We need to include its selector.
currentLine = document.positionAt(stream.pos).line;
openBracesToFind = 0;
let foundSelector = false;
while (!exit && !stream.sof() && !foundSelector && openBracesToFind >= 0) {
consumeLineCommentBackwards();
const ch = stream.backUp(1);
if (/\s/.test(String.fromCharCode(ch))) {
continue;
}
switch (ch) {
case slash:
consumeBlockCommentBackwards();
break;
case closeBrace:
openBracesToFind++;
break;
case openBrace:
openBracesToFind--;
break;
default:
if (!openBracesToFind) {
foundSelector = true;
}
break;
}
if (!stream.sof() && foundSelector) {
startOffset = stream.pos;
}
}
try {
const buffer = ' '.repeat(startOffset) + document.getText().substring(startOffset, endOffset);
return (0, css_parser_1.default)(buffer);
}
catch (e) {
return;
}
}
/**
* Returns node corresponding to given position in the given root node
*/
function getFlatNode(root, offset, includeNodeBoundary) {
if (!root) {
return;
}
function getFlatNodeChild(child) {
if (!child) {
return;
}
const nodeStart = child.start;
const nodeEnd = child.end;
if ((nodeStart < offset && nodeEnd > offset)
|| (includeNodeBoundary && nodeStart <= offset && nodeEnd >= offset)) {
return getFlatNodeChildren(child.children) ?? child;
}
else if ('close' in child) {
// We have an HTML node in this case.
// In case this node is an invalid unpaired HTML node,
// we still want to search its children
const htmlChild = child;
if (htmlChild.open && !htmlChild.close) {
return getFlatNodeChildren(htmlChild.children);
}
}
return;
}
function getFlatNodeChildren(children) {
for (let i = 0; i < children.length; i++) {
const foundChild = getFlatNodeChild(children[i]);
if (foundChild) {
return foundChild;
}
}
return;
}
return getFlatNodeChildren(root.children);
}
exports.allowedMimeTypesInScriptTag = ['text/html', 'text/plain', 'text/x-template', 'text/template', 'text/ng-template'];
/**
* Finds the HTML node within an HTML document at a given position
* If position is inside a script tag of type template, then it will be parsed to find the inner HTML node as well
*/
function getHtmlFlatNode(documentText, root, offset, includeNodeBoundary) {
let currentNode = getFlatNode(root, offset, includeNodeBoundary);
if (!currentNode) {
return;
}
// If the currentNode is a script one, first set up its subtree and then find HTML node.
if (currentNode.name === 'script' && currentNode.children.length === 0) {
const scriptNodeBody = setupScriptNodeSubtree(documentText, currentNode);
if (scriptNodeBody) {
currentNode = getHtmlFlatNode(scriptNodeBody, currentNode, offset, includeNodeBoundary) ?? currentNode;
}
}
else if (currentNode.type === 'cdata') {
const cdataBody = setupCdataNodeSubtree(documentText, currentNode);
currentNode = getHtmlFlatNode(cdataBody, currentNode, offset, includeNodeBoundary) ?? currentNode;
}
return currentNode;
}
function setupScriptNodeSubtree(documentText, scriptNode) {
const isTemplateScript = scriptNode.name === 'script' &&
(scriptNode.attributes &&
scriptNode.attributes.some(x => x.name.toString() === 'type'
&& exports.allowedMimeTypesInScriptTag.includes(x.value.toString())));
if (isTemplateScript
&& scriptNode.open) {
// blank out the rest of the document and generate the subtree.
const beforePadding = ' '.repeat(scriptNode.open.end);
const endToUse = scriptNode.close ? scriptNode.close.start : scriptNode.end;
const scriptBodyText = beforePadding + documentText.substring(scriptNode.open.end, endToUse);
const innerRoot = (0, html_matcher_1.default)(scriptBodyText);
innerRoot.children.forEach(child => {
scriptNode.children.push(child);
child.parent = scriptNode;
});
return scriptBodyText;
}
return '';
}
function setupCdataNodeSubtree(documentText, cdataNode) {
// blank out the rest of the document and generate the subtree.
const cdataStart = '<![CDATA[';
const cdataEnd = ']]>';
const startToUse = cdataNode.start + cdataStart.length;
const endToUse = cdataNode.end - cdataEnd.length;
const beforePadding = ' '.repeat(startToUse);
const cdataBody = beforePadding + documentText.substring(startToUse, endToUse);
const innerRoot = (0, html_matcher_1.default)(cdataBody);
innerRoot.children.forEach(child => {
cdataNode.children.push(child);
child.parent = cdataNode;
});
return cdataBody;
}
async function getEmmetConfiguration(context, syntax) {
const emmetConfig = await context.env.getConfiguration?.('emmet') ?? {};
const syntaxProfiles = Object.assign({}, emmetConfig['syntaxProfiles'] || {});
const preferences = Object.assign({}, emmetConfig['preferences'] || {});
// jsx, xml and xsl syntaxes need to have self closing tags unless otherwise configured by user
if (syntax === 'jsx' || syntax === 'xml' || syntax === 'xsl') {
syntaxProfiles[syntax] = syntaxProfiles[syntax] || {};
if (typeof syntaxProfiles[syntax] === 'object'
&& !syntaxProfiles[syntax].hasOwnProperty('self_closing_tag') // Old Emmet format
&& !syntaxProfiles[syntax].hasOwnProperty('selfClosingStyle') // Emmet 2.0 format
) {
syntaxProfiles[syntax] = {
...syntaxProfiles[syntax],
selfClosingStyle: syntax === 'jsx' ? 'xhtml' : 'xml'
};
}
}
return {
preferences,
showExpandedAbbreviation: emmetConfig['showExpandedAbbreviation'],
showAbbreviationSuggestions: emmetConfig['showAbbreviationSuggestions'],
syntaxProfiles,
variables: emmetConfig['variables'],
excludeLanguages: emmetConfig['excludeLanguages'],
showSuggestionsAsSnippets: emmetConfig['showSuggestionsAsSnippets']
};
}
function getEmbeddedCssNodeIfAny(document, currentNode, position) {
if (!currentNode) {
return;
}
const currentHtmlNode = currentNode;
if (currentHtmlNode && currentHtmlNode.open && currentHtmlNode.close) {
const offset = document.offsetAt(position);
if (currentHtmlNode.open.end < offset && offset <= currentHtmlNode.close.start) {
if (currentHtmlNode.name === 'style') {
const buffer = ' '.repeat(currentHtmlNode.open.end) + document.getText().substring(currentHtmlNode.open.end, currentHtmlNode.close.start);
return (0, css_parser_1.default)(buffer);
}
}
}
return;
}
function getSyntaxes() {
/**
* List of all known syntaxes, from emmetio/emmet
*/
return {
markup: ['html', 'xml', 'xsl', 'jsx', 'js', 'pug', 'slim', 'haml'],
stylesheet: ['css', 'sass', 'scss', 'less', 'sss', 'stylus']
};
}
//# sourceMappingURL=util.js.map

47
node_modules/volar-service-emmet/package.json generated vendored Normal file
View File

@@ -0,0 +1,47 @@
{
"name": "volar-service-emmet",
"version": "0.0.62",
"description": "Integrate @vscode/emmet-helper into Volar",
"homepage": "https://github.com/volarjs/services/tree/master/packages/emmet",
"bugs": "https://github.com/volarjs/services/issues",
"sideEffects": false,
"keywords": [
"volar-service"
],
"license": "MIT",
"files": [
"**/*.js",
"**/*.d.ts"
],
"repository": {
"type": "git",
"url": "https://github.com/volarjs/services.git",
"directory": "packages/emmet"
},
"author": {
"name": "Johnson Chu",
"email": "johnsoncodehk@gmail.com",
"url": "https://github.com/johnsoncodehk"
},
"dependencies": {
"@emmetio/css-parser": "^0.4.0",
"@emmetio/html-matcher": "^1.3.0",
"@vscode/emmet-helper": "^2.9.3",
"vscode-uri": "^3.0.8"
},
"devDependencies": {
"@types/node": "latest"
},
"peerDependencies": {
"@volar/language-service": "~2.4.0"
},
"peerDependenciesMeta": {
"@volar/language-service": {
"optional": true
}
},
"browser": {
"./index.js": "./empty.js"
},
"gitHead": "f1ddbdc4d9df0772db5a0d46ff8ff64eecc9de02"
}