@vue/language-service 2.0.29 → 2.1.0
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/template/cs.json +3 -0
- package/data/template/en.json +3 -0
- package/data/template/fr.json +3 -0
- package/data/template/it.json +3 -0
- package/data/template/ja.json +3 -0
- package/data/template/ko.json +3 -0
- package/data/template/pt.json +3 -0
- package/data/template/ru.json +3 -0
- package/data/template/zh-cn.json +3 -0
- package/data/template/zh-hk.json +3 -0
- package/index.d.ts +3 -1
- package/index.js +5 -5
- package/lib/plugins/data.js +1 -1
- package/lib/plugins/vue-document-drop.js +1 -1
- package/lib/plugins/vue-inlayhints.d.ts +7 -0
- package/lib/plugins/vue-inlayhints.js +240 -0
- package/lib/plugins/vue-sfc.d.ts +0 -5
- package/lib/plugins/vue-sfc.js +48 -34
- package/lib/plugins/vue-template.js +109 -37
- package/package.json +16 -16
- package/scripts/update-html-data.js +6 -1
- package/lib/plugins/vue-toggle-v-bind-codeaction.d.ts +0 -2
- package/lib/plugins/vue-toggle-v-bind-codeaction.js +0 -134
- package/lib/plugins/vue-visualize-hidden-callback-param.d.ts +0 -2
- package/lib/plugins/vue-visualize-hidden-callback-param.js +0 -51
package/data/template/cs.json
CHANGED
|
@@ -1173,6 +1173,7 @@
|
|
|
1173
1173
|
},
|
|
1174
1174
|
{
|
|
1175
1175
|
"name": "v-pre",
|
|
1176
|
+
"valueSet": "v",
|
|
1176
1177
|
"description": {
|
|
1177
1178
|
"kind": "markdown",
|
|
1178
1179
|
"value": "\nPřeskočit kompilaci tohoto elementu a všech jeho potomků.\n\n- **Nepředpokládá výraz** \n\n- **Podrobnosti**\n\n Uvnitř elementu s `v-pre` budou všechny syntaxe Vue šablony zachovány a vykresleny tak, jak jsou. Nejběžnějším použitím je zobrazení nezpracovaných „mustache“ tagů.\n\n- **Příklad**\n\n ```html\n <span v-pre>{{ toto nebude zkompilováno }}</span>\n ```\n"
|
|
@@ -1234,6 +1235,7 @@
|
|
|
1234
1235
|
},
|
|
1235
1236
|
{
|
|
1236
1237
|
"name": "v-once",
|
|
1238
|
+
"valueSet": "v",
|
|
1237
1239
|
"description": {
|
|
1238
1240
|
"kind": "markdown",
|
|
1239
1241
|
"value": "\nVykreslit element nebo komponentu pouze jednou a přeskočit budoucí aktualizace.\n\n- **Nepředpokládá výraz** \n\n- **Podrobnosti**\n\n Při dalších překreslováních budou element/komponenta a všichni potomci považováni za statický obsah a přeskočeni. To lze použít k optimalizaci výkonu aktualizace.\n\n ```html\n <!-- jediný prvek -->\n <span v-once>Toto se nikdy nezmění: {{msg}}</span>\n <!-- element s potomky -->\n <div v-once>\n <h1>Komentář</h1>\n <p>{{msg}}</p>\n </div>\n <!-- komponenta -->\n <MyComponent v-once :comment=\"msg\"></MyComponent>\n <!-- direktiva `v-for` -->\n <ul>\n <li v-for=\"i in list\" v-once>{{i}}</li>\n </ul>\n ```\n\n Od verze 3.2 si můžete také část šablony „zapamatovat“ (memoize) s podmínkami neplatnosti pomocí [`v-memo`](#v-memo).\n\n- **Viz také:**\n - [Syntaxe šablon - Interpolace textu](https://cs.vuejs.org/guide/essentials/template-syntax.html#text-interpolation)\n - [v-memo](#v-memo)\n"
|
|
@@ -1356,6 +1358,7 @@
|
|
|
1356
1358
|
},
|
|
1357
1359
|
{
|
|
1358
1360
|
"name": "v-cloak",
|
|
1361
|
+
"valueSet": "v",
|
|
1359
1362
|
"description": {
|
|
1360
1363
|
"kind": "markdown",
|
|
1361
1364
|
"value": "\nPoužívá se k skrytí nezkompilované šablony, dokud není připravena.\n\n- **Nepředpokládá výraz**\n\n- **Podrobnosti**\n\n **Tato direktiva je potřeba pouze při použití bez build fáze.**\n\n Při použití in-DOM šablon může dojít k „blikání (flashing) nezkompilovaných šablon“: uživatel může vidět nezpracované „mustache“ značky, dokud je připojená (mounted) komponenta nenahradí vykresleným obsahem.\n\n `v-cloak` zůstane na elementu, dokud není připojena příslušná instance komponenty. Spolu s CSS pravidly jako `[v-cloak] { display: none }` lze použít k skrytí nezpracovaných šablon, dokud není komponenta připravena.\n\n- **Příklad**\n\n ```css\n [v-cloak] {\n display: none;\n }\n ```\n\n ```html\n <div v-cloak>\n {{ message }}\n </div>\n ```\n\n `<div>` nebude viditelný, dokud nebude dokončena kompilace.\n"
|
package/data/template/en.json
CHANGED
|
@@ -1173,6 +1173,7 @@
|
|
|
1173
1173
|
},
|
|
1174
1174
|
{
|
|
1175
1175
|
"name": "v-pre",
|
|
1176
|
+
"valueSet": "v",
|
|
1176
1177
|
"description": {
|
|
1177
1178
|
"kind": "markdown",
|
|
1178
1179
|
"value": "\nSkip compilation for this element and all its children.\n\n- **Does not expect expression**\n\n- **Details**\n\n Inside the element with `v-pre`, all Vue template syntax will be preserved and rendered as-is. The most common use case of this is displaying raw mustache tags.\n\n- **Example**\n\n ```html\n <span v-pre>{{ this will not be compiled }}</span>\n ```\n"
|
|
@@ -1234,6 +1235,7 @@
|
|
|
1234
1235
|
},
|
|
1235
1236
|
{
|
|
1236
1237
|
"name": "v-once",
|
|
1238
|
+
"valueSet": "v",
|
|
1237
1239
|
"description": {
|
|
1238
1240
|
"kind": "markdown",
|
|
1239
1241
|
"value": "\nRender the element and component once only, and skip future updates.\n\n- **Does not expect expression**\n\n- **Details**\n\n On subsequent re-renders, the element/component and all its children will be treated as static content and skipped. This can be used to optimize update performance.\n\n ```html\n <!-- single element -->\n <span v-once>This will never change: {{msg}}</span>\n <!-- the element have children -->\n <div v-once>\n <h1>Comment</h1>\n <p>{{msg}}</p>\n </div>\n <!-- component -->\n <MyComponent v-once :comment=\"msg\"></MyComponent>\n <!-- `v-for` directive -->\n <ul>\n <li v-for=\"i in list\" v-once>{{i}}</li>\n </ul>\n ```\n\n Since 3.2, you can also memoize part of the template with invalidation conditions using [`v-memo`](#v-memo).\n\n- **See also**\n - [Data Binding Syntax - interpolations](https://vuejs.org/guide/essentials/template-syntax.html#text-interpolation)\n - [v-memo](#v-memo)\n"
|
|
@@ -1356,6 +1358,7 @@
|
|
|
1356
1358
|
},
|
|
1357
1359
|
{
|
|
1358
1360
|
"name": "v-cloak",
|
|
1361
|
+
"valueSet": "v",
|
|
1359
1362
|
"description": {
|
|
1360
1363
|
"kind": "markdown",
|
|
1361
1364
|
"value": "\nUsed to hide un-compiled template until it is ready.\n\n- **Does not expect expression**\n\n- **Details**\n\n **This directive is only needed in no-build-step setups.**\n\n When using in-DOM templates, there can be a \"flash of un-compiled templates\": the user may see raw mustache tags until the mounted component replaces them with rendered content.\n\n `v-cloak` will remain on the element until the associated component instance is mounted. Combined with CSS rules such as `[v-cloak] { display: none }`, it can be used to hide the raw templates until the component is ready.\n\n- **Example**\n\n ```css\n [v-cloak] {\n display: none;\n }\n ```\n\n ```html\n <div v-cloak>\n {{ message }}\n </div>\n ```\n\n The `<div>` will not be visible until the compilation is done.\n"
|
package/data/template/fr.json
CHANGED
|
@@ -1173,6 +1173,7 @@
|
|
|
1173
1173
|
},
|
|
1174
1174
|
{
|
|
1175
1175
|
"name": "v-pre",
|
|
1176
|
+
"valueSet": "v",
|
|
1176
1177
|
"description": {
|
|
1177
1178
|
"kind": "markdown",
|
|
1178
1179
|
"value": "\nIgnore la compilation pour cet élément et tous ses enfants.\n\n- **N'attend pas d'expression**\n\n- **Détails**\n\n À l'intérieur de l'élément contenant `v-pre`, toute la syntaxe du template Vue sera préservée et rendue telle quelle. Le cas d'utilisation le plus courant est l'affichage brut des balises moustaches.\n\n- **Exemple**\n\n ```html\n <span v-pre>{{ this will not be compiled }}</span>\n ```\n"
|
|
@@ -1234,6 +1235,7 @@
|
|
|
1234
1235
|
},
|
|
1235
1236
|
{
|
|
1236
1237
|
"name": "v-once",
|
|
1238
|
+
"valueSet": "v",
|
|
1237
1239
|
"description": {
|
|
1238
1240
|
"kind": "markdown",
|
|
1239
1241
|
"value": "\nRend l'élément et le composant une seule fois, et ignore les mises à jour futures.\n\n- **N'attend pas d'expression**\n\n- **Détails**\n\n Lors des rendus suivants, l'élément/composant et tous ses enfants seront traités comme du contenu statique et ignorés. Cela peut être utilisé pour optimiser les performances de mise à jour.\n\n ```html\n <!-- élément simple -->\n <span v-once>This will never change: {{msg}}</span>\n <!-- l'élément a des enfants -->\n <div v-once>\n <h1>Comment</h1>\n <p>{{msg}}</p>\n </div>\n <!-- composant -->\n <MyComponent v-once :comment=\"msg\"></MyComponent>\n <!-- directive `v-for` -->\n <ul>\n <li v-for=\"i in list\" v-once>{{i}}</li>\n </ul>\n ```\n\n Depuis la version 3.2, vous pouvez également mémoriser une partie du template avec des conditions d'invalidation en utilisant [`v-memo`](#v-memo).\n\n- **Voir aussi**\n - [Syntaxe de la liaison bidirectionnelle - interpolations](https://fr.vuejs.org/guide/essentials/template-syntax.html#text-interpolation)\n - [v-memo](#v-memo)\n"
|
|
@@ -1356,6 +1358,7 @@
|
|
|
1356
1358
|
},
|
|
1357
1359
|
{
|
|
1358
1360
|
"name": "v-cloak",
|
|
1361
|
+
"valueSet": "v",
|
|
1359
1362
|
"description": {
|
|
1360
1363
|
"kind": "markdown",
|
|
1361
1364
|
"value": "\nUtilisée pour cacher un template non compilé jusqu'à ce qu'il soit prêt.\n\n- **N'attend pas d'expression**\n\n- **Détails**\n\n **Cette directive n'est nécessaire que dans les configurations sans étape de build.**\n\n Lors de l'utilisation de templates à l'intérieur du DOM, il peut y avoir un \"flash de templates non compilés\" : l'utilisateur peut voir des balises moustaches brutes jusqu'à ce que le composant monté les remplace par du contenu rendu.\n\n `v-cloak` restera sur l'élément jusqu'à ce que l'instance du composant associé soit montée. Combiné à des règles CSS telles que `[v-cloak] { display : none }`, elle peut être utilisée pour masquer les templates bruts jusqu'à ce que le composant soit prêt.\n\n- **Exemple**\n\n ```css\n [v-cloak] {\n display: none;\n }\n ```\n\n ```html\n <div v-cloak>\n {{ message }}\n </div>\n ```\n\n La `<div>` ne sera pas visible tant que la compilation n'est pas terminée.\n"
|
package/data/template/it.json
CHANGED
|
@@ -1173,6 +1173,7 @@
|
|
|
1173
1173
|
},
|
|
1174
1174
|
{
|
|
1175
1175
|
"name": "v-pre",
|
|
1176
|
+
"valueSet": "v",
|
|
1176
1177
|
"description": {
|
|
1177
1178
|
"kind": "markdown",
|
|
1178
1179
|
"value": "\nSkip compilation for this element and all its children.\n\n- **Does not expect expression**\n\n- **Details**\n\n Inside the element with `v-pre`, all Vue template syntax will be preserved and rendered as-is. The most common use case of this is displaying raw mustache tags.\n\n- **Example**\n\n ```html\n <span v-pre>{{ this will not be compiled }}</span>\n ```\n"
|
|
@@ -1234,6 +1235,7 @@
|
|
|
1234
1235
|
},
|
|
1235
1236
|
{
|
|
1236
1237
|
"name": "v-once",
|
|
1238
|
+
"valueSet": "v",
|
|
1237
1239
|
"description": {
|
|
1238
1240
|
"kind": "markdown",
|
|
1239
1241
|
"value": "\nRender the element and component once only, and skip future updates.\n\n- **Does not expect expression**\n\n- **Details**\n\n On subsequent re-renders, the element/component and all its children will be treated as static content and skipped. This can be used to optimize update performance.\n\n ```html\n <!-- single element -->\n <span v-once>This will never change: {{msg}}</span>\n <!-- the element have children -->\n <div v-once>\n <h1>comment</h1>\n <p>{{msg}}</p>\n </div>\n <!-- component -->\n <MyComponent v-once :comment=\"msg\"></MyComponent>\n <!-- `v-for` directive -->\n <ul>\n <li v-for=\"i in list\" v-once>{{i}}</li>\n </ul>\n ```\n\n Since 3.2, you can also memoize part of the template with invalidation conditions using [`v-memo`](#v-memo).\n\n- **See also**\n - [Data Binding Syntax - interpolations](https://it.vuejs.org/guide/essentials/template-syntax.html#text-interpolation)\n - [v-memo](#v-memo)\n"
|
|
@@ -1356,6 +1358,7 @@
|
|
|
1356
1358
|
},
|
|
1357
1359
|
{
|
|
1358
1360
|
"name": "v-cloak",
|
|
1361
|
+
"valueSet": "v",
|
|
1359
1362
|
"description": {
|
|
1360
1363
|
"kind": "markdown",
|
|
1361
1364
|
"value": "\nUsed to hide un-compiled template until it is ready.\n\n- **Does not expect expression**\n\n- **Details**\n\n **This directive is only needed in no-build-step setups.**\n\n When using in-DOM templates, there can be a \"flash of un-compiled templates\": the user may see raw mustache tags until the mounted component replaces them with rendered content.\n\n `v-cloak` will remain on the element until the associated component instance is mounted. Combined with CSS rules such as `[v-cloak] { display: none }`, it can be used to hide the raw templates until the component is ready.\n\n- **Example**\n\n ```css\n [v-cloak] {\n display: none;\n }\n ```\n\n ```html\n <div v-cloak>\n {{ message }}\n </div>\n ```\n\n The `<div>` will not be visible until the compilation is done.\n"
|
package/data/template/ja.json
CHANGED
|
@@ -1173,6 +1173,7 @@
|
|
|
1173
1173
|
},
|
|
1174
1174
|
{
|
|
1175
1175
|
"name": "v-pre",
|
|
1176
|
+
"valueSet": "v",
|
|
1176
1177
|
"description": {
|
|
1177
1178
|
"kind": "markdown",
|
|
1178
1179
|
"value": "\nこの要素とすべての子要素のコンパイルをスキップします。\n\n- **式を受け取りません**\n\n- **詳細**\n\n `v-pre` を指定した要素の内部では、Vue テンプレートの構文はすべて維持され、そのままレンダリングされます。この最も一般的な使用例は、未加工のマスタッシュタグを表示することです。\n\n- **例**\n\n ```html\n <span v-pre>{{ this will not be compiled }}</span>\n ```\n"
|
|
@@ -1234,6 +1235,7 @@
|
|
|
1234
1235
|
},
|
|
1235
1236
|
{
|
|
1236
1237
|
"name": "v-once",
|
|
1238
|
+
"valueSet": "v",
|
|
1237
1239
|
"description": {
|
|
1238
1240
|
"kind": "markdown",
|
|
1239
1241
|
"value": "\n要素やコンポーネントを一度だけレンダリングし、その後の更新はスキップします。\n\n- **式を受け取りません**\n\n- **詳細**\n\n その後の再レンダリングでは、要素/コンポーネントとそのすべての子要素は静的コンテンツとして扱われ、スキップされます。これは、更新のパフォーマンスを最適化するために使用できます。\n\n ```html\n <!-- 単一要素 -->\n <span v-once>This will never change: {{msg}}</span>\n <!-- 子要素を持つ要素 -->\n <div v-once>\n <h1>Comment</h1>\n <p>{{msg}}</p>\n </div>\n <!-- コンポーネント -->\n <MyComponent v-once :comment=\"msg\"></MyComponent>\n <!-- `v-for` ディレクティブ -->\n <ul>\n <li v-for=\"i in list\" v-once>{{i}}</li>\n </ul>\n ```\n\n 3.2 以降では、[`v-memo`](#v-memo) を使って、テンプレートの一部を無効化する条件付きでメモ化できます。\n\n- **参照**\n - [データバインディング構文 - 展開](https://ja.vuejs.org/guide/essentials/template-syntax.html#text-interpolation)\n - [v-memo](#v-memo)\n"
|
|
@@ -1356,6 +1358,7 @@
|
|
|
1356
1358
|
},
|
|
1357
1359
|
{
|
|
1358
1360
|
"name": "v-cloak",
|
|
1361
|
+
"valueSet": "v",
|
|
1359
1362
|
"description": {
|
|
1360
1363
|
"kind": "markdown",
|
|
1361
1364
|
"value": "\nコンパイルされていないテンプレートを、準備が整うまで非表示にするために使用します。\n\n- **式を受け取りません**\n\n- **詳細**\n\n **このディレクティブは、ビルドステップがないセットアップでのみ必要です。**\n\n DOM 内テンプレートを使用する場合、「コンパイルされていないテンプレートのフラッシュ」が発生することがあります。マウントされたコンポーネントがそれをレンダリングされたコンテンツに置き換えるまで、未加工のマスタッシュタグがユーザーに表示される場合があります。\n\n `v-cloak` は関連するコンポーネントインスタンスがマウントされるまで、その要素に残ります。`[v-cloak] { display: none }` のような CSS ルールと組み合わせることで、コンポーネントの準備が整うまで未加工のテンプレートを非表示にできます。\n\n- **例**\n\n ```css\n [v-cloak] {\n display: none;\n }\n ```\n\n ```html\n <div v-cloak>\n {{ message }}\n </div>\n ```\n\n この `<div>` はコンパイルが完了するまで表示されません。\n"
|
package/data/template/ko.json
CHANGED
|
@@ -1173,6 +1173,7 @@
|
|
|
1173
1173
|
},
|
|
1174
1174
|
{
|
|
1175
1175
|
"name": "v-pre",
|
|
1176
|
+
"valueSet": "v",
|
|
1176
1177
|
"description": {
|
|
1177
1178
|
"kind": "markdown",
|
|
1178
1179
|
"value": "\n이 엘리먼트와 모든 자식 엘리먼트의 컴파일을 생략합니다.\n\n- **표현식을 허용하지 않습니다**.\n\n- **세부 사항**:\n\n `v-pre`가 있는 엘리먼트 내에서 모든 Vue 템플릿 구문은 그대로 유지되고 렌더링됩니다. 가장 일반적인 사용 사례는 이중 중괄호 태그를 표시하는 것입니다.\n\n- **예제**\n\n ```html\n <span v-pre>{{ 이곳은 컴파일되지 않습니다. }}</span>\n ```\n"
|
|
@@ -1234,6 +1235,7 @@
|
|
|
1234
1235
|
},
|
|
1235
1236
|
{
|
|
1236
1237
|
"name": "v-once",
|
|
1238
|
+
"valueSet": "v",
|
|
1237
1239
|
"description": {
|
|
1238
1240
|
"kind": "markdown",
|
|
1239
1241
|
"value": "\n엘리먼트와 컴포넌트를 한 번만 렌더링하고, 향후 업데이트를 생략합니다.\n\n- **표현식을 허용하지 않습니다**.\n\n- **세부 사항**:\n\n 이후 다시 렌더링할 때 엘리먼트/컴포넌트 및 모든 자식들은 정적 컨텐츠로 처리되어 생략됩니다. 이것은 업데이트 성능을 최적화하는 데 사용할 수 있습니다.\n\n ```html\n <!-- 단일 엘리먼트 -->\n <span v-once>절대 바뀌지 않음: {{msg}}</span>\n <!-- 자식이 있는 엘리먼트 -->\n <div v-once>\n <h1>댓글</h1>\n <p>{{msg}}</p>\n </div>\n <!-- 컴포넌트 -->\n <MyComponent v-once :comment=\"msg\"></MyComponent>\n <!-- `v-for` 디렉티브 -->\n <ul>\n <li v-for=\"i in list\" v-once>{{i}}</li>\n </ul>\n ```\n\n 3.2부터는 [`v-memo`](#v-memo)를 사용하여 무효화 조건으로 템플릿의 일부를 메모화할 수도 있습니다.\n\n- **참고**:\n - [가이드 - 템플릿 문법: 텍스트 보간법](https://ko.vuejs.org/guide/essentials/template-syntax.html#text-interpolation)\n - [v-memo](#v-memo)\n"
|
|
@@ -1356,6 +1358,7 @@
|
|
|
1356
1358
|
},
|
|
1357
1359
|
{
|
|
1358
1360
|
"name": "v-cloak",
|
|
1361
|
+
"valueSet": "v",
|
|
1359
1362
|
"description": {
|
|
1360
1363
|
"kind": "markdown",
|
|
1361
1364
|
"value": "\n준비될 때까지 컴파일되지 않은 템플릿을 숨기는 데 사용됩니다.\n\n- **표현식을 허용하지 않습니다**.\n\n- **세부 사항**:\n\n **이 디렉티브는 빌드 과정이 없는 설정에서만 필요합니다**.\n\n DOM 내 템플릿을 사용할 때, \"컴파일되지 않은 템플릿이 순간 보이는 현상\"이 있을 수 있습니다. 이러면 사용자는 컴포넌트가 렌더링된 컨텐츠로 대체할 때까지 이중 중괄호 태그를 볼 수 있습니다.\n\n `v-cloak`은 연결된 컴포넌트 인스턴스가 마운트될 때까지 엘리먼트에 남아 있습니다. `[v-cloak] { display: none }`과 같은 CSS 규칙과 결합하여, 컴포넌트가 준비될 때까지 템플릿을 숨기는 데 사용할 수 있습니다.\n\n- **예제**\n\n ```css\n [v-cloak] {\n display: none;\n }\n ```\n\n ```html\n <div v-cloak>\n {{ message }}\n </div>\n ```\n\n `<div>`는 컴파일이 완료될 때까지 표시되지 않습니다.\n"
|
package/data/template/pt.json
CHANGED
|
@@ -1173,6 +1173,7 @@
|
|
|
1173
1173
|
},
|
|
1174
1174
|
{
|
|
1175
1175
|
"name": "v-pre",
|
|
1176
|
+
"valueSet": "v",
|
|
1176
1177
|
"description": {
|
|
1177
1178
|
"kind": "markdown",
|
|
1178
1179
|
"value": "\nIgnora a compilação para este elemento e todos os seus filhos.\n\n- **Não espera expressão**\n\n- **Detalhes**\n\n Dentro do elemento com `v-pre`, toda a sintaxe de modelo de marcação da Vue será preservada e desenhada como está. O caso de uso mais comum disto é a exibição de marcadores de bigodes puros.\n\n- **Exemplo**\n\n ```html\n <span v-pre>{{ this will not be compiled }}</span>\n ```\n"
|
|
@@ -1234,6 +1235,7 @@
|
|
|
1234
1235
|
},
|
|
1235
1236
|
{
|
|
1236
1237
|
"name": "v-once",
|
|
1238
|
+
"valueSet": "v",
|
|
1237
1239
|
"description": {
|
|
1238
1240
|
"kind": "markdown",
|
|
1239
1241
|
"value": "\nDesenha o elemento e o componente apenas uma vez, e ignora as futuras atualizações.\n\n- **Não espera expressão**\n\n- **Detalhes**\n\n Nos redesenhos subsequentes, o elemento ou componente e todos os seus filhos serão tratados como conteúdo estático e ignorados. Isto pode ser usado para otimizar o desempenho da atualização.\n\n ```html\n <!-- elemento único -->\n <span v-once>This will never change: {{msg}}</span>\n <!-- o elemento tem filhos -->\n <div v-once>\n <h1>comment</h1>\n <p>{{msg}}</p>\n </div>\n <!-- componente -->\n <MyComponent v-once :comment=\"msg\"></MyComponent>\n <!-- diretiva `v-for` -->\n <ul>\n <li v-for=\"i in list\" v-once>{{i}}</li>\n </ul>\n ```\n\n Desde a 3.2, também podemos memorizar parte do modelo de marcação com condições de invalidação usando a [`v-memo`](#v-memo).\n\n- **Consultar também**\n - [Sintaxe de Vínculo de Dados - Interpolações](https://pt.vuejs.org/guide/essentials/template-syntax.html#text-interpolation)\n - [`v-memo`](#v-memo)\n"
|
|
@@ -1356,6 +1358,7 @@
|
|
|
1356
1358
|
},
|
|
1357
1359
|
{
|
|
1358
1360
|
"name": "v-cloak",
|
|
1361
|
+
"valueSet": "v",
|
|
1359
1362
|
"description": {
|
|
1360
1363
|
"kind": "markdown",
|
|
1361
1364
|
"value": "\nUsada para esconder o modelo de marcação que ainda não foi compilado até que estiver pronto.\n\n- **Não espera expressão**\n\n- **Detalhes**\n\n **Esta diretiva apenas é necessária nas configurações sem etapa de construção.**\n\n Quando usamos os modelos de marcação no DOM, pode existir um \"piscar de modelos de marcação não compilados\": o utilizador pode ver os marcadores de bigodes puros até o componente montado substituí-los com componente desenhado.\n\n `v-cloak` permanecerá no elemento até que a instância do componente associado for montada. Combinada com as regras de CSS como `[v-cloak] { display: none }`, pode ser usada para esconder os modelos de marcação puros até o componente estiver pronto.\n\n- **Exemplo**\n\n ```css\n [v-cloak] {\n display: none;\n }\n ```\n\n ```html\n <div v-cloak>\n {{ message }}\n </div>\n ```\n\n O `<div>` não será visível até que a compilação estiver concluída.\n"
|
package/data/template/ru.json
CHANGED
|
@@ -1173,6 +1173,7 @@
|
|
|
1173
1173
|
},
|
|
1174
1174
|
{
|
|
1175
1175
|
"name": "v-pre",
|
|
1176
|
+
"valueSet": "v",
|
|
1176
1177
|
"description": {
|
|
1177
1178
|
"kind": "markdown",
|
|
1178
1179
|
"value": "\nПропускает компиляцию для элемента и всех его потомков.\n\n- **Не ожидает выражения**\n\n- **Подробности**\n\n Внутри элемента с `v-pre` весь синтаксис шаблона Vue будет сохранен и отображён как есть. Наиболее распространённый вариант использования этого элемента - отображение тегов фигурных скобок.\n\n- **Пример**\n\n ```html\n <span v-pre>{{ это не будет скомпилировано }}</span>\n ```\n"
|
|
@@ -1234,6 +1235,7 @@
|
|
|
1234
1235
|
},
|
|
1235
1236
|
{
|
|
1236
1237
|
"name": "v-once",
|
|
1238
|
+
"valueSet": "v",
|
|
1237
1239
|
"description": {
|
|
1238
1240
|
"kind": "markdown",
|
|
1239
1241
|
"value": "\nОтрисовка элемента и компонента выполняется только один раз, а последующие обновления пропускаются.\n\n- **Не ожидает выражения**\n\n- **Подробности**\n\n При последующих повторных отрисовках этот элемент/компонент и все его дочерние элементы будут рассматриваться как статическое содержимое и пропускаться. Это может быть использовано для оптимизации производительности при обновлении.\n\n ```html\n <!-- элемент -->\n <span v-once>Это значение никогда не изменится: {{msg}}</span>\n <!-- элемент с потомками -->\n <div v-once>\n <h1>Комментарий</h1>\n <p>{{msg}}</p>\n </div>\n <!-- компонент -->\n <MyComponent v-once :comment=\"msg\"></MyComponent>\n <!-- директива `v-for` -->\n <ul>\n <li v-for=\"i in list\" v-once>{{i}}</li>\n </ul>\n ```\n\n Начиная с версии 3.2, можно использовать мемоизацию части шаблона, с возможностью указания условий для инвалидации, с помощью директивы [`v-memo`](#v-memo).\n\n- **См. также**\n - [Синтаксис шаблонов - Текстовые интерполяции](https://ru.vuejs.org/guide/essentials/template-syntax.html#text-interpolation)\n - [v-memo](#v-memo)\n"
|
|
@@ -1356,6 +1358,7 @@
|
|
|
1356
1358
|
},
|
|
1357
1359
|
{
|
|
1358
1360
|
"name": "v-cloak",
|
|
1361
|
+
"valueSet": "v",
|
|
1359
1362
|
"description": {
|
|
1360
1363
|
"kind": "markdown",
|
|
1361
1364
|
"value": "\nИспользуется для скрытия еще нескомпилированного шаблона до тех пор, пока он не будет готов.\n\n- **Не ожидает выражения**\n\n- **Подробности**\n\n **Данная директива нужна только для окружения без этапа сборки.**\n\n При использовании DOM шаблонов может возникнуть \"вспышка некомпилированных шаблонов\": пользователь может видеть необработанные теги фигурных скобок, пока монтируемый компонент не заменит их отрисованным содержимым.\n\n `v-cloak` будет оставаться на элементе до тех пор, пока не будет смонтирован связанный с ним экземпляр компонента. В сочетании с правилами CSS, такими как `[v-cloak] { display: none }`, это может быть использовано для скрытия необработанных шаблонов до тех пор, пока компонент не будет готов.\n\n- **Пример**\n\n ```css\n [v-cloak] {\n display: none;\n }\n ```\n\n ```html\n <div v-cloak>\n {{ message }}\n </div>\n ```\n\n До завершения компиляции `<div>` не будет виден.\n"
|
package/data/template/zh-cn.json
CHANGED
|
@@ -1173,6 +1173,7 @@
|
|
|
1173
1173
|
},
|
|
1174
1174
|
{
|
|
1175
1175
|
"name": "v-pre",
|
|
1176
|
+
"valueSet": "v",
|
|
1176
1177
|
"description": {
|
|
1177
1178
|
"kind": "markdown",
|
|
1178
1179
|
"value": "\n跳过该元素及其所有子元素的编译。\n\n- **无需传入**\n\n- **详细信息**\n\n 元素内具有 `v-pre`,所有 Vue 模板语法都会被保留并按原样渲染。最常见的用例就是显示原始双大括号标签及内容。\n\n- **示例**\n\n ```html\n <span v-pre>{{ this will not be compiled }}</span>\n ```\n"
|
|
@@ -1234,6 +1235,7 @@
|
|
|
1234
1235
|
},
|
|
1235
1236
|
{
|
|
1236
1237
|
"name": "v-once",
|
|
1238
|
+
"valueSet": "v",
|
|
1237
1239
|
"description": {
|
|
1238
1240
|
"kind": "markdown",
|
|
1239
1241
|
"value": "\n仅渲染元素和组件一次,并跳过之后的更新。\n\n- **无需传入**\n\n- **详细信息**\n\n 在随后的重新渲染,元素/组件及其所有子项将被当作静态内容并跳过渲染。这可以用来优化更新时的性能。\n\n ```html\n <!-- 单个元素 -->\n <span v-once>This will never change: {{msg}}</span>\n <!-- 带有子元素的元素 -->\n <div v-once>\n <h1>Comment</h1>\n <p>{{msg}}</p>\n </div>\n <!-- 组件 -->\n <MyComponent v-once :comment=\"msg\" />\n <!-- `v-for` 指令 -->\n <ul>\n <li v-for=\"i in list\" v-once>{{i}}</li>\n </ul>\n ```\n\n 从 3.2 起,你也可以搭配 [`v-memo`](#v-memo) 的无效条件来缓存部分模板。\n\n- **参考**\n - [数据绑定语法 - 插值](https://cn.vuejs.org/guide/essentials/template-syntax.html#text-interpolation)\n - [v-memo](#v-memo)\n"
|
|
@@ -1356,6 +1358,7 @@
|
|
|
1356
1358
|
},
|
|
1357
1359
|
{
|
|
1358
1360
|
"name": "v-cloak",
|
|
1361
|
+
"valueSet": "v",
|
|
1359
1362
|
"description": {
|
|
1360
1363
|
"kind": "markdown",
|
|
1361
1364
|
"value": "\n用于隐藏尚未完成编译的 DOM 模板。\n\n- **无需传入**\n\n- **详细信息**\n\n **该指令只在没有构建步骤的环境下需要使用。**\n\n 当使用直接在 DOM 中书写的模板时,可能会出现一种叫做“未编译模板闪现”的情况:用户可能先看到的是还没编译完成的双大括号标签,直到挂载的组件将它们替换为实际渲染的内容。\n\n `v-cloak` 会保留在所绑定的元素上,直到相关组件实例被挂载后才移除。配合像 `[v-cloak] { display: none }` 这样的 CSS 规则,它可以在组件编译完毕前隐藏原始模板。\n\n- **示例**\n\n ```css\n [v-cloak] {\n display: none;\n }\n ```\n\n ```html\n <div v-cloak>\n {{ message }}\n </div>\n ```\n\n 直到编译完成前,`<div>` 将不可见。\n"
|
package/data/template/zh-hk.json
CHANGED
|
@@ -1173,6 +1173,7 @@
|
|
|
1173
1173
|
},
|
|
1174
1174
|
{
|
|
1175
1175
|
"name": "v-pre",
|
|
1176
|
+
"valueSet": "v",
|
|
1176
1177
|
"description": {
|
|
1177
1178
|
"kind": "markdown",
|
|
1178
1179
|
"value": "\n跳过该元素及其所有子元素的编译。\n\n- **无需传入**\n\n- **详细信息**\n\n 元素内具有 `v-pre`,所有 Vue 模板语法都会被保留并按原样渲染。最常见的用例就是显示原始双大括号标签及内容。\n\n- **示例**\n\n ```html\n <span v-pre>{{ this will not be compiled }}</span>\n ```\n"
|
|
@@ -1234,6 +1235,7 @@
|
|
|
1234
1235
|
},
|
|
1235
1236
|
{
|
|
1236
1237
|
"name": "v-once",
|
|
1238
|
+
"valueSet": "v",
|
|
1237
1239
|
"description": {
|
|
1238
1240
|
"kind": "markdown",
|
|
1239
1241
|
"value": "\n仅渲染元素和组件一次,并跳过之后的更新。\n\n- **无需传入**\n\n- **详细信息**\n\n 在随后的重新渲染,元素/组件及其所有子项将被当作静态内容并跳过渲染。这可以用来优化更新时的性能。\n\n ```html\n <!-- 单个元素 -->\n <span v-once>This will never change: {{msg}}</span>\n <!-- 带有子元素的元素 -->\n <div v-once>\n <h1>Comment</h1>\n <p>{{msg}}</p>\n </div>\n <!-- 组件 -->\n <MyComponent v-once :comment=\"msg\" />\n <!-- `v-for` 指令 -->\n <ul>\n <li v-for=\"i in list\" v-once>{{i}}</li>\n </ul>\n ```\n\n 从 3.2 起,你也可以搭配 [`v-memo`](#v-memo) 的无效条件来缓存部分模板。\n\n- **参考**\n - [数据绑定语法 - 插值](https://zh-hk.vuejs.org/guide/essentials/template-syntax.html#text-interpolation)\n - [v-memo](#v-memo)\n"
|
|
@@ -1356,6 +1358,7 @@
|
|
|
1356
1358
|
},
|
|
1357
1359
|
{
|
|
1358
1360
|
"name": "v-cloak",
|
|
1361
|
+
"valueSet": "v",
|
|
1359
1362
|
"description": {
|
|
1360
1363
|
"kind": "markdown",
|
|
1361
1364
|
"value": "\n用于隐藏尚未完成编译的 DOM 模板。\n\n- **无需传入**\n\n- **详细信息**\n\n **该指令只在没有构建步骤的环境下需要使用。**\n\n 当使用直接在 DOM 中书写的模板时,可能会出现一种叫做“未编译模板闪现”的情况:用户可能先看到的是还没编译完成的双大括号标签,直到挂载的组件将它们替换为实际渲染的内容。\n\n `v-cloak` 会保留在所绑定的元素上,直到相关组件实例被挂载后才移除。配合像 `[v-cloak] { display: none }` 这样的 CSS 规则,它可以在组件编译完毕前隐藏原始模板。\n\n- **示例**\n\n ```css\n [v-cloak] {\n display: none;\n }\n ```\n\n ```html\n <div v-cloak>\n {{ message }}\n </div>\n ```\n\n 直到编译完成前,`<div>` 将不可见。\n"
|
package/index.d.ts
CHANGED
|
@@ -11,5 +11,7 @@ declare module '@volar/language-service' {
|
|
|
11
11
|
};
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
|
-
export declare function getFullLanguageServicePlugins(ts: typeof import('typescript')
|
|
14
|
+
export declare function getFullLanguageServicePlugins(ts: typeof import('typescript'), { disableAutoImportCache }?: {
|
|
15
|
+
disableAutoImportCache?: boolean;
|
|
16
|
+
}): LanguageServicePlugin[];
|
|
15
17
|
export declare function getHybridModeLanguageServicePlugins(ts: typeof import('typescript'), getTsPluginClient: typeof import("@vue/typescript-plugin/lib/client")): LanguageServicePlugin[];
|
package/index.js
CHANGED
|
@@ -39,7 +39,7 @@ const vue_extract_file_1 = require("./lib/plugins/vue-extract-file");
|
|
|
39
39
|
const vue_sfc_1 = require("./lib/plugins/vue-sfc");
|
|
40
40
|
const vue_template_1 = require("./lib/plugins/vue-template");
|
|
41
41
|
const vue_twoslash_queries_1 = require("./lib/plugins/vue-twoslash-queries");
|
|
42
|
-
const
|
|
42
|
+
const vue_inlayhints_1 = require("./lib/plugins/vue-inlayhints");
|
|
43
43
|
const language_core_1 = require("@vue/language-core");
|
|
44
44
|
const common_1 = require("@vue/typescript-plugin/lib/common");
|
|
45
45
|
const collectExtractProps_1 = require("@vue/typescript-plugin/lib/requests/collectExtractProps");
|
|
@@ -48,9 +48,9 @@ const getImportPathForFile_1 = require("@vue/typescript-plugin/lib/requests/getI
|
|
|
48
48
|
const getPropertiesAtLocation_1 = require("@vue/typescript-plugin/lib/requests/getPropertiesAtLocation");
|
|
49
49
|
const vscode_uri_1 = require("vscode-uri");
|
|
50
50
|
const nameCasing_1 = require("./lib/ideFeatures/nameCasing");
|
|
51
|
-
function getFullLanguageServicePlugins(ts) {
|
|
51
|
+
function getFullLanguageServicePlugins(ts, { disableAutoImportCache } = {}) {
|
|
52
52
|
const plugins = [
|
|
53
|
-
...(0, volar_service_typescript_1.create)(ts),
|
|
53
|
+
...(0, volar_service_typescript_1.create)(ts, { disableAutoImportCache }),
|
|
54
54
|
...getCommonLanguageServicePlugins(ts, getTsPluginClientForLSP)
|
|
55
55
|
];
|
|
56
56
|
for (let i = 0; i < plugins.length; i++) {
|
|
@@ -181,12 +181,12 @@ function getCommonLanguageServicePlugins(ts, getTsPluginClient) {
|
|
|
181
181
|
(0, vue_document_drop_1.create)(ts, getTsPluginClient),
|
|
182
182
|
(0, vue_autoinsert_dotvalue_1.create)(ts, getTsPluginClient),
|
|
183
183
|
(0, vue_autoinsert_space_1.create)(),
|
|
184
|
-
(0,
|
|
184
|
+
(0, vue_inlayhints_1.create)(ts),
|
|
185
185
|
(0, vue_directive_comments_1.create)(),
|
|
186
186
|
(0, vue_extract_file_1.create)(ts, getTsPluginClient),
|
|
187
187
|
(0, volar_service_emmet_1.create)({
|
|
188
188
|
mappedLanguages: {
|
|
189
|
-
'vue': 'html',
|
|
189
|
+
'vue-root-tags': 'html',
|
|
190
190
|
'postcss': 'scss',
|
|
191
191
|
},
|
|
192
192
|
}),
|
package/lib/plugins/data.js
CHANGED
|
@@ -38,7 +38,7 @@ function loadTemplateData(lang) {
|
|
|
38
38
|
}
|
|
39
39
|
for (const attr of [...data.globalAttributes ?? []]) {
|
|
40
40
|
if (!attr.name.startsWith('v-')) {
|
|
41
|
-
data.globalAttributes?.push({ ...attr, name: `:${attr.name}` });
|
|
41
|
+
data.globalAttributes?.push({ ...attr, name: `:${attr.name}` }, { ...attr, name: `v-bind:${attr.name}` });
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
44
|
const vOn = data.globalAttributes?.find(d => d.name === 'v-on');
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { LanguageServicePlugin } from '../types';
|
|
2
|
+
import type * as ts from 'typescript';
|
|
3
|
+
export declare function create(ts: typeof import('typescript')): LanguageServicePlugin;
|
|
4
|
+
/**
|
|
5
|
+
* Refactored from https://github.com/vuejs/core/blob/main/packages/compiler-sfc/src/script/definePropsDestructure.ts
|
|
6
|
+
*/
|
|
7
|
+
export declare function findDestructuredProps(ts: typeof import('typescript'), ast: ts.SourceFile, props: string[]): [ts.Identifier, boolean][];
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.create = create;
|
|
4
|
+
exports.findDestructuredProps = findDestructuredProps;
|
|
5
|
+
const language_core_1 = require("@vue/language-core");
|
|
6
|
+
const vscode_uri_1 = require("vscode-uri");
|
|
7
|
+
const common_1 = require("@vue/language-core/lib/codegen/common");
|
|
8
|
+
function create(ts) {
|
|
9
|
+
return {
|
|
10
|
+
name: 'vue-inlay-hints',
|
|
11
|
+
capabilities: {
|
|
12
|
+
inlayHintProvider: {},
|
|
13
|
+
},
|
|
14
|
+
create(context) {
|
|
15
|
+
return {
|
|
16
|
+
async provideInlayHints(document, range) {
|
|
17
|
+
const settings = {};
|
|
18
|
+
const result = [];
|
|
19
|
+
const decoded = context.decodeEmbeddedDocumentUri(vscode_uri_1.URI.parse(document.uri));
|
|
20
|
+
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
|
|
21
|
+
const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
|
|
22
|
+
if (virtualCode instanceof language_core_1.VueVirtualCode) {
|
|
23
|
+
const codegen = language_core_1.tsCodegen.get(virtualCode.sfc);
|
|
24
|
+
const inlayHints = [
|
|
25
|
+
...codegen?.generatedTemplate()?.inlayHints ?? [],
|
|
26
|
+
...codegen?.generatedScript()?.inlayHints ?? [],
|
|
27
|
+
];
|
|
28
|
+
const scriptSetupRanges = codegen?.scriptSetupRanges();
|
|
29
|
+
if (scriptSetupRanges?.props.destructured && virtualCode.sfc.scriptSetup?.ast) {
|
|
30
|
+
for (const [prop, isShorthand] of findDestructuredProps(ts, virtualCode.sfc.scriptSetup.ast, scriptSetupRanges.props.destructured)) {
|
|
31
|
+
const name = prop.text;
|
|
32
|
+
const end = prop.getEnd();
|
|
33
|
+
const pos = isShorthand ? end : end - name.length;
|
|
34
|
+
const label = isShorthand ? `: props.${name}` : 'props.';
|
|
35
|
+
inlayHints.push({
|
|
36
|
+
blockName: 'scriptSetup',
|
|
37
|
+
offset: pos,
|
|
38
|
+
setting: 'vue.inlayHints.destructuredProps',
|
|
39
|
+
label,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const blocks = [
|
|
44
|
+
virtualCode.sfc.template,
|
|
45
|
+
virtualCode.sfc.script,
|
|
46
|
+
virtualCode.sfc.scriptSetup,
|
|
47
|
+
];
|
|
48
|
+
const start = document.offsetAt(range.start);
|
|
49
|
+
const end = document.offsetAt(range.end);
|
|
50
|
+
for (const hint of inlayHints) {
|
|
51
|
+
const block = blocks.find(block => block?.name === hint.blockName);
|
|
52
|
+
const hintOffset = (block?.startTagEnd ?? 0) + hint.offset;
|
|
53
|
+
if (hintOffset >= start && hintOffset <= end) {
|
|
54
|
+
settings[hint.setting] ??= await context.env.getConfiguration?.(hint.setting) ?? false;
|
|
55
|
+
if (!settings[hint.setting]) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
result.push({
|
|
59
|
+
label: hint.label,
|
|
60
|
+
paddingRight: hint.paddingRight,
|
|
61
|
+
paddingLeft: hint.paddingLeft,
|
|
62
|
+
position: document.positionAt(hintOffset),
|
|
63
|
+
kind: 2,
|
|
64
|
+
tooltip: hint.tooltip ? {
|
|
65
|
+
kind: 'markdown',
|
|
66
|
+
value: hint.tooltip,
|
|
67
|
+
} : undefined,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return result;
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Refactored from https://github.com/vuejs/core/blob/main/packages/compiler-sfc/src/script/definePropsDestructure.ts
|
|
80
|
+
*/
|
|
81
|
+
function findDestructuredProps(ts, ast, props) {
|
|
82
|
+
const rootScope = {};
|
|
83
|
+
const scopeStack = [rootScope];
|
|
84
|
+
let currentScope = rootScope;
|
|
85
|
+
const excludedIds = new WeakSet();
|
|
86
|
+
const parentStack = [];
|
|
87
|
+
for (const prop of props) {
|
|
88
|
+
rootScope[prop] = true;
|
|
89
|
+
}
|
|
90
|
+
function pushScope() {
|
|
91
|
+
scopeStack.push((currentScope = Object.create(currentScope)));
|
|
92
|
+
}
|
|
93
|
+
function popScope() {
|
|
94
|
+
scopeStack.pop();
|
|
95
|
+
currentScope = scopeStack[scopeStack.length - 1] || null;
|
|
96
|
+
}
|
|
97
|
+
function registerLocalBinding(id) {
|
|
98
|
+
excludedIds.add(id);
|
|
99
|
+
if (currentScope) {
|
|
100
|
+
currentScope[id.text] = false;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const references = [];
|
|
104
|
+
walkScope(ast, true);
|
|
105
|
+
walk(ast);
|
|
106
|
+
return references;
|
|
107
|
+
function walkScope(node, isRoot = false) {
|
|
108
|
+
ts.forEachChild(node, stmt => {
|
|
109
|
+
if (ts.isVariableStatement(stmt)) {
|
|
110
|
+
for (const decl of stmt.declarationList.declarations) {
|
|
111
|
+
walkVariableDeclaration(decl, isRoot);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
else if (ts.isFunctionDeclaration(stmt) ||
|
|
115
|
+
ts.isClassDeclaration(stmt)) {
|
|
116
|
+
const declare = ts.getModifiers(stmt)?.find(modifier => modifier.kind === ts.SyntaxKind.DeclareKeyword);
|
|
117
|
+
if (!stmt.name || declare) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
registerLocalBinding(stmt.name);
|
|
121
|
+
}
|
|
122
|
+
else if ((ts.isForOfStatement(stmt) || ts.isForInStatement(stmt)) &&
|
|
123
|
+
ts.isVariableDeclarationList(stmt.initializer)) {
|
|
124
|
+
walkVariableDeclaration(stmt.initializer.declarations[0], isRoot);
|
|
125
|
+
}
|
|
126
|
+
else if (ts.isLabeledStatement(stmt) &&
|
|
127
|
+
ts.isVariableDeclaration(stmt.statement)) {
|
|
128
|
+
walkVariableDeclaration(stmt.statement, isRoot);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
function walkVariableDeclaration(decl, isRoot = false) {
|
|
133
|
+
const { initializer, name } = decl;
|
|
134
|
+
const isDefineProps = isRoot
|
|
135
|
+
&& initializer
|
|
136
|
+
&& ts.isCallExpression(initializer)
|
|
137
|
+
&& initializer.expression.getText(ast) === 'defineProps';
|
|
138
|
+
for (const id of (0, common_1.collectIdentifiers)(ts, name)) {
|
|
139
|
+
if (isDefineProps) {
|
|
140
|
+
excludedIds.add(id);
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
registerLocalBinding(id);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function walkFunctionDeclaration(node) {
|
|
148
|
+
const { name, parameters } = node;
|
|
149
|
+
if (name && ts.isIdentifier(name)) {
|
|
150
|
+
registerLocalBinding(name);
|
|
151
|
+
}
|
|
152
|
+
for (const p of parameters) {
|
|
153
|
+
for (const id of (0, common_1.collectIdentifiers)(ts, p)) {
|
|
154
|
+
registerLocalBinding(id);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
function walk(parent) {
|
|
159
|
+
ts.forEachChild(parent, node => {
|
|
160
|
+
if (enter(node) ?? true) {
|
|
161
|
+
walk(node);
|
|
162
|
+
leave(node);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
function enter(node) {
|
|
166
|
+
parent && parentStack.push(parent);
|
|
167
|
+
if (ts.isTypeLiteralNode(node) ||
|
|
168
|
+
ts.isTypeReferenceNode(node)) {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
if (ts.isFunctionLike(node)) {
|
|
172
|
+
pushScope();
|
|
173
|
+
walkFunctionDeclaration(node);
|
|
174
|
+
if ('body' in node) {
|
|
175
|
+
walkScope(node.body);
|
|
176
|
+
}
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
if (ts.isCatchClause(node)) {
|
|
180
|
+
pushScope();
|
|
181
|
+
const { variableDeclaration: p } = node;
|
|
182
|
+
if (p && ts.isIdentifier(p.name)) {
|
|
183
|
+
registerLocalBinding(p.name);
|
|
184
|
+
}
|
|
185
|
+
walkScope(node.block);
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
if (ts.isBlock(node)
|
|
189
|
+
&& !ts.isFunctionLike(parent)
|
|
190
|
+
&& !ts.isCatchClause(parent)) {
|
|
191
|
+
pushScope();
|
|
192
|
+
walkScope(node);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
if (ts.isIdentifier(node)
|
|
196
|
+
&& isReferencedIdentifier(node, parent)
|
|
197
|
+
&& !excludedIds.has(node)) {
|
|
198
|
+
const name = node.text;
|
|
199
|
+
if (currentScope[name]) {
|
|
200
|
+
const isShorthand = ts.isShorthandPropertyAssignment(parent);
|
|
201
|
+
references.push([node, isShorthand]);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function leave(node) {
|
|
206
|
+
parent && parentStack.pop();
|
|
207
|
+
if (ts.isFunctionLike(node)
|
|
208
|
+
|| ts.isCatchClause(node)
|
|
209
|
+
|| (ts.isBlock(node)
|
|
210
|
+
&& !ts.isFunctionLike(parent)
|
|
211
|
+
&& !ts.isCatchClause(parent))) {
|
|
212
|
+
popScope();
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
// TODO: more conditions
|
|
217
|
+
function isReferencedIdentifier(id, parent) {
|
|
218
|
+
if (!parent) {
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
if (id.text === 'arguments') {
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
if (ts.isExpressionWithTypeArguments(parent) ||
|
|
225
|
+
ts.isInterfaceDeclaration(parent) ||
|
|
226
|
+
ts.isTypeAliasDeclaration(parent) ||
|
|
227
|
+
ts.isPropertySignature(parent)) {
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
if (ts.isPropertyAccessExpression(parent) ||
|
|
231
|
+
ts.isPropertyAssignment(parent) ||
|
|
232
|
+
ts.isPropertyDeclaration(parent)) {
|
|
233
|
+
if (parent.name === id) {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=vue-inlayhints.js.map
|
package/lib/plugins/vue-sfc.d.ts
CHANGED
|
@@ -1,7 +1,2 @@
|
|
|
1
1
|
import type { LanguageServicePlugin } from '@volar/language-service';
|
|
2
|
-
import * as vue from '@vue/language-core';
|
|
3
|
-
import type { TextDocument } from 'vscode-languageserver-textdocument';
|
|
4
|
-
export interface Provide {
|
|
5
|
-
'vue/vueFile': (document: TextDocument) => vue.VueVirtualCode | undefined;
|
|
6
|
-
}
|
|
7
2
|
export declare function create(): LanguageServicePlugin;
|
package/lib/plugins/vue-sfc.js
CHANGED
|
@@ -9,7 +9,7 @@ const vscode_uri_1 = require("vscode-uri");
|
|
|
9
9
|
let sfcDataProvider;
|
|
10
10
|
function create() {
|
|
11
11
|
const htmlPlugin = (0, volar_service_html_1.create)({
|
|
12
|
-
documentSelector: ['vue'],
|
|
12
|
+
documentSelector: ['vue-root-tags'],
|
|
13
13
|
useDefaultDataProvider: false,
|
|
14
14
|
getCustomData(context) {
|
|
15
15
|
sfcDataProvider ??= html.newHTMLDataProvider('vue', (0, data_1.loadLanguageBlocks)(context.env.locale ?? 'en'));
|
|
@@ -42,13 +42,6 @@ function create() {
|
|
|
42
42
|
const htmlPluginInstance = htmlPlugin.create(context);
|
|
43
43
|
return {
|
|
44
44
|
...htmlPluginInstance,
|
|
45
|
-
provide: {
|
|
46
|
-
'vue/vueFile': document => {
|
|
47
|
-
return worker(document, context, vueFile => {
|
|
48
|
-
return vueFile;
|
|
49
|
-
});
|
|
50
|
-
},
|
|
51
|
-
},
|
|
52
45
|
provideDocumentLinks: undefined,
|
|
53
46
|
async resolveEmbeddedCodeFormattingOptions(sourceScript, virtualCode, options) {
|
|
54
47
|
if (sourceScript.generated?.root instanceof vue.VueVirtualCode) {
|
|
@@ -160,10 +153,13 @@ function create() {
|
|
|
160
153
|
return;
|
|
161
154
|
}
|
|
162
155
|
result.items = result.items.filter(item => item.label !== '!DOCTYPE' && item.label !== 'Custom Blocks');
|
|
163
|
-
|
|
156
|
+
const tags = sfcDataProvider?.provideTags();
|
|
157
|
+
const scriptLangs = getLangs('script');
|
|
158
|
+
const scriptItems = result.items.filter(item => item.label === 'script' || item.label === 'script setup');
|
|
159
|
+
for (const scriptItem of scriptItems) {
|
|
164
160
|
scriptItem.kind = 17;
|
|
165
161
|
scriptItem.detail = '.js';
|
|
166
|
-
for (const lang of
|
|
162
|
+
for (const lang of scriptLangs) {
|
|
167
163
|
result.items.push({
|
|
168
164
|
...scriptItem,
|
|
169
165
|
detail: `.${lang}`,
|
|
@@ -176,50 +172,68 @@ function create() {
|
|
|
176
172
|
});
|
|
177
173
|
}
|
|
178
174
|
}
|
|
175
|
+
const styleLangs = getLangs('style');
|
|
179
176
|
const styleItem = result.items.find(item => item.label === 'style');
|
|
180
177
|
if (styleItem) {
|
|
181
178
|
styleItem.kind = 17;
|
|
182
179
|
styleItem.detail = '.css';
|
|
183
|
-
for (const lang of
|
|
184
|
-
result.items.push(
|
|
185
|
-
...styleItem,
|
|
186
|
-
kind: 17,
|
|
187
|
-
detail: lang === 'postcss' ? '.css' : `.${lang}`,
|
|
188
|
-
label: styleItem.label + ' lang="' + lang + '"',
|
|
189
|
-
textEdit: styleItem.textEdit ? {
|
|
190
|
-
...styleItem.textEdit,
|
|
191
|
-
newText: styleItem.textEdit.newText + ' lang="' + lang + '"',
|
|
192
|
-
} : undefined,
|
|
193
|
-
});
|
|
180
|
+
for (const lang of styleLangs) {
|
|
181
|
+
result.items.push(getStyleCompletionItem(styleItem, lang), getStyleCompletionItem(styleItem, lang, 'scoped'), getStyleCompletionItem(styleItem, lang, 'module'));
|
|
194
182
|
}
|
|
195
183
|
}
|
|
184
|
+
const templateLangs = getLangs('template');
|
|
196
185
|
const templateItem = result.items.find(item => item.label === 'template');
|
|
197
186
|
if (templateItem) {
|
|
198
187
|
templateItem.kind = 17;
|
|
199
188
|
templateItem.detail = '.html';
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
189
|
+
for (const lang of templateLangs) {
|
|
190
|
+
if (lang === 'html') {
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
result.items.push({
|
|
194
|
+
...templateItem,
|
|
195
|
+
kind: 17,
|
|
196
|
+
detail: `.${lang}`,
|
|
197
|
+
label: templateItem.label + ' lang="' + lang + '"',
|
|
198
|
+
textEdit: templateItem.textEdit ? {
|
|
199
|
+
...templateItem.textEdit,
|
|
200
|
+
newText: templateItem.textEdit.newText + ' lang="' + lang + '"',
|
|
201
|
+
} : undefined,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
210
204
|
}
|
|
211
205
|
return result;
|
|
206
|
+
function getLangs(label) {
|
|
207
|
+
return tags
|
|
208
|
+
?.find(tag => tag.name === label)?.attributes
|
|
209
|
+
.find(attr => attr.name === 'lang')?.values
|
|
210
|
+
?.map(({ name }) => name) ?? [];
|
|
211
|
+
}
|
|
212
212
|
},
|
|
213
213
|
};
|
|
214
214
|
},
|
|
215
215
|
};
|
|
216
216
|
function worker(document, context, callback) {
|
|
217
|
+
if (document.languageId !== 'vue-root-tags') {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
217
220
|
const decoded = context.decodeEmbeddedDocumentUri(vscode_uri_1.URI.parse(document.uri));
|
|
218
221
|
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
return callback(virtualCode);
|
|
222
|
+
if (sourceScript?.generated?.root instanceof vue.VueVirtualCode) {
|
|
223
|
+
return callback(sourceScript.generated.root);
|
|
222
224
|
}
|
|
223
225
|
}
|
|
224
226
|
}
|
|
227
|
+
function getStyleCompletionItem(styleItem, lang, attr) {
|
|
228
|
+
return {
|
|
229
|
+
...styleItem,
|
|
230
|
+
kind: 17,
|
|
231
|
+
detail: lang === 'postcss' ? '.css' : `.${lang}`,
|
|
232
|
+
label: styleItem.label + ' lang="' + lang + '"' + (attr ? ` ${attr}` : ''),
|
|
233
|
+
textEdit: styleItem.textEdit ? {
|
|
234
|
+
...styleItem.textEdit,
|
|
235
|
+
newText: styleItem.textEdit.newText + ' lang="' + lang + '"' + (attr ? ` ${attr}` : ''),
|
|
236
|
+
} : undefined
|
|
237
|
+
};
|
|
238
|
+
}
|
|
225
239
|
//# sourceMappingURL=vue-sfc.js.map
|
|
@@ -11,9 +11,10 @@ const vscode_uri_1 = require("vscode-uri");
|
|
|
11
11
|
const nameCasing_1 = require("../ideFeatures/nameCasing");
|
|
12
12
|
const types_1 = require("../types");
|
|
13
13
|
const data_1 = require("./data");
|
|
14
|
+
const specialTags = new Set(['slot', 'component', 'template']);
|
|
15
|
+
const specialProps = new Set(['class', 'is', 'key', 'ref', 'style']);
|
|
14
16
|
let builtInData;
|
|
15
17
|
let modelData;
|
|
16
|
-
const specialTags = new Set(['slot', 'component', 'template']);
|
|
17
18
|
function create(mode, ts, getTsPluginClient) {
|
|
18
19
|
let customData = [];
|
|
19
20
|
let extraCustomData = [];
|
|
@@ -59,7 +60,10 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
59
60
|
},
|
|
60
61
|
inlayHintProvider: {},
|
|
61
62
|
hoverProvider: true,
|
|
62
|
-
diagnosticProvider: {
|
|
63
|
+
diagnosticProvider: {
|
|
64
|
+
interFileDependencies: false,
|
|
65
|
+
workspaceDiagnostics: false,
|
|
66
|
+
},
|
|
63
67
|
semanticTokensProvider: {
|
|
64
68
|
legend: {
|
|
65
69
|
tokenTypes: ['class'],
|
|
@@ -133,8 +137,12 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
133
137
|
if (!htmlComplete) {
|
|
134
138
|
return;
|
|
135
139
|
}
|
|
136
|
-
if (sourceScript?.generated
|
|
137
|
-
|
|
140
|
+
if (sourceScript?.generated) {
|
|
141
|
+
const virtualCode = sourceScript.generated.embeddedCodes.get('template');
|
|
142
|
+
if (virtualCode) {
|
|
143
|
+
const embeddedDocumentUri = context.encodeEmbeddedDocumentUri(sourceScript.id, virtualCode.id);
|
|
144
|
+
afterHtmlCompletion(htmlComplete, context.documents.get(embeddedDocumentUri, virtualCode.languageId, virtualCode.snapshot));
|
|
145
|
+
}
|
|
138
146
|
}
|
|
139
147
|
return htmlComplete;
|
|
140
148
|
},
|
|
@@ -349,10 +357,13 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
349
357
|
const casing = await (0, nameCasing_1.getNameCasing)(context, sourceDocumentUri);
|
|
350
358
|
if (builtInData.tags) {
|
|
351
359
|
for (const tag of builtInData.tags) {
|
|
360
|
+
if (isInternalItemId(tag.name)) {
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
352
363
|
if (specialTags.has(tag.name)) {
|
|
353
364
|
tag.name = createInternalItemId('specialTag', [tag.name]);
|
|
354
365
|
}
|
|
355
|
-
if (casing.tag === types_1.TagNameCasing.Kebab) {
|
|
366
|
+
else if (casing.tag === types_1.TagNameCasing.Kebab) {
|
|
356
367
|
tag.name = (0, language_core_1.hyphenateTag)(tag.name);
|
|
357
368
|
}
|
|
358
369
|
else {
|
|
@@ -423,8 +434,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
423
434
|
const events = await tsPluginClient?.getComponentEvents(vueCode.fileName, tag) ?? [];
|
|
424
435
|
tagInfos.set(tag, {
|
|
425
436
|
attrs,
|
|
426
|
-
props: props.filter(prop => !prop.startsWith('ref_')
|
|
427
|
-
&& !(0, shared_1.hyphenate)(prop).startsWith('on-vnode-')),
|
|
437
|
+
props: props.filter(prop => !prop.startsWith('ref_')),
|
|
428
438
|
events,
|
|
429
439
|
});
|
|
430
440
|
version++;
|
|
@@ -459,7 +469,8 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
459
469
|
for (const prop of [...props, ...attrs]) {
|
|
460
470
|
const isGlobal = !propsSet.has(prop);
|
|
461
471
|
const name = casing.attr === types_1.AttrNameCasing.Camel ? prop : (0, language_core_1.hyphenateAttr)(prop);
|
|
462
|
-
|
|
472
|
+
const isEvent = (0, language_core_1.hyphenateAttr)(name).startsWith('on-');
|
|
473
|
+
if (isEvent) {
|
|
463
474
|
const propNameBase = name.startsWith('on-')
|
|
464
475
|
? name.slice('on-'.length)
|
|
465
476
|
: (name['on'.length].toLowerCase() + name.slice('onX'.length));
|
|
@@ -472,7 +483,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
472
483
|
description: propKey,
|
|
473
484
|
});
|
|
474
485
|
}
|
|
475
|
-
{
|
|
486
|
+
else {
|
|
476
487
|
const propName = name;
|
|
477
488
|
const propKey = createInternalItemId('componentProp', [isGlobal ? '*' : tag, propName]);
|
|
478
489
|
attributes.push({
|
|
@@ -493,8 +504,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
493
504
|
attributes.push({
|
|
494
505
|
name: 'v-on:' + name,
|
|
495
506
|
description: propKey,
|
|
496
|
-
}
|
|
497
|
-
attributes.push({
|
|
507
|
+
}, {
|
|
498
508
|
name: '@' + name,
|
|
499
509
|
description: propKey,
|
|
500
510
|
});
|
|
@@ -537,8 +547,8 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
537
547
|
}
|
|
538
548
|
};
|
|
539
549
|
}
|
|
540
|
-
function afterHtmlCompletion(completionList,
|
|
541
|
-
const replacement = getReplacement(completionList,
|
|
550
|
+
function afterHtmlCompletion(completionList, document) {
|
|
551
|
+
const replacement = getReplacement(completionList, document);
|
|
542
552
|
if (replacement) {
|
|
543
553
|
const isEvent = replacement.text.startsWith('v-on:') || replacement.text.startsWith('@');
|
|
544
554
|
const isProp = replacement.text.startsWith('v-bind:') || replacement.text.startsWith(':');
|
|
@@ -596,6 +606,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
596
606
|
}
|
|
597
607
|
}
|
|
598
608
|
}
|
|
609
|
+
const originals = new Map();
|
|
599
610
|
for (const item of completionList.items) {
|
|
600
611
|
if (specialTags.has(item.label)) {
|
|
601
612
|
completionList.items = completionList.items.filter(i => i !== item);
|
|
@@ -616,50 +627,98 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
616
627
|
}
|
|
617
628
|
}
|
|
618
629
|
const itemIdKey = typeof item.documentation === 'string' ? item.documentation : item.documentation?.value;
|
|
619
|
-
|
|
630
|
+
let itemId = itemIdKey ? readInternalItemId(itemIdKey) : undefined;
|
|
620
631
|
if (itemId) {
|
|
621
|
-
|
|
632
|
+
let [isEvent, name] = tryGetEventName(itemId);
|
|
633
|
+
if (isEvent) {
|
|
634
|
+
name = 'on' + name;
|
|
635
|
+
}
|
|
636
|
+
const original = originals.get(name);
|
|
637
|
+
item.documentation = original?.documentation;
|
|
622
638
|
}
|
|
639
|
+
else {
|
|
640
|
+
let name = item.label;
|
|
641
|
+
const isVBind = name.startsWith('v-bind:') ? (name = name.slice('v-bind:'.length), true) : false;
|
|
642
|
+
const isVBindAbbr = name.startsWith(':') && name !== ':' ? (name = name.slice(':'.length), true) : false;
|
|
643
|
+
/**
|
|
644
|
+
* for `is`, `key` and `ref` starting with `v-bind:` or `:`
|
|
645
|
+
* that without `internalItemId`.
|
|
646
|
+
*/
|
|
647
|
+
if (isVBind || isVBindAbbr) {
|
|
648
|
+
itemId = {
|
|
649
|
+
type: 'componentProp',
|
|
650
|
+
args: ['^', name]
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
else if (!originals.has(item.label)) {
|
|
654
|
+
originals.set(item.label, item);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
const tokens = [];
|
|
623
658
|
if (item.kind === 10 && lastCompletionComponentNames.has((0, language_core_1.hyphenateTag)(item.label))) {
|
|
624
659
|
item.kind = 6;
|
|
625
|
-
|
|
626
|
-
}
|
|
627
|
-
else if (itemId
|
|
628
|
-
const
|
|
629
|
-
|
|
630
|
-
if (item.label === 'class'
|
|
631
|
-
|| item.label === 'ref'
|
|
632
|
-
|| item.label.endsWith(':class')
|
|
633
|
-
|| item.label.endsWith(':ref')) {
|
|
634
|
-
item.sortText = '\u0000' + (item.sortText ?? item.label);
|
|
635
|
-
}
|
|
636
|
-
else {
|
|
637
|
-
item.sortText = '\u0000\u0000' + (item.sortText ?? item.label);
|
|
638
|
-
}
|
|
639
|
-
}
|
|
660
|
+
tokens.push('\u0000');
|
|
661
|
+
}
|
|
662
|
+
else if (itemId) {
|
|
663
|
+
const isComponent = itemId.args[0] !== '*';
|
|
664
|
+
const [isEvent, name] = tryGetEventName(itemId);
|
|
640
665
|
if (itemId.type === 'componentProp') {
|
|
641
|
-
if (
|
|
666
|
+
if (isComponent || specialProps.has(name)) {
|
|
642
667
|
item.kind = 5;
|
|
643
668
|
}
|
|
644
669
|
}
|
|
645
|
-
else {
|
|
646
|
-
item.kind =
|
|
670
|
+
else if (isEvent) {
|
|
671
|
+
item.kind = 23;
|
|
672
|
+
if (name.startsWith('vnode-')) {
|
|
673
|
+
tokens.push('\u0004');
|
|
674
|
+
}
|
|
675
|
+
}
|
|
676
|
+
if (isComponent
|
|
677
|
+
|| (isComponent && isEvent)
|
|
678
|
+
|| specialProps.has(name)) {
|
|
679
|
+
tokens.push('\u0000');
|
|
680
|
+
if (item.label.startsWith(':')) {
|
|
681
|
+
tokens.push('\u0001');
|
|
682
|
+
}
|
|
683
|
+
else if (item.label.startsWith('@')) {
|
|
684
|
+
tokens.push('\u0002');
|
|
685
|
+
}
|
|
686
|
+
else if (item.label.startsWith('v-bind:')) {
|
|
687
|
+
tokens.push('\u0003');
|
|
688
|
+
}
|
|
689
|
+
else if (item.label.startsWith('v-on:')) {
|
|
690
|
+
tokens.push('\u0004');
|
|
691
|
+
}
|
|
692
|
+
else {
|
|
693
|
+
tokens.push('\u0000');
|
|
694
|
+
}
|
|
695
|
+
if (specialProps.has(name)) {
|
|
696
|
+
tokens.push('\u0001');
|
|
697
|
+
}
|
|
698
|
+
else {
|
|
699
|
+
tokens.push('\u0000');
|
|
700
|
+
}
|
|
647
701
|
}
|
|
648
702
|
}
|
|
703
|
+
else if (specialProps.has(item.label)) {
|
|
704
|
+
item.kind = 5;
|
|
705
|
+
tokens.push('\u0000', '\u0000', '\u0001');
|
|
706
|
+
}
|
|
649
707
|
else if (item.label === 'v-if'
|
|
650
708
|
|| item.label === 'v-else-if'
|
|
651
709
|
|| item.label === 'v-else'
|
|
652
710
|
|| item.label === 'v-for') {
|
|
653
711
|
item.kind = 14;
|
|
654
|
-
|
|
712
|
+
tokens.push('\u0003');
|
|
655
713
|
}
|
|
656
714
|
else if (item.label.startsWith('v-')) {
|
|
657
715
|
item.kind = 3;
|
|
658
|
-
|
|
716
|
+
tokens.push('\u0002');
|
|
659
717
|
}
|
|
660
718
|
else {
|
|
661
|
-
|
|
719
|
+
tokens.push('\u0001');
|
|
662
720
|
}
|
|
721
|
+
item.sortText = tokens.join('') + (item.sortText ?? item.label);
|
|
663
722
|
}
|
|
664
723
|
updateExtraCustomData([]);
|
|
665
724
|
}
|
|
@@ -716,8 +775,11 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
716
775
|
function createInternalItemId(type, args) {
|
|
717
776
|
return '__VLS_::' + type + '::' + args.join(',');
|
|
718
777
|
}
|
|
778
|
+
function isInternalItemId(key) {
|
|
779
|
+
return key.startsWith('__VLS_::');
|
|
780
|
+
}
|
|
719
781
|
function readInternalItemId(key) {
|
|
720
|
-
if (key
|
|
782
|
+
if (isInternalItemId(key)) {
|
|
721
783
|
const strs = key.split('::');
|
|
722
784
|
return {
|
|
723
785
|
type: strs[1],
|
|
@@ -736,4 +798,14 @@ function getReplacement(list, doc) {
|
|
|
736
798
|
}
|
|
737
799
|
}
|
|
738
800
|
}
|
|
801
|
+
function tryGetEventName(itemId) {
|
|
802
|
+
const name = (0, language_core_1.hyphenateAttr)(itemId.args[1]);
|
|
803
|
+
if (name.startsWith('on-')) {
|
|
804
|
+
return [true, name.slice('on-'.length)];
|
|
805
|
+
}
|
|
806
|
+
else if (itemId.type === 'componentEvent') {
|
|
807
|
+
return [true, name];
|
|
808
|
+
}
|
|
809
|
+
return [false, name];
|
|
810
|
+
}
|
|
739
811
|
//# sourceMappingURL=vue-template.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vue/language-service",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"files": [
|
|
6
6
|
"data",
|
|
@@ -16,23 +16,23 @@
|
|
|
16
16
|
"update-html-data": "node ./scripts/update-html-data.js"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@volar/language-core": "~2.4.
|
|
20
|
-
"@volar/language-service": "~2.4.
|
|
21
|
-
"@volar/typescript": "~2.4.
|
|
19
|
+
"@volar/language-core": "~2.4.1",
|
|
20
|
+
"@volar/language-service": "~2.4.1",
|
|
21
|
+
"@volar/typescript": "~2.4.1",
|
|
22
22
|
"@vue/compiler-dom": "^3.4.0",
|
|
23
|
-
"@vue/language-core": "2.0
|
|
23
|
+
"@vue/language-core": "2.1.0",
|
|
24
24
|
"@vue/shared": "^3.4.0",
|
|
25
|
-
"@vue/typescript-plugin": "2.0
|
|
25
|
+
"@vue/typescript-plugin": "2.1.0",
|
|
26
26
|
"computeds": "^0.0.1",
|
|
27
27
|
"path-browserify": "^1.0.1",
|
|
28
|
-
"volar-service-css": "0.0.
|
|
29
|
-
"volar-service-emmet": "0.0.
|
|
30
|
-
"volar-service-html": "0.0.
|
|
31
|
-
"volar-service-json": "0.0.
|
|
32
|
-
"volar-service-pug": "0.0.
|
|
33
|
-
"volar-service-pug-beautify": "0.0.
|
|
34
|
-
"volar-service-typescript": "0.0.
|
|
35
|
-
"volar-service-typescript-twoslash-queries": "0.0.
|
|
28
|
+
"volar-service-css": "0.0.62",
|
|
29
|
+
"volar-service-emmet": "0.0.62",
|
|
30
|
+
"volar-service-html": "0.0.62",
|
|
31
|
+
"volar-service-json": "0.0.62",
|
|
32
|
+
"volar-service-pug": "0.0.62",
|
|
33
|
+
"volar-service-pug-beautify": "0.0.62",
|
|
34
|
+
"volar-service-typescript": "0.0.62",
|
|
35
|
+
"volar-service-typescript-twoslash-queries": "0.0.62",
|
|
36
36
|
"vscode-html-languageservice": "^5.2.0",
|
|
37
37
|
"vscode-languageserver-textdocument": "^1.0.11",
|
|
38
38
|
"vscode-uri": "^3.0.8"
|
|
@@ -40,8 +40,8 @@
|
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@types/node": "latest",
|
|
42
42
|
"@types/path-browserify": "latest",
|
|
43
|
-
"@volar/kit": "~2.4.
|
|
43
|
+
"@volar/kit": "~2.4.1",
|
|
44
44
|
"vscode-languageserver-protocol": "^3.17.5"
|
|
45
45
|
},
|
|
46
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "510063740b90b64caedaee1f0bde70974613a92c"
|
|
47
47
|
}
|
|
@@ -304,7 +304,12 @@ async function templateWorker(lang) {
|
|
|
304
304
|
*/
|
|
305
305
|
const data = {
|
|
306
306
|
name,
|
|
307
|
-
valueSet:
|
|
307
|
+
valueSet:
|
|
308
|
+
name === 'v-cloak' ||
|
|
309
|
+
name === 'v-else' ||
|
|
310
|
+
name === 'v-once' ||
|
|
311
|
+
name === 'v-pre'
|
|
312
|
+
? 'v' : undefined,
|
|
308
313
|
description: {
|
|
309
314
|
kind: 'markdown',
|
|
310
315
|
value: lines.slice(1).join('\n'),
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.create = create;
|
|
4
|
-
const language_core_1 = require("@vue/language-core");
|
|
5
|
-
const vscode_uri_1 = require("vscode-uri");
|
|
6
|
-
function create(ts) {
|
|
7
|
-
return {
|
|
8
|
-
name: 'vue-toggle-v-bind-codeaction',
|
|
9
|
-
capabilities: {
|
|
10
|
-
codeActionProvider: {
|
|
11
|
-
codeActionKinds: ['refactor'],
|
|
12
|
-
},
|
|
13
|
-
},
|
|
14
|
-
create(context) {
|
|
15
|
-
return {
|
|
16
|
-
provideCodeActions(document, range, _context) {
|
|
17
|
-
const startOffset = document.offsetAt(range.start);
|
|
18
|
-
const endOffset = document.offsetAt(range.end);
|
|
19
|
-
const decoded = context.decodeEmbeddedDocumentUri(vscode_uri_1.URI.parse(document.uri));
|
|
20
|
-
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
|
|
21
|
-
const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
|
|
22
|
-
if (!(virtualCode instanceof language_core_1.VueVirtualCode)) {
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
const { template } = virtualCode.sfc;
|
|
26
|
-
if (!template?.ast) {
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
const templateStartOffset = template.startTagEnd;
|
|
30
|
-
const result = [];
|
|
31
|
-
for (const node of (0, language_core_1.forEachElementNode)(template.ast)) {
|
|
32
|
-
if (startOffset > templateStartOffset + node.loc.end.offset || endOffset < templateStartOffset + node.loc.start.offset) {
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
for (const prop of node.props) {
|
|
36
|
-
if (startOffset - templateStartOffset >= prop.loc.start.offset
|
|
37
|
-
&& endOffset - templateStartOffset <= prop.loc.end.offset) {
|
|
38
|
-
if (prop.type === 7 && prop.exp) {
|
|
39
|
-
const sourceFile = ts.createSourceFile('/a.ts', prop.exp.loc.source, ts.ScriptTarget.Latest, true);
|
|
40
|
-
const firstStatement = sourceFile.statements[0];
|
|
41
|
-
if (sourceFile.statements.length === 1 && ts.isExpressionStatement(firstStatement) && ts.isStringLiteralLike(firstStatement.expression)) {
|
|
42
|
-
const stringNode = sourceFile.statements[0];
|
|
43
|
-
const removeTextRanges = [
|
|
44
|
-
[prop.loc.start.offset, prop.loc.start.offset + 1],
|
|
45
|
-
// Work correctly with trivias for cases like <input :type=" 'password' " />
|
|
46
|
-
[prop.exp.loc.start.offset, prop.exp.loc.start.offset + stringNode.pos + stringNode.getLeadingTriviaWidth() + 1],
|
|
47
|
-
[prop.exp.loc.start.offset + stringNode.end - 1, prop.exp.loc.end.offset],
|
|
48
|
-
];
|
|
49
|
-
result.push({
|
|
50
|
-
title: 'Remove v-bind from attribute',
|
|
51
|
-
kind: 'refactor.rewrite.removeVBind',
|
|
52
|
-
edit: {
|
|
53
|
-
changes: {
|
|
54
|
-
[document.uri]: removeTextRanges.map(range => ({
|
|
55
|
-
newText: '',
|
|
56
|
-
range: {
|
|
57
|
-
start: document.positionAt(templateStartOffset + range[0]),
|
|
58
|
-
end: document.positionAt(templateStartOffset + range[1]),
|
|
59
|
-
}
|
|
60
|
-
}))
|
|
61
|
-
},
|
|
62
|
-
},
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
if (prop.type === 6) {
|
|
67
|
-
const edits = [];
|
|
68
|
-
const addVBindPos = document.positionAt(templateStartOffset + prop.loc.start.offset);
|
|
69
|
-
edits.push({
|
|
70
|
-
newText: ':',
|
|
71
|
-
range: {
|
|
72
|
-
start: addVBindPos,
|
|
73
|
-
end: addVBindPos,
|
|
74
|
-
},
|
|
75
|
-
});
|
|
76
|
-
let newPosition;
|
|
77
|
-
if (prop.value) {
|
|
78
|
-
const valueStart = document.positionAt(templateStartOffset + prop.value.loc.start.offset);
|
|
79
|
-
const valueEnd = document.positionAt(templateStartOffset + prop.value.loc.end.offset);
|
|
80
|
-
if (prop.value.loc.end.offset - prop.value.loc.start.offset !== prop.value.content.length) {
|
|
81
|
-
valueStart.character++;
|
|
82
|
-
valueEnd.character--;
|
|
83
|
-
}
|
|
84
|
-
edits.push({
|
|
85
|
-
newText: "'",
|
|
86
|
-
range: {
|
|
87
|
-
start: valueStart,
|
|
88
|
-
end: valueStart,
|
|
89
|
-
},
|
|
90
|
-
});
|
|
91
|
-
edits.push({
|
|
92
|
-
newText: "'",
|
|
93
|
-
range: {
|
|
94
|
-
start: valueEnd,
|
|
95
|
-
end: valueEnd,
|
|
96
|
-
},
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
const addValuePos = document.positionAt(templateStartOffset + prop.loc.end.offset);
|
|
101
|
-
newPosition = {
|
|
102
|
-
line: addValuePos.line,
|
|
103
|
-
character: addValuePos.character + ':'.length + '="'.length,
|
|
104
|
-
};
|
|
105
|
-
edits.push({
|
|
106
|
-
newText: '=""',
|
|
107
|
-
range: {
|
|
108
|
-
start: addValuePos,
|
|
109
|
-
end: addValuePos
|
|
110
|
-
},
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
result.push({
|
|
114
|
-
title: 'Add v-bind to attribute',
|
|
115
|
-
kind: 'refactor.rewrite.addVBind',
|
|
116
|
-
edit: {
|
|
117
|
-
changes: { [document.uri]: edits },
|
|
118
|
-
},
|
|
119
|
-
command: newPosition ? context?.commands.setSelection.create(newPosition) : undefined,
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
return result;
|
|
126
|
-
},
|
|
127
|
-
transformCodeAction(item) {
|
|
128
|
-
return item; // ignore mapping
|
|
129
|
-
},
|
|
130
|
-
};
|
|
131
|
-
},
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
//# sourceMappingURL=vue-toggle-v-bind-codeaction.js.map
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.create = create;
|
|
4
|
-
const vscode_uri_1 = require("vscode-uri");
|
|
5
|
-
function create() {
|
|
6
|
-
return {
|
|
7
|
-
name: 'vue-inlay-hints-hidden-callback-param',
|
|
8
|
-
capabilities: {
|
|
9
|
-
inlayHintProvider: {},
|
|
10
|
-
},
|
|
11
|
-
create(context) {
|
|
12
|
-
return {
|
|
13
|
-
async provideInlayHints(document, range) {
|
|
14
|
-
const settings = {};
|
|
15
|
-
const result = [];
|
|
16
|
-
const decoded = context.decodeEmbeddedDocumentUri(vscode_uri_1.URI.parse(document.uri));
|
|
17
|
-
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
|
|
18
|
-
const vitualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
|
|
19
|
-
if (vitualCode) {
|
|
20
|
-
const start = document.offsetAt(range.start);
|
|
21
|
-
const end = document.offsetAt(range.end);
|
|
22
|
-
for (const mapping of vitualCode.mappings) {
|
|
23
|
-
const hint = mapping.data.__hint;
|
|
24
|
-
if (mapping.generatedOffsets[0] >= start
|
|
25
|
-
&& mapping.generatedOffsets[mapping.generatedOffsets.length - 1] + mapping.lengths[mapping.lengths.length - 1] <= end
|
|
26
|
-
&& hint) {
|
|
27
|
-
settings[hint.setting] ??= await context.env.getConfiguration?.(hint.setting) ?? false;
|
|
28
|
-
if (!settings[hint.setting]) {
|
|
29
|
-
continue;
|
|
30
|
-
}
|
|
31
|
-
result.push({
|
|
32
|
-
label: hint.label,
|
|
33
|
-
paddingRight: hint.paddingRight,
|
|
34
|
-
paddingLeft: hint.paddingLeft,
|
|
35
|
-
position: document.positionAt(mapping.generatedOffsets[0]),
|
|
36
|
-
kind: 2,
|
|
37
|
-
tooltip: {
|
|
38
|
-
kind: 'markdown',
|
|
39
|
-
value: hint.tooltip,
|
|
40
|
-
},
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
return result;
|
|
46
|
-
},
|
|
47
|
-
};
|
|
48
|
-
},
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
//# sourceMappingURL=vue-visualize-hidden-callback-param.js.map
|