@vue/language-service 2.0.0 → 2.0.1

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.
Files changed (36) hide show
  1. package/index.d.ts +7 -0
  2. package/index.js +64 -0
  3. package/lib/ideFeatures/nameCasing.d.ts +13 -0
  4. package/lib/ideFeatures/nameCasing.js +211 -0
  5. package/lib/plugins/css.d.ts +2 -0
  6. package/lib/plugins/css.js +27 -0
  7. package/lib/plugins/data.d.ts +4 -0
  8. package/lib/plugins/data.js +91 -0
  9. package/lib/plugins/vue-autoinsert-dotvalue.d.ts +10 -0
  10. package/lib/plugins/vue-autoinsert-dotvalue.js +177 -0
  11. package/lib/plugins/vue-autoinsert-parentheses.d.ts +2 -0
  12. package/lib/plugins/vue-autoinsert-parentheses.js +60 -0
  13. package/lib/plugins/vue-autoinsert-space.d.ts +2 -0
  14. package/lib/plugins/vue-autoinsert-space.js +34 -0
  15. package/lib/plugins/vue-codelens-references.d.ts +2 -0
  16. package/lib/plugins/vue-codelens-references.js +38 -0
  17. package/lib/plugins/vue-directive-comments.d.ts +2 -0
  18. package/lib/plugins/vue-directive-comments.js +61 -0
  19. package/lib/plugins/vue-document-drop.d.ts +2 -0
  20. package/lib/plugins/vue-document-drop.js +81 -0
  21. package/lib/plugins/vue-extract-file.d.ts +8 -0
  22. package/lib/plugins/vue-extract-file.js +258 -0
  23. package/lib/plugins/vue-sfc.d.ts +7 -0
  24. package/lib/plugins/vue-sfc.js +163 -0
  25. package/lib/plugins/vue-template.d.ts +3 -0
  26. package/lib/plugins/vue-template.js +594 -0
  27. package/lib/plugins/vue-toggle-v-bind-codeaction.d.ts +2 -0
  28. package/lib/plugins/vue-toggle-v-bind-codeaction.js +126 -0
  29. package/lib/plugins/vue-twoslash-queries.d.ts +2 -0
  30. package/lib/plugins/vue-twoslash-queries.js +50 -0
  31. package/lib/plugins/vue-visualize-hidden-callback-param.d.ts +2 -0
  32. package/lib/plugins/vue-visualize-hidden-callback-param.js +45 -0
  33. package/lib/types.d.ts +10 -0
  34. package/lib/types.js +31 -0
  35. package/package.json +6 -6
  36. package/scripts/update-html-data.js +426 -0
