Skip to content

Commit

Permalink
refactor: parse css vars in vue-typescript
Browse files Browse the repository at this point in the history
close #1093
  • Loading branch information
johnsoncodehk committed Mar 21, 2022
1 parent c10295f commit 85dd91c
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 95 deletions.
1 change: 0 additions & 1 deletion packages/typescript-vue-plugin/src/index.ts
Expand Up @@ -29,7 +29,6 @@ const init: ts.server.PluginModuleFactory = (modules) => {
vueCompilerOptions,
baseCssModuleType: 'any',
getCssClasses: () => ({}),
getCssVBindRanges: () => [],
vueLsHost: proxyHost.host,
isTsPlugin: true
});
Expand Down
1 change: 0 additions & 1 deletion packages/vue-language-service/src/documentService.ts
Expand Up @@ -155,7 +155,6 @@ export function getDocumentService(
{},
context.typescript,
'Record<string, string>',
stylesheetExtra.getCssVBindRanges,
stylesheetExtra.getCssClasses,
);
vueDoc = parseVueDocument(vueFile);
Expand Down
1 change: 0 additions & 1 deletion packages/vue-language-service/src/languageService.ts
Expand Up @@ -101,7 +101,6 @@ export function createLanguageService(
vueCompilerOptions,
baseCssModuleType: 'Record<string, string>',
getCssClasses: ef => stylesheetExtra.getCssClasses(ef),
getCssVBindRanges: ef => stylesheetExtra.getCssVBindRanges(ef),
vueLsHost: vueLsHost,
isTsPlugin: false,
});
Expand Down
49 changes: 0 additions & 49 deletions packages/vue-language-service/src/stylesheetExtra.ts
@@ -1,49 +1,21 @@
import * as shared from '@volar/shared';
import { getMatchBindTexts } from '@volar/vue-code-gen/out/parsers/cssBindRanges';
import { TextRange } from '@volar/vue-code-gen/out/types';
import { EmbeddedFile } from '@volar/vue-typescript';
import type * as css from 'vscode-css-languageservice';
import { TextDocument } from 'vscode-languageserver-textdocument';
import type useCssPlugin from './commonPlugins/css';
import { findClassNames } from './utils/cssClasses';

interface StylesheetNode {
children: StylesheetNode[] | undefined,
end: number,
length: number,
offset: number,
parent: StylesheetNode | null,
type: number,
}

