From 583b7586dffae036061987b3e6da87175ba6f69b Mon Sep 17 00:00:00 2001 From: yutent Date: Tue, 6 Jun 2023 15:26:41 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=80=E5=A4=A7=E6=B3=A2=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscodeignore | 3 +- build.mjs | 34 ++++++-- package.json | 25 ++---- src/cache.js | 19 ++-- src/main.js | 19 ++-- src/providers/css.js | 19 ++-- src/providers/formatting.js | 19 ++-- src/providers/hover.js | 20 +++-- src/providers/html.js | 10 +-- src/util.js | 13 ++- syntaxes/es6.inline.css.json | 6 +- syntaxes/es6.inline.html.json | 6 +- syntaxes/es6.inline.less.json | 36 -------- syntaxes/es6.inline.scss.json | 158 +++++++++++++++++++++++++++++++++- tests/index.js | 8 +- 15 files changed, 265 insertions(+), 130 deletions(-) delete mode 100644 syntaxes/es6.inline.less.json diff --git a/.vscodeignore b/.vscodeignore index a5da763..749ee34 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -4,4 +4,5 @@ src/** tests/** .vscode/** .gitignore -.git \ No newline at end of file +.git +build.mjs \ No newline at end of file diff --git a/build.mjs b/build.mjs index f3ff20e..bff73e6 100644 --- a/build.mjs +++ b/build.mjs @@ -7,10 +7,30 @@ import Es from 'esbuild' import fs from 'iofs' -Es.build({ - entryPoints: fs.ls('./src', true).filter(it => fs.isfile(it)), - outdir: 'dist', - target: 'es6', - format: 'cjs' - // minify: true -}) +let args = process.argv.slice(2) +let entryPoints = fs.ls('./src', true).filter(it => fs.isfile(it)) + +if (args.includes('--watch')) { + let res = await Es.context({ + entryPoints, + outdir: 'dist', + target: 'es2022', + format: 'cjs', + // external: ['vscode', 'util'], + platform: 'node' + // bundle: true + }) + console.log('监听文件变化中...\n') + await res.watch() +} else { + Es.build({ + entryPoints, + outdir: 'dist', + target: 'es2022', + format: 'cjs', + minify: true, + // external: ['vscode', 'util'], + platform: 'node' + // bundle: true + }) +} diff --git a/package.json b/package.json index 2712964..70474e9 100644 --- a/package.json +++ b/package.json @@ -21,9 +21,10 @@ "url": "https://github.com/yutent/vscode-string-html" }, "engines": { - "vscode": "^1.22.0" + "vscode": "^1.58.0" }, "scripts": { + "start": "node build.mjs --watch", "build": "node build.mjs" }, "categories": [ @@ -91,28 +92,12 @@ "meta.embedded.block.css": "scss", "meta.template.expression.ts": "typescript" } - }, - { - "injectTo": [ - "source.js", - "source.js.jsx", - "source.jsx", - "source.ts", - "source.ts.tsx", - "source.tsx" - ], - "scopeName": "es6.inline.less", - "path": "./syntaxes/es6.inline.less.json", - "embeddedLanguages": { - "meta.embedded.block.css": "less", - "meta.template.expression.ts": "typescript" - } } ] }, "dependencies": { - "vscode-css-languageservice": "^3.0.7", - "vscode-emmet-helper": "^1.2.0", - "vscode-html-languageservice": "^2.1.1" + "vscode-css-languageservice": "^6.2.6", + "@vscode/emmet-helper": "^2.8.8", + "vscode-html-languageservice": "^5.0.6" } } diff --git a/src/cache.js b/src/cache.js index b16f5a9..6c1749c 100644 --- a/src/cache.js +++ b/src/cache.js @@ -1,28 +1,31 @@ -// Code from https://github.com/Microsoft/typescript-styled-plugin/blob/master/src/styled-template-language-service.ts +// Code from https://github.com/microsoft/typescript-styled-plugin/blob/main/src/_language-service.ts + +function arePositionsEqual(left, right) { + return left.line === right.line && left.character === right.character +} + export class CompletionsCache { _cachedCompletionsFile _cachedCompletionsPosition _cachedCompletionsContent _completions - equalPositions(left, right) { - return left.line === right.line && left.character === right.character - } + getCached(context, position) { if ( this._completions && context.fileName === this._cachedCompletionsFile && this._cachedCompletionsPosition && - this.equalPositions(position, this._cachedCompletionsPosition) && - context.getText() === this._cachedCompletionsContent + arePositionsEqual(position, this._cachedCompletionsPosition) && + context.text === this._cachedCompletionsContent ) { return this._completions } - return undefined } + updateCached(context, position, completions) { this._cachedCompletionsFile = context.fileName this._cachedCompletionsPosition = position - this._cachedCompletionsContent = context.getText() + this._cachedCompletionsContent = context.text this._completions = completions } } diff --git a/src/main.js b/src/main.js index 7b5863c..b25adef 100644 --- a/src/main.js +++ b/src/main.js @@ -1,4 +1,4 @@ -import { languages as Languages } from 'vscode' +import { languages } from 'vscode' import { HTMLCompletionItemProvider } from './providers/html.js' import { CSSCompletionItemProvider, @@ -15,7 +15,12 @@ const selector = [ export function activate(Context) { new CodeFormatterProvider() - Languages.registerCompletionItemProvider( + + languages.registerHoverProvider(selector, new HTMLHoverProvider()) + languages.registerHoverProvider(selector, new CSSHoverProvider()) + + // HTMLCompletionItemProvider + languages.registerCompletionItemProvider( selector, new HTMLCompletionItemProvider(), '<', @@ -37,8 +42,9 @@ export function activate(Context) { '8', '9' ) - Languages.registerHoverProvider(selector, new HTMLHoverProvider()) - Languages.registerCompletionItemProvider( + + // HTMLStyleCompletionItemProvider + languages.registerCompletionItemProvider( selector, new HTMLStyleCompletionItemProvider(), '!', @@ -59,8 +65,9 @@ export function activate(Context) { '8', '9' ) - Languages.registerHoverProvider(selector, new CSSHoverProvider()) - Languages.registerCompletionItemProvider( + + // CSSCompletionItemProvider + languages.registerCompletionItemProvider( selector, new CSSCompletionItemProvider(), '!', diff --git a/src/providers/css.js b/src/providers/css.js index f40585f..0f55a30 100644 --- a/src/providers/css.js +++ b/src/providers/css.js @@ -1,6 +1,6 @@ -import { getLanguageService as GetHTMLanguageService } from 'vscode-html-languageservice' -import { getSCSSLanguageService as GetSCSSLanguageService } from 'vscode-css-languageservice' -import * as emmet from 'vscode-emmet-helper' +import { getLanguageService } from 'vscode-html-languageservice' +import { getSCSSLanguageService } from 'vscode-css-languageservice' +import * as emmet from '@vscode/emmet-helper' import { GetEmmetConfiguration, MatchOffset, @@ -12,10 +12,11 @@ import { import { CompletionsCache } from '../cache.js' export class HTMLStyleCompletionItemProvider { - _cssLanguageService = GetSCSSLanguageService() - _HTMLanguageService = GetHTMLanguageService() - _expression = /(\/\*\s*html\s*\*\/\s*`|html\s*`)([^`]*)(`)/g + _cssLanguageService = getSCSSLanguageService() + _HTMLanguageService = getLanguageService() + _expression = /(html\s*`)([^`]*)(`)/g _cache = new CompletionsCache() + provideCompletionItems(document, position, _token) { const cached = this._cache.getCached(document, position) if (cached) { @@ -83,10 +84,12 @@ export class HTMLStyleCompletionItemProvider { return item } } + export class CSSCompletionItemProvider { - _CSSLanguageService = GetSCSSLanguageService() - _expression = /(\/\*\s*(css|less|scss|sass)\s*\*\/\s*`|css\s*`)([^`]*)(`)/g + _CSSLanguageService = getSCSSLanguageService() + _expression = /(css\s*`)([^`]*)(`)/g _cache = new CompletionsCache() + provideCompletionItems(document, position, _token) { const cached = this._cache.getCached(document, position) if (cached) { diff --git a/src/providers/formatting.js b/src/providers/formatting.js index ee8a5ce..460a84a 100644 --- a/src/providers/formatting.js +++ b/src/providers/formatting.js @@ -1,10 +1,5 @@ -import { - Range, - WorkspaceEdit, - workspace as Workspace, - commands as Commands -} from 'vscode' -import { getLanguageService as GetHTMLanguageService } from 'vscode-html-languageservice' +import { Range, WorkspaceEdit, workspace, commands } from 'vscode' +import { getLanguageService } from 'vscode-html-languageservice' import { CreateVirtualDocument, TranslateHTMLTextEdits, @@ -12,15 +7,17 @@ import { } from '../util.js' export class CodeFormatterProvider { - _expression = /(\/\*\s*html\s*\*\/\s*`|html\s*`)([^`]*)(`)/g + _expression = /(html\s*`)([^`]*)(`)/g document + constructor() { - Commands.registerTextEditorCommand( + commands.registerTextEditorCommand( 'editor.action.formatInlineHtml', this.format, this ) } + format(textEditor) { this.document = textEditor.document var documentText = this.document.getText() @@ -40,7 +37,7 @@ export class CodeFormatterProvider { var vHTML = CreateVirtualDocument('html', text) // TODO - Expose Formatting Options const edits = TranslateHTMLTextEdits( - GetHTMLanguageService().format(vHTML, null, { + getLanguageService().format(vHTML, null, { indentInnerHtml: false, preserveNewLines: true, tabSize: textEditor.options.tabSize, @@ -49,7 +46,7 @@ export class CodeFormatterProvider { }), matchStartPosition.line + 1 ) - Workspace.applyEdit(this.composeEdits(this.document.uri, edits)) + workspace.applyEdit(this.composeEdits(this.document.uri, edits)) } composeEdits(uri, edits) { var ws = new WorkspaceEdit() diff --git a/src/providers/hover.js b/src/providers/hover.js index 471e774..8f59ff2 100644 --- a/src/providers/hover.js +++ b/src/providers/hover.js @@ -1,12 +1,12 @@ -import { getLanguageService as GetHtmlLanguageService } from 'vscode-html-languageservice' -import { getCSSLanguageService as GetCssLanguageService } from 'vscode-css-languageservice' +import { getLanguageService } from 'vscode-html-languageservice' +import { getCSSLanguageService } from 'vscode-css-languageservice' import { CreateVirtualDocument, MatchOffset } from '../util.js' export class HTMLHoverProvider { - _htmlLanguageService = GetHtmlLanguageService() - _cssLanguageService = GetCssLanguageService() - // private _expression = /(html\s*`)([^`]*)(`)/g - _expression = /(\/\*\s*html\s*\*\/\s*`|html\s*`)([^`]*)(`)/g + _htmlLanguageService = getLanguageService() + _cssLanguageService = getCSSLanguageService() + _expression = /(html\s*`)([^`]*)(`)/g + provideHover(document, position, token) { const currentOffset = document.offsetAt(position) const documentText = document.getText() @@ -35,10 +35,12 @@ export class HTMLHoverProvider { return hover } } + export class CSSHoverProvider { - _htmlLanguageService = GetHtmlLanguageService() - _cssLanguageService = GetCssLanguageService() - _expression = /(\/\*\s*(css|less|scss)\s*\*\/\s*`|css\s*`)([^`]*)(`)/g + _htmlLanguageService = getLanguageService() + _cssLanguageService = getCSSLanguageService() + _expression = /(css\s*`)([^`]*)(`)/g + provideHover(document, position, token) { const currentOffset = document.offsetAt(position) const documentText = document.getText() diff --git a/src/providers/html.js b/src/providers/html.js index c8ce87f..d386fac 100644 --- a/src/providers/html.js +++ b/src/providers/html.js @@ -1,5 +1,5 @@ -import { getLanguageService as GetHTMLanguageService } from 'vscode-html-languageservice' -import * as emmet from 'vscode-emmet-helper' +import { getLanguageService } from 'vscode-html-languageservice' +import * as emmet from '@vscode/emmet-helper' import { GetEmmetConfiguration, MatchOffset, @@ -9,10 +9,10 @@ import { import { CompletionsCache } from '../cache.js' export class HTMLCompletionItemProvider { - _htmlLanguageService = GetHTMLanguageService() - _expression = /(\/\*\s*html\s*\*\/\s*`|html\s*`)([^`]*)(`)/g - // private _expression = /(html\s*`)([^`]*)(`)/g + _htmlLanguageService = getLanguageService() + _expression = /(html\s*`)([^`]*)(`)/g _cache = new CompletionsCache() + provideCompletionItems(document, position, token) { const cached = this._cache.getCached(document, position) if (cached) { diff --git a/src/util.js b/src/util.js index 38edc75..fcfc890 100644 --- a/src/util.js +++ b/src/util.js @@ -1,8 +1,5 @@ import { workspace, TextEdit, Position, Range } from 'vscode' -import { - TextDocument as HTMLTextDocument, - TokenType as HTMLTokenType -} from 'vscode-html-languageservice' +import { TextDocument, TokenType } from 'vscode-html-languageservice' export function GetEmmetConfiguration() { const emmetConfig = workspace.getConfiguration('emmet') @@ -47,9 +44,9 @@ export function GetLanguageRegions(service, data) { const scanner = service.createScanner(data) const regions = [] let tokenType - while ((tokenType = scanner.scan()) !== HTMLTokenType.EOS) { + while ((tokenType = scanner.scan()) !== TokenType.EOS) { switch (tokenType) { - case HTMLTokenType.Styles: + case TokenType.Styles: regions.push({ languageId: 'css', start: scanner.getTokenOffset(), @@ -111,12 +108,12 @@ export function TranslateCompletionItems(items, line, expand = false) { }) } export function CreateVirtualDocument( - // context: TextDocument | HTMLTextDocument, + // context: TextDocument | TextDocument, languageId, // position: Position | HtmlPosition, content ) { - const doc = HTMLTextDocument.create( + const doc = TextDocument.create( `embedded://document.${languageId}`, languageId, 1, diff --git a/syntaxes/es6.inline.css.json b/syntaxes/es6.inline.css.json index edba048..f9fe55f 100644 --- a/syntaxes/es6.inline.css.json +++ b/syntaxes/es6.inline.css.json @@ -1,10 +1,11 @@ { + "scopeName": "es6.inline.css", "fileTypes": ["js", "jsx", "ts", "tsx"], "injectionSelector": "L:source.js -comment -string, L:source.jsx -comment -string, L:source.ts -comment -string, L:source.tsx -comment -string", "patterns": [ { "contentName": "meta.embedded.block.css", - "begin": "(?x)(\\s*?(\\w+\\.)?(?:css|/\\*\\s*css\\s*\\*/)\\s*)(`)", + "begin": "(?x)(\\s*?(\\w+\\.)?(?:css)\\s*)(`)", "beginCaptures": { "0": { "name": "string.template.ts, punctuation.definition.string.template.begin.ts" @@ -31,6 +32,5 @@ { "include": "source.ts#template-substitution-element" } - ], - "scopeName": "es6.inline.css" + ] } diff --git a/syntaxes/es6.inline.html.json b/syntaxes/es6.inline.html.json index 66b6fe9..7a7d438 100644 --- a/syntaxes/es6.inline.html.json +++ b/syntaxes/es6.inline.html.json @@ -1,4 +1,5 @@ { + "scopeName": "es6.inline.html", "fileTypes": ["js", "jsx", "ts", "tsx"], "injectionSelector": "L:source.js -comment -string, L:source.jsx -comment -string, L:source.ts -comment -string, L:source.tsx -comment -string", "injections": { @@ -14,7 +15,7 @@ "patterns": [ { "contentName": "meta.embedded.block.html", - "begin": "(?x)(\\s*?(\\w+\\.)?(?:html|/\\*\\s*html\\s*\\*/)\\s*)(`)", + "begin": "(?x)(\\s*?(\\w+\\.)?(?:html)\\s*)(`)", "beginCaptures": { "0": { "name": "string.template.ts, punctuation.definition.string.template.begin.ts" @@ -41,6 +42,5 @@ { "include": "source.ts#template-substitution-element" } - ], - "scopeName": "es6.inline.html" + ] } diff --git a/syntaxes/es6.inline.less.json b/syntaxes/es6.inline.less.json deleted file mode 100644 index d06d604..0000000 --- a/syntaxes/es6.inline.less.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "fileTypes": ["js", "jsx", "ts", "tsx"], - "injectionSelector": "L:source.js -comment -string, L:source.jsx -comment -string, L:source.ts -comment -string, L:source.tsx -comment -string", - "patterns": [ - { - "contentName": "meta.embedded.block.css", - "begin": "(?x)(\\s*?(\\w+\\.)?(?:less|/\\*\\s*less\\s*\\*/)\\s*)(`)", - "beginCaptures": { - "0": { - "name": "string.template.ts, punctuation.definition.string.template.begin.ts" - }, - "1": { - "name": "entity.name.function.tagged-template.ts" - } - }, - "end": "(`)", - "endCaptures": { - "0": { - "name": "string.template.ts, punctuation.definition.string.template.end.ts" - } - }, - "patterns": [ - { - "include": "source.ts#template-substitution-element" - }, - { - "include": "source.css.less" - } - ] - }, - { - "include": "source.ts#template-substitution-element" - } - ], - "scopeName": "es6.inline.less" -} diff --git a/syntaxes/es6.inline.scss.json b/syntaxes/es6.inline.scss.json index 72fdc54..94e4683 100644 --- a/syntaxes/es6.inline.scss.json +++ b/syntaxes/es6.inline.scss.json @@ -1,10 +1,11 @@ { + "scopeName": "es6.inline.scss", "fileTypes": ["js", "jsx", "ts", "tsx"], "injectionSelector": "L:source.js -comment -string, L:source.jsx -comment -string, L:source.ts -comment -string, L:source.tsx -comment -string", "patterns": [ { "contentName": "meta.embedded.block.css", - "begin": "(?x)(\\s*?(\\w+\\.)?(?:scss|/\\*\\s*scss\\s*\\*/)\\s*)(`)", + "begin": "(?x)(\\s*?(\\w+\\.)?(?:scss)\\s*)(`)", "beginCaptures": { "0": { "name": "string.template.ts, punctuation.definition.string.template.begin.ts" @@ -32,5 +33,158 @@ "include": "source.ts#template-substitution-element" } ], - "scopeName": "es6.inline.scss" + "repository": { + "reserved-words": { + "name": "support.type.property-name.css.postcss", + "match": "\\b(false|from|in|not|null|through|to|true)\\b" + }, + "double-quoted": { + "patterns": [ + { + "include": "#quoted-interpolation" + } + ], + "begin": "\"", + "name": "string.quoted.double.css.postcss", + "end": "\"" + }, + "operator": { + "name": "keyword.operator.postcss", + "match": "\\+|\\s-\\s|\\s-(?=\\$)|(?<=\\()-(?=\\$)|\\s-(?=\\()|\\*|/|%|=|!|<|>|~" + }, + "function-content": { + "name": "string.quoted.double.css.postcss", + "match": "(?<=url\\(|format\\(|attr\\().+?(?=\\))" + }, + "double-slash": { + "patterns": [ + { + "include": "#comment-tag" + } + ], + "begin": "//", + "name": "comment.line.postcss", + "end": "$" + }, + "numeric": { + "name": "constant.numeric.css.postcss", + "match": "(-|\\.)?[0-9]+(\\.[0-9]+)?" + }, + "variable-root-css": { + "name": "variable.parameter.postcss", + "match": "(?