@@ -0,0 +1,594 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.create = void 0;
4
+ const language_core_1 = require("@vue/language-core");
5
+ const shared_1 = require("@vue/shared");
6
+ const namedPipeClient = require("@vue/typescript-plugin/lib/client");
7
+ const volar_service_html_1 = require("volar-service-html");
8
+ const volar_service_pug_1 = require("volar-service-pug");
9
+ const html = require("vscode-html-languageservice");
10
+ const nameCasing_1 = require("../ideFeatures/nameCasing");
11
+ const types_1 = require("../types");
12
+ const data_1 = require("./data");
13
+ let builtInData;
14
+ let modelData;
15
+ function create(mode, ts, getVueOptions) {
16
+ let customData = [];
17
+ const onDidChangeCustomDataListeners = new Set();
18
+ const onDidChangeCustomData = (listener) => {
19
+ onDidChangeCustomDataListeners.add(listener);
20
+ return {
21
+ dispose() {
22
+ onDidChangeCustomDataListeners.delete(listener);
23
+ },
24
+ };
25
+ };
26
+ const baseServicePlugin = mode === 'pug' ? volar_service_pug_1.create : volar_service_html_1.create;
27
+ const baseService = baseServicePlugin({
28
+ getCustomData() {
29
+ return customData;
30
+ },
31
+ onDidChangeCustomData,
32
+ });
33
+ return {
34
+ name: `vue-template (${mode})`,
35
+ triggerCharacters: [
36
+ ...baseService.triggerCharacters ?? [],
37
+ '@', // vue event shorthand
38
+ ],
39
+ create(context) {
40
+ const baseServiceInstance = baseService.create(context);
41
+ const vueCompilerOptions = getVueOptions(context.env);
42
+ builtInData ??= (0, data_1.loadTemplateData)(context.env.locale ?? 'en');
43
+ modelData ??= (0, data_1.loadModelModifiersData)(context.env.locale ?? 'en');
44
+ // https://vuejs.org/api/built-in-directives.html#v-on
45
+ // https://vuejs.org/api/built-in-directives.html#v-bind
46
+ const eventModifiers = {};
47
+ const propModifiers = {};
48
+ const vOn = builtInData.globalAttributes?.find(x => x.name === 'v-on');
49
+ const vBind = builtInData.globalAttributes?.find(x => x.name === 'v-bind');
50
+ if (vOn) {
51
+ const markdown = (typeof vOn.description === 'string' ? vOn.description : vOn.description?.value) ?? '';
52
+ const modifiers = markdown
53
+ .split('\n- ')[4]
54
+ .split('\n').slice(2, -1);
55
+ for (let text of modifiers) {
56
+ text = text.substring(' - `.'.length);
57
+ const [name, disc] = text.split('` - ');
58
+ eventModifiers[name] = disc;
59
+ }
60
+ }
61
+ if (vBind) {
62
+ const markdown = (typeof vBind.description === 'string' ? vBind.description : vBind.description?.value) ?? '';
63
+ const modifiers = markdown
64
+ .split('\n- ')[4]
65
+ .split('\n').slice(2, -1);
66
+ for (let text of modifiers) {
67
+ text = text.substring(' - `.'.length);
68
+ const [name, disc] = text.split('` - ');
69
+ propModifiers[name] = disc;
70
+ }
71
+ }
72
+ return {
73
+ ...baseServiceInstance,
74
+ async provideCompletionItems(document, position, completionContext, token) {
75
+ if (!isSupportedDocument(document))
76
+ return;
77
+ let sync;
78
+ let currentVersion;
79
+ const [_, sourceFile] = context.documents.getVirtualCodeByUri(document.uri);
80
+ if (sourceFile?.generated?.code instanceof language_core_1.VueGeneratedCode) {
81
+ sync = (await provideHtmlData(sourceFile.id, sourceFile.generated.code)).sync;
82
+ currentVersion = await sync();
83
+ }
84
+ let htmlComplete = await baseServiceInstance.provideCompletionItems?.(document, position, completionContext, token);
85
+ while (currentVersion !== (currentVersion = await sync?.())) {
86
+ htmlComplete = await baseServiceInstance.provideCompletionItems?.(document, position, completionContext, token);
87
+ }
88
+ if (!htmlComplete)
89
+ return;
90
+ if (sourceFile?.generated?.code instanceof language_core_1.VueGeneratedCode) {
91
+ await afterHtmlCompletion(htmlComplete, context.documents.get(sourceFile.id, sourceFile.languageId, sourceFile.snapshot), sourceFile.generated.code);
92
+ }
93
+ return htmlComplete;
94
+ },
95
+ async provideInlayHints(document) {
96
+ if (!isSupportedDocument(document))
97
+ return;
98
+ const enabled = await context.env.getConfiguration?.('vue.inlayHints.missingProps') ?? false;
99
+ if (!enabled)
100
+ return;
101
+ const result = [];
102
+ const [virtualCode] = context.documents.getVirtualCodeByUri(document.uri);
103
+ if (!virtualCode)
104
+ return;
105
+ for (const map of context.documents.getMaps(virtualCode)) {
106
+ const code = context.language.files.get(map.sourceDocument.uri)?.generated?.code;
107
+ const scanner = getScanner(baseServiceInstance, document);
108
+ if (code instanceof language_core_1.VueGeneratedCode && scanner) {
109
+ // visualize missing required props
110
+ const casing = await (0, nameCasing_1.getNameCasing)(context, map.sourceDocument.uri);
111
+ const components = await namedPipeClient.getComponentNames(code.fileName) ?? [];
112
+ const componentProps = {};
113
+ let token;
114
+ let current;
115
+ while ((token = scanner.scan()) !== html.TokenType.EOS) {
116
+ if (token === html.TokenType.StartTag) {
117
+ const tagName = scanner.getTokenText();
118
+ const component = tagName.indexOf('.') >= 0
119
+ ? components.find(component => component === tagName.split('.')[0])
120
+ : components.find(component => component === tagName || (0, language_core_1.hyphenateTag)(component) === tagName);
121
+ const checkTag = tagName.indexOf('.') >= 0 ? tagName : component;
122
+ if (checkTag) {
123
+ componentProps[checkTag] ??= await namedPipeClient.getComponentProps(code.fileName, checkTag, true) ?? [];
124
+ current = {
125
+ unburnedRequiredProps: [...componentProps[checkTag]],
126
+ labelOffset: scanner.getTokenOffset() + scanner.getTokenLength(),
127
+ insertOffset: scanner.getTokenOffset() + scanner.getTokenLength(),
128
+ };
129
+ }
130
+ }
131
+ else if (token === html.TokenType.AttributeName) {
132
+ if (current) {
133
+ let attrText = scanner.getTokenText();
134
+ if (attrText === 'v-bind') {
135
+ current.unburnedRequiredProps = [];
136
+ }
137
+ else {
138
+ // remove modifiers
139
+ if (attrText.indexOf('.') >= 0) {
140
+ attrText = attrText.split('.')[0];
141
+ }
142
+ // normalize
143
+ if (attrText.startsWith('v-bind:')) {
144
+ attrText = attrText.substring('v-bind:'.length);
145
+ }
146
+ else if (attrText.startsWith(':')) {
147
+ attrText = attrText.substring(':'.length);
148
+ }
149
+ else if (attrText.startsWith('v-model:')) {
150
+ attrText = attrText.substring('v-model:'.length);
151
+ }
152
+ else if (attrText === 'v-model') {
153
+ attrText = vueCompilerOptions.target >= 3 ? 'modelValue' : 'value'; // TODO: support for experimentalModelPropName?
154
+ }
155
+ else if (attrText.startsWith('@')) {
156
+ attrText = 'on-' + (0, language_core_1.hyphenateAttr)(attrText.substring('@'.length));
157
+ }
158
+ current.unburnedRequiredProps = current.unburnedRequiredProps.filter(propName => {
159
+ return attrText !== propName
160
+ && attrText !== (0, language_core_1.hyphenateAttr)(propName);
161
+ });
162
+ }
163
+ }
164
+ }
165
+ else if (token === html.TokenType.StartTagSelfClose || token === html.TokenType.StartTagClose) {
166
+ if (current) {
167
+ for (const requiredProp of current.unburnedRequiredProps) {
168
+ result.push({
169
+ label: `${requiredProp}!`,
170
+ paddingLeft: true,
171
+ position: document.positionAt(current.labelOffset),
172
+ kind: 2,
173
+ textEdits: [{
174
+ range: {
175
+ start: document.positionAt(current.insertOffset),
176
+ end: document.positionAt(current.insertOffset),
177
+ },
178
+ newText: ` :${casing.attr === types_1.AttrNameCasing.Kebab ? (0, language_core_1.hyphenateAttr)(requiredProp) : requiredProp}=`,
179
+ }],
180
+ });
181
+ }
182
+ current = undefined;
183
+ }
184
+ }
185
+ if (token === html.TokenType.AttributeName || token === html.TokenType.AttributeValue) {
186
+ if (current) {
187
+ current.insertOffset = scanner.getTokenOffset() + scanner.getTokenLength();
188
+ }
189
+ }
190
+ }
191
+ }
192
+ }
193
+ return result;
194
+ },
195
+ provideHover(document, position, token) {
196
+ if (!isSupportedDocument(document))
197
+ return;
198
+ if (context.documents.getVirtualCodeByUri(document.uri)[0])
199
+ updateCustomData([]);
200
+ return baseServiceInstance.provideHover?.(document, position, token);
201
+ },
202
+ async provideDiagnostics(document, token) {
203
+ if (!isSupportedDocument(document))
204
+ return;
205
+ const originalResult = await baseServiceInstance.provideDiagnostics?.(document, token);
206
+ const [virtualCode] = context.documents.getVirtualCodeByUri(document.uri);
207
+ if (!virtualCode)
208
+ return;
209
+ for (const map of context.documents.getMaps(virtualCode)) {
210
+ const code = context.language.files.get(map.sourceDocument.uri)?.generated?.code;
211
+ if (!(code instanceof language_core_1.VueGeneratedCode))
212
+ continue;
213
+ const templateErrors = [];
214
+ const { template } = code.sfc;
215
+ if (template) {
216
+ for (const error of template.errors) {
217
+ onCompilerError(error, 1);
218
+ }
219
+ for (const warning of template.warnings) {
220
+ onCompilerError(warning, 2);
221
+ }
222
+ function onCompilerError(error, severity) {
223
+ const templateHtmlRange = {
224
+ start: error.loc?.start.offset ?? 0,
225
+ end: error.loc?.end.offset ?? 0,
226
+ };
227
+ let errorMessage = error.message;
228
+ templateErrors.push({
229
+ range: {
230
+ start: document.positionAt(templateHtmlRange.start),
231
+ end: document.positionAt(templateHtmlRange.end),
232
+ },
233
+ severity,
234
+ code: error.code,
235
+ source: 'vue',
236
+ message: errorMessage,
237
+ });
238
+ }
239
+ }
240
+ return [
241
+ ...originalResult ?? [],
242
+ ...templateErrors,
243
+ ];
244
+ }
245
+ },
246
+ };
247
+ async function provideHtmlData(sourceDocumentUri, vueCode) {
248
+ const casing = await (0, nameCasing_1.getNameCasing)(context, sourceDocumentUri);
249
+ if (builtInData.tags) {
250
+ for (const tag of builtInData.tags) {
251
+ if (tag.name === 'slot')
252
+ continue;
253
+ if (tag.name === 'component')
254
+ continue;
255
+ if (tag.name === 'template')
256
+ continue;
257
+ if (casing.tag === types_1.TagNameCasing.Kebab) {
258
+ tag.name = (0, language_core_1.hyphenateTag)(tag.name);
259
+ }
260
+ else {
261
+ tag.name = (0, shared_1.camelize)((0, shared_1.capitalize)(tag.name));
262
+ }
263
+ }
264
+ }
265
+ const promises = [];
266
+ const tagInfos = new Map();
267
+ let version = 0;
268
+ let components;
269
+ let templateContextProps;
270
+ updateCustomData([
271
+ html.newHTMLDataProvider('vue-template-built-in', builtInData),
272
+ {
273
+ getId: () => 'vue-template',
274
+ isApplicable: () => true,
275
+ provideTags: () => {
276
+ if (!components) {
277
+ promises.push((async () => {
278
+ components = (await namedPipeClient.getComponentNames(vueCode.fileName) ?? [])
279
+ .filter(name => name !== 'Transition'
280
+ && name !== 'TransitionGroup'
281
+ && name !== 'KeepAlive'
282
+ && name !== 'Suspense'
283
+ && name !== 'Teleport');
284
+ version++;
285
+ })());
286
+ return [];
287
+ }
288
+ const scriptSetupRanges = vueCode.sfc.scriptSetup ? (0, language_core_1.parseScriptSetupRanges)(ts, vueCode.sfc.scriptSetup.ast, vueCompilerOptions) : undefined;
289
+ const names = new Set();
290
+ const tags = [];
291
+ for (const tag of components) {
292
+ if (casing.tag === types_1.TagNameCasing.Kebab) {
293
+ names.add((0, language_core_1.hyphenateTag)(tag));
294
+ }
295
+ else if (casing.tag === types_1.TagNameCasing.Pascal) {
296
+ names.add(tag);
297
+ }
298
+ }
299
+ for (const binding of scriptSetupRanges?.bindings ?? []) {
300
+ const name = vueCode.sfc.scriptSetup.content.substring(binding.start, binding.end);
301
+ if (casing.tag === types_1.TagNameCasing.Kebab) {
302
+ names.add((0, language_core_1.hyphenateTag)(name));
303
+ }
304
+ else if (casing.tag === types_1.TagNameCasing.Pascal) {
305
+ names.add(name);
306
+ }
307
+ }
308
+ for (const name of names) {
309
+ tags.push({
310
+ name: name,
311
+ attributes: [],
312
+ });
313
+ }
314
+ return tags;
315
+ },
316
+ provideAttributes: (tag) => {
317
+ namedPipeClient.getTemplateContextProps;
318
+ let failed = false;
319
+ let tagInfo = tagInfos.get(tag);
320
+ if (!tagInfo) {
321
+ promises.push((async () => {
322
+ const attrs = await namedPipeClient.getElementAttrs(vueCode.fileName, tag) ?? [];
323
+ const props = await namedPipeClient.getComponentProps(vueCode.fileName, tag) ?? [];
324
+ const events = await namedPipeClient.getComponentEvents(vueCode.fileName, tag) ?? [];
325
+ tagInfos.set(tag, {
326
+ attrs,
327
+ props,
328
+ events,
329
+ });
330
+ version++;
331
+ })());
332
+ return [];
333
+ }
334
+ if (failed) {
335
+ return [];
336
+ }
337
+ const { attrs, props, events } = tagInfo;
338
+ const attributes = [];
339
+ const _tsCodegen = language_core_1.tsCodegen.get(vueCode.sfc);
340
+ if (_tsCodegen) {
341
+ if (!templateContextProps) {
342
+ promises.push((async () => {
343
+ templateContextProps = await namedPipeClient.getTemplateContextProps(vueCode.fileName) ?? [];
344
+ version++;
345
+ })());
346
+ return [];
347
+ }
348
+ let ctxVars = [
349
+ ..._tsCodegen.scriptRanges()?.bindings.map(binding => vueCode.sfc.script.content.substring(binding.start, binding.end)) ?? [],
350
+ ..._tsCodegen.scriptSetupRanges()?.bindings.map(binding => vueCode.sfc.scriptSetup.content.substring(binding.start, binding.end)) ?? [],
351
+ ...templateContextProps,
352
+ ];
353
+ ctxVars = [...new Set(ctxVars)];
354
+ const dirs = ctxVars.map(language_core_1.hyphenateAttr).filter(v => v.startsWith('v-'));
355
+ for (const dir of dirs) {
356
+ attributes.push({
357
+ name: dir,
358
+ });
359
+ }
360
+ }
361
+ const propsSet = new Set(props);
362
+ for (const prop of [...props, ...attrs]) {
363
+ const isGlobal = !propsSet.has(prop);
364
+ const name = casing.attr === types_1.AttrNameCasing.Camel ? prop : (0, language_core_1.hyphenateAttr)(prop);
365
+ if ((0, language_core_1.hyphenateAttr)(name).startsWith('on-')) {
366
+ const propNameBase = name.startsWith('on-')
367
+ ? name.slice('on-'.length)
368
+ : (name['on'.length].toLowerCase() + name.slice('onX'.length));
369
+ const propKey = createInternalItemId('componentEvent', [isGlobal ? '*' : tag, propNameBase]);
370
+ attributes.push({
371
+ name: 'v-on:' + propNameBase,
372
+ description: propKey,
373
+ }, {
374
+ name: '@' + propNameBase,
375
+ description: propKey,
376
+ });
377
+ }
378
+ {
379
+ const propName = name;
380
+ const propKey = createInternalItemId('componentProp', [isGlobal ? '*' : tag, propName]);
381
+ attributes.push({
382
+ name: propName,
383
+ description: propKey,
384
+ }, {
385
+ name: ':' + propName,
386
+ description: propKey,
387
+ }, {
388
+ name: 'v-bind:' + propName,
389
+ description: propKey,
390
+ });
391
+ }
392
+ }
393
+ for (const event of events) {
394
+ const name = casing.attr === types_1.AttrNameCasing.Camel ? event : (0, language_core_1.hyphenateAttr)(event);
395
+ const propKey = createInternalItemId('componentEvent', [tag, name]);
396
+ attributes.push({
397
+ name: 'v-on:' + name,
398
+ description: propKey,
399
+ });
400
+ attributes.push({
401
+ name: '@' + name,
402
+ description: propKey,
403
+ });
404
+ }
405
+ const models = [];
406
+ for (const prop of [...props, ...attrs]) {
407
+ if (prop.startsWith('onUpdate:')) {
408
+ const isGlobal = !propsSet.has(prop);
409
+ models.push([isGlobal, prop.substring('onUpdate:'.length)]);
410
+ }
411
+ }
412
+ for (const event of events) {
413
+ if (event.startsWith('update:')) {
414
+ models.push([false, event.substring('update:'.length)]);
415
+ }
416
+ }
417
+ for (const [isGlobal, model] of models) {
418
+ const name = casing.attr === types_1.AttrNameCasing.Camel ? model : (0, language_core_1.hyphenateAttr)(model);
419
+ const propKey = createInternalItemId('componentProp', [isGlobal ? '*' : tag, name]);
420
+ attributes.push({
421
+ name: 'v-model:' + name,
422
+ description: propKey,
423
+ });
424
+ if (model === 'modelValue') {
425
+ attributes.push({
426
+ name: 'v-model',
427
+ description: propKey,
428
+ });
429
+ }
430
+ }
431
+ return attributes;
432
+ },
433
+ provideValues: () => [],
434
+ },
435
+ ]);
436
+ return {
437
+ async sync() {
438
+ await Promise.all(promises);
439
+ return version;
440
+ }
441
+ };
442
+ }
443
+ async function afterHtmlCompletion(completionList, sourceDocument, code) {
444
+ const replacement = getReplacement(completionList, sourceDocument);
445
+ const componentNames = new Set((await namedPipeClient.getComponentNames(code.fileName) ?? [])
446
+ .map(language_core_1.hyphenateTag));
447
+ if (replacement) {
448
+ const isEvent = replacement.text.startsWith('v-on:') || replacement.text.startsWith('@');
449
+ const isProp = replacement.text.startsWith('v-bind:') || replacement.text.startsWith(':');
450
+ const isModel = replacement.text.startsWith('v-model:') || replacement.text.split('.')[0] === 'v-model';
451
+ const hasModifier = replacement.text.includes('.');
452
+ const validModifiers = isEvent ? eventModifiers
453
+ : isProp ? propModifiers
454
+ : undefined;
455
+ const modifiers = replacement.text.split('.').slice(1);
456
+ const textWithoutModifier = replacement.text.split('.')[0];
457
+ if (validModifiers && hasModifier) {
458
+ for (const modifier in validModifiers) {
459
+ if (modifiers.includes(modifier))
460
+ continue;
461
+ const modifierDes = validModifiers[modifier];
462
+ const insertText = textWithoutModifier + modifiers.slice(0, -1).map(m => '.' + m).join('') + '.' + modifier;
463
+ const newItem = {
464
+ label: modifier,
465
+ filterText: insertText,
466
+ documentation: {
467
+ kind: 'markdown',
468
+ value: modifierDes,
469
+ },
470
+ textEdit: {
471
+ range: replacement.textEdit.range,
472
+ newText: insertText,
473
+ },
474
+ kind: 20,
475
+ };
476
+ completionList.items.push(newItem);
477
+ }
478
+ }
479
+ else if (hasModifier && isModel) {
480
+ for (const modifier of modelData.globalAttributes ?? []) {
481
+ if (modifiers.includes(modifier.name))
482
+ continue;
483
+ const insertText = textWithoutModifier + modifiers.slice(0, -1).map(m => '.' + m).join('') + '.' + modifier.name;
484
+ const newItem = {
485
+ label: modifier.name,
486
+ filterText: insertText,
487
+ documentation: {
488
+ kind: 'markdown',
489
+ value: (typeof modifier.description === 'object' ? modifier.description.value : modifier.description)
490
+ + '\n\n' + modifier.references?.map(ref => `[${ref.name}](${ref.url})`).join(' | '),
491
+ },
492
+ textEdit: {
493
+ range: replacement.textEdit.range,
494
+ newText: insertText,
495
+ },
496
+ kind: 20,
497
+ };
498
+ completionList.items.push(newItem);
499
+ }
500
+ }
501
+ }
502
+ for (const item of completionList.items) {
503
+ const itemIdKey = typeof item.documentation === 'string' ? item.documentation : item.documentation?.value;
504
+ const itemId = itemIdKey ? readInternalItemId(itemIdKey) : undefined;
505
+ if (itemId) {
506
+ item.documentation = undefined;
507
+ }
508
+ if (item.kind === 10 && componentNames.has((0, language_core_1.hyphenateTag)(item.label))) {
509
+ item.kind = 6;
510
+ item.sortText = '\u0000' + (item.sortText ?? item.label);
511
+ }
512
+ else if (itemId && (itemId.type === 'componentProp' || itemId.type === 'componentEvent')) {
513
+ const [componentName] = itemId.args;
514
+ if (componentName !== '*') {
515
+ item.sortText = '\u0000' + (item.sortText ?? item.label);
516
+ }
517
+ if (itemId.type === 'componentProp') {
518
+ if (componentName !== '*') {
519
+ item.kind = 5;
520
+ }
521
+ }
522
+ else {
523
+ item.kind = componentName !== '*' ? 3 : 23;
524
+ }
525
+ }
526
+ else if (item.label === 'v-if'
527
+ || item.label === 'v-else-if'
528
+ || item.label === 'v-else'
529
+ || item.label === 'v-for') {
530
+ item.kind = 14;
531
+ item.sortText = '\u0003' + (item.sortText ?? item.label);
532
+ }
533
+ else if (item.label.startsWith('v-')) {
534
+ item.kind = 3;
535
+ item.sortText = '\u0002' + (item.sortText ?? item.label);
536
+ }
537
+ else {
538
+ item.sortText = '\u0001' + (item.sortText ?? item.label);
539
+ }
540
+ }
541
+ updateCustomData([]);
542
+ }
543
+ },
544
+ };
545
+ function getScanner(service, document) {
546
+ if (mode === 'html') {
547
+ return service.provide['html/languageService']().createScanner(document.getText());
548
+ }
549
+ else {
550
+ const pugDocument = service.provide['pug/pugDocument'](document);
551
+ if (pugDocument) {
552
+ return service.provide['pug/languageService']().createScanner(pugDocument);
553
+ }
554
+ }
555
+ }
556
+ function updateCustomData(extraData) {
557
+ customData = extraData;
558
+ onDidChangeCustomDataListeners.forEach(l => l());
559
+ }
560
+ function isSupportedDocument(document) {
561
+ if (mode === 'pug') {
562
+ return document.languageId === 'jade';
563
+ }
564
+ else {
565
+ return document.languageId === 'html';
566
+ }
567
+ }
568
+ }
569
+ exports.create = create;
570
+ ;
571
+ function createInternalItemId(type, args) {
572
+ return '__VLS_::' + type + '::' + args.join(',');
573
+ }
574
+ function readInternalItemId(key) {
575
+ if (key.startsWith('__VLS_::')) {
576
+ const strs = key.split('::');
577
+ return {
578
+ type: strs[1],
579
+ args: strs[2].split(','),
580
+ };
581
+ }
582
+ }
583
+ function getReplacement(list, doc) {
584
+ for (const item of list.items) {
585
+ if (item.textEdit && 'range' in item.textEdit) {
586
+ return {
587
+ item: item,
588
+ textEdit: item.textEdit,
589
+ text: doc.getText(item.textEdit.range)
590
+ };
591
+ }
592
+ }
593
+ }
594
+ //# sourceMappingURL=vue-template.js.map
@@ -0,0 +1,2 @@
1
+ import type { ServicePlugin } from '@volar/language-service';
2
+ export declare function create(ts: typeof import('typescript')): ServicePlugin;