@vue/language-service 3.0.0-alpha.8 → 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/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 +2 -3
- package/lib/plugins/vue-template.d.ts +1 -2
- package/lib/plugins/vue-template.js +66 -82
- package/package.json +9 -13
- package/lib/types.d.ts +0 -18
- package/lib/types.js +0 -39
package/index.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
export * from '@volar/language-service';
|
|
2
|
-
export * from '@
|
|
3
|
-
export * from './lib/nameCasing';
|
|
4
|
-
export * from './lib/types';
|
|
2
|
+
export * from '@volar/language-service/lib/utils/featureWorkers';
|
|
5
3
|
import type { LanguageServicePlugin } from '@volar/language-service';
|
|
6
|
-
import {
|
|
4
|
+
import type { VueCompilerOptions } from '@vue/language-core';
|
|
5
|
+
import type * as ts from 'typescript';
|
|
7
6
|
declare module '@volar/language-service' {
|
|
8
7
|
interface ProjectContext {
|
|
9
8
|
vue?: {
|
|
@@ -11,8 +10,6 @@ declare module '@volar/language-service' {
|
|
|
11
10
|
};
|
|
12
11
|
}
|
|
13
12
|
}
|
|
14
|
-
export declare function
|
|
15
|
-
import type * as ts from 'typescript';
|
|
16
|
-
export declare function getHybridModeLanguageServicePlugins(ts: typeof import('typescript'), tsPluginClient: (import('@vue/typescript-plugin/lib/requests').Requests & {
|
|
13
|
+
export declare function createVueLanguageServicePlugins(ts: typeof import('typescript'), tsPluginClient: (import('@vue/typescript-plugin/lib/requests').Requests & {
|
|
17
14
|
getDocumentHighlights: (fileName: string, position: number) => Promise<ts.DocumentHighlights[] | null>;
|
|
18
15
|
}) | undefined): LanguageServicePlugin<any>[];
|
package/index.js
CHANGED
|
@@ -15,17 +15,13 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
16
16
|
};
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.
|
|
19
|
-
exports.getHybridModeLanguageServicePlugins = getHybridModeLanguageServicePlugins;
|
|
18
|
+
exports.createVueLanguageServicePlugins = createVueLanguageServicePlugins;
|
|
20
19
|
__exportStar(require("@volar/language-service"), exports);
|
|
21
|
-
|
|
22
|
-
__exportStar(require("
|
|
23
|
-
__exportStar(require("./lib/types"), exports);
|
|
24
|
-
const types_1 = require("./lib/types");
|
|
20
|
+
// for @vue/language-server usage
|
|
21
|
+
__exportStar(require("@volar/language-service/lib/utils/featureWorkers"), exports);
|
|
25
22
|
const volar_service_emmet_1 = require("volar-service-emmet");
|
|
26
23
|
const volar_service_json_1 = require("volar-service-json");
|
|
27
24
|
const volar_service_pug_beautify_1 = require("volar-service-pug-beautify");
|
|
28
|
-
const volar_service_typescript_1 = require("volar-service-typescript");
|
|
29
25
|
const volar_service_typescript_twoslash_queries_1 = require("volar-service-typescript-twoslash-queries");
|
|
30
26
|
const docCommentTemplate_1 = require("volar-service-typescript/lib/plugins/docCommentTemplate");
|
|
31
27
|
const syntactic_1 = require("volar-service-typescript/lib/plugins/syntactic");
|
|
@@ -44,130 +40,7 @@ const vue_missing_props_hints_1 = require("./lib/plugins/vue-missing-props-hints
|
|
|
44
40
|
const vue_sfc_1 = require("./lib/plugins/vue-sfc");
|
|
45
41
|
const vue_template_1 = require("./lib/plugins/vue-template");
|
|
46
42
|
const vue_twoslash_queries_1 = require("./lib/plugins/vue-twoslash-queries");
|
|
47
|
-
|
|
48
|
-
const common_1 = require("@vue/typescript-plugin/lib/common");
|
|
49
|
-
const collectExtractProps_1 = require("@vue/typescript-plugin/lib/requests/collectExtractProps");
|
|
50
|
-
const getComponentDirectives_1 = require("@vue/typescript-plugin/lib/requests/getComponentDirectives");
|
|
51
|
-
const getComponentEvents_1 = require("@vue/typescript-plugin/lib/requests/getComponentEvents");
|
|
52
|
-
const getComponentNames_1 = require("@vue/typescript-plugin/lib/requests/getComponentNames");
|
|
53
|
-
const getComponentProps_1 = require("@vue/typescript-plugin/lib/requests/getComponentProps");
|
|
54
|
-
const getElementAttrs_1 = require("@vue/typescript-plugin/lib/requests/getElementAttrs");
|
|
55
|
-
const getElementNames_1 = require("@vue/typescript-plugin/lib/requests/getElementNames");
|
|
56
|
-
const getImportPathForFile_1 = require("@vue/typescript-plugin/lib/requests/getImportPathForFile");
|
|
57
|
-
const getPropertiesAtLocation_1 = require("@vue/typescript-plugin/lib/requests/getPropertiesAtLocation");
|
|
58
|
-
const vscode_uri_1 = require("vscode-uri");
|
|
59
|
-
const nameCasing_1 = require("./lib/nameCasing");
|
|
60
|
-
function getFullLanguageServicePlugins(ts) {
|
|
61
|
-
const plugins = [
|
|
62
|
-
...(0, volar_service_typescript_1.create)(ts),
|
|
63
|
-
...getCommonLanguageServicePlugins(ts, getTsPluginClientForLSP),
|
|
64
|
-
];
|
|
65
|
-
for (let i = 0; i < plugins.length; i++) {
|
|
66
|
-
const plugin = plugins[i];
|
|
67
|
-
if (plugin.name === 'typescript-semantic') {
|
|
68
|
-
plugins[i] = {
|
|
69
|
-
...plugin,
|
|
70
|
-
create(context) {
|
|
71
|
-
const created = plugin.create(context);
|
|
72
|
-
if (!context.project.typescript) {
|
|
73
|
-
return created;
|
|
74
|
-
}
|
|
75
|
-
const languageService = created.provide['typescript/languageService']();
|
|
76
|
-
if (context.project.vue) {
|
|
77
|
-
const proxy = (0, common_1.proxyLanguageServiceForVue)(ts, context.language, languageService, context.project.vue.compilerOptions, s => context.project.typescript?.uriConverter.asUri(s));
|
|
78
|
-
languageService.getCompletionsAtPosition = proxy.getCompletionsAtPosition;
|
|
79
|
-
languageService.getCompletionEntryDetails = proxy.getCompletionEntryDetails;
|
|
80
|
-
languageService.getCodeFixesAtPosition = proxy.getCodeFixesAtPosition;
|
|
81
|
-
languageService.getDefinitionAndBoundSpan = proxy.getDefinitionAndBoundSpan;
|
|
82
|
-
languageService.getQuickInfoAtPosition = proxy.getQuickInfoAtPosition;
|
|
83
|
-
}
|
|
84
|
-
return created;
|
|
85
|
-
},
|
|
86
|
-
};
|
|
87
|
-
break;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
return plugins;
|
|
91
|
-
function getTsPluginClientForLSP(context) {
|
|
92
|
-
if (!context.project.typescript) {
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
const languageService = context.inject('typescript/languageService');
|
|
96
|
-
if (!languageService) {
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
const requestContext = {
|
|
100
|
-
typescript: ts,
|
|
101
|
-
language: context.language,
|
|
102
|
-
languageService,
|
|
103
|
-
languageServiceHost: context.project.typescript.languageServiceHost,
|
|
104
|
-
isTsPlugin: false,
|
|
105
|
-
getFileId: s => context.project.typescript.uriConverter.asUri(s),
|
|
106
|
-
};
|
|
107
|
-
return {
|
|
108
|
-
async collectExtractProps(...args) {
|
|
109
|
-
return collectExtractProps_1.collectExtractProps.apply(requestContext, args);
|
|
110
|
-
},
|
|
111
|
-
async getPropertiesAtLocation(...args) {
|
|
112
|
-
return getPropertiesAtLocation_1.getPropertiesAtLocation.apply(requestContext, args);
|
|
113
|
-
},
|
|
114
|
-
async getImportPathForFile(...args) {
|
|
115
|
-
return getImportPathForFile_1.getImportPathForFile.apply(requestContext, args);
|
|
116
|
-
},
|
|
117
|
-
async getComponentEvents(...args) {
|
|
118
|
-
return getComponentEvents_1.getComponentEvents.apply(requestContext, args);
|
|
119
|
-
},
|
|
120
|
-
async getComponentDirectives(...args) {
|
|
121
|
-
return getComponentDirectives_1.getComponentDirectives.apply(requestContext, args);
|
|
122
|
-
},
|
|
123
|
-
async getComponentNames(...args) {
|
|
124
|
-
return getComponentNames_1.getComponentNames.apply(requestContext, args);
|
|
125
|
-
},
|
|
126
|
-
async getComponentProps(...args) {
|
|
127
|
-
return getComponentProps_1.getComponentProps.apply(requestContext, args);
|
|
128
|
-
},
|
|
129
|
-
async getElementAttrs(...args) {
|
|
130
|
-
return getElementAttrs_1.getElementAttrs.apply(requestContext, args);
|
|
131
|
-
},
|
|
132
|
-
async getElementNames(...args) {
|
|
133
|
-
return getElementNames_1.getElementNames.apply(requestContext, args);
|
|
134
|
-
},
|
|
135
|
-
async getQuickInfoAtPosition(fileName, position) {
|
|
136
|
-
const languageService = context.getLanguageService();
|
|
137
|
-
const uri = context.project.typescript.uriConverter.asUri(fileName);
|
|
138
|
-
const sourceScript = context.language.scripts.get(uri);
|
|
139
|
-
if (!sourceScript) {
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
const hover = await languageService.getHover(uri, position);
|
|
143
|
-
let text = '';
|
|
144
|
-
if (typeof hover?.contents === 'string') {
|
|
145
|
-
text = hover.contents;
|
|
146
|
-
}
|
|
147
|
-
else if (Array.isArray(hover?.contents)) {
|
|
148
|
-
text = hover.contents.map(c => typeof c === 'string' ? c : c.value).join('\n');
|
|
149
|
-
}
|
|
150
|
-
else if (hover) {
|
|
151
|
-
text = hover.contents.value;
|
|
152
|
-
}
|
|
153
|
-
text = text.replace(/```typescript/g, '');
|
|
154
|
-
text = text.replace(/```/g, '');
|
|
155
|
-
text = text.replace(/---/g, '');
|
|
156
|
-
text = text.trim();
|
|
157
|
-
while (true) {
|
|
158
|
-
const newText = text.replace(/\n\n/g, '\n');
|
|
159
|
-
if (newText === text) {
|
|
160
|
-
break;
|
|
161
|
-
}
|
|
162
|
-
text = newText;
|
|
163
|
-
}
|
|
164
|
-
text = text.replace(/\n/g, ' | ');
|
|
165
|
-
return text;
|
|
166
|
-
},
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
function getHybridModeLanguageServicePlugins(ts, tsPluginClient) {
|
|
43
|
+
function createVueLanguageServicePlugins(ts, tsPluginClient) {
|
|
171
44
|
const plugins = [
|
|
172
45
|
(0, syntactic_1.create)(ts),
|
|
173
46
|
(0, docCommentTemplate_1.create)(ts),
|
|
@@ -208,56 +81,6 @@ function getCommonLanguageServicePlugins(ts, getTsPluginClient) {
|
|
|
208
81
|
'postcss': 'scss',
|
|
209
82
|
},
|
|
210
83
|
}),
|
|
211
|
-
{
|
|
212
|
-
name: 'vue-parse-sfc',
|
|
213
|
-
capabilities: {
|
|
214
|
-
executeCommandProvider: {
|
|
215
|
-
commands: [types_1.commands.parseSfc],
|
|
216
|
-
},
|
|
217
|
-
},
|
|
218
|
-
create() {
|
|
219
|
-
return {
|
|
220
|
-
executeCommand(_command, [source]) {
|
|
221
|
-
return (0, language_core_1.parse)(source);
|
|
222
|
-
},
|
|
223
|
-
};
|
|
224
|
-
},
|
|
225
|
-
},
|
|
226
|
-
{
|
|
227
|
-
name: 'vue-name-casing',
|
|
228
|
-
capabilities: {
|
|
229
|
-
executeCommandProvider: {
|
|
230
|
-
commands: [
|
|
231
|
-
types_1.commands.detectNameCasing,
|
|
232
|
-
types_1.commands.convertTagsToKebabCase,
|
|
233
|
-
types_1.commands.convertTagsToPascalCase,
|
|
234
|
-
types_1.commands.convertPropsToKebabCase,
|
|
235
|
-
types_1.commands.convertPropsToCamelCase,
|
|
236
|
-
],
|
|
237
|
-
}
|
|
238
|
-
},
|
|
239
|
-
create(context) {
|
|
240
|
-
return {
|
|
241
|
-
executeCommand(command, [uri]) {
|
|
242
|
-
if (command === types_1.commands.detectNameCasing) {
|
|
243
|
-
return (0, nameCasing_1.detect)(context, vscode_uri_1.URI.parse(uri));
|
|
244
|
-
}
|
|
245
|
-
else if (command === types_1.commands.convertTagsToKebabCase) {
|
|
246
|
-
return (0, nameCasing_1.convertTagName)(context, vscode_uri_1.URI.parse(uri), types_1.TagNameCasing.Kebab, getTsPluginClient(context));
|
|
247
|
-
}
|
|
248
|
-
else if (command === types_1.commands.convertTagsToPascalCase) {
|
|
249
|
-
return (0, nameCasing_1.convertTagName)(context, vscode_uri_1.URI.parse(uri), types_1.TagNameCasing.Pascal, getTsPluginClient(context));
|
|
250
|
-
}
|
|
251
|
-
else if (command === types_1.commands.convertPropsToKebabCase) {
|
|
252
|
-
return (0, nameCasing_1.convertAttrName)(context, vscode_uri_1.URI.parse(uri), types_1.AttrNameCasing.Kebab, getTsPluginClient(context));
|
|
253
|
-
}
|
|
254
|
-
else if (command === types_1.commands.convertPropsToCamelCase) {
|
|
255
|
-
return (0, nameCasing_1.convertAttrName)(context, vscode_uri_1.URI.parse(uri), types_1.AttrNameCasing.Camel, getTsPluginClient(context));
|
|
256
|
-
}
|
|
257
|
-
},
|
|
258
|
-
};
|
|
259
|
-
},
|
|
260
|
-
}
|
|
261
84
|
];
|
|
262
85
|
}
|
|
263
86
|
//# sourceMappingURL=index.js.map
|
package/lib/nameCasing.d.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import type { LanguageServiceContext } from '@volar/language-service';
|
|
2
|
-
import type * as vscode from 'vscode-languageserver-protocol';
|
|
3
2
|
import type { URI } from 'vscode-uri';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
export declare enum TagNameCasing {
|
|
4
|
+
Kebab = 0,
|
|
5
|
+
Pascal = 1
|
|
6
|
+
}
|
|
7
|
+
export declare enum AttrNameCasing {
|
|
8
|
+
Kebab = 0,
|
|
9
|
+
Camel = 1
|
|
10
|
+
}
|
|
11
|
+
export declare function checkCasing(context: LanguageServiceContext, uri: URI): Promise<{
|
|
8
12
|
tag: TagNameCasing;
|
|
9
13
|
attr: AttrNameCasing;
|
|
10
14
|
}>;
|
|
11
|
-
export declare function detect(context: LanguageServiceContext, uri: URI): Promise<{
|
|
12
|
-
tag: TagNameCasing[];
|
|
13
|
-
attr: AttrNameCasing[];
|
|
14
|
-
}>;
|
package/lib/nameCasing.js
CHANGED
|
@@ -1,201 +1,127 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.
|
|
5
|
-
exports.getNameCasing = getNameCasing;
|
|
6
|
-
exports.detect = detect;
|
|
3
|
+
exports.AttrNameCasing = exports.TagNameCasing = void 0;
|
|
4
|
+
exports.checkCasing = checkCasing;
|
|
7
5
|
const language_core_1 = require("@vue/language-core");
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
if (!template) {
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
const document = context.documents.get(sourceFile.id, sourceFile.languageId, sourceFile.snapshot);
|
|
24
|
-
const edits = [];
|
|
25
|
-
const components = await tsPluginClient?.getComponentNames(root.fileName) ?? [];
|
|
26
|
-
const tags = getTemplateTagsAndAttrs(root);
|
|
27
|
-
for (const [tagName, { offsets }] of tags) {
|
|
28
|
-
const componentName = components.find(component => component === tagName || (0, language_core_1.hyphenateTag)(component) === tagName);
|
|
29
|
-
if (componentName) {
|
|
30
|
-
for (const offset of offsets) {
|
|
31
|
-
const start = document.positionAt(template.startTagEnd + offset);
|
|
32
|
-
const end = document.positionAt(template.startTagEnd + offset + tagName.length);
|
|
33
|
-
const range = { start, end };
|
|
34
|
-
if (casing === types_1.TagNameCasing.Kebab && tagName !== (0, language_core_1.hyphenateTag)(componentName)) {
|
|
35
|
-
edits.push({ range, newText: (0, language_core_1.hyphenateTag)(componentName) });
|
|
36
|
-
}
|
|
37
|
-
if (casing === types_1.TagNameCasing.Pascal && tagName !== componentName) {
|
|
38
|
-
edits.push({ range, newText: componentName });
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
return edits;
|
|
44
|
-
}
|
|
45
|
-
async function convertAttrName(context, uri, casing, tsPluginClient) {
|
|
46
|
-
const sourceFile = context.language.scripts.get(uri);
|
|
47
|
-
if (!sourceFile) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
const root = sourceFile?.generated?.root;
|
|
51
|
-
if (!(root instanceof language_core_1.VueVirtualCode)) {
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
const { template } = root.sfc;
|
|
55
|
-
if (!template) {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
const document = context.documents.get(uri, sourceFile.languageId, sourceFile.snapshot);
|
|
59
|
-
const edits = [];
|
|
60
|
-
const components = await tsPluginClient?.getComponentNames(root.fileName) ?? [];
|
|
61
|
-
const tags = getTemplateTagsAndAttrs(root);
|
|
62
|
-
for (const [tagName, { attrs }] of tags) {
|
|
63
|
-
const componentName = components.find(component => component === tagName || (0, language_core_1.hyphenateTag)(component) === tagName);
|
|
64
|
-
if (componentName) {
|
|
65
|
-
const props = (await tsPluginClient?.getComponentProps(root.fileName, componentName) ?? []).map(prop => prop.name);
|
|
66
|
-
for (const [attrName, { offsets }] of attrs) {
|
|
67
|
-
const propName = props.find(prop => prop === attrName || (0, language_core_1.hyphenateAttr)(prop) === attrName);
|
|
68
|
-
if (propName) {
|
|
69
|
-
for (const offset of offsets) {
|
|
70
|
-
const start = document.positionAt(template.startTagEnd + offset);
|
|
71
|
-
const end = document.positionAt(template.startTagEnd + offset + attrName.length);
|
|
72
|
-
const range = { start, end };
|
|
73
|
-
if (casing === types_1.AttrNameCasing.Kebab && attrName !== (0, language_core_1.hyphenateAttr)(propName)) {
|
|
74
|
-
edits.push({ range, newText: (0, language_core_1.hyphenateAttr)(propName) });
|
|
75
|
-
}
|
|
76
|
-
if (casing === types_1.AttrNameCasing.Camel && attrName !== propName) {
|
|
77
|
-
edits.push({ range, newText: propName });
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return edits;
|
|
85
|
-
}
|
|
86
|
-
async function getNameCasing(context, uri) {
|
|
87
|
-
const detected = await detect(context, uri);
|
|
6
|
+
var TagNameCasing;
|
|
7
|
+
(function (TagNameCasing) {
|
|
8
|
+
TagNameCasing[TagNameCasing["Kebab"] = 0] = "Kebab";
|
|
9
|
+
TagNameCasing[TagNameCasing["Pascal"] = 1] = "Pascal";
|
|
10
|
+
})(TagNameCasing || (exports.TagNameCasing = TagNameCasing = {}));
|
|
11
|
+
var AttrNameCasing;
|
|
12
|
+
(function (AttrNameCasing) {
|
|
13
|
+
AttrNameCasing[AttrNameCasing["Kebab"] = 0] = "Kebab";
|
|
14
|
+
AttrNameCasing[AttrNameCasing["Camel"] = 1] = "Camel";
|
|
15
|
+
})(AttrNameCasing || (exports.AttrNameCasing = AttrNameCasing = {}));
|
|
16
|
+
async function checkCasing(context, uri) {
|
|
17
|
+
const detected = detect(context, uri);
|
|
88
18
|
const [attr, tag] = await Promise.all([
|
|
89
19
|
context.env.getConfiguration?.('vue.complete.casing.props', uri.toString()),
|
|
90
20
|
context.env.getConfiguration?.('vue.complete.casing.tags', uri.toString()),
|
|
91
21
|
]);
|
|
92
|
-
const tagNameCasing = detected.tag.length === 1 && (tag === 'autoPascal' || tag === 'autoKebab')
|
|
93
|
-
|
|
22
|
+
const tagNameCasing = detected.tag.length === 1 && (tag === 'autoPascal' || tag === 'autoKebab')
|
|
23
|
+
? detected.tag[0]
|
|
24
|
+
: (tag === 'autoKebab' || tag === 'kebab')
|
|
25
|
+
? TagNameCasing.Kebab
|
|
26
|
+
: TagNameCasing.Pascal;
|
|
27
|
+
const attrNameCasing = detected.attr.length === 1 && (attr === 'autoCamel' || attr === 'autoKebab')
|
|
28
|
+
? detected.attr[0]
|
|
29
|
+
: (attr === 'autoCamel' || attr === 'camel')
|
|
30
|
+
? AttrNameCasing.Camel
|
|
31
|
+
: AttrNameCasing.Kebab;
|
|
94
32
|
return {
|
|
95
33
|
tag: tagNameCasing,
|
|
96
34
|
attr: attrNameCasing,
|
|
97
35
|
};
|
|
98
36
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
attr: [],
|
|
105
|
-
};
|
|
37
|
+
const cache = new WeakMap();
|
|
38
|
+
function detect(context, uri) {
|
|
39
|
+
const root = context.language.scripts.get(uri)?.generated?.root;
|
|
40
|
+
if (!(root instanceof language_core_1.VueVirtualCode)) {
|
|
41
|
+
return { tag: [], attr: [] };
|
|
106
42
|
}
|
|
107
43
|
return {
|
|
108
|
-
tag:
|
|
109
|
-
attr:
|
|
44
|
+
tag: detectTagCasing(root),
|
|
45
|
+
attr: detectAttrCasing(root),
|
|
110
46
|
};
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
47
|
+
}
|
|
48
|
+
function detectAttrCasing(code) {
|
|
49
|
+
let tags;
|
|
50
|
+
if (cache.has(code)) {
|
|
51
|
+
tags = cache.get(code);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
cache.set(code, tags = collectTags(code));
|
|
55
|
+
}
|
|
56
|
+
const result = new Set();
|
|
57
|
+
for (const [, attrs] of tags ?? []) {
|
|
58
|
+
for (const attr of attrs) {
|
|
59
|
+
// attrName
|
|
60
|
+
if (attr !== (0, language_core_1.hyphenateTag)(attr)) {
|
|
61
|
+
result.add(AttrNameCasing.Camel);
|
|
62
|
+
break;
|
|
121
63
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
64
|
+
}
|
|
65
|
+
for (const attr of attrs) {
|
|
66
|
+
// attr-name
|
|
67
|
+
if (attr.includes('-')) {
|
|
68
|
+
result.add(AttrNameCasing.Kebab);
|
|
69
|
+
break;
|
|
128
70
|
}
|
|
129
71
|
}
|
|
130
|
-
return result;
|
|
131
72
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
73
|
+
return [...result];
|
|
74
|
+
}
|
|
75
|
+
function detectTagCasing(code) {
|
|
76
|
+
let tags;
|
|
77
|
+
if (cache.has(code)) {
|
|
78
|
+
tags = cache.get(code);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
cache.set(code, tags = collectTags(code));
|
|
82
|
+
}
|
|
83
|
+
const result = new Set();
|
|
84
|
+
for (const [tag] of tags ?? []) {
|
|
85
|
+
if (tag !== (0, language_core_1.hyphenateTag)(tag)) {
|
|
86
|
+
// TagName
|
|
87
|
+
result.add(TagNameCasing.Pascal);
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
// tag-name
|
|
91
|
+
result.add(TagNameCasing.Kebab);
|
|
148
92
|
}
|
|
149
|
-
return [...result];
|
|
150
93
|
}
|
|
94
|
+
return [...result];
|
|
151
95
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
96
|
+
function collectTags(root) {
|
|
97
|
+
if (!(root instanceof language_core_1.VueVirtualCode)) {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
const ast = root.sfc.template?.ast;
|
|
101
|
+
if (!ast) {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
const tags = new Map();
|
|
105
|
+
for (const node of (0, language_core_1.forEachElementNode)(ast)) {
|
|
106
|
+
let tag = tags.get(node.tag);
|
|
107
|
+
if (!tag) {
|
|
108
|
+
tags.set(node.tag, tag = []);
|
|
109
|
+
}
|
|
110
|
+
for (const prop of node.props) {
|
|
111
|
+
let name;
|
|
112
|
+
if (prop.type === 7
|
|
113
|
+
&& prop.arg?.type === 4
|
|
114
|
+
&& prop.arg.isStatic) {
|
|
115
|
+
name = prop.arg.content;
|
|
158
116
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if (ast) {
|
|
162
|
-
for (const node of (0, language_core_1.forEachElementNode)(ast)) {
|
|
163
|
-
if (!tags.has(node.tag)) {
|
|
164
|
-
tags.set(node.tag, { offsets: [], attrs: new Map() });
|
|
165
|
-
}
|
|
166
|
-
const tag = tags.get(node.tag);
|
|
167
|
-
const startTagHtmlOffset = node.loc.start.offset + node.loc.source.indexOf(node.tag);
|
|
168
|
-
const endTagHtmlOffset = node.loc.start.offset + node.loc.source.lastIndexOf(node.tag);
|
|
169
|
-
tag.offsets.push(startTagHtmlOffset);
|
|
170
|
-
if (!node.isSelfClosing) {
|
|
171
|
-
tag.offsets.push(endTagHtmlOffset);
|
|
172
|
-
}
|
|
173
|
-
for (const prop of node.props) {
|
|
174
|
-
let name;
|
|
175
|
-
let offset;
|
|
176
|
-
if (prop.type === 7
|
|
177
|
-
&& prop.arg?.type === 4
|
|
178
|
-
&& prop.arg.isStatic) {
|
|
179
|
-
name = prop.arg.content;
|
|
180
|
-
offset = prop.arg.loc.start.offset;
|
|
181
|
-
}
|
|
182
|
-
else if (prop.type === 6) {
|
|
183
|
-
name = prop.name;
|
|
184
|
-
offset = prop.loc.start.offset;
|
|
185
|
-
}
|
|
186
|
-
if (name !== undefined && offset !== undefined) {
|
|
187
|
-
if (!tag.attrs.has(name)) {
|
|
188
|
-
tag.attrs.set(name, { offsets: [] });
|
|
189
|
-
}
|
|
190
|
-
tag.attrs.get(name).offsets.push(offset);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
117
|
+
else if (prop.type === 6) {
|
|
118
|
+
name = prop.name;
|
|
194
119
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
120
|
+
if (name !== undefined) {
|
|
121
|
+
tag.push(name);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
198
124
|
}
|
|
199
|
-
return
|
|
125
|
+
return tags;
|
|
200
126
|
}
|
|
201
127
|
//# sourceMappingURL=nameCasing.js.map
|
package/lib/plugins/utils.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { LanguageServicePlugin } from '
|
|
1
|
+
import type { LanguageServicePlugin } from '@volar/language-service';
|
|
2
2
|
export declare function create(): LanguageServicePlugin;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { LanguageServiceContext, LanguageServicePlugin } from '@volar/language-service';
|
|
2
2
|
export declare function create(ts: typeof import('typescript'), getTsPluginClient?: (context: LanguageServiceContext) => import('@vue/typescript-plugin/lib/requests').Requests | undefined): LanguageServicePlugin;
|
|
@@ -6,8 +6,8 @@ const shared_1 = require("@vue/shared");
|
|
|
6
6
|
const path_browserify_1 = require("path-browserify");
|
|
7
7
|
const getUserPreferences_1 = require("volar-service-typescript/lib/configs/getUserPreferences");
|
|
8
8
|
const vscode_uri_1 = require("vscode-uri");
|
|
9
|
+
const nameCasing_1 = require("../nameCasing");
|
|
9
10
|
const vue_extract_file_1 = require("../plugins/vue-extract-file");
|
|
10
|
-
const types_1 = require("../types");
|
|
11
11
|
function create(ts, getTsPluginClient) {
|
|
12
12
|
return {
|
|
13
13
|
name: 'vue-document-drop',
|
|
@@ -18,7 +18,7 @@ function create(ts, getTsPluginClient) {
|
|
|
18
18
|
if (!context.project.vue) {
|
|
19
19
|
return {};
|
|
20
20
|
}
|
|
21
|
-
let casing =
|
|
21
|
+
let casing = nameCasing_1.TagNameCasing.Pascal; // TODO
|
|
22
22
|
const tsPluginClient = getTsPluginClient?.(context);
|
|
23
23
|
const vueCompilerOptions = context.project.vue.compilerOptions;
|
|
24
24
|
return {
|
|
@@ -103,7 +103,7 @@ function create(ts, getTsPluginClient) {
|
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
return {
|
|
106
|
-
insertText: `<${casing ===
|
|
106
|
+
insertText: `<${casing === nameCasing_1.TagNameCasing.Kebab ? (0, shared_1.hyphenate)(newName) : newName}$0 />`,
|
|
107
107
|
insertTextFormat: 2,
|
|
108
108
|
additionalEdit,
|
|
109
109
|
};
|
|
@@ -16,52 +16,84 @@ function create() {
|
|
|
16
16
|
const decoded = context.decodeEmbeddedDocumentUri(uri);
|
|
17
17
|
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
|
|
18
18
|
const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
|
|
19
|
-
if (!sourceScript?.generated || virtualCode?.id !== 'template') {
|
|
19
|
+
if (!sourceScript?.generated || (virtualCode?.id !== 'template' && virtualCode?.id !== "scriptsetup_raw")) {
|
|
20
20
|
return;
|
|
21
21
|
}
|
|
22
22
|
const root = sourceScript.generated.root;
|
|
23
23
|
if (!(root instanceof language_core_1.VueVirtualCode)) {
|
|
24
24
|
return;
|
|
25
25
|
}
|
|
26
|
-
const result = [];
|
|
27
26
|
const { sfc } = root;
|
|
28
27
|
const codegen = language_core_1.tsCodegen.get(sfc);
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
28
|
+
const result = [];
|
|
29
|
+
if (virtualCode.id === 'template') {
|
|
30
|
+
const scopedClasses = codegen?.getGeneratedTemplate()?.scopedClasses ?? [];
|
|
31
|
+
const styleClasses = new Map();
|
|
32
|
+
const option = root.vueCompilerOptions.resolveStyleClassNames;
|
|
33
|
+
for (let i = 0; i < sfc.styles.length; i++) {
|
|
34
|
+
const style = sfc.styles[i];
|
|
35
|
+
if (option === true || (option === 'scoped' && style.scoped)) {
|
|
36
|
+
for (const className of style.classNames) {
|
|
37
|
+
if (!styleClasses.has(className.text.slice(1))) {
|
|
38
|
+
styleClasses.set(className.text.slice(1), []);
|
|
39
|
+
}
|
|
40
|
+
styleClasses.get(className.text.slice(1)).push({
|
|
41
|
+
index: i,
|
|
42
|
+
style,
|
|
43
|
+
classOffset: className.offset,
|
|
44
|
+
});
|
|
38
45
|
}
|
|
39
|
-
styleClasses.get(className.text.slice(1)).push({
|
|
40
|
-
index: i,
|
|
41
|
-
style,
|
|
42
|
-
classOffset: className.offset,
|
|
43
|
-
});
|
|
44
46
|
}
|
|
45
47
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
48
|
+
for (const { className, offset } of scopedClasses) {
|
|
49
|
+
const styles = styleClasses.get(className);
|
|
50
|
+
if (styles) {
|
|
51
|
+
for (const style of styles) {
|
|
52
|
+
const styleDocumentUri = context.encodeEmbeddedDocumentUri(decoded[0], 'style_' + style.index);
|
|
53
|
+
const styleVirtualCode = sourceScript.generated.embeddedCodes.get('style_' + style.index);
|
|
54
|
+
if (!styleVirtualCode) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const styleDocument = context.documents.get(styleDocumentUri, styleVirtualCode.languageId, styleVirtualCode.snapshot);
|
|
58
|
+
const start = styleDocument.positionAt(style.classOffset);
|
|
59
|
+
const end = styleDocument.positionAt(style.classOffset + className.length + 1);
|
|
60
|
+
result.push({
|
|
61
|
+
range: {
|
|
62
|
+
start: document.positionAt(offset),
|
|
63
|
+
end: document.positionAt(offset + className.length),
|
|
64
|
+
},
|
|
65
|
+
target: context.encodeEmbeddedDocumentUri(decoded[0], 'style_' + style.index) + `#L${start.line + 1},${start.character + 1}-L${end.line + 1},${end.character + 1}`,
|
|
66
|
+
});
|
|
55
67
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else if (virtualCode.id === 'scriptsetup_raw') {
|
|
72
|
+
if (!sfc.scriptSetup) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const templateVirtualCode = sourceScript.generated.embeddedCodes.get('template');
|
|
76
|
+
if (!templateVirtualCode) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
const templateDocumentUri = context.encodeEmbeddedDocumentUri(decoded[0], 'template');
|
|
80
|
+
const templateDocument = context.documents.get(templateDocumentUri, templateVirtualCode.languageId, templateVirtualCode.snapshot);
|
|
81
|
+
const templateRefs = codegen?.getGeneratedTemplate()?.templateRefs;
|
|
82
|
+
const useTemplateRefs = codegen?.getScriptSetupRanges()?.useTemplateRef ?? [];
|
|
83
|
+
for (const { arg } of useTemplateRefs) {
|
|
84
|
+
if (!arg) {
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const name = sfc.scriptSetup.content.slice(arg.start + 1, arg.end - 1);
|
|
88
|
+
for (const { offset } of templateRefs?.get(name) ?? []) {
|
|
89
|
+
const start = templateDocument.positionAt(offset);
|
|
90
|
+
const end = templateDocument.positionAt(offset + name.length);
|
|
59
91
|
result.push({
|
|
60
92
|
range: {
|
|
61
|
-
start: document.positionAt(
|
|
62
|
-
end: document.positionAt(
|
|
93
|
+
start: document.positionAt(arg.start + 1),
|
|
94
|
+
end: document.positionAt(arg.end - 1),
|
|
63
95
|
},
|
|
64
|
-
target:
|
|
96
|
+
target: templateDocumentUri + `#L${start.line + 1},${start.character + 1}-L${end.line + 1},${end.character + 1}`,
|
|
65
97
|
});
|
|
66
98
|
}
|
|
67
99
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import type { LanguageServicePlugin } from '@volar/language-service';
|
|
1
2
|
import type * as ts from 'typescript';
|
|
2
|
-
import type { LanguageServicePlugin } from '../types';
|
|
3
3
|
export declare function create(ts: typeof import('typescript')): LanguageServicePlugin;
|
|
4
4
|
/**
|
|
5
5
|
* Refactored from https://github.com/vuejs/core/blob/main/packages/compiler-sfc/src/script/definePropsDestructure.ts
|
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.create = create;
|
|
4
4
|
exports.findDestructuredProps = findDestructuredProps;
|
|
5
5
|
const language_core_1 = require("@vue/language-core");
|
|
6
|
-
const index_1 = require("@vue/language-core/lib/codegen/utils/index");
|
|
7
6
|
const vscode_uri_1 = require("vscode-uri");
|
|
8
7
|
function create(ts) {
|
|
9
8
|
return {
|
|
@@ -148,7 +147,7 @@ function findDestructuredProps(ts, ast, props) {
|
|
|
148
147
|
&& initializer
|
|
149
148
|
&& ts.isCallExpression(initializer)
|
|
150
149
|
&& initializer.expression.getText(ast) === 'defineProps';
|
|
151
|
-
for (const { id } of (0,
|
|
150
|
+
for (const { id } of (0, language_core_1.collectIdentifiers)(ts, name)) {
|
|
152
151
|
if (isDefineProps) {
|
|
153
152
|
excludedIds.add(id);
|
|
154
153
|
}
|
|
@@ -163,7 +162,7 @@ function findDestructuredProps(ts, ast, props) {
|
|
|
163
162
|
registerLocalBinding(name);
|
|
164
163
|
}
|
|
165
164
|
for (const p of parameters) {
|
|
166
|
-
for (const { id } of (0,
|
|
165
|
+
for (const { id } of (0, language_core_1.collectIdentifiers)(ts, p)) {
|
|
167
166
|
registerLocalBinding(id);
|
|
168
167
|
}
|
|
169
168
|
}
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import type { LanguageServiceContext } from '@volar/language-service';
|
|
2
|
-
import { type LanguageServicePlugin } from '../types';
|
|
1
|
+
import type { LanguageServiceContext, LanguageServicePlugin } from '@volar/language-service';
|
|
3
2
|
export declare function create(getTsPluginClient?: (context: LanguageServiceContext) => import('@vue/typescript-plugin/lib/requests').Requests | undefined): LanguageServicePlugin;
|
|
@@ -5,7 +5,6 @@ const language_core_1 = require("@vue/language-core");
|
|
|
5
5
|
const html = require("vscode-html-languageservice");
|
|
6
6
|
const vscode_uri_1 = require("vscode-uri");
|
|
7
7
|
const nameCasing_1 = require("../nameCasing");
|
|
8
|
-
const types_1 = require("../types");
|
|
9
8
|
function create(getTsPluginClient) {
|
|
10
9
|
return {
|
|
11
10
|
name: 'vue-missing-props-hints',
|
|
@@ -43,7 +42,7 @@ function create(getTsPluginClient) {
|
|
|
43
42
|
return;
|
|
44
43
|
}
|
|
45
44
|
const result = [];
|
|
46
|
-
const casing = await (0, nameCasing_1.
|
|
45
|
+
const casing = await (0, nameCasing_1.checkCasing)(context, decoded[0]);
|
|
47
46
|
const components = await tsPluginClient?.getComponentNames(root.fileName) ?? [];
|
|
48
47
|
const componentProps = {};
|
|
49
48
|
intrinsicElementNames ??= new Set(await tsPluginClient?.getElementNames(root.fileName) ?? []);
|
|
@@ -128,7 +127,7 @@ function create(getTsPluginClient) {
|
|
|
128
127
|
start: document.positionAt(current.labelOffset),
|
|
129
128
|
end: document.positionAt(current.labelOffset),
|
|
130
129
|
},
|
|
131
|
-
newText: ` :${casing.attr ===
|
|
130
|
+
newText: ` :${casing.attr === nameCasing_1.AttrNameCasing.Kebab ? (0, language_core_1.hyphenateAttr)(requiredProp) : requiredProp}=`,
|
|
132
131
|
}],
|
|
133
132
|
});
|
|
134
133
|
}
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import type { LanguageServiceContext } from '@volar/language-service';
|
|
2
|
-
import { type LanguageServicePlugin } from '../types';
|
|
1
|
+
import type { LanguageServiceContext, LanguageServicePlugin } from '@volar/language-service';
|
|
3
2
|
export declare function create(mode: 'html' | 'pug', getTsPluginClient?: (context: LanguageServiceContext) => import('@vue/typescript-plugin/lib/requests').Requests | undefined): LanguageServicePlugin;
|
|
@@ -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.8",
|
|
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.8",
|
|
27
|
-
"alien-signals": "^2.0.5",
|
|
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
|
}
|
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
|