@vue/language-service 2.0.0 → 2.0.2
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 +7 -0
- package/index.js +64 -0
- package/lib/ideFeatures/nameCasing.d.ts +13 -0
- package/lib/ideFeatures/nameCasing.js +211 -0
- package/lib/plugins/css.d.ts +2 -0
- package/lib/plugins/css.js +27 -0
- package/lib/plugins/data.d.ts +4 -0
- package/lib/plugins/data.js +91 -0
- package/lib/plugins/vue-autoinsert-dotvalue.d.ts +10 -0
- package/lib/plugins/vue-autoinsert-dotvalue.js +177 -0
- package/lib/plugins/vue-autoinsert-parentheses.d.ts +2 -0
- package/lib/plugins/vue-autoinsert-parentheses.js +60 -0
- package/lib/plugins/vue-autoinsert-space.d.ts +2 -0
- package/lib/plugins/vue-autoinsert-space.js +34 -0
- package/lib/plugins/vue-codelens-references.d.ts +2 -0
- package/lib/plugins/vue-codelens-references.js +38 -0
- package/lib/plugins/vue-directive-comments.d.ts +2 -0
- package/lib/plugins/vue-directive-comments.js +61 -0
- package/lib/plugins/vue-document-drop.d.ts +2 -0
- package/lib/plugins/vue-document-drop.js +81 -0
- package/lib/plugins/vue-extract-file.d.ts +8 -0
- package/lib/plugins/vue-extract-file.js +258 -0
- package/lib/plugins/vue-sfc.d.ts +7 -0
- package/lib/plugins/vue-sfc.js +163 -0
- package/lib/plugins/vue-template.d.ts +3 -0
- package/lib/plugins/vue-template.js +594 -0
- package/lib/plugins/vue-toggle-v-bind-codeaction.d.ts +2 -0
- package/lib/plugins/vue-toggle-v-bind-codeaction.js +126 -0
- package/lib/plugins/vue-twoslash-queries.d.ts +2 -0
- package/lib/plugins/vue-twoslash-queries.js +50 -0
- package/lib/plugins/vue-visualize-hidden-callback-param.d.ts +2 -0
- package/lib/plugins/vue-visualize-hidden-callback-param.js +45 -0
- package/lib/types.d.ts +10 -0
- package/lib/types.js +31 -0
- package/package.json +6 -6
- package/scripts/update-html-data.js +426 -0
package/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from '@volar/language-service';
|
|
2
|
+
export * from '@vue/language-core';
|
|
3
|
+
export * from './lib/ideFeatures/nameCasing';
|
|
4
|
+
export * from './lib/types';
|
|
5
|
+
import type { ServiceEnvironment, ServicePlugin } from '@volar/language-service';
|
|
6
|
+
import type { VueCompilerOptions } from './lib/types';
|
|
7
|
+
export declare function createVueServicePlugins(ts: typeof import('typescript'), getVueOptions: (env: ServiceEnvironment) => VueCompilerOptions): ServicePlugin[];
|
package/index.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
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.createVueServicePlugins = void 0;
|
|
18
|
+
__exportStar(require("@volar/language-service"), exports);
|
|
19
|
+
__exportStar(require("@vue/language-core"), exports);
|
|
20
|
+
__exportStar(require("./lib/ideFeatures/nameCasing"), exports);
|
|
21
|
+
__exportStar(require("./lib/types"), exports);
|
|
22
|
+
const volar_service_emmet_1 = require("volar-service-emmet");
|
|
23
|
+
const volar_service_json_1 = require("volar-service-json");
|
|
24
|
+
const volar_service_pug_beautify_1 = require("volar-service-pug-beautify");
|
|
25
|
+
const volar_service_typescript_1 = require("volar-service-typescript");
|
|
26
|
+
const volar_service_typescript_twoslash_queries_1 = require("volar-service-typescript-twoslash-queries");
|
|
27
|
+
const css_1 = require("./lib/plugins/css");
|
|
28
|
+
const vue_autoinsert_dotvalue_1 = require("./lib/plugins/vue-autoinsert-dotvalue");
|
|
29
|
+
const vue_autoinsert_parentheses_1 = require("./lib/plugins/vue-autoinsert-parentheses");
|
|
30
|
+
const vue_autoinsert_space_1 = require("./lib/plugins/vue-autoinsert-space");
|
|
31
|
+
const vue_codelens_references_1 = require("./lib/plugins/vue-codelens-references");
|
|
32
|
+
const vue_directive_comments_1 = require("./lib/plugins/vue-directive-comments");
|
|
33
|
+
const vue_document_drop_1 = require("./lib/plugins/vue-document-drop");
|
|
34
|
+
const vue_extract_file_1 = require("./lib/plugins/vue-extract-file");
|
|
35
|
+
const vue_sfc_1 = require("./lib/plugins/vue-sfc");
|
|
36
|
+
const vue_template_1 = require("./lib/plugins/vue-template");
|
|
37
|
+
const vue_toggle_v_bind_codeaction_1 = require("./lib/plugins/vue-toggle-v-bind-codeaction");
|
|
38
|
+
const vue_twoslash_queries_1 = require("./lib/plugins/vue-twoslash-queries");
|
|
39
|
+
const vue_visualize_hidden_callback_param_1 = require("./lib/plugins/vue-visualize-hidden-callback-param");
|
|
40
|
+
function createVueServicePlugins(ts, getVueOptions) {
|
|
41
|
+
return [
|
|
42
|
+
(0, volar_service_typescript_1.create)(ts),
|
|
43
|
+
(0, volar_service_typescript_twoslash_queries_1.create)(),
|
|
44
|
+
(0, css_1.create)(),
|
|
45
|
+
(0, volar_service_pug_beautify_1.create)(),
|
|
46
|
+
(0, volar_service_json_1.create)(),
|
|
47
|
+
(0, vue_template_1.create)('html', ts, getVueOptions),
|
|
48
|
+
(0, vue_template_1.create)('pug', ts, getVueOptions),
|
|
49
|
+
(0, vue_sfc_1.create)(),
|
|
50
|
+
(0, vue_twoslash_queries_1.create)(ts),
|
|
51
|
+
(0, vue_codelens_references_1.create)(),
|
|
52
|
+
(0, vue_document_drop_1.create)(ts),
|
|
53
|
+
(0, vue_autoinsert_dotvalue_1.create)(ts),
|
|
54
|
+
(0, vue_autoinsert_parentheses_1.create)(ts),
|
|
55
|
+
(0, vue_autoinsert_space_1.create)(),
|
|
56
|
+
(0, vue_visualize_hidden_callback_param_1.create)(),
|
|
57
|
+
(0, vue_directive_comments_1.create)(),
|
|
58
|
+
(0, vue_extract_file_1.create)(ts),
|
|
59
|
+
(0, vue_toggle_v_bind_codeaction_1.create)(ts),
|
|
60
|
+
(0, volar_service_emmet_1.create)(),
|
|
61
|
+
];
|
|
62
|
+
}
|
|
63
|
+
exports.createVueServicePlugins = createVueServicePlugins;
|
|
64
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ServiceContext } from '@volar/language-service';
|
|
2
|
+
import type * as vscode from 'vscode-languageserver-protocol';
|
|
3
|
+
import { AttrNameCasing, TagNameCasing } from '../types';
|
|
4
|
+
export declare function convertTagName(context: ServiceContext, uri: string, casing: TagNameCasing): Promise<vscode.TextEdit[] | undefined>;
|
|
5
|
+
export declare function convertAttrName(context: ServiceContext, uri: string, casing: AttrNameCasing): Promise<vscode.TextEdit[] | undefined>;
|
|
6
|
+
export declare function getNameCasing(context: ServiceContext, uri: string): Promise<{
|
|
7
|
+
tag: TagNameCasing;
|
|
8
|
+
attr: AttrNameCasing;
|
|
9
|
+
}>;
|
|
10
|
+
export declare function detect(context: ServiceContext, uri: string): Promise<{
|
|
11
|
+
tag: TagNameCasing[];
|
|
12
|
+
attr: AttrNameCasing[];
|
|
13
|
+
}>;
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detect = exports.getNameCasing = exports.convertAttrName = exports.convertTagName = void 0;
|
|
4
|
+
const vue = require("@vue/language-core");
|
|
5
|
+
const language_core_1 = require("@vue/language-core");
|
|
6
|
+
const namedPipeClient = require("@vue/typescript-plugin/lib/client");
|
|
7
|
+
const computeds_1 = require("computeds");
|
|
8
|
+
const types_1 = require("../types");
|
|
9
|
+
async function convertTagName(context, uri, casing) {
|
|
10
|
+
const sourceFile = context.language.files.get(uri);
|
|
11
|
+
if (!sourceFile)
|
|
12
|
+
return;
|
|
13
|
+
const rootCode = sourceFile?.generated?.code;
|
|
14
|
+
if (!(rootCode instanceof language_core_1.VueGeneratedCode))
|
|
15
|
+
return;
|
|
16
|
+
const desc = rootCode.sfc;
|
|
17
|
+
if (!desc.template)
|
|
18
|
+
return;
|
|
19
|
+
const template = desc.template;
|
|
20
|
+
const document = context.documents.get(sourceFile.id, sourceFile.languageId, sourceFile.snapshot);
|
|
21
|
+
const edits = [];
|
|
22
|
+
const components = await namedPipeClient.getComponentNames(rootCode.fileName) ?? [];
|
|
23
|
+
const tags = getTemplateTagsAndAttrs(rootCode);
|
|
24
|
+
for (const [tagName, { offsets }] of tags) {
|
|
25
|
+
const componentName = components.find(component => component === tagName || (0, language_core_1.hyphenateTag)(component) === tagName);
|
|
26
|
+
if (componentName) {
|
|
27
|
+
for (const offset of offsets) {
|
|
28
|
+
const start = document.positionAt(template.startTagEnd + offset);
|
|
29
|
+
const end = document.positionAt(template.startTagEnd + offset + tagName.length);
|
|
30
|
+
const range = { start, end };
|
|
31
|
+
if (casing === types_1.TagNameCasing.Kebab && tagName !== (0, language_core_1.hyphenateTag)(componentName)) {
|
|
32
|
+
edits.push({ range, newText: (0, language_core_1.hyphenateTag)(componentName) });
|
|
33
|
+
}
|
|
34
|
+
if (casing === types_1.TagNameCasing.Pascal && tagName !== componentName) {
|
|
35
|
+
edits.push({ range, newText: componentName });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return edits;
|
|
41
|
+
}
|
|
42
|
+
exports.convertTagName = convertTagName;
|
|
43
|
+
async function convertAttrName(context, uri, casing) {
|
|
44
|
+
const sourceFile = context.language.files.get(uri);
|
|
45
|
+
if (!sourceFile)
|
|
46
|
+
return;
|
|
47
|
+
const rootCode = sourceFile?.generated?.code;
|
|
48
|
+
if (!(rootCode instanceof language_core_1.VueGeneratedCode))
|
|
49
|
+
return;
|
|
50
|
+
const desc = rootCode.sfc;
|
|
51
|
+
if (!desc.template)
|
|
52
|
+
return;
|
|
53
|
+
const template = desc.template;
|
|
54
|
+
const document = context.documents.get(uri, sourceFile.languageId, sourceFile.snapshot);
|
|
55
|
+
const edits = [];
|
|
56
|
+
const components = await namedPipeClient.getComponentNames(rootCode.fileName) ?? [];
|
|
57
|
+
const tags = getTemplateTagsAndAttrs(rootCode);
|
|
58
|
+
for (const [tagName, { attrs }] of tags) {
|
|
59
|
+
const componentName = components.find(component => component === tagName || (0, language_core_1.hyphenateTag)(component) === tagName);
|
|
60
|
+
if (componentName) {
|
|
61
|
+
const props = await namedPipeClient.getComponentProps(rootCode.fileName, componentName) ?? [];
|
|
62
|
+
for (const [attrName, { offsets }] of attrs) {
|
|
63
|
+
const propName = props.find(prop => prop === attrName || (0, language_core_1.hyphenateAttr)(prop) === attrName);
|
|
64
|
+
if (propName) {
|
|
65
|
+
for (const offset of offsets) {
|
|
66
|
+
const start = document.positionAt(template.startTagEnd + offset);
|
|
67
|
+
const end = document.positionAt(template.startTagEnd + offset + attrName.length);
|
|
68
|
+
const range = { start, end };
|
|
69
|
+
if (casing === types_1.AttrNameCasing.Kebab && attrName !== (0, language_core_1.hyphenateAttr)(propName)) {
|
|
70
|
+
edits.push({ range, newText: (0, language_core_1.hyphenateAttr)(propName) });
|
|
71
|
+
}
|
|
72
|
+
if (casing === types_1.AttrNameCasing.Camel && attrName !== propName) {
|
|
73
|
+
edits.push({ range, newText: propName });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return edits;
|
|
81
|
+
}
|
|
82
|
+
exports.convertAttrName = convertAttrName;
|
|
83
|
+
async function getNameCasing(context, uri) {
|
|
84
|
+
const detected = await detect(context, uri);
|
|
85
|
+
const [attr, tag] = await Promise.all([
|
|
86
|
+
context.env.getConfiguration?.('vue.complete.casing.props', uri),
|
|
87
|
+
context.env.getConfiguration?.('vue.complete.casing.tags', uri),
|
|
88
|
+
]);
|
|
89
|
+
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;
|
|
90
|
+
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;
|
|
91
|
+
return {
|
|
92
|
+
tag: tagNameCasing,
|
|
93
|
+
attr: attrNameCasing,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
exports.getNameCasing = getNameCasing;
|
|
97
|
+
async function detect(context, uri) {
|
|
98
|
+
const rootFile = context.language.files.get(uri)?.generated?.code;
|
|
99
|
+
if (!(rootFile instanceof language_core_1.VueGeneratedCode)) {
|
|
100
|
+
return {
|
|
101
|
+
tag: [],
|
|
102
|
+
attr: [],
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
tag: await getTagNameCase(rootFile),
|
|
107
|
+
attr: getAttrNameCase(rootFile),
|
|
108
|
+
};
|
|
109
|
+
function getAttrNameCase(file) {
|
|
110
|
+
const tags = getTemplateTagsAndAttrs(file);
|
|
111
|
+
const result = [];
|
|
112
|
+
for (const [_, { attrs }] of tags) {
|
|
113
|
+
for (const [tagName] of attrs) {
|
|
114
|
+
// attrName
|
|
115
|
+
if (tagName !== (0, language_core_1.hyphenateTag)(tagName)) {
|
|
116
|
+
result.push(types_1.AttrNameCasing.Camel);
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
for (const [tagName] of attrs) {
|
|
121
|
+
// attr-name
|
|
122
|
+
if (tagName.indexOf('-') >= 0) {
|
|
123
|
+
result.push(types_1.AttrNameCasing.Kebab);
|
|
124
|
+
break;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
async function getTagNameCase(file) {
|
|
131
|
+
const components = await namedPipeClient.getComponentNames(file.fileName) ?? [];
|
|
132
|
+
const tagNames = getTemplateTagsAndAttrs(file);
|
|
133
|
+
const result = [];
|
|
134
|
+
let anyComponentUsed = false;
|
|
135
|
+
for (const component of components) {
|
|
136
|
+
if (tagNames.has(component) || tagNames.has((0, language_core_1.hyphenateTag)(component))) {
|
|
137
|
+
anyComponentUsed = true;
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if (!anyComponentUsed) {
|
|
142
|
+
return []; // not sure component style, because do not have any component using in <template> for check
|
|
143
|
+
}
|
|
144
|
+
for (const [tagName] of tagNames) {
|
|
145
|
+
// TagName
|
|
146
|
+
if (tagName !== (0, language_core_1.hyphenateTag)(tagName)) {
|
|
147
|
+
result.push(types_1.TagNameCasing.Pascal);
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
for (const component of components) {
|
|
152
|
+
// Tagname -> tagname
|
|
153
|
+
// TagName -> tag-name
|
|
154
|
+
if (component !== (0, language_core_1.hyphenateTag)(component) && tagNames.has((0, language_core_1.hyphenateTag)(component))) {
|
|
155
|
+
result.push(types_1.TagNameCasing.Kebab);
|
|
156
|
+
break;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return result;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
exports.detect = detect;
|
|
163
|
+
const map = new WeakMap();
|
|
164
|
+
function getTemplateTagsAndAttrs(sourceFile) {
|
|
165
|
+
if (!map.has(sourceFile)) {
|
|
166
|
+
const getter = (0, computeds_1.computed)(() => {
|
|
167
|
+
if (!(sourceFile instanceof vue.VueGeneratedCode))
|
|
168
|
+
return;
|
|
169
|
+
const ast = sourceFile.sfc.template?.ast;
|
|
170
|
+
const tags = new Map();
|
|
171
|
+
if (ast) {
|
|
172
|
+
for (const node of vue.eachElementNode(ast)) {
|
|
173
|
+
if (!tags.has(node.tag)) {
|
|
174
|
+
tags.set(node.tag, { offsets: [], attrs: new Map() });
|
|
175
|
+
}
|
|
176
|
+
const tag = tags.get(node.tag);
|
|
177
|
+
const startTagHtmlOffset = node.loc.start.offset + node.loc.source.indexOf(node.tag);
|
|
178
|
+
const endTagHtmlOffset = node.loc.start.offset + node.loc.source.lastIndexOf(node.tag);
|
|
179
|
+
tag.offsets.push(startTagHtmlOffset);
|
|
180
|
+
if (!node.isSelfClosing) {
|
|
181
|
+
tag.offsets.push(endTagHtmlOffset);
|
|
182
|
+
}
|
|
183
|
+
for (const prop of node.props) {
|
|
184
|
+
let name;
|
|
185
|
+
let offset;
|
|
186
|
+
if (prop.type === 7
|
|
187
|
+
&& prop.arg?.type === 4
|
|
188
|
+
&& prop.arg.isStatic) {
|
|
189
|
+
name = prop.arg.content;
|
|
190
|
+
offset = prop.arg.loc.start.offset;
|
|
191
|
+
}
|
|
192
|
+
else if (prop.type === 6) {
|
|
193
|
+
name = prop.name;
|
|
194
|
+
offset = prop.loc.start.offset;
|
|
195
|
+
}
|
|
196
|
+
if (name !== undefined && offset !== undefined) {
|
|
197
|
+
if (!tag.attrs.has(name)) {
|
|
198
|
+
tag.attrs.set(name, { offsets: [] });
|
|
199
|
+
}
|
|
200
|
+
tag.attrs.get(name).offsets.push(offset);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return tags;
|
|
206
|
+
});
|
|
207
|
+
map.set(sourceFile, getter);
|
|
208
|
+
}
|
|
209
|
+
return map.get(sourceFile)() ?? new Map();
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=nameCasing.js.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.create = void 0;
|
|
4
|
+
const volar_service_css_1 = require("volar-service-css");
|
|
5
|
+
function create() {
|
|
6
|
+
const base = (0, volar_service_css_1.create)({ scssDocumentSelector: ['scss', 'postcss'] });
|
|
7
|
+
return {
|
|
8
|
+
...base,
|
|
9
|
+
create(context) {
|
|
10
|
+
const baseInstance = base.create(context);
|
|
11
|
+
return {
|
|
12
|
+
...baseInstance,
|
|
13
|
+
async provideDiagnostics(document, token) {
|
|
14
|
+
let diagnostics = await baseInstance.provideDiagnostics?.(document, token) ?? [];
|
|
15
|
+
if (document.languageId === 'postcss') {
|
|
16
|
+
diagnostics = diagnostics.filter(diag => diag.code !== 'css-semicolonexpected');
|
|
17
|
+
diagnostics = diagnostics.filter(diag => diag.code !== 'css-ruleorselectorexpected');
|
|
18
|
+
diagnostics = diagnostics.filter(diag => diag.code !== 'unknownAtRules');
|
|
19
|
+
}
|
|
20
|
+
return diagnostics;
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
exports.create = create;
|
|
27
|
+
//# sourceMappingURL=css.js.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type * as html from 'vscode-html-languageservice';
|
|
2
|
+
export declare function loadTemplateData(lang: string): html.HTMLDataV1;
|
|
3
|
+
export declare function loadLanguageBlocks(lang: string): html.HTMLDataV1;
|
|
4
|
+
export declare function loadModelModifiersData(lang: string): html.HTMLDataV1;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.loadModelModifiersData = exports.loadLanguageBlocks = exports.loadTemplateData = void 0;
|
|
4
|
+
function loadTemplateData(lang) {
|
|
5
|
+
lang = lang.toLowerCase();
|
|
6
|
+
let data;
|
|
7
|
+
if (lang === 'ja') {
|
|
8
|
+
data = require('../../data/template/ja.json');
|
|
9
|
+
}
|
|
10
|
+
else if (lang === 'fr') {
|
|
11
|
+
data = require('../../data/template/fr.json');
|
|
12
|
+
}
|
|
13
|
+
else if (lang === 'ko') {
|
|
14
|
+
data = require('../../data/template/ko.json');
|
|
15
|
+
}
|
|
16
|
+
else if (lang === 'pt-br') {
|
|
17
|
+
data = require('../../data/template/pt.json');
|
|
18
|
+
}
|
|
19
|
+
else if (lang === 'zh-cn') {
|
|
20
|
+
data = require('../../data/template/zh-cn.json');
|
|
21
|
+
}
|
|
22
|
+
else if (lang === 'it') {
|
|
23
|
+
data = require('../../data/template/it.json');
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
data = require('../../data/template/en.json');
|
|
27
|
+
}
|
|
28
|
+
for (const attr of [...data.globalAttributes ?? []]) {
|
|
29
|
+
if (!attr.name.startsWith('v-')) {
|
|
30
|
+
data.globalAttributes?.push({ ...attr, name: `:${attr.name}` });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const vOn = data.globalAttributes?.find(d => d.name === 'v-on');
|
|
34
|
+
const vSlot = data.globalAttributes?.find(d => d.name === 'v-slot');
|
|
35
|
+
const vBind = data.globalAttributes?.find(d => d.name === 'v-bind');
|
|
36
|
+
if (vOn)
|
|
37
|
+
data.globalAttributes?.push({ ...vOn, name: '@' });
|
|
38
|
+
if (vSlot)
|
|
39
|
+
data.globalAttributes?.push({ ...vSlot, name: '#' });
|
|
40
|
+
if (vBind)
|
|
41
|
+
data.globalAttributes?.push({ ...vBind, name: ':' });
|
|
42
|
+
return data;
|
|
43
|
+
}
|
|
44
|
+
exports.loadTemplateData = loadTemplateData;
|
|
45
|
+
function loadLanguageBlocks(lang) {
|
|
46
|
+
lang = lang.toLowerCase();
|
|
47
|
+
if (lang === 'ja') {
|
|
48
|
+
return require('../../data/language-blocks/ja.json');
|
|
49
|
+
}
|
|
50
|
+
else if (lang === 'fr') {
|
|
51
|
+
return require('../../data/language-blocks/fr.json');
|
|
52
|
+
}
|
|
53
|
+
else if (lang === 'ko') {
|
|
54
|
+
return require('../../data/language-blocks/ko.json');
|
|
55
|
+
}
|
|
56
|
+
else if (lang === 'pt-br') {
|
|
57
|
+
return require('../../data/language-blocks/pt.json');
|
|
58
|
+
}
|
|
59
|
+
else if (lang === 'zh-cn') {
|
|
60
|
+
return require('../../data/language-blocks/zh-cn.json');
|
|
61
|
+
}
|
|
62
|
+
else if (lang === 'it') {
|
|
63
|
+
return require('../../data/language-blocks/it.json');
|
|
64
|
+
}
|
|
65
|
+
return require('../../data/language-blocks/en.json');
|
|
66
|
+
}
|
|
67
|
+
exports.loadLanguageBlocks = loadLanguageBlocks;
|
|
68
|
+
function loadModelModifiersData(lang) {
|
|
69
|
+
lang = lang.toLowerCase();
|
|
70
|
+
if (lang === 'ja') {
|
|
71
|
+
return require('../../data/model-modifiers/ja.json');
|
|
72
|
+
}
|
|
73
|
+
else if (lang === 'fr') {
|
|
74
|
+
return require('../../data/model-modifiers/fr.json');
|
|
75
|
+
}
|
|
76
|
+
else if (lang === 'ko') {
|
|
77
|
+
return require('../../data/model-modifiers/ko.json');
|
|
78
|
+
}
|
|
79
|
+
else if (lang === 'pt-br') {
|
|
80
|
+
return require('../../data/model-modifiers/pt.json');
|
|
81
|
+
}
|
|
82
|
+
else if (lang === 'zh-cn') {
|
|
83
|
+
return require('../../data/model-modifiers/zh-cn.json');
|
|
84
|
+
}
|
|
85
|
+
else if (lang === 'it') {
|
|
86
|
+
return require('../../data/model-modifiers/it.json');
|
|
87
|
+
}
|
|
88
|
+
return require('../../data/model-modifiers/en.json');
|
|
89
|
+
}
|
|
90
|
+
exports.loadModelModifiersData = loadModelModifiersData;
|
|
91
|
+
//# sourceMappingURL=data.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ServicePlugin } from '@volar/language-service';
|
|
2
|
+
import type * as ts from 'typescript';
|
|
3
|
+
import type * as vscode from 'vscode-languageserver-protocol';
|
|
4
|
+
import type { TextDocument } from 'vscode-languageserver-textdocument';
|
|
5
|
+
export declare function create(ts: typeof import('typescript')): ServicePlugin;
|
|
6
|
+
export declare function isCharacterTyping(document: TextDocument, lastChange: {
|
|
7
|
+
range: vscode.Range;
|
|
8
|
+
text: string;
|
|
9
|
+
}): boolean;
|
|
10
|
+
export declare function isBlacklistNode(ts: typeof import('typescript'), node: ts.Node, pos: number, allowAccessDotValue: boolean): boolean;
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isBlacklistNode = exports.isCharacterTyping = exports.create = void 0;
|
|
4
|
+
const language_core_1 = require("@vue/language-core");
|
|
5
|
+
const namedPipeClient = require("@vue/typescript-plugin/lib/client");
|
|
6
|
+
const asts = new WeakMap();
|
|
7
|
+
function getAst(ts, fileName, snapshot, scriptKind) {
|
|
8
|
+
let ast = asts.get(snapshot);
|
|
9
|
+
if (!ast) {
|
|
10
|
+
ast = ts.createSourceFile(fileName, snapshot.getText(0, snapshot.getLength()), ts.ScriptTarget.Latest, undefined, scriptKind);
|
|
11
|
+
asts.set(snapshot, ast);
|
|
12
|
+
}
|
|
13
|
+
return ast;
|
|
14
|
+
}
|
|
15
|
+
function create(ts) {
|
|
16
|
+
return {
|
|
17
|
+
name: 'vue-autoinsert-dotvalue',
|
|
18
|
+
create(context) {
|
|
19
|
+
let currentReq = 0;
|
|
20
|
+
return {
|
|
21
|
+
async provideAutoInsertionEdit(document, position, lastChange) {
|
|
22
|
+
if (!isTsDocument(document))
|
|
23
|
+
return;
|
|
24
|
+
if (!isCharacterTyping(document, lastChange))
|
|
25
|
+
return;
|
|
26
|
+
const req = ++currentReq;
|
|
27
|
+
// Wait for tsserver to sync
|
|
28
|
+
await sleep(250);
|
|
29
|
+
if (req !== currentReq)
|
|
30
|
+
return;
|
|
31
|
+
const enabled = await context.env.getConfiguration?.('vue.autoInsert.dotValue') ?? true;
|
|
32
|
+
if (!enabled)
|
|
33
|
+
return;
|
|
34
|
+
const [code, file] = context.documents.getVirtualCodeByUri(document.uri);
|
|
35
|
+
if (!file)
|
|
36
|
+
return;
|
|
37
|
+
let ast;
|
|
38
|
+
let sourceCodeOffset = document.offsetAt(position);
|
|
39
|
+
const fileName = context.env.typescript.uriToFileName(file.id);
|
|
40
|
+
if (file?.generated) {
|
|
41
|
+
const script = file.generated.languagePlugin.typescript?.getScript(file.generated.code);
|
|
42
|
+
if (script?.code !== code) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
ast = getAst(ts, fileName, script.code.snapshot, script.scriptKind);
|
|
46
|
+
let mapped = false;
|
|
47
|
+
for (const [_1, [_2, map]] of context.language.files.getMaps(code)) {
|
|
48
|
+
const sourceOffset = map.getSourceOffset(document.offsetAt(position));
|
|
49
|
+
if (sourceOffset !== undefined) {
|
|
50
|
+
sourceCodeOffset = sourceOffset[0];
|
|
51
|
+
mapped = true;
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (!mapped) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
ast = getAst(ts, fileName, file.snapshot);
|
|
61
|
+
}
|
|
62
|
+
if (isBlacklistNode(ts, ast, document.offsetAt(position), false))
|
|
63
|
+
return;
|
|
64
|
+
const props = await namedPipeClient.getPropertiesAtLocation(fileName, sourceCodeOffset) ?? [];
|
|
65
|
+
if (props.some(prop => prop === 'value')) {
|
|
66
|
+
return '${1:.value}';
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
exports.create = create;
|
|
74
|
+
function sleep(ms) {
|
|
75
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
76
|
+
}
|
|
77
|
+
function isTsDocument(document) {
|
|
78
|
+
return document.languageId === 'javascript' ||
|
|
79
|
+
document.languageId === 'typescript' ||
|
|
80
|
+
document.languageId === 'javascriptreact' ||
|
|
81
|
+
document.languageId === 'typescriptreact';
|
|
82
|
+
}
|
|
83
|
+
const charReg = /\w/;
|
|
84
|
+
function isCharacterTyping(document, lastChange) {
|
|
85
|
+
const lastCharacter = lastChange.text[lastChange.text.length - 1];
|
|
86
|
+
const rangeStart = lastChange.range.start;
|
|
87
|
+
const position = {
|
|
88
|
+
line: rangeStart.line,
|
|
89
|
+
character: rangeStart.character + lastChange.text.length,
|
|
90
|
+
};
|
|
91
|
+
const nextCharacter = document.getText({
|
|
92
|
+
start: position,
|
|
93
|
+
end: { line: position.line, character: position.character + 1 },
|
|
94
|
+
});
|
|
95
|
+
if (lastCharacter === undefined) { // delete text
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
if (lastChange.text.indexOf('\n') >= 0) { // multi-line change
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
return charReg.test(lastCharacter) && !charReg.test(nextCharacter);
|
|
102
|
+
}
|
|
103
|
+
exports.isCharacterTyping = isCharacterTyping;
|
|
104
|
+
function isBlacklistNode(ts, node, pos, allowAccessDotValue) {
|
|
105
|
+
if (ts.isVariableDeclaration(node) && pos >= node.name.getFullStart() && pos <= node.name.getEnd()) {
|
|
106
|
+
return true;
|
|
107
|
+
}
|
|
108
|
+
else if (ts.isFunctionDeclaration(node) && node.name && pos >= node.name.getFullStart() && pos <= node.name.getEnd()) {
|
|
109
|
+
return true;
|
|
110
|
+
}
|
|
111
|
+
else if (ts.isParameter(node) && pos >= node.name.getFullStart() && pos <= node.name.getEnd()) {
|
|
112
|
+
return true;
|
|
113
|
+
}
|
|
114
|
+
else if (ts.isPropertyAssignment(node) && pos >= node.name.getFullStart() && pos <= node.name.getEnd()) {
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
else if (ts.isShorthandPropertyAssignment(node)) {
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
else if (ts.isImportDeclaration(node)) {
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
else if (ts.isLiteralTypeNode(node)) {
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
else if (ts.isTypeReferenceNode(node)) {
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
else if (!allowAccessDotValue && ts.isPropertyAccessExpression(node) && node.expression.end === pos && node.name.text === 'value') {
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
else if (ts.isCallExpression(node)
|
|
133
|
+
&& ts.isIdentifier(node.expression)
|
|
134
|
+
&& isWatchOrUseFunction(node.expression.text)
|
|
135
|
+
&& isTopLevelArgOrArrayTopLevelItemItem(node)) {
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
let _isBlacklistNode = false;
|
|
140
|
+
node.forEachChild(node => {
|
|
141
|
+
if (_isBlacklistNode)
|
|
142
|
+
return;
|
|
143
|
+
if (pos >= node.getFullStart() && pos <= node.getEnd()) {
|
|
144
|
+
if (isBlacklistNode(ts, node, pos, allowAccessDotValue)) {
|
|
145
|
+
_isBlacklistNode = true;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
return _isBlacklistNode;
|
|
150
|
+
}
|
|
151
|
+
function isWatchOrUseFunction(fnName) {
|
|
152
|
+
return fnName === 'watch'
|
|
153
|
+
|| fnName === 'unref'
|
|
154
|
+
|| fnName === 'triggerRef'
|
|
155
|
+
|| fnName === 'isRef'
|
|
156
|
+
|| (0, language_core_1.hyphenateAttr)(fnName).startsWith('use-');
|
|
157
|
+
}
|
|
158
|
+
function isTopLevelArgOrArrayTopLevelItemItem(node) {
|
|
159
|
+
for (const arg of node.arguments) {
|
|
160
|
+
if (pos >= arg.getFullStart() && pos <= arg.getEnd()) {
|
|
161
|
+
if (ts.isIdentifier(arg)) {
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
if (ts.isArrayLiteralExpression(arg)) {
|
|
165
|
+
for (const el of arg.elements) {
|
|
166
|
+
if (pos >= el.getFullStart() && pos <= el.getEnd()) {
|
|
167
|
+
return ts.isIdentifier(el);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
exports.isBlacklistNode = isBlacklistNode;
|
|
177
|
+
//# sourceMappingURL=vue-autoinsert-dotvalue.js.map
|