@vue/language-service 2.0.6 → 2.0.10
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/data/language-blocks/en.json +1 -1
- package/data/model-modifiers/ja.json +1 -1
- package/data/template/ja.json +1 -1
- package/index.d.ts +3 -2
- package/index.js +88 -23
- package/lib/ideFeatures/nameCasing.d.ts +2 -2
- package/lib/ideFeatures/nameCasing.js +23 -16
- package/lib/plugins/css.d.ts +2 -2
- package/lib/plugins/data.js +6 -3
- package/lib/plugins/vue-autoinsert-dotvalue.d.ts +5 -5
- package/lib/plugins/vue-autoinsert-dotvalue.js +37 -31
- package/lib/plugins/vue-autoinsert-parentheses.d.ts +2 -2
- package/lib/plugins/vue-autoinsert-parentheses.js +15 -6
- package/lib/plugins/vue-autoinsert-space.d.ts +2 -2
- package/lib/plugins/vue-autoinsert-space.js +7 -14
- package/lib/plugins/vue-codelens-references.d.ts +2 -2
- package/lib/plugins/vue-codelens-references.js +8 -4
- package/lib/plugins/vue-directive-comments.d.ts +2 -2
- package/lib/plugins/vue-directive-comments.js +4 -3
- package/lib/plugins/vue-document-drop.d.ts +2 -2
- package/lib/plugins/vue-document-drop.js +36 -14
- package/lib/plugins/vue-extract-file.d.ts +2 -2
- package/lib/plugins/vue-extract-file.js +32 -18
- package/lib/plugins/vue-sfc.d.ts +2 -2
- package/lib/plugins/vue-sfc.js +40 -35
- package/lib/plugins/vue-template.d.ts +3 -3
- package/lib/plugins/vue-template.js +86 -32
- package/lib/plugins/vue-toggle-v-bind-codeaction.d.ts +2 -2
- package/lib/plugins/vue-toggle-v-bind-codeaction.js +6 -3
- package/lib/plugins/vue-twoslash-queries.d.ts +2 -2
- package/lib/plugins/vue-twoslash-queries.js +9 -5
- package/lib/plugins/vue-visualize-hidden-callback-param.d.ts +2 -2
- package/lib/plugins/vue-visualize-hidden-callback-param.js +7 -4
- package/package.json +19 -19
|
@@ -556,7 +556,7 @@
|
|
|
556
556
|
"valueSet": "v",
|
|
557
557
|
"description": {
|
|
558
558
|
"kind": "markdown",
|
|
559
|
-
"value": "\nA `<style module>` tag is compiled as [CSS Modules](https://github.com/css-modules/css-modules) and exposes the resulting CSS classes to the component as an object under the key of `$style`:\n\n```vue\n<template>\n <p :class=\"$style.red\">This should be red</p>\n</template>\n\n<style module>\n.red {\n color: red;\n}\n</style>\n```\n\nThe resulting classes are hashed to avoid collision, achieving the same effect of scoping the CSS to the current component only.\n\nRefer to the [CSS Modules spec](https://github.com/css-modules/css-modules) for more details such as [global exceptions](https://github.com/css-modules/css-modules#exceptions) and [composition](https://github.com/css-modules/css-modules#composition).\n\n### Custom Inject Name \n\nYou can customize the property key of the injected classes object by giving the `module` attribute a value:\n\n```vue\n<template>\n <p :class=\"classes.red\">red</p>\n</template>\n\n<style module=\"classes\">\n.red {\n color: red;\n}\n</style>\n```\n\n### Usage with Composition API \n\nThe injected classes can be accessed in `setup()` and `<script setup>` via the `useCssModule` API. For `<style module>` blocks with custom injection names, `useCssModule` accepts the matching `module` attribute value as the first argument:\n\n```js\nimport { useCssModule } from 'vue'\n\n// inside setup() scope...\n// default, returns classes for <style module>\nuseCssModule()\n\n// named, returns classes for <style module=\"classes\">\nuseCssModule('classes')\n```\n"
|
|
559
|
+
"value": "\nA `<style module>` tag is compiled as [CSS Modules](https://github.com/css-modules/css-modules) and exposes the resulting CSS classes to the component as an object under the key of `$style`:\n\n```vue\n<template>\n <p :class=\"$style.red\">This should be red</p>\n</template>\n\n<style module>\n.red {\n color: red;\n}\n</style>\n```\n\nThe resulting classes are hashed to avoid collision, achieving the same effect of scoping the CSS to the current component only.\n\nRefer to the [CSS Modules spec](https://github.com/css-modules/css-modules) for more details such as [global exceptions](https://github.com/css-modules/css-modules/blob/master/docs/composition.md#exceptions) and [composition](https://github.com/css-modules/css-modules/blob/master/docs/composition.md#composition).\n\n### Custom Inject Name \n\nYou can customize the property key of the injected classes object by giving the `module` attribute a value:\n\n```vue\n<template>\n <p :class=\"classes.red\">red</p>\n</template>\n\n<style module=\"classes\">\n.red {\n color: red;\n}\n</style>\n```\n\n### Usage with Composition API \n\nThe injected classes can be accessed in `setup()` and `<script setup>` via the `useCssModule` API. For `<style module>` blocks with custom injection names, `useCssModule` accepts the matching `module` attribute value as the first argument:\n\n```js\nimport { useCssModule } from 'vue'\n\n// inside setup() scope...\n// default, returns classes for <style module>\nuseCssModule()\n\n// named, returns classes for <style module=\"classes\">\nuseCssModule('classes')\n```\n"
|
|
560
560
|
},
|
|
561
561
|
"references": [
|
|
562
562
|
{
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"name": "lazy",
|
|
6
6
|
"description": {
|
|
7
7
|
"kind": "markdown",
|
|
8
|
-
"value": "\nデフォルトでは、 `v-model` は各 `input`
|
|
8
|
+
"value": "\nデフォルトでは、 `v-model` は各 `input` イベントの後に、入力とデータを同期します([上記](#vmodel-ime-tip) の IME による入力は例外とします)。 代わりに `change` イベント後に同期する `lazy` 修飾子を追加することができます。\n\n```html\n<!-- \"input\" の代わりに \"change\" イベント後に同期されます -->\n<input v-model.lazy=\"msg\" />\n```\n"
|
|
9
9
|
},
|
|
10
10
|
"references": [
|
|
11
11
|
{
|
package/data/template/ja.json
CHANGED
|
@@ -736,7 +736,7 @@
|
|
|
736
736
|
"name": "v-bind",
|
|
737
737
|
"description": {
|
|
738
738
|
"kind": "markdown",
|
|
739
|
-
"value": "\n1 つ以上の属性やコンポーネントの props を式に動的にバインドします。\n\n- **省略記法:**\n - `:` or `.`(`.prop` 修飾子使用時)\n - 値の省略(属性とバインドされた値が同じ名前の場合)<sup class=\"vt-badge\">3.4+</sup>\n\n- **期待する値:** `any
|
|
739
|
+
"value": "\n1 つ以上の属性やコンポーネントの props を式に動的にバインドします。\n\n- **省略記法:**\n - `:` or `.`(`.prop` 修飾子使用時)\n - 値の省略(属性とバインドされた値が同じ名前の場合)<sup class=\"vt-badge\">3.4+</sup>\n\n- **期待する値:** `any(引数ありの場合)| Object(引数なしの場合)`\n\n- **引数:** `attrOrProp(省略可能)`\n\n- **修飾子**\n\n - `.camel` - kebab-case の属性名を camelCase に変換します。\n - `.prop` - バインディングを DOM プロパティとして設定するよう強制します。<sup class=\"vt-badge\">3.2+</sup>\n - `.attr` - バインディングを DOM 属性として設定するよう強制します。<sup class=\"vt-badge\">3.2+</sup>\n\n- **使用法**\n\n `class` や `style` 属性をバインドする際に使用する `v-bind` は、Array や Object などの追加の値の型をサポートします。詳しくは、以下のリンク先のガイドを参照してください。\n\n 要素にバインディングを設定するとき、Vue はデフォルトで、`in` 演算子チェックを使用して、プロパティとして定義されたキーが要素にあるかどうかを確認します。プロパティが定義されている場合、Vue はその値を属性ではなく DOM プロパティとして設定します。これはほとんどの場合において有効ですが、`.prop` や `.attr` という修飾子を明示的に使用することでこの動作をオーバーライドできます。これは、特に[カスタム要素を扱う](https://ja.vuejs.org/guide/extras/web-components.html#passing-dom-properties)ときに必要になることがあります。\n\n コンポーネントの props をバインドするために使用する場合、その props は子コンポーネントで適切に宣言されている必要があります。\n\n 引数なしで使用する場合、属性の名前と値のペアを含むオブジェクトをバインドするために使用できます。\n\n- **例**\n\n ```html\n <!-- 属性をバインドする -->\n <img v-bind:src=\"imageSrc\" />\n\n <!-- 動的な属性名 -->\n <button v-bind:[key]=\"value\"></button>\n\n <!-- 省略記法 -->\n <img :src=\"imageSrc\" />\n\n <!-- 同名省略記法(3.4+), :src=\"src\" のように展開する -->\n <img :src />\n\n <!-- 動的な属性名の省略記法 -->\n <button :[key]=\"value\"></button>\n\n <!-- インラインの文字列連結 -->\n <img :src=\"'/path/to/images/' + fileName\" />\n\n <!-- クラスのバインド -->\n <div :class=\"{ red: isRed }\"></div>\n <div :class=\"[classA, classB]\"></div>\n <div :class=\"[classA, { classB: isB, classC: isC }]\"></div>\n\n <!-- スタイルのバインド -->\n <div :style=\"{ fontSize: size + 'px' }\"></div>\n <div :style=\"[styleObjectA, styleObjectB]\"></div>\n\n <!-- 属性のオブジェクトをバインド -->\n <div v-bind=\"{ id: someProp, 'other-attr': otherProp }\"></div>\n\n <!-- props のバインド。\"prop\" は子コンポーネントで宣言する必要があります。 -->\n <MyComponent :prop=\"someThing\" />\n\n <!-- 親の props を子コンポーネントと共有するために渡す -->\n <MyComponent v-bind=\"$props\" />\n\n <!-- XLink -->\n <svg><a :xlink:special=\"foo\"></a></svg>\n ```\n\n `.prop` 修飾子には、専用の短縮形 `.` もあります:\n\n ```html\n <div :someProperty.prop=\"someObject\"></div>\n\n <!-- 以下と同じ -->\n <div .someProperty=\"someObject\"></div>\n ```\n\n `.camel` 修飾子は、DOM 内テンプレートを使用する際に、 `v-bind` 属性名をキャメル化できます(例: SVG の `viewBox` 属性):\n\n ```html\n <svg :view-box.camel=\"viewBox\"></svg>\n ```\n\n 文字列テンプレートを使用する場合や、ビルドステップでテンプレートを事前コンパイルする場合は、`.camel` は必要ありません。\n\n- **参照**\n - [クラスとスタイルのバインディング](https://ja.vuejs.org/guide/essentials/class-and-style.html)\n - [コンポーネント - props 渡しの詳細](https://ja.vuejs.org/guide/components/props.html#prop-passing-details)\n"
|
|
740
740
|
},
|
|
741
741
|
"references": [
|
|
742
742
|
{
|
package/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from '@volar/language-service';
|
|
|
2
2
|
export * from '@vue/language-core';
|
|
3
3
|
export * from './lib/ideFeatures/nameCasing';
|
|
4
4
|
export * from './lib/types';
|
|
5
|
-
import type { ServiceEnvironment,
|
|
5
|
+
import type { ServiceContext, ServiceEnvironment, LanguageServicePlugin } from '@volar/language-service';
|
|
6
6
|
import type { VueCompilerOptions } from './lib/types';
|
|
7
|
-
export declare function createVueServicePlugins(ts: typeof import('typescript'), getVueOptions: (env: ServiceEnvironment) => VueCompilerOptions,
|
|
7
|
+
export declare function createVueServicePlugins(ts: typeof import('typescript'), getVueOptions: (env: ServiceEnvironment) => VueCompilerOptions, getTsPluginClient?: (context: ServiceContext) => typeof import("@vue/typescript-plugin/lib/client") | undefined, hybridMode?: boolean): LanguageServicePlugin[];
|
|
8
|
+
export declare function createDefaultGetTsPluginClient(ts: typeof import('typescript'), getVueOptions: (env: ServiceEnvironment) => VueCompilerOptions): (context: ServiceContext) => typeof import('@vue/typescript-plugin/lib/client') | undefined;
|
package/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.createVueServicePlugins = void 0;
|
|
17
|
+
exports.createDefaultGetTsPluginClient = exports.createVueServicePlugins = void 0;
|
|
18
18
|
__exportStar(require("@volar/language-service"), exports);
|
|
19
19
|
__exportStar(require("@vue/language-core"), exports);
|
|
20
20
|
__exportStar(require("./lib/ideFeatures/nameCasing"), exports);
|
|
@@ -24,6 +24,8 @@ const volar_service_json_1 = require("volar-service-json");
|
|
|
24
24
|
const volar_service_pug_beautify_1 = require("volar-service-pug-beautify");
|
|
25
25
|
const volar_service_typescript_1 = require("volar-service-typescript");
|
|
26
26
|
const volar_service_typescript_twoslash_queries_1 = require("volar-service-typescript-twoslash-queries");
|
|
27
|
+
const docCommentTemplate_1 = require("volar-service-typescript/lib/plugins/docCommentTemplate");
|
|
28
|
+
const syntactic_1 = require("volar-service-typescript/lib/plugins/syntactic");
|
|
27
29
|
const css_1 = require("./lib/plugins/css");
|
|
28
30
|
const vue_autoinsert_dotvalue_1 = require("./lib/plugins/vue-autoinsert-dotvalue");
|
|
29
31
|
const vue_autoinsert_parentheses_1 = require("./lib/plugins/vue-autoinsert-parentheses");
|
|
@@ -37,28 +39,91 @@ const vue_template_1 = require("./lib/plugins/vue-template");
|
|
|
37
39
|
const vue_toggle_v_bind_codeaction_1 = require("./lib/plugins/vue-toggle-v-bind-codeaction");
|
|
38
40
|
const vue_twoslash_queries_1 = require("./lib/plugins/vue-twoslash-queries");
|
|
39
41
|
const vue_visualize_hidden_callback_param_1 = require("./lib/plugins/vue-visualize-hidden-callback-param");
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
(0,
|
|
50
|
-
(0
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
42
|
+
const common_1 = require("@vue/typescript-plugin/lib/common");
|
|
43
|
+
const collectExtractProps_1 = require("@vue/typescript-plugin/lib/requests/collectExtractProps");
|
|
44
|
+
const componentInfos_1 = require("@vue/typescript-plugin/lib/requests/componentInfos");
|
|
45
|
+
const getImportPathForFile_1 = require("@vue/typescript-plugin/lib/requests/getImportPathForFile");
|
|
46
|
+
const getPropertiesAtLocation_1 = require("@vue/typescript-plugin/lib/requests/getPropertiesAtLocation");
|
|
47
|
+
const getQuickInfoAtPosition_1 = require("@vue/typescript-plugin/lib/requests/getQuickInfoAtPosition");
|
|
48
|
+
function createVueServicePlugins(ts, getVueOptions, getTsPluginClient = createDefaultGetTsPluginClient(ts, getVueOptions), hybridMode = false) {
|
|
49
|
+
const plugins = [];
|
|
50
|
+
if (!hybridMode) {
|
|
51
|
+
plugins.push(...(0, volar_service_typescript_1.create)(ts));
|
|
52
|
+
for (let i = 0; i < plugins.length; i++) {
|
|
53
|
+
const plugin = plugins[i];
|
|
54
|
+
if (plugin.name === 'typescript-semantic') {
|
|
55
|
+
plugins[i] = {
|
|
56
|
+
...plugin,
|
|
57
|
+
create(context) {
|
|
58
|
+
const created = plugin.create(context);
|
|
59
|
+
if (!context.language.typescript) {
|
|
60
|
+
return created;
|
|
61
|
+
}
|
|
62
|
+
const languageService = created.provide['typescript/languageService']();
|
|
63
|
+
const vueOptions = getVueOptions(context.env);
|
|
64
|
+
(0, common_1.decorateLanguageServiceForVue)(context.language, languageService, vueOptions, ts, false);
|
|
65
|
+
return created;
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
plugins.push((0, syntactic_1.create)(ts), (0, docCommentTemplate_1.create)(ts));
|
|
74
|
+
}
|
|
75
|
+
plugins.push((0, volar_service_typescript_twoslash_queries_1.create)(ts), (0, css_1.create)(), (0, volar_service_pug_beautify_1.create)(), (0, volar_service_json_1.create)(), (0, vue_template_1.create)('html', ts, getVueOptions, getTsPluginClient), (0, vue_template_1.create)('pug', ts, getVueOptions, getTsPluginClient), (0, vue_sfc_1.create)(), (0, vue_twoslash_queries_1.create)(ts, getTsPluginClient), (0, vue_codelens_references_1.create)(), (0, vue_document_drop_1.create)(ts, getTsPluginClient), (0, vue_autoinsert_dotvalue_1.create)(ts, getTsPluginClient), (0, vue_autoinsert_parentheses_1.create)(ts), (0, vue_autoinsert_space_1.create)(), (0, vue_visualize_hidden_callback_param_1.create)(), (0, vue_directive_comments_1.create)(), (0, vue_extract_file_1.create)(ts, getTsPluginClient), (0, vue_toggle_v_bind_codeaction_1.create)(ts), (0, volar_service_emmet_1.create)());
|
|
76
|
+
return plugins;
|
|
62
77
|
}
|
|
63
78
|
exports.createVueServicePlugins = createVueServicePlugins;
|
|
79
|
+
function createDefaultGetTsPluginClient(ts, getVueOptions) {
|
|
80
|
+
return context => {
|
|
81
|
+
if (!context.language.typescript) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const languageService = context.inject('typescript/languageService');
|
|
85
|
+
if (!languageService) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
const requestContext = {
|
|
89
|
+
typescript: ts,
|
|
90
|
+
language: context.language,
|
|
91
|
+
languageService,
|
|
92
|
+
languageServiceHost: context.language.typescript.languageServiceHost,
|
|
93
|
+
vueOptions: getVueOptions(context.env),
|
|
94
|
+
isTsPlugin: false,
|
|
95
|
+
getFileId: context.env.typescript.fileNameToUri,
|
|
96
|
+
};
|
|
97
|
+
return {
|
|
98
|
+
async collectExtractProps(...args) {
|
|
99
|
+
return await collectExtractProps_1.collectExtractProps.apply(requestContext, args);
|
|
100
|
+
},
|
|
101
|
+
async getPropertiesAtLocation(...args) {
|
|
102
|
+
return await getPropertiesAtLocation_1.getPropertiesAtLocation.apply(requestContext, args);
|
|
103
|
+
},
|
|
104
|
+
async getImportPathForFile(...args) {
|
|
105
|
+
return await getImportPathForFile_1.getImportPathForFile.apply(requestContext, args);
|
|
106
|
+
},
|
|
107
|
+
async getComponentEvents(...args) {
|
|
108
|
+
return await componentInfos_1.getComponentEvents.apply(requestContext, args);
|
|
109
|
+
},
|
|
110
|
+
async getComponentNames(...args) {
|
|
111
|
+
return await componentInfos_1.getComponentNames.apply(requestContext, args);
|
|
112
|
+
},
|
|
113
|
+
async getComponentProps(...args) {
|
|
114
|
+
return await componentInfos_1.getComponentProps.apply(requestContext, args);
|
|
115
|
+
},
|
|
116
|
+
async getElementAttrs(...args) {
|
|
117
|
+
return await componentInfos_1.getElementAttrs.apply(requestContext, args);
|
|
118
|
+
},
|
|
119
|
+
async getTemplateContextProps(...args) {
|
|
120
|
+
return await componentInfos_1.getTemplateContextProps.apply(requestContext, args);
|
|
121
|
+
},
|
|
122
|
+
async getQuickInfoAtPosition(...args) {
|
|
123
|
+
return await getQuickInfoAtPosition_1.getQuickInfoAtPosition.apply(requestContext, args);
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
exports.createDefaultGetTsPluginClient = createDefaultGetTsPluginClient;
|
|
64
129
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { ServiceContext } from '@volar/language-service';
|
|
2
2
|
import type * as vscode from 'vscode-languageserver-protocol';
|
|
3
3
|
import { AttrNameCasing, TagNameCasing } from '../types';
|
|
4
|
-
export declare function convertTagName(context: ServiceContext, uri: string, casing: TagNameCasing, tsPluginClient: typeof import('@vue/typescript-plugin/lib/client')): Promise<vscode.TextEdit[] | undefined>;
|
|
5
|
-
export declare function convertAttrName(context: ServiceContext, uri: string, casing: AttrNameCasing, tsPluginClient
|
|
4
|
+
export declare function convertTagName(context: ServiceContext, uri: string, casing: TagNameCasing, tsPluginClient: typeof import('@vue/typescript-plugin/lib/client') | undefined): Promise<vscode.TextEdit[] | undefined>;
|
|
5
|
+
export declare function convertAttrName(context: ServiceContext, uri: string, casing: AttrNameCasing, tsPluginClient?: typeof import('@vue/typescript-plugin/lib/client')): Promise<vscode.TextEdit[] | undefined>;
|
|
6
6
|
export declare function getNameCasing(context: ServiceContext, uri: string, tsPluginClient?: typeof import('@vue/typescript-plugin/lib/client')): Promise<{
|
|
7
7
|
tag: TagNameCasing;
|
|
8
8
|
attr: AttrNameCasing;
|
|
@@ -6,19 +6,22 @@ const language_core_1 = require("@vue/language-core");
|
|
|
6
6
|
const computeds_1 = require("computeds");
|
|
7
7
|
const types_1 = require("../types");
|
|
8
8
|
async function convertTagName(context, uri, casing, tsPluginClient) {
|
|
9
|
-
const sourceFile = context.language.
|
|
10
|
-
if (!sourceFile)
|
|
9
|
+
const sourceFile = context.language.scripts.get(uri);
|
|
10
|
+
if (!sourceFile) {
|
|
11
11
|
return;
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
}
|
|
13
|
+
const rootCode = sourceFile?.generated?.root;
|
|
14
|
+
if (!(rootCode instanceof language_core_1.VueGeneratedCode)) {
|
|
14
15
|
return;
|
|
16
|
+
}
|
|
15
17
|
const desc = rootCode.sfc;
|
|
16
|
-
if (!desc.template)
|
|
18
|
+
if (!desc.template) {
|
|
17
19
|
return;
|
|
20
|
+
}
|
|
18
21
|
const template = desc.template;
|
|
19
22
|
const document = context.documents.get(sourceFile.id, sourceFile.languageId, sourceFile.snapshot);
|
|
20
23
|
const edits = [];
|
|
21
|
-
const components = await tsPluginClient
|
|
24
|
+
const components = await tsPluginClient?.getComponentNames(rootCode.fileName) ?? [];
|
|
22
25
|
const tags = getTemplateTagsAndAttrs(rootCode);
|
|
23
26
|
for (const [tagName, { offsets }] of tags) {
|
|
24
27
|
const componentName = components.find(component => component === tagName || (0, language_core_1.hyphenateTag)(component) === tagName);
|
|
@@ -40,24 +43,27 @@ async function convertTagName(context, uri, casing, tsPluginClient) {
|
|
|
40
43
|
}
|
|
41
44
|
exports.convertTagName = convertTagName;
|
|
42
45
|
async function convertAttrName(context, uri, casing, tsPluginClient) {
|
|
43
|
-
const sourceFile = context.language.
|
|
44
|
-
if (!sourceFile)
|
|
46
|
+
const sourceFile = context.language.scripts.get(uri);
|
|
47
|
+
if (!sourceFile) {
|
|
45
48
|
return;
|
|
46
|
-
|
|
47
|
-
|
|
49
|
+
}
|
|
50
|
+
const rootCode = sourceFile?.generated?.root;
|
|
51
|
+
if (!(rootCode instanceof language_core_1.VueGeneratedCode)) {
|
|
48
52
|
return;
|
|
53
|
+
}
|
|
49
54
|
const desc = rootCode.sfc;
|
|
50
|
-
if (!desc.template)
|
|
55
|
+
if (!desc.template) {
|
|
51
56
|
return;
|
|
57
|
+
}
|
|
52
58
|
const template = desc.template;
|
|
53
59
|
const document = context.documents.get(uri, sourceFile.languageId, sourceFile.snapshot);
|
|
54
60
|
const edits = [];
|
|
55
|
-
const components = await tsPluginClient
|
|
61
|
+
const components = await tsPluginClient?.getComponentNames(rootCode.fileName) ?? [];
|
|
56
62
|
const tags = getTemplateTagsAndAttrs(rootCode);
|
|
57
63
|
for (const [tagName, { attrs }] of tags) {
|
|
58
64
|
const componentName = components.find(component => component === tagName || (0, language_core_1.hyphenateTag)(component) === tagName);
|
|
59
65
|
if (componentName) {
|
|
60
|
-
const props = await tsPluginClient
|
|
66
|
+
const props = await tsPluginClient?.getComponentProps(rootCode.fileName, componentName) ?? [];
|
|
61
67
|
for (const [attrName, { offsets }] of attrs) {
|
|
62
68
|
const propName = props.find(prop => prop === attrName || (0, language_core_1.hyphenateAttr)(prop) === attrName);
|
|
63
69
|
if (propName) {
|
|
@@ -94,7 +100,7 @@ async function getNameCasing(context, uri, tsPluginClient) {
|
|
|
94
100
|
}
|
|
95
101
|
exports.getNameCasing = getNameCasing;
|
|
96
102
|
async function detect(context, uri, tsPluginClient) {
|
|
97
|
-
const rootFile = context.language.
|
|
103
|
+
const rootFile = context.language.scripts.get(uri)?.generated?.root;
|
|
98
104
|
if (!(rootFile instanceof language_core_1.VueGeneratedCode)) {
|
|
99
105
|
return {
|
|
100
106
|
tag: [],
|
|
@@ -163,12 +169,13 @@ const map = new WeakMap();
|
|
|
163
169
|
function getTemplateTagsAndAttrs(sourceFile) {
|
|
164
170
|
if (!map.has(sourceFile)) {
|
|
165
171
|
const getter = (0, computeds_1.computed)(() => {
|
|
166
|
-
if (!(sourceFile instanceof vue.VueGeneratedCode))
|
|
172
|
+
if (!(sourceFile instanceof vue.VueGeneratedCode)) {
|
|
167
173
|
return;
|
|
174
|
+
}
|
|
168
175
|
const ast = sourceFile.sfc.template?.ast;
|
|
169
176
|
const tags = new Map();
|
|
170
177
|
if (ast) {
|
|
171
|
-
for (const node of vue.
|
|
178
|
+
for (const node of vue.forEachElementNode(ast)) {
|
|
172
179
|
if (!tags.has(node.tag)) {
|
|
173
180
|
tags.set(node.tag, { offsets: [], attrs: new Map() });
|
|
174
181
|
}
|
package/lib/plugins/css.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function create():
|
|
1
|
+
import type { LanguageServicePlugin } from '@volar/language-service';
|
|
2
|
+
export declare function create(): LanguageServicePlugin;
|
package/lib/plugins/data.js
CHANGED
|
@@ -33,12 +33,15 @@ function loadTemplateData(lang) {
|
|
|
33
33
|
const vOn = data.globalAttributes?.find(d => d.name === 'v-on');
|
|
34
34
|
const vSlot = data.globalAttributes?.find(d => d.name === 'v-slot');
|
|
35
35
|
const vBind = data.globalAttributes?.find(d => d.name === 'v-bind');
|
|
36
|
-
if (vOn)
|
|
36
|
+
if (vOn) {
|
|
37
37
|
data.globalAttributes?.push({ ...vOn, name: '@' });
|
|
38
|
-
|
|
38
|
+
}
|
|
39
|
+
if (vSlot) {
|
|
39
40
|
data.globalAttributes?.push({ ...vSlot, name: '#' });
|
|
40
|
-
|
|
41
|
+
}
|
|
42
|
+
if (vBind) {
|
|
41
43
|
data.globalAttributes?.push({ ...vBind, name: ':' });
|
|
44
|
+
}
|
|
42
45
|
return data;
|
|
43
46
|
}
|
|
44
47
|
exports.loadTemplateData = loadTemplateData;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ServiceContext, LanguageServicePlugin } from '@volar/language-service';
|
|
2
2
|
import type * as ts from 'typescript';
|
|
3
|
-
import type * as vscode from 'vscode-languageserver-protocol';
|
|
4
3
|
import type { TextDocument } from 'vscode-languageserver-textdocument';
|
|
5
|
-
export declare function create(ts: typeof import('typescript'),
|
|
6
|
-
export declare function isCharacterTyping(document: TextDocument,
|
|
7
|
-
range: vscode.Range;
|
|
4
|
+
export declare function create(ts: typeof import('typescript'), getTsPluginClient?: (context: ServiceContext) => typeof import('@vue/typescript-plugin/lib/client') | undefined): LanguageServicePlugin;
|
|
5
|
+
export declare function isCharacterTyping(document: TextDocument, change: {
|
|
8
6
|
text: string;
|
|
7
|
+
rangeOffset: number;
|
|
8
|
+
rangeLength: number;
|
|
9
9
|
}): boolean;
|
|
10
10
|
export declare function isBlacklistNode(ts: typeof import('typescript'), node: ts.Node, pos: number, allowAccessDotValue: boolean): boolean;
|
|
@@ -11,40 +11,52 @@ function getAst(ts, fileName, snapshot, scriptKind) {
|
|
|
11
11
|
}
|
|
12
12
|
return ast;
|
|
13
13
|
}
|
|
14
|
-
function create(ts,
|
|
14
|
+
function create(ts, getTsPluginClient) {
|
|
15
15
|
return {
|
|
16
16
|
name: 'vue-autoinsert-dotvalue',
|
|
17
17
|
create(context) {
|
|
18
|
+
const tsPluginClient = getTsPluginClient?.(context);
|
|
18
19
|
let currentReq = 0;
|
|
19
20
|
return {
|
|
20
|
-
async provideAutoInsertionEdit(document,
|
|
21
|
-
|
|
21
|
+
async provideAutoInsertionEdit(document, selection, change) {
|
|
22
|
+
// selection must at end of change
|
|
23
|
+
if (document.offsetAt(selection) !== change.rangeOffset + change.text.length) {
|
|
22
24
|
return;
|
|
23
|
-
|
|
25
|
+
}
|
|
26
|
+
if (!isTsDocument(document)) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
if (!isCharacterTyping(document, change)) {
|
|
24
30
|
return;
|
|
31
|
+
}
|
|
25
32
|
const req = ++currentReq;
|
|
26
33
|
// Wait for tsserver to sync
|
|
27
34
|
await sleep(250);
|
|
28
|
-
if (req !== currentReq)
|
|
35
|
+
if (req !== currentReq) {
|
|
29
36
|
return;
|
|
37
|
+
}
|
|
30
38
|
const enabled = await context.env.getConfiguration?.('vue.autoInsert.dotValue') ?? true;
|
|
31
|
-
if (!enabled)
|
|
39
|
+
if (!enabled) {
|
|
32
40
|
return;
|
|
33
|
-
|
|
34
|
-
|
|
41
|
+
}
|
|
42
|
+
const decoded = context.decodeEmbeddedDocumentUri(document.uri);
|
|
43
|
+
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
|
|
44
|
+
const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
|
|
45
|
+
if (!sourceScript) {
|
|
35
46
|
return;
|
|
47
|
+
}
|
|
36
48
|
let ast;
|
|
37
|
-
let sourceCodeOffset = document.offsetAt(
|
|
38
|
-
const fileName = context.env.typescript.uriToFileName(
|
|
39
|
-
if (
|
|
40
|
-
const
|
|
41
|
-
if (
|
|
49
|
+
let sourceCodeOffset = document.offsetAt(selection);
|
|
50
|
+
const fileName = context.env.typescript.uriToFileName(sourceScript.id);
|
|
51
|
+
if (sourceScript.generated) {
|
|
52
|
+
const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root);
|
|
53
|
+
if (!serviceScript || serviceScript?.code !== virtualCode) {
|
|
42
54
|
return;
|
|
43
55
|
}
|
|
44
|
-
ast = getAst(ts, fileName,
|
|
56
|
+
ast = getAst(ts, fileName, virtualCode.snapshot, serviceScript.scriptKind);
|
|
45
57
|
let mapped = false;
|
|
46
|
-
for (const [_1, [_2, map]] of context.language.
|
|
47
|
-
const sourceOffset = map.getSourceOffset(document.offsetAt(
|
|
58
|
+
for (const [_1, [_2, map]] of context.language.maps.forEach(virtualCode)) {
|
|
59
|
+
const sourceOffset = map.getSourceOffset(document.offsetAt(selection));
|
|
48
60
|
if (sourceOffset !== undefined) {
|
|
49
61
|
sourceCodeOffset = sourceOffset[0];
|
|
50
62
|
mapped = true;
|
|
@@ -56,10 +68,11 @@ function create(ts, tsPluginClient) {
|
|
|
56
68
|
}
|
|
57
69
|
}
|
|
58
70
|
else {
|
|
59
|
-
ast = getAst(ts, fileName,
|
|
71
|
+
ast = getAst(ts, fileName, sourceScript.snapshot);
|
|
60
72
|
}
|
|
61
|
-
if (isBlacklistNode(ts, ast, document.offsetAt(
|
|
73
|
+
if (isBlacklistNode(ts, ast, document.offsetAt(selection), false)) {
|
|
62
74
|
return;
|
|
75
|
+
}
|
|
63
76
|
const props = await tsPluginClient?.getPropertiesAtLocation(fileName, sourceCodeOffset) ?? [];
|
|
64
77
|
if (props.some(prop => prop === 'value')) {
|
|
65
78
|
return '${1:.value}';
|
|
@@ -80,21 +93,13 @@ function isTsDocument(document) {
|
|
|
80
93
|
document.languageId === 'typescriptreact';
|
|
81
94
|
}
|
|
82
95
|
const charReg = /\w/;
|
|
83
|
-
function isCharacterTyping(document,
|
|
84
|
-
const lastCharacter =
|
|
85
|
-
const
|
|
86
|
-
const position = {
|
|
87
|
-
line: rangeStart.line,
|
|
88
|
-
character: rangeStart.character + lastChange.text.length,
|
|
89
|
-
};
|
|
90
|
-
const nextCharacter = document.getText({
|
|
91
|
-
start: position,
|
|
92
|
-
end: { line: position.line, character: position.character + 1 },
|
|
93
|
-
});
|
|
96
|
+
function isCharacterTyping(document, change) {
|
|
97
|
+
const lastCharacter = change.text[change.text.length - 1];
|
|
98
|
+
const nextCharacter = document.getText().substring(change.rangeOffset + change.text.length, change.rangeOffset + change.text.length + 1);
|
|
94
99
|
if (lastCharacter === undefined) { // delete text
|
|
95
100
|
return false;
|
|
96
101
|
}
|
|
97
|
-
if (
|
|
102
|
+
if (change.text.indexOf('\n') >= 0) { // multi-line change
|
|
98
103
|
return false;
|
|
99
104
|
}
|
|
100
105
|
return charReg.test(lastCharacter) && !charReg.test(nextCharacter);
|
|
@@ -137,8 +142,9 @@ function isBlacklistNode(ts, node, pos, allowAccessDotValue) {
|
|
|
137
142
|
else {
|
|
138
143
|
let _isBlacklistNode = false;
|
|
139
144
|
node.forEachChild(node => {
|
|
140
|
-
if (_isBlacklistNode)
|
|
145
|
+
if (_isBlacklistNode) {
|
|
141
146
|
return;
|
|
147
|
+
}
|
|
142
148
|
if (pos >= node.getFullStart() && pos <= node.getEnd()) {
|
|
143
149
|
if (isBlacklistNode(ts, node, pos, allowAccessDotValue)) {
|
|
144
150
|
_isBlacklistNode = true;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function create(ts: typeof import('typescript')):
|
|
1
|
+
import type { LanguageServicePlugin } from '@volar/language-service';
|
|
2
|
+
export declare function create(ts: typeof import('typescript')): LanguageServicePlugin;
|
|
@@ -7,16 +7,25 @@ function create(ts) {
|
|
|
7
7
|
name: 'vue-autoinsert-parentheses',
|
|
8
8
|
create(context) {
|
|
9
9
|
return {
|
|
10
|
-
async provideAutoInsertionEdit(document,
|
|
10
|
+
async provideAutoInsertionEdit(document, selection, change) {
|
|
11
|
+
// selection must at end of change
|
|
12
|
+
if (document.offsetAt(selection) !== change.rangeOffset + change.text.length) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
11
15
|
const enabled = await context.env.getConfiguration?.('vue.autoInsert.parentheses') ?? false;
|
|
12
|
-
if (!enabled)
|
|
16
|
+
if (!enabled) {
|
|
13
17
|
return;
|
|
14
|
-
|
|
18
|
+
}
|
|
19
|
+
if (!(0, vue_autoinsert_dotvalue_1.isCharacterTyping)(document, change)) {
|
|
15
20
|
return;
|
|
16
|
-
|
|
17
|
-
|
|
21
|
+
}
|
|
22
|
+
const decoded = context.decodeEmbeddedDocumentUri(document.uri);
|
|
23
|
+
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
|
|
24
|
+
const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
|
|
25
|
+
if (!virtualCode?.id.startsWith('template_inline_ts_')) {
|
|
18
26
|
return;
|
|
19
|
-
|
|
27
|
+
}
|
|
28
|
+
const offset = document.offsetAt(selection);
|
|
20
29
|
for (const mappedRange of virtualCode.mappings) {
|
|
21
30
|
const generatedCodeEnd = mappedRange.generatedOffsets[mappedRange.generatedOffsets.length - 1]
|
|
22
31
|
+ mappedRange.lengths[mappedRange.lengths.length - 1];
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function create():
|
|
1
|
+
import type { LanguageServicePlugin } from '@volar/language-service';
|
|
2
|
+
export declare function create(): LanguageServicePlugin;
|
|
@@ -6,23 +6,16 @@ function create() {
|
|
|
6
6
|
name: 'vue-autoinsert-space',
|
|
7
7
|
create(context) {
|
|
8
8
|
return {
|
|
9
|
-
async provideAutoInsertionEdit(document,
|
|
9
|
+
async provideAutoInsertionEdit(document, selection, change) {
|
|
10
10
|
if (document.languageId === 'html' || document.languageId === 'jade') {
|
|
11
11
|
const enabled = await context.env.getConfiguration?.('vue.autoInsert.bracketSpacing') ?? true;
|
|
12
|
-
if (!enabled)
|
|
12
|
+
if (!enabled) {
|
|
13
13
|
return;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return {
|
|
20
|
-
newText: ` $0 `,
|
|
21
|
-
range: {
|
|
22
|
-
start: { line: lastChange.range.start.line, character: lastChange.range.start.character + 1 },
|
|
23
|
-
end: { line: lastChange.range.start.line, character: lastChange.range.start.character + 1 }
|
|
24
|
-
},
|
|
25
|
-
};
|
|
14
|
+
}
|
|
15
|
+
if (change.text === '{}'
|
|
16
|
+
&& document.getText().substring(change.rangeOffset - 1, change.rangeOffset + 3) === '{{}}'
|
|
17
|
+
&& document.offsetAt(selection) === change.rangeOffset + 1) {
|
|
18
|
+
return ` $0 `;
|
|
26
19
|
}
|
|
27
20
|
}
|
|
28
21
|
},
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function create():
|
|
1
|
+
import type { LanguageServicePlugin } from '@volar/language-service';
|
|
2
|
+
export declare function create(): LanguageServicePlugin;
|
|
@@ -12,8 +12,9 @@ function create() {
|
|
|
12
12
|
const result = [];
|
|
13
13
|
for (const map of context.documents.getMaps(virtualCode) ?? []) {
|
|
14
14
|
for (const mapping of map.map.mappings) {
|
|
15
|
-
if (!mapping.data.__referencesCodeLens)
|
|
15
|
+
if (!mapping.data.__referencesCodeLens) {
|
|
16
16
|
continue;
|
|
17
|
+
}
|
|
17
18
|
result.push({
|
|
18
19
|
start: document.positionAt(mapping.generatedOffsets[0]),
|
|
19
20
|
end: document.positionAt(mapping.generatedOffsets[mapping.generatedOffsets.length - 1]
|
|
@@ -26,10 +27,13 @@ function create() {
|
|
|
26
27
|
},
|
|
27
28
|
};
|
|
28
29
|
function worker(uri, callback) {
|
|
29
|
-
const
|
|
30
|
-
|
|
30
|
+
const decoded = context.decodeEmbeddedDocumentUri(uri);
|
|
31
|
+
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
|
|
32
|
+
const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
|
|
33
|
+
if (!virtualCode || !(sourceScript?.generated?.root instanceof language_core_1.VueGeneratedCode) || !sourceScript) {
|
|
31
34
|
return;
|
|
32
|
-
|
|
35
|
+
}
|
|
36
|
+
return callback(virtualCode, sourceScript);
|
|
33
37
|
}
|
|
34
38
|
},
|
|
35
39
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function create():
|
|
1
|
+
import type { LanguageServicePlugin } from '@volar/language-service';
|
|
2
|
+
export declare function create(): LanguageServicePlugin;
|
|
@@ -14,12 +14,14 @@ function create() {
|
|
|
14
14
|
create() {
|
|
15
15
|
return {
|
|
16
16
|
provideCompletionItems(document, position) {
|
|
17
|
-
if (document.languageId !== 'html')
|
|
17
|
+
if (document.languageId !== 'html') {
|
|
18
18
|
return;
|
|
19
|
+
}
|
|
19
20
|
const line = document.getText({ start: { line: position.line, character: 0 }, end: position });
|
|
20
21
|
const cmdStart = line.match(directiveCommentReg);
|
|
21
|
-
if (!cmdStart)
|
|
22
|
+
if (!cmdStart) {
|
|
22
23
|
return;
|
|
24
|
+
}
|
|
23
25
|
const startIndex = cmdStart.index + cmdStart[0].length;
|
|
24
26
|
const remainText = line.substring(startIndex);
|
|
25
27
|
const result = [];
|
|
@@ -27,7 +29,6 @@ function create() {
|
|
|
27
29
|
let match = true;
|
|
28
30
|
for (let i = 0; i < remainText.length; i++) {
|
|
29
31
|
if (remainText[i] !== cmd[i]) {
|
|
30
|
-
console.log(JSON.stringify(remainText[i]), JSON.stringify(cmd[i]));
|
|
31
32
|
match = false;
|
|
32
33
|
break;
|
|
33
34
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare function create(ts: typeof import('typescript')):
|
|
1
|
+
import { LanguageServicePlugin, ServiceContext } from '../types';
|
|
2
|
+
export declare function create(ts: typeof import('typescript'), getTsPluginClient?: (context: ServiceContext) => typeof import('@vue/typescript-plugin/lib/client') | undefined): LanguageServicePlugin;
|