@vue/language-service 3.0.0-alpha.6 → 3.0.0-beta.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.
- package/index.d.ts +4 -7
- package/index.js +4 -181
- package/lib/nameCasing.d.ts +9 -9
- package/lib/nameCasing.js +100 -174
- package/lib/plugins/css.js +54 -42
- package/lib/plugins/utils.d.ts +1 -1
- package/lib/plugins/vue-compiler-dom-errors.d.ts +1 -1
- package/lib/plugins/vue-document-drop.d.ts +1 -1
- package/lib/plugins/vue-document-drop.js +3 -3
- package/lib/plugins/vue-document-links.js +63 -31
- package/lib/plugins/vue-inlayhints.d.ts +1 -1
- package/lib/plugins/vue-inlayhints.js +2 -3
- package/lib/plugins/vue-missing-props-hints.d.ts +1 -2
- package/lib/plugins/vue-missing-props-hints.js +3 -5
- package/lib/plugins/vue-template.d.ts +1 -2
- package/lib/plugins/vue-template.js +66 -82
- package/package.json +9 -13
- package/lib/ideFeatures/nameCasing.d.ts +0 -14
- package/lib/ideFeatures/nameCasing.js +0 -202
- package/lib/types.d.ts +0 -18
- package/lib/types.js +0 -39
|
@@ -8,7 +8,6 @@ const volar_service_pug_1 = require("volar-service-pug");
|
|
|
8
8
|
const html = require("vscode-html-languageservice");
|
|
9
9
|
const vscode_uri_1 = require("vscode-uri");
|
|
10
10
|
const nameCasing_1 = require("../nameCasing");
|
|
11
|
-
const types_1 = require("../types");
|
|
12
11
|
const data_1 = require("./data");
|
|
13
12
|
const specialTags = new Set([
|
|
14
13
|
'slot',
|
|
@@ -80,8 +79,10 @@ function create(mode, getTsPluginClient) {
|
|
|
80
79
|
// https://vuejs.org/api/built-in-directives.html#v-bind
|
|
81
80
|
const vOnModifiers = {};
|
|
82
81
|
const vBindModifiers = {};
|
|
82
|
+
const vModelModifiers = {};
|
|
83
83
|
const vOn = builtInData.globalAttributes?.find(x => x.name === 'v-on');
|
|
84
84
|
const vBind = builtInData.globalAttributes?.find(x => x.name === 'v-bind');
|
|
85
|
+
const vModel = builtInData.globalAttributes?.find(x => x.name === 'v-model');
|
|
85
86
|
if (vOn) {
|
|
86
87
|
const markdown = (typeof vOn.description === 'string' ? vOn.description : vOn.description?.value) ?? '';
|
|
87
88
|
const modifiers = markdown
|
|
@@ -104,6 +105,13 @@ function create(mode, getTsPluginClient) {
|
|
|
104
105
|
vBindModifiers[name] = desc;
|
|
105
106
|
}
|
|
106
107
|
}
|
|
108
|
+
if (vModel) {
|
|
109
|
+
for (const modifier of modelData.globalAttributes ?? []) {
|
|
110
|
+
const description = typeof modifier.description === 'object' ? modifier.description.value : modifier.description;
|
|
111
|
+
const references = modifier.references?.map(ref => `[${ref.name}](${ref.url})`).join(' | ');
|
|
112
|
+
vModelModifiers[modifier.name] = description + '\n\n' + references;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
107
115
|
const disposable = context.env.onDidChangeConfiguration?.(() => initializing = undefined);
|
|
108
116
|
let initializing;
|
|
109
117
|
return {
|
|
@@ -159,7 +167,7 @@ function create(mode, getTsPluginClient) {
|
|
|
159
167
|
};
|
|
160
168
|
async function provideHtmlData(sourceDocumentUri, vueCode) {
|
|
161
169
|
await (initializing ??= initialize());
|
|
162
|
-
const casing = await (0, nameCasing_1.
|
|
170
|
+
const casing = await (0, nameCasing_1.checkCasing)(context, sourceDocumentUri);
|
|
163
171
|
if (builtInData.tags) {
|
|
164
172
|
for (const tag of builtInData.tags) {
|
|
165
173
|
if (isItemKey(tag.name)) {
|
|
@@ -168,7 +176,7 @@ function create(mode, getTsPluginClient) {
|
|
|
168
176
|
if (specialTags.has(tag.name)) {
|
|
169
177
|
tag.name = generateItemKey('specialTag', tag.name, '');
|
|
170
178
|
}
|
|
171
|
-
else if (casing.tag ===
|
|
179
|
+
else if (casing.tag === nameCasing_1.TagNameCasing.Kebab) {
|
|
172
180
|
tag.name = (0, language_core_1.hyphenateTag)(tag.name);
|
|
173
181
|
}
|
|
174
182
|
else {
|
|
@@ -204,19 +212,19 @@ function create(mode, getTsPluginClient) {
|
|
|
204
212
|
const names = new Set();
|
|
205
213
|
const tags = [];
|
|
206
214
|
for (const tag of components) {
|
|
207
|
-
if (casing.tag ===
|
|
215
|
+
if (casing.tag === nameCasing_1.TagNameCasing.Kebab) {
|
|
208
216
|
names.add((0, language_core_1.hyphenateTag)(tag));
|
|
209
217
|
}
|
|
210
|
-
else if (casing.tag ===
|
|
218
|
+
else if (casing.tag === nameCasing_1.TagNameCasing.Pascal) {
|
|
211
219
|
names.add(tag);
|
|
212
220
|
}
|
|
213
221
|
}
|
|
214
222
|
for (const binding of scriptSetupRanges?.bindings ?? []) {
|
|
215
223
|
const name = vueCode.sfc.scriptSetup.content.slice(binding.range.start, binding.range.end);
|
|
216
|
-
if (casing.tag ===
|
|
224
|
+
if (casing.tag === nameCasing_1.TagNameCasing.Kebab) {
|
|
217
225
|
names.add((0, language_core_1.hyphenateTag)(name));
|
|
218
226
|
}
|
|
219
|
-
else if (casing.tag ===
|
|
227
|
+
else if (casing.tag === nameCasing_1.TagNameCasing.Pascal) {
|
|
220
228
|
names.add(name);
|
|
221
229
|
}
|
|
222
230
|
}
|
|
@@ -259,7 +267,7 @@ function create(mode, getTsPluginClient) {
|
|
|
259
267
|
...attrs.map(attr => ({ name: attr })),
|
|
260
268
|
]) {
|
|
261
269
|
const isGlobal = prop.isAttribute || !propsSet.has(prop.name);
|
|
262
|
-
const name = casing.attr ===
|
|
270
|
+
const name = casing.attr === nameCasing_1.AttrNameCasing.Camel ? prop.name : (0, language_core_1.hyphenateAttr)(prop.name);
|
|
263
271
|
const isEvent = (0, language_core_1.hyphenateAttr)(name).startsWith('on-');
|
|
264
272
|
if (isEvent) {
|
|
265
273
|
const propNameBase = name.startsWith('on-')
|
|
@@ -277,7 +285,7 @@ function create(mode, getTsPluginClient) {
|
|
|
277
285
|
else {
|
|
278
286
|
const propName = name;
|
|
279
287
|
const propInfo = propInfos.find(prop => {
|
|
280
|
-
const name = casing.attr ===
|
|
288
|
+
const name = casing.attr === nameCasing_1.AttrNameCasing.Camel ? prop.name : (0, language_core_1.hyphenateAttr)(prop.name);
|
|
281
289
|
return name === propName;
|
|
282
290
|
});
|
|
283
291
|
const propKey = generateItemKey('componentProp', isGlobal ? '*' : tag, propName, propInfo?.deprecated);
|
|
@@ -298,7 +306,7 @@ function create(mode, getTsPluginClient) {
|
|
|
298
306
|
}
|
|
299
307
|
}
|
|
300
308
|
for (const event of events) {
|
|
301
|
-
const name = casing.attr ===
|
|
309
|
+
const name = casing.attr === nameCasing_1.AttrNameCasing.Camel ? event : (0, language_core_1.hyphenateAttr)(event);
|
|
302
310
|
const propKey = generateItemKey('componentEvent', tag, name);
|
|
303
311
|
attributes.push({
|
|
304
312
|
name: 'v-on:' + name,
|
|
@@ -330,7 +338,7 @@ function create(mode, getTsPluginClient) {
|
|
|
330
338
|
}
|
|
331
339
|
}
|
|
332
340
|
for (const [isGlobal, model] of models) {
|
|
333
|
-
const name = casing.attr ===
|
|
341
|
+
const name = casing.attr === nameCasing_1.AttrNameCasing.Camel ? model : (0, language_core_1.hyphenateAttr)(model);
|
|
334
342
|
const propKey = generateItemKey('componentProp', isGlobal ? '*' : tag, name);
|
|
335
343
|
attributes.push({
|
|
336
344
|
name: 'v-model:' + name,
|
|
@@ -356,69 +364,45 @@ function create(mode, getTsPluginClient) {
|
|
|
356
364
|
};
|
|
357
365
|
}
|
|
358
366
|
function afterHtmlCompletion(completionList, document) {
|
|
359
|
-
|
|
367
|
+
addDirectiveModifiers();
|
|
368
|
+
function addDirectiveModifiers() {
|
|
360
369
|
const replacement = getReplacement(completionList, document);
|
|
361
|
-
if (!replacement) {
|
|
362
|
-
|
|
363
|
-
}
|
|
364
|
-
const hasModifier = replacement.text.includes('.');
|
|
365
|
-
if (!hasModifier) {
|
|
366
|
-
break;
|
|
370
|
+
if (!replacement?.text.includes('.')) {
|
|
371
|
+
return;
|
|
367
372
|
}
|
|
368
373
|
const [text, ...modifiers] = replacement.text.split('.');
|
|
369
374
|
const isVOn = text.startsWith('v-on:') || text.startsWith('@') && text.length > 1;
|
|
370
375
|
const isVBind = text.startsWith('v-bind:') || text.startsWith(':') && text.length > 1;
|
|
371
376
|
const isVModel = text.startsWith('v-model:') || text === 'v-model';
|
|
372
|
-
const
|
|
377
|
+
const currentModifiers = isVOn ? vOnModifiers
|
|
373
378
|
: isVBind ? vBindModifiers
|
|
374
|
-
:
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
continue;
|
|
379
|
-
}
|
|
380
|
-
const description = validModifiers[modifier];
|
|
381
|
-
const insertText = text + modifiers.slice(0, -1).map(m => '.' + m).join('') + '.' + modifier;
|
|
382
|
-
const newItem = {
|
|
383
|
-
label: modifier,
|
|
384
|
-
filterText: insertText,
|
|
385
|
-
documentation: {
|
|
386
|
-
kind: 'markdown',
|
|
387
|
-
value: description,
|
|
388
|
-
},
|
|
389
|
-
textEdit: {
|
|
390
|
-
range: replacement.textEdit.range,
|
|
391
|
-
newText: insertText,
|
|
392
|
-
},
|
|
393
|
-
kind: 20,
|
|
394
|
-
};
|
|
395
|
-
completionList.items.push(newItem);
|
|
396
|
-
}
|
|
379
|
+
: isVModel ? vModelModifiers
|
|
380
|
+
: undefined;
|
|
381
|
+
if (!currentModifiers) {
|
|
382
|
+
return;
|
|
397
383
|
}
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
continue;
|
|
402
|
-
}
|
|
403
|
-
const insertText = text + modifiers.slice(0, -1).map(m => '.' + m).join('') + '.' + modifier.name;
|
|
404
|
-
const newItem = {
|
|
405
|
-
label: modifier.name,
|
|
406
|
-
filterText: insertText,
|
|
407
|
-
documentation: {
|
|
408
|
-
kind: 'markdown',
|
|
409
|
-
value: (typeof modifier.description === 'object' ? modifier.description.value : modifier.description)
|
|
410
|
-
+ '\n\n' + modifier.references?.map(ref => `[${ref.name}](${ref.url})`).join(' | '),
|
|
411
|
-
},
|
|
412
|
-
textEdit: {
|
|
413
|
-
range: replacement.textEdit.range,
|
|
414
|
-
newText: insertText,
|
|
415
|
-
},
|
|
416
|
-
kind: 20,
|
|
417
|
-
};
|
|
418
|
-
completionList.items.push(newItem);
|
|
384
|
+
for (const modifier in currentModifiers) {
|
|
385
|
+
if (modifiers.includes(modifier)) {
|
|
386
|
+
continue;
|
|
419
387
|
}
|
|
388
|
+
const description = currentModifiers[modifier];
|
|
389
|
+
const insertText = text + modifiers.slice(0, -1).map(m => '.' + m).join('') + '.' + modifier;
|
|
390
|
+
const newItem = {
|
|
391
|
+
label: modifier,
|
|
392
|
+
filterText: insertText,
|
|
393
|
+
documentation: {
|
|
394
|
+
kind: 'markdown',
|
|
395
|
+
value: description,
|
|
396
|
+
},
|
|
397
|
+
textEdit: {
|
|
398
|
+
range: replacement.textEdit.range,
|
|
399
|
+
newText: insertText,
|
|
400
|
+
},
|
|
401
|
+
kind: 20,
|
|
402
|
+
};
|
|
403
|
+
completionList.items.push(newItem);
|
|
420
404
|
}
|
|
421
|
-
}
|
|
405
|
+
}
|
|
422
406
|
completionList.items = completionList.items.filter(item => !specialTags.has(parseLabel(item.label).name));
|
|
423
407
|
const htmlDocumentations = new Map();
|
|
424
408
|
for (const item of completionList.items) {
|
|
@@ -428,11 +412,11 @@ function create(mode, getTsPluginClient) {
|
|
|
428
412
|
}
|
|
429
413
|
}
|
|
430
414
|
for (const item of completionList.items) {
|
|
431
|
-
const
|
|
432
|
-
if (
|
|
433
|
-
const name =
|
|
434
|
-
item.label =
|
|
435
|
-
const text =
|
|
415
|
+
const parsedLabel = parseItemKey(item.label);
|
|
416
|
+
if (parsedLabel) {
|
|
417
|
+
const name = parsedLabel.tag;
|
|
418
|
+
item.label = parsedLabel.leadingSlash ? '/' + name : name;
|
|
419
|
+
const text = parsedLabel.leadingSlash ? `/${name}>` : name;
|
|
436
420
|
if (item.textEdit) {
|
|
437
421
|
item.textEdit.newText = text;
|
|
438
422
|
}
|
|
@@ -444,16 +428,16 @@ function create(mode, getTsPluginClient) {
|
|
|
444
428
|
item.sortText = text;
|
|
445
429
|
}
|
|
446
430
|
}
|
|
447
|
-
const
|
|
448
|
-
let
|
|
431
|
+
const itemKey = typeof item.documentation === 'string' ? item.documentation : item.documentation?.value;
|
|
432
|
+
let parsedItem = itemKey ? parseItemKey(itemKey) : undefined;
|
|
449
433
|
let propInfo;
|
|
450
|
-
if (
|
|
434
|
+
if (parsedItem) {
|
|
451
435
|
const documentations = [];
|
|
452
|
-
propInfo = cachedPropInfos.get(
|
|
436
|
+
propInfo = cachedPropInfos.get(parsedItem.prop);
|
|
453
437
|
if (propInfo?.commentMarkdown) {
|
|
454
438
|
documentations.push(propInfo.commentMarkdown);
|
|
455
439
|
}
|
|
456
|
-
let { isEvent, propName } = getPropName(
|
|
440
|
+
let { isEvent, propName } = getPropName(parsedItem);
|
|
457
441
|
if (isEvent) {
|
|
458
442
|
// click -> onclick
|
|
459
443
|
propName = 'on' + propName;
|
|
@@ -481,7 +465,7 @@ function create(mode, getTsPluginClient) {
|
|
|
481
465
|
}
|
|
482
466
|
// for special props without internal item key
|
|
483
467
|
if (specialProps.has(propName)) {
|
|
484
|
-
|
|
468
|
+
parsedItem = {
|
|
485
469
|
type: 'componentProp',
|
|
486
470
|
tag: '^',
|
|
487
471
|
prop: propName,
|
|
@@ -510,10 +494,10 @@ function create(mode, getTsPluginClient) {
|
|
|
510
494
|
item.kind = 6;
|
|
511
495
|
tokens.push('\u0000');
|
|
512
496
|
}
|
|
513
|
-
else if (
|
|
514
|
-
const isComponent =
|
|
515
|
-
const { isEvent, propName } = getPropName(
|
|
516
|
-
if (
|
|
497
|
+
else if (parsedItem) {
|
|
498
|
+
const isComponent = parsedItem.tag !== '*';
|
|
499
|
+
const { isEvent, propName } = getPropName(parsedItem);
|
|
500
|
+
if (parsedItem.type === 'componentProp') {
|
|
517
501
|
if (isComponent || specialProps.has(propName)) {
|
|
518
502
|
item.kind = 5;
|
|
519
503
|
}
|
|
@@ -646,12 +630,12 @@ function getReplacement(list, doc) {
|
|
|
646
630
|
}
|
|
647
631
|
}
|
|
648
632
|
}
|
|
649
|
-
function getPropName(
|
|
650
|
-
const name = (0, language_core_1.hyphenateAttr)(
|
|
633
|
+
function getPropName(parsedItem) {
|
|
634
|
+
const name = (0, language_core_1.hyphenateAttr)(parsedItem.prop);
|
|
651
635
|
if (name.startsWith('on-')) {
|
|
652
636
|
return { isEvent: true, propName: name.slice('on-'.length) };
|
|
653
637
|
}
|
|
654
|
-
else if (
|
|
638
|
+
else if (parsedItem.type === 'componentEvent') {
|
|
655
639
|
return { isEvent: true, propName: name };
|
|
656
640
|
}
|
|
657
641
|
return { isEvent: false, propName: name };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vue/language-service",
|
|
3
|
-
"version": "3.0.0-
|
|
3
|
+
"version": "3.0.0-beta.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"files": [
|
|
6
6
|
"data",
|
|
@@ -17,14 +17,9 @@
|
|
|
17
17
|
"update-html-data": "node ./scripts/update-html-data.js"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@volar/language-
|
|
21
|
-
"@
|
|
22
|
-
"@volar/typescript": "~2.4.13",
|
|
23
|
-
"@vue/compiler-dom": "^3.5.0",
|
|
24
|
-
"@vue/language-core": "3.0.0-alpha.6",
|
|
20
|
+
"@volar/language-service": "2.4.14",
|
|
21
|
+
"@vue/language-core": "3.0.0-beta.1",
|
|
25
22
|
"@vue/shared": "^3.5.0",
|
|
26
|
-
"@vue/typescript-plugin": "3.0.0-alpha.6",
|
|
27
|
-
"alien-signals": "^1.0.3",
|
|
28
23
|
"path-browserify": "^1.0.1",
|
|
29
24
|
"volar-service-css": "0.0.64",
|
|
30
25
|
"volar-service-emmet": "0.0.64",
|
|
@@ -34,16 +29,17 @@
|
|
|
34
29
|
"volar-service-pug-beautify": "0.0.64",
|
|
35
30
|
"volar-service-typescript": "0.0.64",
|
|
36
31
|
"volar-service-typescript-twoslash-queries": "0.0.64",
|
|
37
|
-
"vscode-css-languageservice": "^6.3.1",
|
|
38
32
|
"vscode-html-languageservice": "^5.2.0",
|
|
39
|
-
"vscode-languageserver-textdocument": "^1.0.11",
|
|
40
33
|
"vscode-uri": "^3.0.8"
|
|
41
34
|
},
|
|
42
35
|
"devDependencies": {
|
|
43
36
|
"@types/node": "^22.10.4",
|
|
44
37
|
"@types/path-browserify": "^1.0.1",
|
|
45
|
-
"@volar/kit": "
|
|
46
|
-
"
|
|
38
|
+
"@volar/kit": "2.4.14",
|
|
39
|
+
"@volar/typescript": "2.4.14",
|
|
40
|
+
"@vue/compiler-dom": "^3.5.0",
|
|
41
|
+
"@vue/typescript-plugin": "3.0.0-beta.1",
|
|
42
|
+
"vscode-css-languageservice": "^6.3.1"
|
|
47
43
|
},
|
|
48
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "7a2ea48123679387d7095a81ac49cfc667aeeabb"
|
|
49
45
|
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { LanguageServiceContext } from '@volar/language-service';
|
|
2
|
-
import type * as vscode from 'vscode-languageserver-protocol';
|
|
3
|
-
import type { URI } from 'vscode-uri';
|
|
4
|
-
import { AttrNameCasing, TagNameCasing } from '../types';
|
|
5
|
-
export declare function convertTagName(context: LanguageServiceContext, uri: URI, casing: TagNameCasing, tsPluginClient: typeof import('@vue/typescript-plugin/lib/client') | undefined): Promise<vscode.TextEdit[] | undefined>;
|
|
6
|
-
export declare function convertAttrName(context: LanguageServiceContext, uri: URI, casing: AttrNameCasing, tsPluginClient?: typeof import('@vue/typescript-plugin/lib/client')): Promise<vscode.TextEdit[] | undefined>;
|
|
7
|
-
export declare function getNameCasing(context: LanguageServiceContext, uri: URI): Promise<{
|
|
8
|
-
tag: TagNameCasing;
|
|
9
|
-
attr: AttrNameCasing;
|
|
10
|
-
}>;
|
|
11
|
-
export declare function detect(context: LanguageServiceContext, uri: URI): Promise<{
|
|
12
|
-
tag: TagNameCasing[];
|
|
13
|
-
attr: AttrNameCasing[];
|
|
14
|
-
}>;
|
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.convertTagName = convertTagName;
|
|
4
|
-
exports.convertAttrName = convertAttrName;
|
|
5
|
-
exports.getNameCasing = getNameCasing;
|
|
6
|
-
exports.detect = detect;
|
|
7
|
-
const vue = require("@vue/language-core");
|
|
8
|
-
const language_core_1 = require("@vue/language-core");
|
|
9
|
-
const alien_signals_1 = require("alien-signals");
|
|
10
|
-
const types_1 = require("../types");
|
|
11
|
-
async function convertTagName(context, uri, casing, tsPluginClient) {
|
|
12
|
-
const sourceFile = context.language.scripts.get(uri);
|
|
13
|
-
if (!sourceFile) {
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
const root = sourceFile?.generated?.root;
|
|
17
|
-
if (!(root instanceof language_core_1.VueVirtualCode)) {
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
const { template } = root.sfc;
|
|
21
|
-
if (!template) {
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
const document = context.documents.get(sourceFile.id, sourceFile.languageId, sourceFile.snapshot);
|
|
25
|
-
const edits = [];
|
|
26
|
-
const components = await tsPluginClient?.getComponentNames(root.fileName) ?? [];
|
|
27
|
-
const tags = getTemplateTagsAndAttrs(root);
|
|
28
|
-
for (const [tagName, { offsets }] of tags) {
|
|
29
|
-
const componentName = components.find(component => component === tagName || (0, language_core_1.hyphenateTag)(component) === tagName);
|
|
30
|
-
if (componentName) {
|
|
31
|
-
for (const offset of offsets) {
|
|
32
|
-
const start = document.positionAt(template.startTagEnd + offset);
|
|
33
|
-
const end = document.positionAt(template.startTagEnd + offset + tagName.length);
|
|
34
|
-
const range = { start, end };
|
|
35
|
-
if (casing === types_1.TagNameCasing.Kebab && tagName !== (0, language_core_1.hyphenateTag)(componentName)) {
|
|
36
|
-
edits.push({ range, newText: (0, language_core_1.hyphenateTag)(componentName) });
|
|
37
|
-
}
|
|
38
|
-
if (casing === types_1.TagNameCasing.Pascal && tagName !== componentName) {
|
|
39
|
-
edits.push({ range, newText: componentName });
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
return edits;
|
|
45
|
-
}
|
|
46
|
-
async function convertAttrName(context, uri, casing, tsPluginClient) {
|
|
47
|
-
const sourceFile = context.language.scripts.get(uri);
|
|
48
|
-
if (!sourceFile) {
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
const root = sourceFile?.generated?.root;
|
|
52
|
-
if (!(root instanceof language_core_1.VueVirtualCode)) {
|
|
53
|
-
return;
|
|
54
|
-
}
|
|
55
|
-
const { template } = root.sfc;
|
|
56
|
-
if (!template) {
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
const document = context.documents.get(uri, sourceFile.languageId, sourceFile.snapshot);
|
|
60
|
-
const edits = [];
|
|
61
|
-
const components = await tsPluginClient?.getComponentNames(root.fileName) ?? [];
|
|
62
|
-
const tags = getTemplateTagsAndAttrs(root);
|
|
63
|
-
for (const [tagName, { attrs }] of tags) {
|
|
64
|
-
const componentName = components.find(component => component === tagName || (0, language_core_1.hyphenateTag)(component) === tagName);
|
|
65
|
-
if (componentName) {
|
|
66
|
-
const props = (await tsPluginClient?.getComponentProps(root.fileName, componentName) ?? []).map(prop => prop.name);
|
|
67
|
-
for (const [attrName, { offsets }] of attrs) {
|
|
68
|
-
const propName = props.find(prop => prop === attrName || (0, language_core_1.hyphenateAttr)(prop) === attrName);
|
|
69
|
-
if (propName) {
|
|
70
|
-
for (const offset of offsets) {
|
|
71
|
-
const start = document.positionAt(template.startTagEnd + offset);
|
|
72
|
-
const end = document.positionAt(template.startTagEnd + offset + attrName.length);
|
|
73
|
-
const range = { start, end };
|
|
74
|
-
if (casing === types_1.AttrNameCasing.Kebab && attrName !== (0, language_core_1.hyphenateAttr)(propName)) {
|
|
75
|
-
edits.push({ range, newText: (0, language_core_1.hyphenateAttr)(propName) });
|
|
76
|
-
}
|
|
77
|
-
if (casing === types_1.AttrNameCasing.Camel && attrName !== propName) {
|
|
78
|
-
edits.push({ range, newText: propName });
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
return edits;
|
|
86
|
-
}
|
|
87
|
-
async function getNameCasing(context, uri) {
|
|
88
|
-
const detected = await detect(context, uri);
|
|
89
|
-
const [attr, tag] = await Promise.all([
|
|
90
|
-
context.env.getConfiguration?.('vue.complete.casing.props', uri.toString()),
|
|
91
|
-
context.env.getConfiguration?.('vue.complete.casing.tags', uri.toString()),
|
|
92
|
-
]);
|
|
93
|
-
const tagNameCasing = detected.tag.length === 1 && (tag === 'autoPascal' || tag === 'autoKebab') ? detected.tag[0] : (tag === 'autoKebab' || tag === 'kebab') ? types_1.TagNameCasing.Kebab : types_1.TagNameCasing.Pascal;
|
|
94
|
-
const attrNameCasing = detected.attr.length === 1 && (attr === 'autoCamel' || attr === 'autoKebab') ? detected.attr[0] : (attr === 'autoCamel' || attr === 'camel') ? types_1.AttrNameCasing.Camel : types_1.AttrNameCasing.Kebab;
|
|
95
|
-
return {
|
|
96
|
-
tag: tagNameCasing,
|
|
97
|
-
attr: attrNameCasing,
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
async function detect(context, uri) {
|
|
101
|
-
const rootFile = context.language.scripts.get(uri)?.generated?.root;
|
|
102
|
-
if (!(rootFile instanceof language_core_1.VueVirtualCode)) {
|
|
103
|
-
return {
|
|
104
|
-
tag: [],
|
|
105
|
-
attr: [],
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
return {
|
|
109
|
-
tag: await getTagNameCase(rootFile),
|
|
110
|
-
attr: getAttrNameCase(rootFile),
|
|
111
|
-
};
|
|
112
|
-
function getAttrNameCase(file) {
|
|
113
|
-
const tags = getTemplateTagsAndAttrs(file);
|
|
114
|
-
const result = [];
|
|
115
|
-
for (const [_, { attrs }] of tags) {
|
|
116
|
-
for (const [tagName] of attrs) {
|
|
117
|
-
// attrName
|
|
118
|
-
if (tagName !== (0, language_core_1.hyphenateTag)(tagName)) {
|
|
119
|
-
result.push(types_1.AttrNameCasing.Camel);
|
|
120
|
-
break;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
for (const [tagName] of attrs) {
|
|
124
|
-
// attr-name
|
|
125
|
-
if (tagName.includes('-')) {
|
|
126
|
-
result.push(types_1.AttrNameCasing.Kebab);
|
|
127
|
-
break;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
return result;
|
|
132
|
-
}
|
|
133
|
-
function getTagNameCase(file) {
|
|
134
|
-
const result = new Set();
|
|
135
|
-
if (file.sfc.template?.ast) {
|
|
136
|
-
for (const element of vue.forEachElementNode(file.sfc.template.ast)) {
|
|
137
|
-
if (element.tagType === 1) {
|
|
138
|
-
if (element.tag !== (0, language_core_1.hyphenateTag)(element.tag)) {
|
|
139
|
-
// TagName
|
|
140
|
-
result.add(types_1.TagNameCasing.Pascal);
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
// Tagname -> tagname
|
|
144
|
-
// TagName -> tag-name
|
|
145
|
-
result.add(types_1.TagNameCasing.Kebab);
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
return [...result];
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
const map = new WeakMap();
|
|
154
|
-
function getTemplateTagsAndAttrs(sourceFile) {
|
|
155
|
-
if (!map.has(sourceFile)) {
|
|
156
|
-
const getter = (0, alien_signals_1.computed)(() => {
|
|
157
|
-
if (!(sourceFile instanceof vue.VueVirtualCode)) {
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
const ast = sourceFile.sfc.template?.ast;
|
|
161
|
-
const tags = new Map();
|
|
162
|
-
if (ast) {
|
|
163
|
-
for (const node of vue.forEachElementNode(ast)) {
|
|
164
|
-
if (!tags.has(node.tag)) {
|
|
165
|
-
tags.set(node.tag, { offsets: [], attrs: new Map() });
|
|
166
|
-
}
|
|
167
|
-
const tag = tags.get(node.tag);
|
|
168
|
-
const startTagHtmlOffset = node.loc.start.offset + node.loc.source.indexOf(node.tag);
|
|
169
|
-
const endTagHtmlOffset = node.loc.start.offset + node.loc.source.lastIndexOf(node.tag);
|
|
170
|
-
tag.offsets.push(startTagHtmlOffset);
|
|
171
|
-
if (!node.isSelfClosing) {
|
|
172
|
-
tag.offsets.push(endTagHtmlOffset);
|
|
173
|
-
}
|
|
174
|
-
for (const prop of node.props) {
|
|
175
|
-
let name;
|
|
176
|
-
let offset;
|
|
177
|
-
if (prop.type === 7
|
|
178
|
-
&& prop.arg?.type === 4
|
|
179
|
-
&& prop.arg.isStatic) {
|
|
180
|
-
name = prop.arg.content;
|
|
181
|
-
offset = prop.arg.loc.start.offset;
|
|
182
|
-
}
|
|
183
|
-
else if (prop.type === 6) {
|
|
184
|
-
name = prop.name;
|
|
185
|
-
offset = prop.loc.start.offset;
|
|
186
|
-
}
|
|
187
|
-
if (name !== undefined && offset !== undefined) {
|
|
188
|
-
if (!tag.attrs.has(name)) {
|
|
189
|
-
tag.attrs.set(name, { offsets: [] });
|
|
190
|
-
}
|
|
191
|
-
tag.attrs.get(name).offsets.push(offset);
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
return tags;
|
|
197
|
-
});
|
|
198
|
-
map.set(sourceFile, getter);
|
|
199
|
-
}
|
|
200
|
-
return map.get(sourceFile)() ?? new Map();
|
|
201
|
-
}
|
|
202
|
-
//# sourceMappingURL=nameCasing.js.map
|
package/lib/types.d.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
export declare enum TagNameCasing {
|
|
2
|
-
Kebab = 0,
|
|
3
|
-
Pascal = 1
|
|
4
|
-
}
|
|
5
|
-
export declare enum AttrNameCasing {
|
|
6
|
-
Kebab = 0,
|
|
7
|
-
Camel = 1
|
|
8
|
-
}
|
|
9
|
-
export declare const commands: {
|
|
10
|
-
parseSfc: string;
|
|
11
|
-
detectNameCasing: string;
|
|
12
|
-
convertTagsToKebabCase: string;
|
|
13
|
-
convertTagsToPascalCase: string;
|
|
14
|
-
convertPropsToKebabCase: string;
|
|
15
|
-
convertPropsToCamelCase: string;
|
|
16
|
-
};
|
|
17
|
-
export * from '@volar/language-service/lib/types';
|
|
18
|
-
export * from '@vue/language-core/lib/types';
|
package/lib/types.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.commands = exports.AttrNameCasing = exports.TagNameCasing = void 0;
|
|
18
|
-
var TagNameCasing;
|
|
19
|
-
(function (TagNameCasing) {
|
|
20
|
-
TagNameCasing[TagNameCasing["Kebab"] = 0] = "Kebab";
|
|
21
|
-
TagNameCasing[TagNameCasing["Pascal"] = 1] = "Pascal";
|
|
22
|
-
})(TagNameCasing || (exports.TagNameCasing = TagNameCasing = {}));
|
|
23
|
-
var AttrNameCasing;
|
|
24
|
-
(function (AttrNameCasing) {
|
|
25
|
-
AttrNameCasing[AttrNameCasing["Kebab"] = 0] = "Kebab";
|
|
26
|
-
AttrNameCasing[AttrNameCasing["Camel"] = 1] = "Camel";
|
|
27
|
-
})(AttrNameCasing || (exports.AttrNameCasing = AttrNameCasing = {}));
|
|
28
|
-
exports.commands = {
|
|
29
|
-
parseSfc: 'vue.parseSfc',
|
|
30
|
-
detectNameCasing: 'vue.detectNameCasing',
|
|
31
|
-
convertTagsToKebabCase: 'vue.convertTagsToKebabCase',
|
|
32
|
-
convertTagsToPascalCase: 'vue.convertTagsToPascalCase',
|
|
33
|
-
convertPropsToKebabCase: 'vue.convertPropsToKebabCase',
|
|
34
|
-
convertPropsToCamelCase: 'vue.convertPropsToCamelCase',
|
|
35
|
-
};
|
|
36
|
-
// only export types of depend packages
|
|
37
|
-
__exportStar(require("@volar/language-service/lib/types"), exports);
|
|
38
|
-
__exportStar(require("@vue/language-core/lib/types"), exports);
|
|
39
|
-
//# sourceMappingURL=types.js.map
|