@vue/language-core 1.7.0 → 1.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,10 +5,10 @@ import type * as ts from 'typescript/lib/tsserverlibrary';
5
5
  import type * as templateGen from '../generators/template';
6
6
  import type { ScriptRanges } from '../parsers/scriptRanges';
7
7
  import type { ScriptSetupRanges } from '../parsers/scriptSetupRanges';
8
- import { collectCssVars, collectStyleCssClasses } from '../plugins/vue-tsx';
9
8
  import { Sfc } from '../types';
10
9
  import type { VueCompilerOptions } from '../types';
11
- export declare function generate(ts: typeof import('typescript/lib/tsserverlibrary'), fileName: string, _sfc: Sfc, lang: string, scriptRanges: ScriptRanges | undefined, scriptSetupRanges: ScriptSetupRanges | undefined, cssVars: ReturnType<typeof collectCssVars>, cssModuleClasses: ReturnType<typeof collectStyleCssClasses>, cssScopedClasses: ReturnType<typeof collectStyleCssClasses>, htmlGen: ReturnType<typeof templateGen['generate']> | undefined, compilerOptions: ts.CompilerOptions, vueCompilerOptions: VueCompilerOptions, sharedTypesImport: string): {
10
+ export declare function generate(ts: typeof import('typescript/lib/tsserverlibrary'), fileName: string, _sfc: Sfc, lang: string, scriptRanges: ScriptRanges | undefined, scriptSetupRanges: ScriptSetupRanges | undefined, htmlGen: ReturnType<typeof templateGen['generate']> | undefined, compilerOptions: ts.CompilerOptions, vueCompilerOptions: VueCompilerOptions, sharedTypesImport: string, codegenStack: boolean): {
12
11
  codes: Segment<FileRangeCapabilities>[];
12
+ codeStacks: SourceMaps.StackNode[];
13
13
  mirrorBehaviorMappings: SourceMaps.Mapping<[MirrorBehaviorCapabilities, MirrorBehaviorCapabilities]>[];
14
14
  };
@@ -9,8 +9,8 @@ const shared_2 = require("../utils/shared");
9
9
  const transform_1 = require("../utils/transform");
10
10
  const sharedTypes = require("../utils/directorySharedTypes");
11
11
  const muggle = require("muggle-string");
12
- function generate(ts, fileName, _sfc, lang, scriptRanges, scriptSetupRanges, cssVars, cssModuleClasses, cssScopedClasses, htmlGen, compilerOptions, vueCompilerOptions, sharedTypesImport) {
13
- const codes = [];
12
+ function generate(ts, fileName, _sfc, lang, scriptRanges, scriptSetupRanges, htmlGen, compilerOptions, vueCompilerOptions, sharedTypesImport, codegenStack) {
13
+ const [codes, codeStacks] = codegenStack ? muggle.track([]) : [[], []];
14
14
  const mirrorBehaviorMappings = [];
15
15
  //#region monkey fix: https://github.com/vuejs/language-tools/pull/2113
16
16
  const sfc = {
@@ -78,6 +78,7 @@ function generate(ts, fileName, _sfc, lang, scriptRanges, scriptSetupRanges, css
78
78
  }
79
79
  return {
80
80
  codes,
81
+ codeStacks,
81
82
  mirrorBehaviorMappings,
82
83
  };
83
84
  function generateHelperTypes() {
@@ -717,10 +718,13 @@ declare function defineProp<T>(value?: T | (() => T), required?: boolean, rest?:
717
718
  }
718
719
  codes.push(`InstanceType<import('${sharedTypesImport}').PickNotAny<typeof __VLS_internalComponent, new () => {}>> & {\n`);
719
720
  /* CSS Module */
720
- for (const cssModule of cssModuleClasses) {
721
- codes.push(`${cssModule.style.module}: Record<string, string> & import('${sharedTypesImport}').Prettify<{}`);
722
- for (const classNameRange of cssModule.classNameRanges) {
723
- generateCssClassProperty(cssModule.index, cssModule.style.content.substring(classNameRange.start + 1, classNameRange.end), classNameRange, 'string', false);
721
+ for (let i = 0; i < _sfc.styles.length; i++) {
722
+ const style = _sfc.styles[i];
723
+ if (!style.module)
724
+ continue;
725
+ codes.push(`${style.module}: Record<string, string> & import('${sharedTypesImport}').Prettify<{}`);
726
+ for (const className of style.classNames) {
727
+ generateCssClassProperty(i, className.text.substring(1), { start: className.offset, end: className.offset + className.text.length }, 'string', false);
724
728
  }
725
729
  codes.push('>;\n');
726
730
  }
@@ -734,9 +738,12 @@ declare function defineProp<T>(value?: T | (() => T), required?: boolean, rest?:
734
738
  /* Style Scoped */
735
739
  codes.push('/* Style Scoped */\n');
736
740
  codes.push('type __VLS_StyleScopedClasses = {}');
737
- for (const scopedCss of cssScopedClasses) {
738
- for (const classNameRange of scopedCss.classNameRanges) {
739
- generateCssClassProperty(scopedCss.index, scopedCss.style.content.substring(classNameRange.start + 1, classNameRange.end), classNameRange, 'boolean', true);
741
+ for (let i = 0; i < _sfc.styles.length; i++) {
742
+ const style = _sfc.styles[i];
743
+ if (!style.scoped)
744
+ continue;
745
+ for (const className of style.classNames) {
746
+ generateCssClassProperty(i, className.text.substring(1), { start: className.offset, end: className.offset + className.text.length }, 'boolean', true);
740
747
  }
741
748
  }
742
749
  codes.push(';\n');
@@ -745,9 +752,14 @@ declare function defineProp<T>(value?: T | (() => T), required?: boolean, rest?:
745
752
  const cssIds = generateCssVars();
746
753
  codes.push(`/* CSS variable injection end */\n`);
747
754
  if (htmlGen) {
755
+ muggle.setTracking(false);
748
756
  for (const s of htmlGen.codes) {
749
757
  codes.push(s);
750
758
  }
759
+ muggle.setTracking(true);
760
+ for (const s of htmlGen.codeStacks) {
761
+ codeStacks.push(s);
762
+ }
751
763
  }
752
764
  if (!htmlGen) {
753
765
  codes.push(`// no template\n`);
@@ -799,18 +811,17 @@ declare function defineProp<T>(value?: T | (() => T), required?: boolean, rest?:
799
811
  function generateCssVars() {
800
812
  const emptyLocalVars = {};
801
813
  const identifiers = new Set();
802
- for (const cssVar of cssVars) {
803
- for (const cssBind of cssVar.ranges) {
804
- const code = cssVar.style.content.substring(cssBind.start, cssBind.end);
805
- (0, transform_1.walkInterpolationFragment)(ts, code, ts.createSourceFile('/a.txt', code, ts.ScriptTarget.ESNext), (frag, fragOffset, onlyForErrorMapping) => {
814
+ for (const style of _sfc.styles) {
815
+ for (const cssBind of style.cssVars) {
816
+ (0, transform_1.walkInterpolationFragment)(ts, cssBind.text, ts.createSourceFile('/a.txt', cssBind.text, ts.ScriptTarget.ESNext), (frag, fragOffset, onlyForErrorMapping) => {
806
817
  if (fragOffset === undefined) {
807
818
  codes.push(frag);
808
819
  }
809
820
  else {
810
821
  codes.push([
811
822
  frag,
812
- cssVar.style.name,
813
- cssBind.start + fragOffset,
823
+ style.name,
824
+ cssBind.offset + fragOffset,
814
825
  onlyForErrorMapping
815
826
  ? { diagnostic: true }
816
827
  : language_core_1.FileRangeCapabilities.full,
@@ -851,14 +862,17 @@ declare function defineProp<T>(value?: T | (() => T), required?: boolean, rest?:
851
862
  return usageVars;
852
863
  }
853
864
  function addVirtualCode(vueTag, start, end) {
865
+ muggle.offsetStack();
854
866
  codes.push([
855
867
  sfc[vueTag].content.substring(start, end),
856
868
  vueTag,
857
869
  start,
858
870
  language_core_1.FileRangeCapabilities.full, // diagnostic also working for setup() returns unused in template checking
859
871
  ]);
872
+ muggle.resetOffsetStack();
860
873
  }
861
874
  function addExtraReferenceVirtualCode(vueTag, start, end) {
875
+ muggle.offsetStack();
862
876
  codes.push([
863
877
  sfc[vueTag].content.substring(start, end),
864
878
  vueTag,
@@ -869,6 +883,7 @@ declare function defineProp<T>(value?: T | (() => T), required?: boolean, rest?:
869
883
  rename: true,
870
884
  },
871
885
  ]);
886
+ muggle.resetOffsetStack();
872
887
  }
873
888
  }
874
889
  exports.generate = generate;
@@ -2,12 +2,16 @@ import { Segment } from '@volar/source-map';
2
2
  import { FileRangeCapabilities } from '@volar/language-core';
3
3
  import * as CompilerDOM from '@vue/compiler-dom';
4
4
  import type * as ts from 'typescript/lib/tsserverlibrary';
5
- import { VueCompilerOptions } from '../types';
5
+ import { Sfc, VueCompilerOptions } from '../types';
6
+ import * as muggle from 'muggle-string';
6
7
  type Code = Segment<FileRangeCapabilities>;
7
- export declare function generate(ts: typeof import('typescript/lib/tsserverlibrary'), compilerOptions: ts.CompilerOptions, vueCompilerOptions: VueCompilerOptions, sourceTemplate: string, sourceLang: string, templateAst: CompilerDOM.RootNode, hasScriptSetupSlots: boolean, sharedTypesImport: string, cssScopedClasses?: string[]): {
8
+ export declare function generate(ts: typeof import('typescript/lib/tsserverlibrary'), compilerOptions: ts.CompilerOptions, vueCompilerOptions: VueCompilerOptions, sourceTemplate: string, sourceLang: string, sfc: Sfc, hasScriptSetupSlots: boolean, sharedTypesImport: string, codegenStack: boolean): {
8
9
  codes: Code[];
10
+ codeStacks: muggle.StackNode[];
9
11
  formatCodes: Code[];
12
+ formatCodeStacks: muggle.StackNode[];
10
13
  cssCodes: Code[];
14
+ cssCodeStacks: muggle.StackNode[];
11
15
  tagNames: Record<string, number[]>;
12
16
  identifiers: Set<string>;
13
17
  hasSlot: boolean;
@@ -57,13 +57,12 @@ const transformContext = {
57
57
  },
58
58
  expressionPlugins: ['typescript'],
59
59
  };
60
- function generate(ts, compilerOptions, vueCompilerOptions, sourceTemplate, sourceLang, templateAst, hasScriptSetupSlots, sharedTypesImport, cssScopedClasses = []) {
61
- const codes = [];
62
- const formatCodes = [];
63
- const cssCodes = [];
60
+ function generate(ts, compilerOptions, vueCompilerOptions, sourceTemplate, sourceLang, sfc, hasScriptSetupSlots, sharedTypesImport, codegenStack) {
61
+ const [codes, codeStacks] = codegenStack ? muggle.track([]) : [[], []];
62
+ const [formatCodes, formatCodeStacks] = codegenStack ? muggle.track([]) : [[], []];
63
+ const [cssCodes, cssCodeStacks] = codegenStack ? muggle.track([]) : [[], []];
64
64
  const slots = new Map();
65
65
  const slotExps = new Map();
66
- const cssScopedClassesSet = new Set(cssScopedClasses);
67
66
  const tagNames = collectTagOffsets();
68
67
  const localVars = {};
69
68
  const tempVars = [];
@@ -73,7 +72,9 @@ function generate(ts, compilerOptions, vueCompilerOptions, sourceTemplate, sourc
73
72
  let hasSlot = false;
74
73
  let elementIndex = 0;
75
74
  const componentVars = generateComponentVars();
76
- visitNode(templateAst, undefined, undefined);
75
+ if (sfc.templateAst) {
76
+ visitNode(sfc.templateAst, undefined, undefined);
77
+ }
77
78
  generateStyleScopedClasses();
78
79
  if (!hasScriptSetupSlots) {
79
80
  codes.push('var __VLS_slots!:', ...createSlotsTypeCode(), ';\n');
@@ -81,8 +82,11 @@ function generate(ts, compilerOptions, vueCompilerOptions, sourceTemplate, sourc
81
82
  generateAutoImportCompletionCode();
82
83
  return {
83
84
  codes,
85
+ codeStacks,
84
86
  formatCodes,
87
+ formatCodeStacks,
85
88
  cssCodes,
89
+ cssCodeStacks,
86
90
  tagNames,
87
91
  identifiers,
88
92
  hasSlot,
@@ -111,6 +115,14 @@ function generate(ts, compilerOptions, vueCompilerOptions, sourceTemplate, sourc
111
115
  return codes;
112
116
  }
113
117
  function generateStyleScopedClasses() {
118
+ const allClasses = new Set();
119
+ for (const block of sfc.styles) {
120
+ if (block.scoped) {
121
+ for (const className of block.classNames) {
122
+ allClasses.add(className.text.substring(1));
123
+ }
124
+ }
125
+ }
114
126
  codes.push(`if (typeof __VLS_styleScopedClasses === 'object' && !Array.isArray(__VLS_styleScopedClasses)) {\n`);
115
127
  for (const { className, offset } of scopedClasses) {
116
128
  codes.push(`__VLS_styleScopedClasses[`);
@@ -120,7 +132,7 @@ function generate(ts, compilerOptions, vueCompilerOptions, sourceTemplate, sourc
120
132
  offset,
121
133
  {
122
134
  ...capabilitiesPresets.scopedClassName,
123
- displayWithLink: cssScopedClassesSet.has(className),
135
+ displayWithLink: allClasses.has(className),
124
136
  },
125
137
  ]));
126
138
  codes.push(`];\n`);
@@ -192,7 +204,10 @@ function generate(ts, compilerOptions, vueCompilerOptions, sourceTemplate, sourc
192
204
  }
193
205
  function collectTagOffsets() {
194
206
  const tagOffsetsMap = {};
195
- walkElementNodes(templateAst, node => {
207
+ if (!sfc.templateAst) {
208
+ return tagOffsetsMap;
209
+ }
210
+ walkElementNodes(sfc.templateAst, node => {
196
211
  if (node.tag === 'slot') {
197
212
  // ignore
198
213
  }
@@ -466,7 +481,7 @@ function generate(ts, compilerOptions, vueCompilerOptions, sourceTemplate, sourc
466
481
  }
467
482
  generateDirectives(node, var_originalComponent);
468
483
  generateElReferences(node); // <el ref="foo" />
469
- if (cssScopedClasses.length) {
484
+ if (sfc.styles.some(s => s.scoped)) {
470
485
  generateClassScoped(node);
471
486
  }
472
487
  if (componentCtxVar) {
@@ -507,7 +522,7 @@ function generate(ts, compilerOptions, vueCompilerOptions, sourceTemplate, sourc
507
522
  ], ` = (await import('${sharedTypesImport}')).getSlotParam(`);
508
523
  }
509
524
  }
510
- codes.push(['', 'template', (slotDir.arg ?? slotDir).loc.start.offset, capabilitiesPresets.diagnosticOnly], `${componentCtxVar}.slots!`, ...((slotDir?.arg?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */ && slotDir.arg.content)
525
+ codes.push(['', 'template', (slotDir.arg ?? slotDir).loc.start.offset, capabilitiesPresets.diagnosticOnly], `(${componentCtxVar}.slots!)`, ...((slotDir?.arg?.type === 4 /* CompilerDOM.NodeTypes.SIMPLE_EXPRESSION */ && slotDir.arg.content)
511
526
  ? createPropertyAccessCode([
512
527
  slotDir.arg.loc.source,
513
528
  'template',
@@ -1,5 +1,5 @@
1
1
  import type { Language } from '@volar/language-core';
2
2
  import { VueCompilerOptions } from './types';
3
3
  import type * as ts from 'typescript/lib/tsserverlibrary';
4
- export declare function createLanguage(compilerOptions?: ts.CompilerOptions, vueCompilerOptions?: VueCompilerOptions, ts?: typeof import('typescript/lib/tsserverlibrary')): Language;
5
- export declare function createLanguages(compilerOptions?: ts.CompilerOptions, vueCompilerOptions?: VueCompilerOptions, ts?: typeof import('typescript/lib/tsserverlibrary')): Language[];
4
+ export declare function createLanguage(compilerOptions?: ts.CompilerOptions, vueCompilerOptions?: VueCompilerOptions, ts?: typeof import('typescript/lib/tsserverlibrary'), codegenStack?: boolean): Language;
5
+ export declare function createLanguages(compilerOptions?: ts.CompilerOptions, vueCompilerOptions?: VueCompilerOptions, ts?: typeof import('typescript/lib/tsserverlibrary'), codegenStack?: boolean): Language[];
@@ -6,16 +6,16 @@ const plugins_1 = require("./plugins");
6
6
  const sourceFile_1 = require("./sourceFile");
7
7
  const sharedTypes = require("./utils/directorySharedTypes");
8
8
  const ts_1 = require("./utils/ts");
9
- function createLanguage(compilerOptions = {}, vueCompilerOptions = (0, ts_1.resolveVueCompilerOptions)({}), ts = require('typescript')) {
9
+ function createLanguage(compilerOptions = {}, vueCompilerOptions = (0, ts_1.resolveVueCompilerOptions)({}), ts = require('typescript'), codegenStack = false) {
10
10
  patchResolveModuleNames(ts, vueCompilerOptions);
11
- const vueLanguagePlugin = (0, plugins_1.getDefaultVueLanguagePlugins)(ts, compilerOptions, vueCompilerOptions);
11
+ const vueLanguagePlugin = (0, plugins_1.getDefaultVueLanguagePlugins)(ts, compilerOptions, vueCompilerOptions, codegenStack);
12
12
  const sharedTypesSnapshot = ts.ScriptSnapshot.fromString(sharedTypes.getTypesCode(vueCompilerOptions));
13
13
  const languageModule = {
14
14
  createVirtualFile(fileName, snapshot, languageId) {
15
15
  if (languageId === 'vue'
16
16
  || (!languageId
17
17
  && vueCompilerOptions.extensions.some(ext => fileName.endsWith(ext)))) {
18
- return new sourceFile_1.VueFile(fileName, snapshot, ts, vueLanguagePlugin);
18
+ return new sourceFile_1.VueFile(fileName, snapshot, vueCompilerOptions, vueLanguagePlugin, ts, codegenStack);
19
19
  }
20
20
  },
21
21
  updateVirtualFile(sourceFile, snapshot) {
@@ -63,9 +63,9 @@ function createLanguage(compilerOptions = {}, vueCompilerOptions = (0, ts_1.reso
63
63
  }
64
64
  }
65
65
  exports.createLanguage = createLanguage;
66
- function createLanguages(compilerOptions = {}, vueCompilerOptions = (0, ts_1.resolveVueCompilerOptions)({}), ts = require('typescript')) {
66
+ function createLanguages(compilerOptions = {}, vueCompilerOptions = (0, ts_1.resolveVueCompilerOptions)({}), ts = require('typescript'), codegenStack = false) {
67
67
  return [
68
- createLanguage(compilerOptions, vueCompilerOptions, ts),
68
+ createLanguage(compilerOptions, vueCompilerOptions, ts, codegenStack),
69
69
  ...vueCompilerOptions.experimentalAdditionalLanguageModules?.map(module => require(module)) ?? [],
70
70
  ];
71
71
  }
@@ -1,14 +1,3 @@
1
- import { Sfc, VueLanguagePlugin } from '../types';
2
- import { TextRange } from '../types';
1
+ import { VueLanguagePlugin } from '../types';
3
2
  declare const plugin: VueLanguagePlugin;
4
3
  export default plugin;
5
- export declare function collectStyleCssClasses(sfc: Sfc, condition: (style: Sfc['styles'][number]) => boolean): {
6
- style: (typeof sfc.styles)[number];
7
- index: number;
8
- classNameRanges: TextRange[];
9
- classNames: string[];
10
- }[];
11
- export declare function collectCssVars(sfc: Sfc): {
12
- style: (typeof sfc.styles)[number];
13
- ranges: TextRange[];
14
- }[];
@@ -1,16 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.collectCssVars = exports.collectStyleCssClasses = void 0;
4
3
  const reactivity_1 = require("@vue/reactivity");
5
4
  const script_1 = require("../generators/script");
6
5
  const templateGen = require("../generators/template");
7
6
  const scriptRanges_1 = require("../parsers/scriptRanges");
8
7
  const scriptSetupRanges_1 = require("../parsers/scriptSetupRanges");
9
8
  const language_core_1 = require("@volar/language-core");
10
- const parseCssClassNames_1 = require("../utils/parseCssClassNames");
11
- const parseCssVars_1 = require("../utils/parseCssVars");
12
9
  const sharedTypes = require("../utils/directorySharedTypes");
13
- const plugin = ({ modules, vueCompilerOptions, compilerOptions }) => {
10
+ const muggle = require("muggle-string");
11
+ const plugin = ({ modules, vueCompilerOptions, compilerOptions, codegenStack }) => {
14
12
  const ts = modules.typescript;
15
13
  const instances = new WeakMap();
16
14
  const sharedTypesImport = sharedTypes.getImportName(compilerOptions);
@@ -41,7 +39,9 @@ const plugin = ({ modules, vueCompilerOptions, compilerOptions }) => {
41
39
  };
42
40
  const tsx = _tsx.tsxGen.value;
43
41
  if (tsx) {
44
- embeddedFile.content = [...tsx.codes];
42
+ const [content, contentStacks] = codegenStack ? muggle.track([...tsx.codes], [...tsx.codeStacks]) : [[...tsx.codes], [...tsx.codeStacks]];
43
+ embeddedFile.content = content;
44
+ embeddedFile.contentStacks = contentStacks;
45
45
  embeddedFile.mirrorBehaviorMappings = [...tsx.mirrorBehaviorMappings];
46
46
  }
47
47
  }
@@ -56,16 +56,18 @@ const plugin = ({ modules, vueCompilerOptions, compilerOptions }) => {
56
56
  inlayHint: false,
57
57
  };
58
58
  if (_tsx.htmlGen.value) {
59
- embeddedFile.content = [..._tsx.htmlGen.value.formatCodes];
59
+ const [content, contentStacks] = codegenStack ? muggle.track([..._tsx.htmlGen.value.formatCodes], [..._tsx.htmlGen.value.formatCodeStacks]) : [[..._tsx.htmlGen.value.formatCodes], [..._tsx.htmlGen.value.formatCodeStacks]];
60
+ embeddedFile.content = content;
61
+ embeddedFile.contentStacks = contentStacks;
60
62
  }
61
- for (const cssVar of _tsx.cssVars.value) {
63
+ for (const style of sfc.styles) {
62
64
  embeddedFile.content.push('\n\n');
63
- for (const range of cssVar.ranges) {
65
+ for (const cssVar of style.cssVars) {
64
66
  embeddedFile.content.push('(');
65
67
  embeddedFile.content.push([
66
- cssVar.style.content.substring(range.start, range.end),
67
- cssVar.style.name,
68
- range.start,
68
+ cssVar.text,
69
+ style.name,
70
+ cssVar.offset,
69
71
  {},
70
72
  ]);
71
73
  embeddedFile.content.push(');\n');
@@ -75,7 +77,9 @@ const plugin = ({ modules, vueCompilerOptions, compilerOptions }) => {
75
77
  else if (suffix.match(/^\.template_style\.css$/)) {
76
78
  embeddedFile.parentFileName = fileName + '.template.' + sfc.template?.lang;
77
79
  if (_tsx.htmlGen.value) {
78
- embeddedFile.content = [..._tsx.htmlGen.value.cssCodes];
80
+ const [content, contentStacks] = codegenStack ? muggle.track([..._tsx.htmlGen.value.cssCodes], [..._tsx.htmlGen.value.cssCodeStacks]) : [[..._tsx.htmlGen.value.cssCodes], [..._tsx.htmlGen.value.cssCodeStacks]];
81
+ embeddedFile.content = content;
82
+ embeddedFile.contentStacks = contentStacks;
79
83
  }
80
84
  // for color pickers support
81
85
  embeddedFile.capabilities.documentSymbol = true;
@@ -95,64 +99,28 @@ const plugin = ({ modules, vueCompilerOptions, compilerOptions }) => {
95
99
  : _sfc.script && _sfc.script.lang !== 'js' ? _sfc.script.lang
96
100
  : 'js';
97
101
  });
98
- const cssVars = (0, reactivity_1.computed)(() => collectCssVars(_sfc));
99
102
  const scriptRanges = (0, reactivity_1.computed)(() => _sfc.scriptAst
100
103
  ? (0, scriptRanges_1.parseScriptRanges)(ts, _sfc.scriptAst, !!_sfc.scriptSetup, false)
101
104
  : undefined);
102
105
  const scriptSetupRanges = (0, reactivity_1.computed)(() => _sfc.scriptSetupAst
103
106
  ? (0, scriptSetupRanges_1.parseScriptSetupRanges)(ts, _sfc.scriptSetupAst, vueCompilerOptions)
104
107
  : undefined);
105
- const cssModuleClasses = (0, reactivity_1.computed)(() => collectStyleCssClasses(_sfc, style => !!style.module));
106
- const cssScopedClasses = (0, reactivity_1.computed)(() => collectStyleCssClasses(_sfc, style => {
107
- const setting = vueCompilerOptions.experimentalResolveStyleCssClasses;
108
- return (setting === 'scoped' && style.scoped) || setting === 'always';
109
- }));
110
108
  const htmlGen = (0, reactivity_1.computed)(() => {
111
109
  if (!_sfc.templateAst)
112
110
  return;
113
- return templateGen.generate(ts, compilerOptions, vueCompilerOptions, _sfc.template?.content ?? '', _sfc.template?.lang ?? 'html', _sfc.templateAst, hasScriptSetupSlots.value, sharedTypesImport, Object.values(cssScopedClasses.value).map(style => style.classNames).flat());
111
+ return templateGen.generate(ts, compilerOptions, vueCompilerOptions, _sfc.template?.content ?? '', _sfc.template?.lang ?? 'html', _sfc, hasScriptSetupSlots.value, sharedTypesImport, codegenStack);
114
112
  });
115
113
  const hasScriptSetupSlots = (0, reactivity_1.shallowRef)(false); // remove when https://github.com/vuejs/core/pull/5912 merged
116
114
  const tsxGen = (0, reactivity_1.computed)(() => {
117
115
  hasScriptSetupSlots.value = !!scriptSetupRanges.value?.slotsTypeArg;
118
- return (0, script_1.generate)(ts, fileName, _sfc, lang.value, scriptRanges.value, scriptSetupRanges.value, cssVars.value, cssModuleClasses.value, cssScopedClasses.value, htmlGen.value, compilerOptions, vueCompilerOptions, sharedTypesImport);
116
+ return (0, script_1.generate)(ts, fileName, _sfc, lang.value, scriptRanges.value, scriptSetupRanges.value, htmlGen.value, compilerOptions, vueCompilerOptions, sharedTypesImport, codegenStack);
119
117
  });
120
118
  return {
121
119
  lang,
122
120
  tsxGen,
123
121
  htmlGen,
124
- cssVars,
125
122
  };
126
123
  }
127
124
  };
128
125
  exports.default = plugin;
129
- function collectStyleCssClasses(sfc, condition) {
130
- const result = [];
131
- for (let i = 0; i < sfc.styles.length; i++) {
132
- const style = sfc.styles[i];
133
- if (condition(style)) {
134
- const classNameRanges = [...(0, parseCssClassNames_1.parseCssClassNames)(style.content)];
135
- result.push({
136
- style: style,
137
- index: i,
138
- classNameRanges: classNameRanges,
139
- classNames: classNameRanges.map(range => style.content.substring(range.start + 1, range.end)),
140
- });
141
- }
142
- }
143
- return result;
144
- }
145
- exports.collectStyleCssClasses = collectStyleCssClasses;
146
- function collectCssVars(sfc) {
147
- const result = [];
148
- for (let i = 0; i < sfc.styles.length; i++) {
149
- const style = sfc.styles[i];
150
- result.push({
151
- style,
152
- ranges: [...(0, parseCssVars_1.parseCssVars)(style.content)],
153
- });
154
- }
155
- return result;
156
- }
157
- exports.collectCssVars = collectCssVars;
158
126
  //# sourceMappingURL=vue-tsx.js.map
package/out/plugins.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type * as ts from 'typescript/lib/tsserverlibrary';
2
2
  import { VueCompilerOptions } from './types';
3
3
  import * as CompilerDOM from '@vue/compiler-dom';
4
- export declare function getDefaultVueLanguagePlugins(ts: typeof import('typescript/lib/tsserverlibrary'), compilerOptions: ts.CompilerOptions, vueCompilerOptions: VueCompilerOptions): {
4
+ export declare function getDefaultVueLanguagePlugins(ts: typeof import('typescript/lib/tsserverlibrary'), compilerOptions: ts.CompilerOptions, vueCompilerOptions: VueCompilerOptions, codegenStack: boolean): {
5
5
  version: 1;
6
6
  name?: string | undefined;
7
7
  order?: number | undefined;
package/out/plugins.js CHANGED
@@ -12,7 +12,7 @@ const useHtmlTemplatePlugin = require("./plugins/vue-template-html");
12
12
  const vue_tsx_1 = require("./plugins/vue-tsx");
13
13
  const CompilerDOM = require("@vue/compiler-dom");
14
14
  const CompilerVue2 = require("./utils/vue2TemplateCompiler");
15
- function getDefaultVueLanguagePlugins(ts, compilerOptions, vueCompilerOptions) {
15
+ function getDefaultVueLanguagePlugins(ts, compilerOptions, vueCompilerOptions, codegenStack) {
16
16
  const plugins = [
17
17
  useMdFilePlugin,
18
18
  useHtmlFilePlugin,
@@ -32,6 +32,7 @@ function getDefaultVueLanguagePlugins(ts, compilerOptions, vueCompilerOptions) {
32
32
  },
33
33
  compilerOptions,
34
34
  vueCompilerOptions,
35
+ codegenStack,
35
36
  };
36
37
  const pluginInstances = plugins
37
38
  .map(plugin => plugin(pluginCtx))
@@ -1,24 +1,28 @@
1
1
  import { FileCapabilities, VirtualFile, FileKind, FileRangeCapabilities, MirrorBehaviorCapabilities } from '@volar/language-core';
2
- import { Mapping, Segment } from '@volar/source-map';
2
+ import { Mapping, Segment, StackNode, Stack } from '@volar/source-map';
3
3
  import * as CompilerDom from '@vue/compiler-dom';
4
- import { SFCBlock, SFCParseResult, SFCScriptBlock, SFCStyleBlock, SFCTemplateBlock } from '@vue/compiler-sfc';
4
+ import type { SFCBlock, SFCParseResult, SFCScriptBlock, SFCStyleBlock, SFCTemplateBlock } from '@vue/compiler-sfc';
5
5
  import { ComputedRef } from '@vue/reactivity';
6
6
  import type * as ts from 'typescript/lib/tsserverlibrary';
7
7
  import { Sfc, SfcBlock, VueLanguagePlugin } from './types';
8
+ import { VueCompilerOptions } from './types';
8
9
  export declare class VueEmbeddedFile {
9
10
  fileName: string;
11
+ content: Segment<FileRangeCapabilities>[];
12
+ contentStacks: StackNode[];
10
13
  parentFileName?: string;
11
14
  kind: FileKind;
12
15
  capabilities: FileCapabilities;
13
- content: Segment<FileRangeCapabilities>[];
14
16
  mirrorBehaviorMappings: Mapping<[MirrorBehaviorCapabilities, MirrorBehaviorCapabilities]>[];
15
- constructor(fileName: string);
17
+ constructor(fileName: string, content: Segment<FileRangeCapabilities>[], contentStacks: StackNode[]);
16
18
  }
17
19
  export declare class VueFile implements VirtualFile {
18
20
  fileName: string;
19
21
  snapshot: ts.IScriptSnapshot;
20
- private ts;
21
- private plugins;
22
+ vueCompilerOptions: VueCompilerOptions;
23
+ plugins: ReturnType<VueLanguagePlugin>[];
24
+ ts: typeof import('typescript/lib/tsserverlibrary');
25
+ codegenStack: boolean;
22
26
  parsedSfcCache: {
23
27
  snapshot: ts.IScriptSnapshot;
24
28
  sfc: SFCParseResult;
@@ -33,6 +37,7 @@ export declare class VueFile implements VirtualFile {
33
37
  capabilities: FileCapabilities;
34
38
  kind: FileKind;
35
39
  mappings: Mapping<FileRangeCapabilities>[];
40
+ codegenStacks: Stack[];
36
41
  get compiledSFCTemplate(): {
37
42
  errors: CompilerDom.CompilerError[];
38
43
  warnings: CompilerDom.CompilerError[];
@@ -40,7 +45,6 @@ export declare class VueFile implements VirtualFile {
40
45
  } | undefined;
41
46
  get mainScriptName(): string;
42
47
  get embeddedFiles(): VirtualFile[];
43
- parsedSfc: SFCParseResult | undefined;
44
48
  sfc: Sfc;
45
49
  _sfcBlocks: ComputedRef<Record<string, SfcBlock>>;
46
50
  _compiledSfcTemplate: ComputedRef<{
@@ -52,20 +56,22 @@ export declare class VueFile implements VirtualFile {
52
56
  file: VueEmbeddedFile;
53
57
  snapshot: ts.IScriptSnapshot;
54
58
  mappings: Mapping<FileRangeCapabilities>[];
59
+ codegenStacks: Stack[];
55
60
  }[]>[];
56
61
  _allEmbeddedFiles: ComputedRef<{
57
62
  file: VueEmbeddedFile;
58
63
  snapshot: ts.IScriptSnapshot;
59
64
  mappings: Mapping<FileRangeCapabilities>[];
65
+ codegenStacks: Stack[];
60
66
  }[]>;
61
67
  _embeddedFiles: ComputedRef<VirtualFile[]>;
62
- constructor(fileName: string, snapshot: ts.IScriptSnapshot, ts: typeof import('typescript/lib/tsserverlibrary'), plugins: ReturnType<VueLanguagePlugin>[]);
68
+ constructor(fileName: string, snapshot: ts.IScriptSnapshot, vueCompilerOptions: VueCompilerOptions, plugins: ReturnType<VueLanguagePlugin>[], ts: typeof import('typescript/lib/tsserverlibrary'), codegenStack: boolean);
63
69
  update(newScriptSnapshot: ts.IScriptSnapshot): void;
64
70
  parseSfc(): SFCParseResult | undefined;
65
- updateTemplate(block: SFCTemplateBlock | null): void;
66
- updateScript(block: SFCScriptBlock | null): void;
67
- updateScriptSetup(block: SFCScriptBlock | null): void;
68
- updateStyles(blocks: SFCStyleBlock[]): void;
69
- updateCustomBlocks(blocks: SFCBlock[]): void;
70
- updateBlock<T extends object>(oldBlock: T, newBlock: T): void;
71
+ parseTemplateBlock(block: SFCTemplateBlock): NonNullable<Sfc['template']>;
72
+ parseScriptBlock(block: SFCScriptBlock): NonNullable<Sfc['script']>;
73
+ parseScriptSetupBlock(block: SFCScriptBlock): NonNullable<Sfc['scriptSetup']>;
74
+ parseStyleBlock(block: SFCStyleBlock, i: number): Sfc['styles'][number];
75
+ parseCustomBlock(block: SFCBlock, i: number): Sfc['customBlocks'][number];
76
+ parseBlock(block: SFCBlock): Omit<SfcBlock, 'name' | 'lang'>;
71
77
  }
package/out/sourceFile.js CHANGED
@@ -5,12 +5,15 @@ const language_core_1 = require("@volar/language-core");
5
5
  const source_map_1 = require("@volar/source-map");
6
6
  const reactivity_1 = require("@vue/reactivity");
7
7
  const muggle = require("muggle-string");
8
+ const parseCssVars_1 = require("./utils/parseCssVars");
9
+ const parseCssClassNames_1 = require("./utils/parseCssClassNames");
8
10
  class VueEmbeddedFile {
9
- constructor(fileName) {
11
+ constructor(fileName, content, contentStacks) {
10
12
  this.fileName = fileName;
13
+ this.content = content;
14
+ this.contentStacks = contentStacks;
11
15
  this.kind = language_core_1.FileKind.TextFile;
12
16
  this.capabilities = {};
13
- this.content = [];
14
17
  this.mirrorBehaviorMappings = [];
15
18
  }
16
19
  }
@@ -25,15 +28,17 @@ class VueFile {
25
28
  get embeddedFiles() {
26
29
  return this._embeddedFiles.value;
27
30
  }
28
- // functions
29
- constructor(fileName, snapshot, ts, plugins) {
31
+ constructor(fileName, snapshot, vueCompilerOptions, plugins, ts, codegenStack) {
30
32
  this.fileName = fileName;
31
33
  this.snapshot = snapshot;
32
- this.ts = ts;
34
+ this.vueCompilerOptions = vueCompilerOptions;
33
35
  this.plugins = plugins;
36
+ this.ts = ts;
37
+ this.codegenStack = codegenStack;
34
38
  this.capabilities = language_core_1.FileCapabilities.full;
35
39
  this.kind = language_core_1.FileKind.TextFile;
36
40
  this.mappings = [];
41
+ this.codegenStacks = [];
37
42
  // refs
38
43
  this.sfc = (0, reactivity_1.reactive)({
39
44
  template: null,
@@ -54,12 +59,6 @@ class VueFile {
54
59
  return this.ts.createSourceFile(this.fileName + '.' + this.sfc.scriptSetup.lang, this.sfc.scriptSetup.content, this.ts.ScriptTarget.Latest);
55
60
  }
56
61
  }),
57
- ...{
58
- // backward compatible
59
- getTemplateAst: () => {
60
- return this.compiledSFCTemplate?.ast;
61
- },
62
- },
63
62
  }) /* avoid Sfc unwrap in .d.ts by reactive */;
64
63
  // computed
65
64
  this._sfcBlocks = (0, reactivity_1.computed)(() => {
@@ -171,7 +170,8 @@ class VueFile {
171
170
  for (const embeddedFileName of embeddedFileNames) {
172
171
  if (!embeddedFiles[embeddedFileName]) {
173
172
  embeddedFiles[embeddedFileName] = (0, reactivity_1.computed)(() => {
174
- const file = new VueEmbeddedFile(embeddedFileName);
173
+ const [content, stacks] = this.codegenStack ? muggle.track([]) : [[], []];
174
+ const file = new VueEmbeddedFile(embeddedFileName, content, stacks);
175
175
  for (const plugin of this.plugins) {
176
176
  if (plugin.resolveEmbeddedFile) {
177
177
  try {
@@ -182,7 +182,45 @@ class VueFile {
182
182
  }
183
183
  }
184
184
  }
185
- return file;
185
+ const newText = (0, source_map_1.toString)(file.content);
186
+ const changeRanges = new Map();
187
+ const snapshot = {
188
+ getText: (start, end) => newText.slice(start, end),
189
+ getLength: () => newText.length,
190
+ getChangeRange(oldSnapshot) {
191
+ if (!changeRanges.has(oldSnapshot)) {
192
+ changeRanges.set(oldSnapshot, undefined);
193
+ const oldText = oldSnapshot.getText(0, oldSnapshot.getLength());
194
+ for (let start = 0; start < oldText.length && start < newText.length; start++) {
195
+ if (oldText[start] !== newText[start]) {
196
+ let end = oldText.length;
197
+ for (let i = 0; i < oldText.length - start && i < newText.length - start; i++) {
198
+ if (oldText[oldText.length - i - 1] !== newText[newText.length - i - 1]) {
199
+ break;
200
+ }
201
+ end--;
202
+ }
203
+ let length = end - start;
204
+ let newLength = length + (newText.length - oldText.length);
205
+ if (newLength < 0) {
206
+ length -= newLength;
207
+ newLength = 0;
208
+ }
209
+ changeRanges.set(oldSnapshot, {
210
+ span: { start, length },
211
+ newLength,
212
+ });
213
+ break;
214
+ }
215
+ }
216
+ }
217
+ return changeRanges.get(oldSnapshot);
218
+ },
219
+ };
220
+ return {
221
+ file,
222
+ snapshot,
223
+ };
186
224
  });
187
225
  }
188
226
  }
@@ -195,7 +233,8 @@ class VueFile {
195
233
  });
196
234
  return (0, reactivity_1.computed)(() => {
197
235
  return files.value.map(_file => {
198
- const file = _file.value;
236
+ const file = _file.value.file;
237
+ const snapshot = _file.value.snapshot;
199
238
  const mappings = (0, source_map_1.buildMappings)(file.content);
200
239
  for (const mapping of mappings) {
201
240
  if (mapping.source !== undefined) {
@@ -205,49 +244,18 @@ class VueFile {
205
244
  mapping.sourceRange[0] + block.startTagEnd,
206
245
  mapping.sourceRange[1] + block.startTagEnd,
207
246
  ];
208
- mapping.source = undefined;
209
247
  }
248
+ else {
249
+ // ignore
250
+ }
251
+ mapping.source = undefined;
210
252
  }
211
253
  }
212
- const newText = (0, source_map_1.toString)(file.content);
213
- const changeRanges = new Map();
214
- const snapshot = {
215
- getText: (start, end) => newText.slice(start, end),
216
- getLength: () => newText.length,
217
- getChangeRange(oldSnapshot) {
218
- if (!changeRanges.has(oldSnapshot)) {
219
- changeRanges.set(oldSnapshot, undefined);
220
- const oldText = oldSnapshot.getText(0, oldSnapshot.getLength());
221
- for (let start = 0; start < oldText.length && start < newText.length; start++) {
222
- if (oldText[start] !== newText[start]) {
223
- let end = oldText.length;
224
- for (let i = 0; i < oldText.length - start && i < newText.length - start; i++) {
225
- if (oldText[oldText.length - i - 1] !== newText[newText.length - i - 1]) {
226
- break;
227
- }
228
- end--;
229
- }
230
- let length = end - start;
231
- let newLength = length + (newText.length - oldText.length);
232
- if (newLength < 0) {
233
- length -= newLength;
234
- newLength = 0;
235
- }
236
- changeRanges.set(oldSnapshot, {
237
- span: { start, length },
238
- newLength,
239
- });
240
- break;
241
- }
242
- }
243
- }
244
- return changeRanges.get(oldSnapshot);
245
- },
246
- };
247
254
  return {
248
255
  file,
249
256
  snapshot,
250
257
  mappings,
258
+ codegenStacks: (0, source_map_1.buildStacks)(file.content, file.contentStacks),
251
259
  };
252
260
  });
253
261
  });
@@ -271,11 +279,12 @@ class VueFile {
271
279
  break;
272
280
  }
273
281
  }
274
- for (const { file, snapshot, mappings } of remain) {
282
+ for (const { file, snapshot, mappings, codegenStacks } of remain) {
275
283
  embeddedFiles.push({
276
284
  ...file,
277
285
  snapshot,
278
286
  mappings,
287
+ codegenStacks,
279
288
  embeddedFiles: [],
280
289
  });
281
290
  console.error('Unable to resolve embedded: ' + file.parentFileName + ' -> ' + file.fileName);
@@ -283,12 +292,13 @@ class VueFile {
283
292
  return embeddedFiles;
284
293
  function consumeRemain() {
285
294
  for (let i = remain.length - 1; i >= 0; i--) {
286
- const { file, snapshot, mappings } = remain[i];
295
+ const { file, snapshot, mappings, codegenStacks } = remain[i];
287
296
  if (!file.parentFileName) {
288
297
  embeddedFiles.push({
289
298
  ...file,
290
299
  snapshot,
291
300
  mappings,
301
+ codegenStacks,
292
302
  embeddedFiles: [],
293
303
  });
294
304
  remain.splice(i, 1);
@@ -300,6 +310,7 @@ class VueFile {
300
310
  ...file,
301
311
  snapshot,
302
312
  mappings,
313
+ codegenStacks,
303
314
  embeddedFiles: [],
304
315
  });
305
316
  remain.splice(i, 1);
@@ -323,21 +334,17 @@ class VueFile {
323
334
  }
324
335
  update(newScriptSnapshot) {
325
336
  this.snapshot = newScriptSnapshot;
326
- this.parsedSfc = this.parseSfc();
327
- if (this.parsedSfc) {
328
- this.updateTemplate(this.parsedSfc.descriptor.template);
329
- this.updateScript(this.parsedSfc.descriptor.script);
330
- this.updateScriptSetup(this.parsedSfc.descriptor.scriptSetup);
331
- this.updateStyles(this.parsedSfc.descriptor.styles);
332
- this.updateCustomBlocks(this.parsedSfc.descriptor.customBlocks);
333
- }
334
- else {
335
- this.updateTemplate(null);
336
- this.updateScript(null);
337
- this.updateScriptSetup(null);
338
- this.updateStyles([]);
339
- this.updateCustomBlocks([]);
340
- }
337
+ const parsedSfc = this.parseSfc();
338
+ updateObj(this.sfc, {
339
+ template: parsedSfc?.descriptor.template ? this.parseTemplateBlock(parsedSfc.descriptor.template) : null,
340
+ script: parsedSfc?.descriptor.script ? this.parseScriptBlock(parsedSfc.descriptor.script) : null,
341
+ scriptSetup: parsedSfc?.descriptor.scriptSetup ? this.parseScriptSetupBlock(parsedSfc.descriptor.scriptSetup) : null,
342
+ styles: parsedSfc?.descriptor.styles.map(this.parseStyleBlock.bind(this)) ?? [],
343
+ customBlocks: parsedSfc?.descriptor.customBlocks.map(this.parseCustomBlock.bind(this)) ?? [],
344
+ templateAst: '__IGNORE__',
345
+ scriptAst: '__IGNORE__',
346
+ scriptSetupAst: '__IGNORE__',
347
+ });
341
348
  const str = [[this.snapshot.getText(0, this.snapshot.getLength()), undefined, 0, language_core_1.FileRangeCapabilities.full]];
342
349
  for (const block of [
343
350
  this.sfc.script,
@@ -399,130 +406,95 @@ class VueFile {
399
406
  }
400
407
  }
401
408
  }
402
- updateTemplate(block) {
403
- const newData = block ? {
409
+ parseTemplateBlock(block) {
410
+ return {
411
+ ...this.parseBlock(block),
404
412
  name: 'template',
405
- start: this.snapshot.getText(0, block.loc.start.offset).lastIndexOf('<' + block.type),
406
- end: block.loc.end.offset + this.snapshot.getText(block.loc.end.offset, this.snapshot.getLength()).indexOf('>') + 1,
407
- startTagEnd: block.loc.start.offset,
408
- endTagStart: block.loc.end.offset,
409
- content: block.content,
410
413
  lang: block.lang ?? 'html',
411
- attrs: block.attrs,
412
- } : null;
413
- if (this.sfc.template && newData) {
414
- this.updateBlock(this.sfc.template, newData);
415
- }
416
- else {
417
- this.sfc.template = newData;
418
- }
414
+ };
419
415
  }
420
- updateScript(block) {
421
- const newData = block ? {
416
+ parseScriptBlock(block) {
417
+ return {
418
+ ...this.parseBlock(block),
422
419
  name: 'script',
423
- start: this.snapshot.getText(0, block.loc.start.offset).lastIndexOf('<' + block.type),
424
- end: block.loc.end.offset + this.snapshot.getText(block.loc.end.offset, this.snapshot.getLength()).indexOf('>') + 1,
425
- startTagEnd: block.loc.start.offset,
426
- endTagStart: block.loc.end.offset,
427
- content: block.content,
428
420
  lang: block.lang ?? 'js',
429
421
  src: block.src,
430
422
  srcOffset: block.src ? this.snapshot.getText(0, block.loc.start.offset).lastIndexOf(block.src) - block.loc.start.offset : -1,
431
- attrs: block.attrs,
432
- } : null;
433
- if (this.sfc.script && newData) {
434
- this.updateBlock(this.sfc.script, newData);
435
- }
436
- else {
437
- this.sfc.script = newData;
438
- }
423
+ };
439
424
  }
440
- updateScriptSetup(block) {
441
- const newData = block ? {
425
+ parseScriptSetupBlock(block) {
426
+ return {
427
+ ...this.parseBlock(block),
442
428
  name: 'scriptSetup',
429
+ lang: block.lang ?? 'js',
430
+ generic: typeof block.attrs.generic === 'string' ? block.attrs.generic : undefined,
431
+ genericOffset: typeof block.attrs.generic === 'string' ? this.snapshot.getText(0, block.loc.start.offset).lastIndexOf(block.attrs.generic) - block.loc.start.offset : -1,
432
+ };
433
+ }
434
+ parseStyleBlock(block, i) {
435
+ const setting = this.vueCompilerOptions.experimentalResolveStyleCssClasses;
436
+ const shouldParseClassNames = block.module || (setting === 'scoped' && block.scoped) || setting === 'always';
437
+ return {
438
+ ...this.parseBlock(block),
439
+ name: 'style_' + i,
440
+ lang: block.lang ?? 'css',
441
+ module: typeof block.module === 'string' ? block.module : block.module ? '$style' : undefined,
442
+ scoped: !!block.scoped,
443
+ cssVars: [...(0, parseCssVars_1.parseCssVars)(block.content)],
444
+ classNames: shouldParseClassNames ? [...(0, parseCssClassNames_1.parseCssClassNames)(block.content)] : [],
445
+ };
446
+ }
447
+ parseCustomBlock(block, i) {
448
+ return {
449
+ ...this.parseBlock(block),
450
+ name: 'customBlock_' + i,
451
+ lang: block.lang ?? 'txt',
452
+ type: block.type,
453
+ };
454
+ }
455
+ parseBlock(block) {
456
+ return {
443
457
  start: this.snapshot.getText(0, block.loc.start.offset).lastIndexOf('<' + block.type),
444
458
  end: block.loc.end.offset + this.snapshot.getText(block.loc.end.offset, this.snapshot.getLength()).indexOf('>') + 1,
445
459
  startTagEnd: block.loc.start.offset,
446
460
  endTagStart: block.loc.end.offset,
447
461
  content: block.content,
448
- lang: block.lang ?? 'js',
449
- generic: typeof block.attrs.generic === 'string' ? block.attrs.generic : undefined,
450
- genericOffset: typeof block.attrs.generic === 'string' ? this.snapshot.getText(0, block.loc.start.offset).lastIndexOf(block.attrs.generic) - block.loc.start.offset : -1,
451
462
  attrs: block.attrs,
452
- } : null;
453
- if (this.sfc.scriptSetup && newData) {
454
- this.updateBlock(this.sfc.scriptSetup, newData);
455
- }
456
- else {
457
- this.sfc.scriptSetup = newData;
458
- }
463
+ };
459
464
  }
460
- updateStyles(blocks) {
461
- for (let i = 0; i < blocks.length; i++) {
462
- const block = blocks[i];
463
- const newData = {
464
- name: 'style_' + i,
465
- start: this.snapshot.getText(0, block.loc.start.offset).lastIndexOf('<' + block.type),
466
- end: block.loc.end.offset + this.snapshot.getText(block.loc.end.offset, this.snapshot.getLength()).indexOf('>') + 1,
467
- startTagEnd: block.loc.start.offset,
468
- endTagStart: block.loc.end.offset,
469
- content: block.content,
470
- lang: block.lang ?? 'css',
471
- module: typeof block.module === 'string' ? block.module : block.module ? '$style' : undefined,
472
- scoped: !!block.scoped,
473
- attrs: block.attrs,
474
- };
475
- if (this.sfc.styles.length > i) {
476
- this.updateBlock(this.sfc.styles[i], newData);
465
+ }
466
+ exports.VueFile = VueFile;
467
+ function updateObj(oldObj, newObj) {
468
+ if (Array.isArray(oldObj) && Array.isArray(newObj)) {
469
+ for (let i = 0; i < newObj.length; i++) {
470
+ if (oldObj.length > i) {
471
+ updateObj(oldObj[i], newObj[i]);
477
472
  }
478
473
  else {
479
- this.sfc.styles.push(newData);
474
+ oldObj.push(newObj[i]);
480
475
  }
481
476
  }
482
- while (this.sfc.styles.length > blocks.length) {
483
- this.sfc.styles.pop();
477
+ if (oldObj.length > newObj.length) {
478
+ oldObj.splice(newObj.length, oldObj.length - newObj.length);
484
479
  }
485
480
  }
486
- updateCustomBlocks(blocks) {
487
- for (let i = 0; i < blocks.length; i++) {
488
- const block = blocks[i];
489
- const newData = {
490
- name: 'customBlock_' + i,
491
- start: this.snapshot.getText(0, block.loc.start.offset).lastIndexOf('<' + block.type),
492
- end: block.loc.end.offset + this.snapshot.getText(block.loc.end.offset, this.snapshot.getLength()).indexOf('>') + 1,
493
- startTagEnd: block.loc.start.offset,
494
- endTagStart: block.loc.end.offset,
495
- content: block.content,
496
- lang: block.lang ?? 'txt',
497
- type: block.type,
498
- attrs: block.attrs,
499
- };
500
- if (this.sfc.customBlocks.length > i) {
501
- this.updateBlock(this.sfc.customBlocks[i], newData);
481
+ else {
482
+ for (const key in newObj) {
483
+ if (newObj[key] === '__IGNORE__') {
484
+ continue;
502
485
  }
503
- else {
504
- this.sfc.customBlocks.push(newData);
505
- }
506
- }
507
- while (this.sfc.customBlocks.length > blocks.length) {
508
- this.sfc.customBlocks.pop();
509
- }
510
- }
511
- updateBlock(oldBlock, newBlock) {
512
- for (const key in newBlock) {
513
- if (typeof oldBlock[key] === 'object' && typeof newBlock[key] === 'object') {
514
- this.updateBlock(oldBlock[key], newBlock[key]);
486
+ else if (oldObj[key] !== null && newObj[key] !== null && typeof oldObj[key] === 'object' && typeof newObj[key] === 'object') {
487
+ updateObj(oldObj[key], newObj[key]);
515
488
  }
516
489
  else {
517
- oldBlock[key] = newBlock[key];
490
+ oldObj[key] = newObj[key];
518
491
  }
519
492
  }
520
- for (const key in oldBlock) {
521
- if (!(key in newBlock)) {
522
- delete oldBlock[key];
493
+ for (const key in oldObj) {
494
+ if (!(key in newObj)) {
495
+ delete oldObj[key];
523
496
  }
524
497
  }
525
498
  }
526
499
  }
527
- exports.VueFile = VueFile;
528
500
  //# sourceMappingURL=sourceFile.js.map
package/out/types.d.ts CHANGED
@@ -1,12 +1,8 @@
1
- import * as embedded from '@volar/language-core';
2
- import { SFCParseResult } from '@vue/compiler-sfc';
1
+ import type { SFCParseResult } from '@vue/compiler-sfc';
3
2
  import * as CompilerDom from '@vue/compiler-dom';
4
3
  import type * as ts from 'typescript/lib/tsserverlibrary';
5
4
  import { VueEmbeddedFile } from './sourceFile';
6
5
  export type { SFCParseResult } from '@vue/compiler-sfc';
7
- export interface VueLanguageServiceHost extends embedded.LanguageServiceHost {
8
- getVueCompilationSettings(): VueCompilerOptions | undefined;
9
- }
10
6
  export type RawVueCompilerOptions = Partial<Omit<VueCompilerOptions, 'target' | 'plugins'>> & {
11
7
  target?: 'auto' | 2 | 2.7 | 3 | 3.3;
12
8
  plugins?: string[];
@@ -43,6 +39,7 @@ export type VueLanguagePlugin = (ctx: {
43
39
  };
44
40
  compilerOptions: ts.CompilerOptions;
45
41
  vueCompilerOptions: VueCompilerOptions;
42
+ codegenStack: boolean;
46
43
  }) => {
47
44
  version: 1;
48
45
  name?: string;
@@ -86,6 +83,14 @@ export interface Sfc {
86
83
  styles: (SfcBlock & {
87
84
  module: string | undefined;
88
85
  scoped: boolean;
86
+ cssVars: {
87
+ text: string;
88
+ offset: number;
89
+ }[];
90
+ classNames: {
91
+ text: string;
92
+ offset: number;
93
+ }[];
89
94
  })[];
90
95
  customBlocks: (SfcBlock & {
91
96
  type: string;
@@ -1,4 +1,4 @@
1
1
  export declare function parseCssClassNames(styleContent: string): Generator<{
2
- start: number;
3
- end: number;
2
+ offset: number;
3
+ text: string;
4
4
  }, void, unknown>;
@@ -10,7 +10,7 @@ function* parseCssClassNames(styleContent) {
10
10
  if (match.index !== undefined) {
11
11
  const matchText = match[1];
12
12
  if (matchText !== undefined) {
13
- yield { start: match.index, end: match.index + matchText.length };
13
+ yield { offset: match.index, text: matchText };
14
14
  }
15
15
  }
16
16
  }
@@ -1,5 +1,5 @@
1
1
  export declare function parseCssVars(styleContent: string): Generator<{
2
- start: number;
3
- end: number;
2
+ offset: number;
3
+ text: string;
4
4
  }, void, unknown>;
5
5
  export declare function clearComments(css: string): string;
@@ -11,7 +11,7 @@ function* parseCssVars(styleContent) {
11
11
  const matchText = match[1] ?? match[2] ?? match[3];
12
12
  if (matchText !== undefined) {
13
13
  const offset = match.index + styleContent.slice(match.index).indexOf(matchText);
14
- yield { start: offset, end: offset + matchText.length };
14
+ yield { offset, text: matchText };
15
15
  }
16
16
  }
17
17
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vue/language-core",
3
- "version": "1.7.0",
3
+ "version": "1.7.3",
4
4
  "main": "out/index.js",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -13,17 +13,26 @@
13
13
  "directory": "packages/vue-language-core"
14
14
  },
15
15
  "dependencies": {
16
- "@volar/language-core": "1.5.4",
17
- "@volar/source-map": "1.5.4",
18
- "@vue/compiler-dom": "^3.3.0-beta.3",
19
- "@vue/compiler-sfc": "^3.3.0-beta.3",
20
- "@vue/reactivity": "^3.3.0-beta.3",
21
- "@vue/shared": "^3.3.0-beta.3",
16
+ "@volar/language-core": "1.6.3",
17
+ "@volar/source-map": "1.6.3",
18
+ "@vue/compiler-dom": "^3.3.0",
19
+ "@vue/reactivity": "^3.3.0",
20
+ "@vue/shared": "^3.3.0",
22
21
  "minimatch": "^9.0.0",
23
- "muggle-string": "^0.2.2",
22
+ "muggle-string": "^0.3.1",
24
23
  "vue-template-compiler": "^2.7.14"
25
24
  },
26
25
  "devDependencies": {
27
- "@types/minimatch": "^5.1.2"
28
- }
26
+ "@types/minimatch": "^5.1.2",
27
+ "@vue/compiler-sfc": "^3.3.0"
28
+ },
29
+ "peerDependencies": {
30
+ "typescript": "*"
31
+ },
32
+ "peerDependenciesMeta": {
33
+ "typescript": {
34
+ "optional": true
35
+ }
36
+ },
37
+ "gitHead": "0afe0eb39ed144513faddbfa4fddc667e8864cdf"
29
38
  }