export function createStylesheetExtra(cssPlugin: ReturnType<typeof useCssPlugin>) {

const embeddedDocuments = new WeakMap<EmbeddedFile, TextDocument>();
const stylesheetVBinds = new WeakMap<css.Stylesheet, TextRange[]>();
const stylesheetClasses = new WeakMap<css.Stylesheet, Record<string, TextRange[]>>();
const embeddedDocumentVersions = new Map<string, number>();

return {
getCssVBindRanges,
getCssClasses,
};

function getCssVBindRanges(embeddedFile: EmbeddedFile) {

const document = getDocumentFromEmbeddedFile(embeddedFile);

const stylesheet = cssPlugin.getStylesheet?.(document);
if (!stylesheet)
return [];

let binds = stylesheetVBinds.get(stylesheet);
if (!binds) {
binds = findStylesheetVBindRanges(embeddedFile.content, stylesheet);
stylesheetVBinds.set(stylesheet, binds)
}

return binds;
}
function getDocumentFromEmbeddedFile(embeddedFile: EmbeddedFile) {

let document = embeddedDocuments.get(embeddedFile);
Expand All @@ -66,27 +38,6 @@ export function createStylesheetExtra(cssPlugin: ReturnType<typeof useCssPlugin>

return document;
}
function findStylesheetVBindRanges(docText: string, ss: css.Stylesheet) {
const result: TextRange[] = [];
visChild(ss as StylesheetNode);
function visChild(node: StylesheetNode) {
if (node.type === 22) {
const nodeText = docText.substring(node.offset, node.end);
for (const textRange of getMatchBindTexts(nodeText)) {
result.push({
start: textRange.start + node.offset,
end: textRange.end + node.offset,
});
}
}
else if (node.children) {
for (let i = 0; i < node.children.length; i++) {
visChild(node.children[i]);
}
}
}
return result;
}
function getCssClasses(embeddedFile: EmbeddedFile) {

const document = getDocumentFromEmbeddedFile(embeddedFile);
Expand Down
1 change: 0 additions & 1 deletion packages/vue-tsc/src/proxy.ts
Expand Up @@ -41,7 +41,6 @@ export function createProgramProxy(
typescript: ts,
baseCssModuleType: 'any',
getCssClasses: () => ({}),
getCssVBindRanges: () => [],
vueCompilerOptions,
vueLsHost: vueLsHost,
isVueTsc: true,
Expand Down
2 changes: 0 additions & 2 deletions packages/vue-typescript/src/typescriptRuntime.ts
Expand Up @@ -23,7 +23,6 @@ export function createTypeScriptRuntime(options: {
typescript: typeof import('typescript/lib/tsserverlibrary'),
vueCompilerOptions: VueCompilerOptions,
baseCssModuleType: string,
getCssVBindRanges: (cssEmbeddeFile: EmbeddedFile) => TextRange[],
getCssClasses: (cssEmbeddeFile: EmbeddedFile) => Record<string, TextRange[]>,
vueLsHost: LanguageServiceHost,
isTsPlugin?: boolean,
Expand Down Expand Up @@ -322,7 +321,6 @@ export function createTypeScriptRuntime(options: {
options.vueCompilerOptions,
options.typescript,
options.baseCssModuleType,
options.getCssVBindRanges,
options.getCssClasses,
));
vueScriptContentsUpdate = true;
Expand Down
@@ -1,11 +1,12 @@
export function* getMatchBindTexts(nodeText: string) {
// https://github.com/vuejs/core/blob/main/packages/compiler-sfc/src/cssVars.ts#L47-L61
export function* parseCssVars(styleContent: string) {
const reg = /\bv-bind\(\s*(?:'([^']+)'|"([^"]+)"|([^'"][^)]*))\s*\)/g;
const matchs = nodeText.matchAll(reg);
const matchs = styleContent.matchAll(reg);
for (const match of matchs) {
if (match.index !== undefined) {
const matchText = match[1] ?? match[2] ?? match[3];
if (matchText !== undefined) {
const offset = match.index + nodeText.slice(match.index).indexOf(matchText);
const offset = match.index + styleContent.slice(match.index).indexOf(matchText);
yield { start: offset, end: offset + matchText.length };
}
}
Expand Down
86 changes: 49 additions & 37 deletions packages/vue-typescript/src/vueFile.ts
Expand Up @@ -17,6 +17,7 @@ import { useSfcTemplateScript } from './use/useSfcTemplateScript';
import { Teleport } from './utils/sourceMaps';
import { SearchTexts } from './utils/string';
import { untrack } from './utils/untrack';
import { parseCssVars } from './utils/parseCssVars';

import type * as _0 from 'typescript/lib/tsserverlibrary'; // fix TS2742

Expand Down Expand Up @@ -80,7 +81,6 @@ export function createVueFile(
compilerOptions: VueCompilerOptions,
ts: typeof import('typescript/lib/tsserverlibrary'),
baseCssModuleType: string,
getCssVBindRanges: (cssEmbeddeFile: EmbeddedFile) => TextRange[],
getCssClasses: (cssEmbeddeFile: EmbeddedFile) => Record<string, TextRange[]>,
) {

Expand Down Expand Up @@ -108,6 +108,7 @@ export function createVueFile(
props: [],
setupReturns: [],
}) as ITemplateScriptData;
const cssVars = new WeakMap<EmbeddedFile, TextRange[]>();

// computeds
const parsedSfc = computed(() => parse(content.value, { sourceMap: false, ignoreEmpty: false }));
Expand Down Expand Up @@ -248,21 +249,27 @@ export function createVueFile(

const embeddeds: EmbeddedStructure[] = [];

// styles
for (const style of sfcStyles.embeddeds.value) {
embeddeds.push({
self: style,
embeddeds: [],
});
}

// customBlocks
for (const customBlock of sfcCustomBlocks.embeddeds.value) {
embeddeds.push({
self: customBlock,
embeddeds: [],
});
}
// template
embeddeds.push({
self: sfcTemplate.embedded.value,
embeddeds: [
{
self: sfcTemplateScript.embedded.value,
inheritParentIndent: true,
embeddeds: [],
},
{
self: sfcTemplateScript.formatEmbedded.value,
inheritParentIndent: true,
embeddeds: [],
},
{
self: sfcTemplateScript.inlineCssEmbedded.value,
inheritParentIndent: true,
embeddeds: [],
},
],
});

// scripts - format
embeddeds.push({
Expand Down Expand Up @@ -294,27 +301,21 @@ export function createVueFile(
embeddeds: [],
});

// template
embeddeds.push({
self: sfcTemplate.embedded.value,
embeddeds: [
{
self: sfcTemplateScript.embedded.value,
inheritParentIndent: true,
embeddeds: [],
},
{
self: sfcTemplateScript.formatEmbedded.value,
inheritParentIndent: true,
embeddeds: [],
},
{
self: sfcTemplateScript.inlineCssEmbedded.value,
inheritParentIndent: true,
embeddeds: [],
},
],
});
// styles
for (const style of sfcStyles.embeddeds.value) {
embeddeds.push({
self: style,
embeddeds: [],
});
}

// customBlocks
for (const customBlock of sfcCustomBlocks.embeddeds.value) {
embeddeds.push({
self: customBlock,
embeddeds: [],
});
}

return embeddeds;
});
Expand Down Expand Up @@ -579,6 +580,17 @@ export function createVueFile(

return dirty;
}
function getCssVBindRanges(embeddedFile: EmbeddedFile) {

let binds = cssVars.get(embeddedFile);

if (!binds) {
binds = [...parseCssVars(embeddedFile.content)];
cssVars.set(embeddedFile, binds)
}

return binds;
}
}

function eqSet<T>(as: Set<T>, bs: Set<T>) {
Expand Down

0 comments on commit 85dd91c

Please sign in to comment.