@vue/language-service 2.1.6 → 2.1.8
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 +1 -1
- package/data/template/en.json +1 -1
- package/data/template/ru.json +4 -4
- package/lib/ideFeatures/nameCasing.js +8 -8
- package/lib/plugins/vue-document-drop.js +1 -1
- package/lib/plugins/vue-document-links.js +4 -4
- package/lib/plugins/vue-extract-file.js +2 -2
- package/lib/plugins/vue-inlayhints.d.ts +1 -1
- package/lib/plugins/vue-inlayhints.js +26 -22
- package/lib/plugins/vue-sfc.js +2 -2
- package/lib/plugins/vue-template.js +24 -13
- package/package.json +12 -11
package/data/template/cs.json
CHANGED
|
@@ -1544,7 +1544,7 @@
|
|
|
1544
1544
|
"name": "is",
|
|
1545
1545
|
"description": {
|
|
1546
1546
|
"kind": "markdown",
|
|
1547
|
-
"value": "\nPoužívá se pro binding [dynamických komponent](https://cs.vuejs.org/guide/essentials/component-basics.html#dynamic-components).\n\n- **Očekává:** `string | Komponenta`\n\n- **Použití na nativních elementech
|
|
1547
|
+
"value": "\nPoužívá se pro binding [dynamických komponent](https://cs.vuejs.org/guide/essentials/component-basics.html#dynamic-components).\n\n- **Očekává:** `string | Komponenta`\n\n- **Použití na nativních elementech**\n\n - Podporováno až od verze 3.1+\n\n Když je atribut `is` použit na nativním HTML elementu, bude interpretován jako [custom vestavěný element](https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements-customized-builtin-example), což je nativní funkce webové platformy.\n\n Existuje však případ použití, kdy můžete potřebovat, aby Vue nahradilo nativní element Vue komponentou, jak je vysvětleno v [upozornění na omezení při parsování in-DOM šablon](https://cs.vuejs.org/guide/essentials/component-basics.html#in-dom-template-parsing-caveats). Můžete atributu `is` přidat předponu `vue:`, aby Vue vykreslilo element jako Vue komponentu:\n\n ```html\n <table>\n <tr is=\"vue:my-row-component\"></tr>\n </table>\n ```\n\n- **Viz také:**\n\n - [Vestavěné speciální elementy - `<component>`](https://cs.vuejs.org/api/built-in-special-elements.html#component)\n - [Dynamické komponenty](https://cs.vuejs.org/guide/essentials/component-basics.html#dynamic-components)\n"
|
|
1548
1548
|
},
|
|
1549
1549
|
"references": [
|
|
1550
1550
|
{
|
package/data/template/en.json
CHANGED
|
@@ -1544,7 +1544,7 @@
|
|
|
1544
1544
|
"name": "is",
|
|
1545
1545
|
"description": {
|
|
1546
1546
|
"kind": "markdown",
|
|
1547
|
-
"value": "\nUsed for binding [dynamic components](https://vuejs.org/guide/essentials/component-basics.html#dynamic-components).\n\n- **Expects:** `string | Component`\n\n- **Usage on native elements
|
|
1547
|
+
"value": "\nUsed for binding [dynamic components](https://vuejs.org/guide/essentials/component-basics.html#dynamic-components).\n\n- **Expects:** `string | Component`\n\n- **Usage on native elements**\n \n - Only supported in 3.1+\n\n When the `is` attribute is used on a native HTML element, it will be interpreted as a [Customized built-in element](https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements-customized-builtin-example), which is a native web platform feature.\n\n There is, however, a use case where you may need Vue to replace a native element with a Vue component, as explained in [in-DOM Template Parsing Caveats](https://vuejs.org/guide/essentials/component-basics.html#in-dom-template-parsing-caveats). You can prefix the value of the `is` attribute with `vue:` so that Vue will render the element as a Vue component instead:\n\n ```html\n <table>\n <tr is=\"vue:my-row-component\"></tr>\n </table>\n ```\n\n- **See also**\n\n - [Built-in Special Element - `<component>`](https://vuejs.org/api/built-in-special-elements.html#component)\n - [Dynamic Components](https://vuejs.org/guide/essentials/component-basics.html#dynamic-components)\n"
|
|
1548
1548
|
},
|
|
1549
1549
|
"references": [
|
|
1550
1550
|
{
|
package/data/template/ru.json
CHANGED
|
@@ -191,7 +191,7 @@
|
|
|
191
191
|
"name": "Teleport",
|
|
192
192
|
"description": {
|
|
193
193
|
"kind": "markdown",
|
|
194
|
-
"value": "\nПеремещает содержимое своего слота в другую часть DOM.\n\n- **Входные параметры**\n\n ```ts\n interface TeleportProps {\n /**\n * Обязательный. Задаёт целевой контейнер.\n * Может быть селектором или непосредственно элементом.\n */\n to: string | HTMLElement\n /**\n * Если `true`, содержимое останется на своем первоначальном\n * месте, вместо перемещения в целевой контейнер.\n * Может изменяться динамически.\n */\n disabled?: boolean\n }\n ```\n\n- **Пример**\n\n Указание целевого контейнера:\n\n ```html\n <Teleport to=\"#some-id\" />\n <Teleport to=\".some-class\" />\n <Teleport to=\"[data-teleport]\" />\n ```\n\n Перемещение по условию:\n\n ```html\n <Teleport to=\"#popup\" :disabled=\"displayVideoInline\">\n <video src=\"./my-movie.mp4\">\n </Teleport>\n ```\n\n- **См. также** [Руководство — Teleport](https://ru.vuejs.org/guide/built-ins/teleport.html)\n"
|
|
194
|
+
"value": "\nПеремещает содержимое своего слота в другую часть DOM.\n\n- **Входные параметры**\n\n ```ts\n interface TeleportProps {\n /**\n * Обязательный. Задаёт целевой контейнер.\n * Может быть селектором или непосредственно элементом.\n */\n to: string | HTMLElement\n /**\n * Если `true`, содержимое останется на своем первоначальном\n * месте, вместо перемещения в целевой контейнер.\n * Может изменяться динамически.\n */\n disabled?: boolean\n /**\n * When `true`, the Teleport will defer until other\n * parts of the application have been mounted before\n * resolving its target. (3.5+)\n */\n defer?: boolean\n }\n ```\n\n- **Пример**\n\n Указание целевого контейнера:\n\n ```html\n <Teleport to=\"#some-id\" />\n <Teleport to=\".some-class\" />\n <Teleport to=\"[data-teleport]\" />\n ```\n\n Перемещение по условию:\n\n ```html\n <Teleport to=\"#popup\" :disabled=\"displayVideoInline\">\n <video src=\"./my-movie.mp4\">\n </Teleport>\n ```\n\n Defer target resolution <sup class=\"vt-badge\" data-text=\"3.5+\" />:\n\n ```html\n <Teleport defer to=\"#late-div\">...</Teleport>\n\n <!-- somewhere later in the template -->\n <div id=\"late-div\"></div>\n ```\n\n- **См. также** [Руководство — Teleport](https://ru.vuejs.org/guide/built-ins/teleport.html)\n"
|
|
195
195
|
},
|
|
196
196
|
"attributes": [],
|
|
197
197
|
"references": [
|
|
@@ -992,7 +992,7 @@
|
|
|
992
992
|
"name": "v-bind",
|
|
993
993
|
"description": {
|
|
994
994
|
"kind": "markdown",
|
|
995
|
-
"value": "\nДинамически привязывает один или несколько атрибутов или входных параметров компонента к выражению.\n\n- **Сокращённая запись**\n - `:` или `.` (при использовании модификатора `.prop`)\n - Пропуск значения (когда атрибут и связанное значение имеют одинаковое имя)
|
|
995
|
+
"value": "\nДинамически привязывает один или несколько атрибутов или входных параметров компонента к выражению.\n\n- **Сокращённая запись**\n - `:` или `.` (при использовании модификатора `.prop`)\n - Пропуск значения (когда атрибут и связанное значение имеют одинаковое имя) requires 3.4+\n\n- **Ожидает:** `any (если указан аргумент) | Object (без аргумента)`\n\n- **Аргумент:** `attrOrProp (опционально)`\n\n- **Модификаторы**\n\n - `.camel` - преобразование имён атрибутов из kebab-case в camelCase.\n - `.prop` - принудительная установить привязку в качестве свойства DOM (3.2+).\n - `.attr` - принудительно установить привязку в качестве атрибута DOM (3.2+).\n\n- **Применение**\n\n При использовании для привязки атрибутов `class` или `style`, `v-bind` поддерживает дополнительные типы значений, такие как Array или Objects. Более подробная информация приведена в разделе руководства по ссылкам ниже.\n\n Устанавливая привязку к элементу, Vue по умолчанию проверяет, имеет ли элемент ключ, определенный как свойство, используя проверку оператора `in`. Если свойство определено, то Vue установит значение как свойство DOM, а не как атрибут. В большинстве случаев это должно работать, но вы можете переопределить это поведение, явно используя модификаторы `.prop` или `.attr`. Иногда это необходимо, особенно при [работе с пользовательскими элементами](https://ru.vuejs.org/guide/extras/web-components.html#passing-dom-properties).\n\n При привязке входных параметров к дочернему компоненту необходимо также объявлять их внутри него.\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 <!-- привязка входного параметра. \"prop\" должен быть объявлен в my-component. -->\n <MyComponent :prop=\"someThing\" />\n\n <!-- передача всех входных параметров родительского компонента в дочерний -->\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` позволяет приводить имя атрибута `v-bind` в camelCase при использовании DOM-шаблонов, например для атрибута SVG `viewBox`:\n\n ```html\n <svg :view-box.camel=\"viewBox\"></svg>\n ```\n\n Модификатор `.camel` не нужен, если вы используете строковые шаблоны или предварительно компилируете шаблон на этапе сборки.\n\n- **См. также**\n - [Работа с классами и стилями](https://ru.vuejs.org/guide/essentials/class-and-style.html)\n - [Компоненты - Детали передачи входных параметров](https://ru.vuejs.org/guide/components/props.html#prop-passing-details)\n"
|
|
996
996
|
},
|
|
997
997
|
"references": [
|
|
998
998
|
{
|
|
@@ -1299,7 +1299,7 @@
|
|
|
1299
1299
|
"name": "v-memo",
|
|
1300
1300
|
"description": {
|
|
1301
1301
|
"kind": "markdown",
|
|
1302
|
-
"value": "\n- **Ожидает:** `any[]`\n\n- **Подробности**\n\n Мемоизация части поддерева шаблона. Может использоваться как для элементов, так и для компонентов. Директива ожидает массив фиксированной длины зависимых значений, которые станут использоваться для сравнения при мемоизации. Если каждое значение массива осталось таким же, как при последней отрисовке, то обновление всего поддерева будет пропущено. Например:\n\n ```html\n <div v-memo=\"[valueA, valueB]\">\n ...\n </div>\n ```\n\n При повторном рендеринге компонента, если `valueA` и `valueB` остались прежними, все обновления для этого `<div>` и его дочерних элементов будут пропущены. Фактически, будет пропущено даже создание VNode виртуального DOM, поскольку мемоизированная копия поддерева может быть использована повторно.\n\n Важно правильно указать массив мемоизации, иначе мы можем пропустить обновления, которые действительно должны быть применены. `v-memo` с пустым массивом зависимостей (`v-memo=\"[]\"`) будет функционально эквивалентен `v-once`.\n\n **Использование вместе с `v-for`**\n\n `v-memo` предоставляется исключительно для микрооптимизации в критичных к производительности сценариях и может понадобиться крайне редко. Наиболее распространённым случаем, когда это может оказаться полезным, является отрисовка больших списков `v-for` (когда `length > 1000`):\n\n ```html\n <div v-for=\"item in list\" :key=\"item.id\" v-memo=\"[item.id === selected]\">\n <p>ID: {{ item.id }} - выбран: {{ item.id === selected }}</p>\n <p>...больше дочерних элементов</p>\n </div>\n ```\n\n При изменении состояния компонента `selected` будет создано большое количество VNodes, даже если большинство элементов остались прежними. Использование `v-memo` здесь, по сути, говорит: \"обновляйте этот элемент только в том случае, если он перешел из состояния `не выбран` в состояние `выбран`, или наоборот\". Это позволяет каждому незатронутому элементу повторно использовать свой предыдущий VNode и полностью пропустить операцию сравнения. Обратите внимание, что нам не нужно включать `item.id` в массив зависимостей memo, поскольку Vue автоматически определяет его из `:key` элемента.\n\n :::warning Предупреждение\n При использовании `v-memo` с `v-for` убедитесь, что они используются на одном и том же элементе. **`v-memo` не работает внутри `v-for`.**.\n :::\n\n `v-memo` также может быть использовано для компонентов, чтобы вручную предотвратить нежелательные обновления в некоторых крайних случаях, когда проверка обновлений дочерних компонентов была де-оптимизирована. Но, повторимся, ответственность за корректное указание массивов зависимостей во избежание пропуска необходимых обновлений лежит на разработчике.\n\n- **См. также**\n - [v-once](#v-once)\n"
|
|
1302
|
+
"value": "\n- Only supported in 3.2+\n\n- **Ожидает:** `any[]`\n\n- **Подробности**\n\n Мемоизация части поддерева шаблона. Может использоваться как для элементов, так и для компонентов. Директива ожидает массив фиксированной длины зависимых значений, которые станут использоваться для сравнения при мемоизации. Если каждое значение массива осталось таким же, как при последней отрисовке, то обновление всего поддерева будет пропущено. Например:\n\n ```html\n <div v-memo=\"[valueA, valueB]\">\n ...\n </div>\n ```\n\n При повторном рендеринге компонента, если `valueA` и `valueB` остались прежними, все обновления для этого `<div>` и его дочерних элементов будут пропущены. Фактически, будет пропущено даже создание VNode виртуального DOM, поскольку мемоизированная копия поддерева может быть использована повторно.\n\n Важно правильно указать массив мемоизации, иначе мы можем пропустить обновления, которые действительно должны быть применены. `v-memo` с пустым массивом зависимостей (`v-memo=\"[]\"`) будет функционально эквивалентен `v-once`.\n\n **Использование вместе с `v-for`**\n\n `v-memo` предоставляется исключительно для микрооптимизации в критичных к производительности сценариях и может понадобиться крайне редко. Наиболее распространённым случаем, когда это может оказаться полезным, является отрисовка больших списков `v-for` (когда `length > 1000`):\n\n ```html\n <div v-for=\"item in list\" :key=\"item.id\" v-memo=\"[item.id === selected]\">\n <p>ID: {{ item.id }} - выбран: {{ item.id === selected }}</p>\n <p>...больше дочерних элементов</p>\n </div>\n ```\n\n При изменении состояния компонента `selected` будет создано большое количество VNodes, даже если большинство элементов остались прежними. Использование `v-memo` здесь, по сути, говорит: \"обновляйте этот элемент только в том случае, если он перешел из состояния `не выбран` в состояние `выбран`, или наоборот\". Это позволяет каждому незатронутому элементу повторно использовать свой предыдущий VNode и полностью пропустить операцию сравнения. Обратите внимание, что нам не нужно включать `item.id` в массив зависимостей memo, поскольку Vue автоматически определяет его из `:key` элемента.\n\n :::warning Предупреждение\n При использовании `v-memo` с `v-for` убедитесь, что они используются на одном и том же элементе. **`v-memo` не работает внутри `v-for`.**.\n :::\n\n `v-memo` также может быть использовано для компонентов, чтобы вручную предотвратить нежелательные обновления в некоторых крайних случаях, когда проверка обновлений дочерних компонентов была де-оптимизирована. Но, повторимся, ответственность за корректное указание массивов зависимостей во избежание пропуска необходимых обновлений лежит на разработчике.\n\n- **См. также**\n - [v-once](#v-once)\n"
|
|
1303
1303
|
},
|
|
1304
1304
|
"references": [
|
|
1305
1305
|
{
|
|
@@ -1544,7 +1544,7 @@
|
|
|
1544
1544
|
"name": "is",
|
|
1545
1545
|
"description": {
|
|
1546
1546
|
"kind": "markdown",
|
|
1547
|
-
"value": "\nИспользуется для [динамических компонентов](https://ru.vuejs.org/guide/essentials/component-basics.html#dynamic-components).\n\n- **Ожидает** `string | Component`\n\n- **Использование на нативных
|
|
1547
|
+
"value": "\nИспользуется для [динамических компонентов](https://ru.vuejs.org/guide/essentials/component-basics.html#dynamic-components).\n\n- **Ожидает** `string | Component`\n\n- **Использование на нативных элементах**\n \n - Поддерживается только в 3.1+\n\n Когда атрибут `is` используется на нативном HTML-элементе, то он интерпретируется как [пользовательский встроенный элемент](https://html.spec.whatwg.org/multipage/custom-elements#custom-elements-customized-builtin-example). Это нативная возможность веб-платформы.\n\n Однако есть случай использования, когда может понадобиться, чтобы Vue заменил нативный элемент на компонент Vue, как это разъясняется в [Особенности парсинга DOM-шаблона](https://ru.vuejs.org/guide/essentials/component-basics.html#dom-template-parsing-caveats). В таком случае можно добавить значению атрибута `is` префикс `vue:`, чтобы Vue вместо элемента отрисовал компонент Vue:\n\n ```html\n <table>\n <tr is=\"vue:my-row-component\"></tr>\n </table>\n ```\n\n- **См. также**\n\n - [Специальные встроенные элементы - `<component>`](https://ru.vuejs.org/api/built-in-special-elements.html#component)\n - [Динамические компоненты](https://ru.vuejs.org/guide/essentials/component-basics.html#dynamic-components)\n"
|
|
1548
1548
|
},
|
|
1549
1549
|
"references": [
|
|
1550
1550
|
{
|
|
@@ -6,7 +6,7 @@ exports.getNameCasing = getNameCasing;
|
|
|
6
6
|
exports.detect = detect;
|
|
7
7
|
const vue = require("@vue/language-core");
|
|
8
8
|
const language_core_1 = require("@vue/language-core");
|
|
9
|
-
const
|
|
9
|
+
const alien_signals_1 = require("alien-signals");
|
|
10
10
|
const types_1 = require("../types");
|
|
11
11
|
async function convertTagName(context, uri, casing, tsPluginClient) {
|
|
12
12
|
const sourceFile = context.language.scripts.get(uri);
|
|
@@ -17,7 +17,7 @@ async function convertTagName(context, uri, casing, tsPluginClient) {
|
|
|
17
17
|
if (!(rootCode instanceof language_core_1.VueVirtualCode)) {
|
|
18
18
|
return;
|
|
19
19
|
}
|
|
20
|
-
const desc = rootCode.
|
|
20
|
+
const desc = rootCode._sfc;
|
|
21
21
|
if (!desc.template) {
|
|
22
22
|
return;
|
|
23
23
|
}
|
|
@@ -53,7 +53,7 @@ async function convertAttrName(context, uri, casing, tsPluginClient) {
|
|
|
53
53
|
if (!(rootCode instanceof language_core_1.VueVirtualCode)) {
|
|
54
54
|
return;
|
|
55
55
|
}
|
|
56
|
-
const desc = rootCode.
|
|
56
|
+
const desc = rootCode._sfc;
|
|
57
57
|
if (!desc.template) {
|
|
58
58
|
return;
|
|
59
59
|
}
|
|
@@ -134,8 +134,8 @@ async function detect(context, uri) {
|
|
|
134
134
|
}
|
|
135
135
|
function getTagNameCase(file) {
|
|
136
136
|
const result = new Set();
|
|
137
|
-
if (file.
|
|
138
|
-
for (const element of vue.forEachElementNode(file.
|
|
137
|
+
if (file._sfc.template?.ast) {
|
|
138
|
+
for (const element of vue.forEachElementNode(file._sfc.template.ast)) {
|
|
139
139
|
if (element.tagType === 1) {
|
|
140
140
|
if (element.tag !== (0, language_core_1.hyphenateTag)(element.tag)) {
|
|
141
141
|
// TagName
|
|
@@ -155,11 +155,11 @@ async function detect(context, uri) {
|
|
|
155
155
|
const map = new WeakMap();
|
|
156
156
|
function getTemplateTagsAndAttrs(sourceFile) {
|
|
157
157
|
if (!map.has(sourceFile)) {
|
|
158
|
-
const getter = (0,
|
|
158
|
+
const getter = (0, alien_signals_1.computed)(() => {
|
|
159
159
|
if (!(sourceFile instanceof vue.VueVirtualCode)) {
|
|
160
160
|
return;
|
|
161
161
|
}
|
|
162
|
-
const ast = sourceFile.
|
|
162
|
+
const ast = sourceFile._sfc.template?.ast;
|
|
163
163
|
const tags = new Map();
|
|
164
164
|
if (ast) {
|
|
165
165
|
for (const node of vue.forEachElementNode(ast)) {
|
|
@@ -199,6 +199,6 @@ function getTemplateTagsAndAttrs(sourceFile) {
|
|
|
199
199
|
});
|
|
200
200
|
map.set(sourceFile, getter);
|
|
201
201
|
}
|
|
202
|
-
return map.get(sourceFile)() ?? new Map();
|
|
202
|
+
return map.get(sourceFile).get() ?? new Map();
|
|
203
203
|
}
|
|
204
204
|
//# sourceMappingURL=nameCasing.js.map
|
|
@@ -45,7 +45,7 @@ function create(ts, getTsPluginClient) {
|
|
|
45
45
|
let baseName = importUri.substring(importUri.lastIndexOf('/') + 1);
|
|
46
46
|
baseName = baseName.substring(0, baseName.lastIndexOf('.'));
|
|
47
47
|
const newName = (0, shared_1.capitalize)((0, shared_1.camelize)(baseName));
|
|
48
|
-
const { sfc } = vueVirtualCode;
|
|
48
|
+
const { _sfc: sfc } = vueVirtualCode;
|
|
49
49
|
const script = sfc.scriptSetup ?? sfc.script;
|
|
50
50
|
if (!script) {
|
|
51
51
|
return;
|
|
@@ -17,12 +17,12 @@ function create() {
|
|
|
17
17
|
const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
|
|
18
18
|
if (sourceScript?.generated?.root instanceof language_core_1.VueVirtualCode && virtualCode?.id === 'template') {
|
|
19
19
|
const result = [];
|
|
20
|
-
const codegen = language_core_1.tsCodegen.get(sourceScript.generated.root.
|
|
21
|
-
const scopedClasses = codegen?.generatedTemplate()?.scopedClasses ?? [];
|
|
20
|
+
const codegen = language_core_1.tsCodegen.get(sourceScript.generated.root._sfc);
|
|
21
|
+
const scopedClasses = codegen?.generatedTemplate.get()?.scopedClasses ?? [];
|
|
22
22
|
const styleClasses = new Map();
|
|
23
23
|
const option = sourceScript.generated.root.vueCompilerOptions.experimentalResolveStyleCssClasses;
|
|
24
|
-
for (let i = 0; i < sourceScript.generated.root.
|
|
25
|
-
const style = sourceScript.generated.root.
|
|
24
|
+
for (let i = 0; i < sourceScript.generated.root._sfc.styles.length; i++) {
|
|
25
|
+
const style = sourceScript.generated.root._sfc.styles[i];
|
|
26
26
|
if (option === 'always' || (option === 'scoped' && style.scoped)) {
|
|
27
27
|
for (const className of style.classNames) {
|
|
28
28
|
if (!styleClasses.has(className.text.substring(1))) {
|
|
@@ -29,7 +29,7 @@ function create(ts, getTsPluginClient) {
|
|
|
29
29
|
if (!(sourceScript?.generated?.root instanceof language_core_1.VueVirtualCode) || virtualCode?.id !== 'template') {
|
|
30
30
|
return;
|
|
31
31
|
}
|
|
32
|
-
const { sfc } = sourceScript.generated.root;
|
|
32
|
+
const { _sfc: sfc } = sourceScript.generated.root;
|
|
33
33
|
const script = sfc.scriptSetup ?? sfc.script;
|
|
34
34
|
if (!sfc.template || !script) {
|
|
35
35
|
return;
|
|
@@ -62,7 +62,7 @@ function create(ts, getTsPluginClient) {
|
|
|
62
62
|
}
|
|
63
63
|
const document = context.documents.get(parsedUri, virtualCode.languageId, virtualCode.snapshot);
|
|
64
64
|
const sfcDocument = context.documents.get(sourceScript.id, sourceScript.languageId, sourceScript.snapshot);
|
|
65
|
-
const { sfc } = sourceScript.generated.root;
|
|
65
|
+
const { _sfc: sfc } = sourceScript.generated.root;
|
|
66
66
|
const script = sfc.scriptSetup ?? sfc.script;
|
|
67
67
|
if (!sfc.template || !script) {
|
|
68
68
|
return codeAction;
|
|
@@ -4,4 +4,4 @@ export declare function create(ts: typeof import('typescript')): LanguageService
|
|
|
4
4
|
/**
|
|
5
5
|
* Refactored from https://github.com/vuejs/core/blob/main/packages/compiler-sfc/src/script/definePropsDestructure.ts
|
|
6
6
|
*/
|
|
7
|
-
export declare function findDestructuredProps(ts: typeof import('typescript'), ast: ts.SourceFile, props: string
|
|
7
|
+
export declare function findDestructuredProps(ts: typeof import('typescript'), ast: ts.SourceFile, props: Set<string>): [ts.Identifier, boolean][];
|
|
@@ -20,30 +20,34 @@ function create(ts) {
|
|
|
20
20
|
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
|
|
21
21
|
const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
|
|
22
22
|
if (virtualCode instanceof language_core_1.VueVirtualCode) {
|
|
23
|
-
const codegen = language_core_1.tsCodegen.get(virtualCode.
|
|
23
|
+
const codegen = language_core_1.tsCodegen.get(virtualCode._sfc);
|
|
24
24
|
const inlayHints = [
|
|
25
|
-
...codegen?.generatedTemplate()?.inlayHints ?? [],
|
|
26
|
-
...codegen?.generatedScript()?.inlayHints ?? [],
|
|
25
|
+
...codegen?.generatedTemplate.get()?.inlayHints ?? [],
|
|
26
|
+
...codegen?.generatedScript.get()?.inlayHints ?? [],
|
|
27
27
|
];
|
|
28
|
-
const scriptSetupRanges = codegen?.scriptSetupRanges();
|
|
29
|
-
if (scriptSetupRanges?.props.destructured && virtualCode.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
28
|
+
const scriptSetupRanges = codegen?.scriptSetupRanges.get();
|
|
29
|
+
if (scriptSetupRanges?.props.destructured && virtualCode._sfc.scriptSetup?.ast) {
|
|
30
|
+
const setting = 'vue.inlayHints.destructuredProps';
|
|
31
|
+
settings[setting] ??= await context.env.getConfiguration?.(setting) ?? false;
|
|
32
|
+
if (settings[setting]) {
|
|
33
|
+
for (const [prop, isShorthand] of findDestructuredProps(ts, virtualCode._sfc.scriptSetup.ast, scriptSetupRanges.props.destructured)) {
|
|
34
|
+
const name = prop.text;
|
|
35
|
+
const end = prop.getEnd();
|
|
36
|
+
const pos = isShorthand ? end : end - name.length;
|
|
37
|
+
const label = isShorthand ? `: props.${name}` : 'props.';
|
|
38
|
+
inlayHints.push({
|
|
39
|
+
blockName: 'scriptSetup',
|
|
40
|
+
offset: pos,
|
|
41
|
+
setting,
|
|
42
|
+
label,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
41
45
|
}
|
|
42
46
|
}
|
|
43
47
|
const blocks = [
|
|
44
|
-
virtualCode.
|
|
45
|
-
virtualCode.
|
|
46
|
-
virtualCode.
|
|
48
|
+
virtualCode._sfc.template,
|
|
49
|
+
virtualCode._sfc.script,
|
|
50
|
+
virtualCode._sfc.scriptSetup,
|
|
47
51
|
];
|
|
48
52
|
const start = document.offsetAt(range.start);
|
|
49
53
|
const end = document.offsetAt(range.end);
|
|
@@ -79,7 +83,7 @@ function create(ts) {
|
|
|
79
83
|
* Refactored from https://github.com/vuejs/core/blob/main/packages/compiler-sfc/src/script/definePropsDestructure.ts
|
|
80
84
|
*/
|
|
81
85
|
function findDestructuredProps(ts, ast, props) {
|
|
82
|
-
const rootScope =
|
|
86
|
+
const rootScope = Object.create(null);
|
|
83
87
|
const scopeStack = [rootScope];
|
|
84
88
|
let currentScope = rootScope;
|
|
85
89
|
const excludedIds = new WeakSet();
|
|
@@ -135,7 +139,7 @@ function findDestructuredProps(ts, ast, props) {
|
|
|
135
139
|
&& initializer
|
|
136
140
|
&& ts.isCallExpression(initializer)
|
|
137
141
|
&& initializer.expression.getText(ast) === 'defineProps';
|
|
138
|
-
for (const id of (0, common_1.collectIdentifiers)(ts, name)) {
|
|
142
|
+
for (const [id] of (0, common_1.collectIdentifiers)(ts, name)) {
|
|
139
143
|
if (isDefineProps) {
|
|
140
144
|
excludedIds.add(id);
|
|
141
145
|
}
|
|
@@ -150,7 +154,7 @@ function findDestructuredProps(ts, ast, props) {
|
|
|
150
154
|
registerLocalBinding(name);
|
|
151
155
|
}
|
|
152
156
|
for (const p of parameters) {
|
|
153
|
-
for (const id of (0, common_1.collectIdentifiers)(ts, p)) {
|
|
157
|
+
for (const [id] of (0, common_1.collectIdentifiers)(ts, p)) {
|
|
154
158
|
registerLocalBinding(id);
|
|
155
159
|
}
|
|
156
160
|
}
|
package/lib/plugins/vue-sfc.js
CHANGED
|
@@ -19,7 +19,7 @@ function create() {
|
|
|
19
19
|
return await worker(document, context, async (vueCode) => {
|
|
20
20
|
const formatSettings = await context.env.getConfiguration?.('html.format') ?? {};
|
|
21
21
|
const blockTypes = ['template', 'script', 'style'];
|
|
22
|
-
for (const customBlock of vueCode.
|
|
22
|
+
for (const customBlock of vueCode._sfc.customBlocks) {
|
|
23
23
|
blockTypes.push(customBlock.type);
|
|
24
24
|
}
|
|
25
25
|
return {
|
|
@@ -66,7 +66,7 @@ function create() {
|
|
|
66
66
|
provideDocumentSymbols(document) {
|
|
67
67
|
return worker(document, context, vueSourceFile => {
|
|
68
68
|
const result = [];
|
|
69
|
-
const descriptor = vueSourceFile.
|
|
69
|
+
const descriptor = vueSourceFile._sfc;
|
|
70
70
|
if (descriptor.template) {
|
|
71
71
|
result.push({
|
|
72
72
|
name: 'template',
|
|
@@ -280,7 +280,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
280
280
|
return;
|
|
281
281
|
}
|
|
282
282
|
const templateErrors = [];
|
|
283
|
-
const { template } = code.
|
|
283
|
+
const { template } = code._sfc;
|
|
284
284
|
if (template) {
|
|
285
285
|
for (const error of template.errors) {
|
|
286
286
|
onCompilerError(error, 1);
|
|
@@ -327,10 +327,10 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
327
327
|
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
|
|
328
328
|
if (!sourceScript
|
|
329
329
|
|| !(sourceScript.generated?.root instanceof language_core_1.VueVirtualCode)
|
|
330
|
-
|| !sourceScript.generated.root.
|
|
330
|
+
|| !sourceScript.generated.root._sfc.template) {
|
|
331
331
|
return [];
|
|
332
332
|
}
|
|
333
|
-
const { template } = sourceScript.generated.root.
|
|
333
|
+
const { template } = sourceScript.generated.root._sfc;
|
|
334
334
|
const spans = common_1.getComponentSpans.call({
|
|
335
335
|
files: context.language.scripts,
|
|
336
336
|
languageService,
|
|
@@ -397,8 +397,8 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
397
397
|
})());
|
|
398
398
|
return [];
|
|
399
399
|
}
|
|
400
|
-
const scriptSetupRanges = vueCode.
|
|
401
|
-
? (0, language_core_1.parseScriptSetupRanges)(ts, vueCode.
|
|
400
|
+
const scriptSetupRanges = vueCode._sfc.scriptSetup
|
|
401
|
+
? (0, language_core_1.parseScriptSetupRanges)(ts, vueCode._sfc.scriptSetup.ast, vueCompilerOptions)
|
|
402
402
|
: undefined;
|
|
403
403
|
const names = new Set();
|
|
404
404
|
const tags = [];
|
|
@@ -411,7 +411,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
411
411
|
}
|
|
412
412
|
}
|
|
413
413
|
for (const binding of scriptSetupRanges?.bindings ?? []) {
|
|
414
|
-
const name = vueCode.
|
|
414
|
+
const name = vueCode._sfc.scriptSetup.content.substring(binding.start, binding.end);
|
|
415
415
|
if (casing.tag === types_1.TagNameCasing.Kebab) {
|
|
416
416
|
names.add((0, language_core_1.hyphenateTag)(name));
|
|
417
417
|
}
|
|
@@ -446,7 +446,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
446
446
|
const { attrs, propsInfo, events } = tagInfo;
|
|
447
447
|
const props = propsInfo.map(prop => prop.name);
|
|
448
448
|
const attributes = [];
|
|
449
|
-
const _tsCodegen = language_core_1.tsCodegen.get(vueCode.
|
|
449
|
+
const _tsCodegen = language_core_1.tsCodegen.get(vueCode._sfc);
|
|
450
450
|
if (_tsCodegen) {
|
|
451
451
|
if (!templateContextProps) {
|
|
452
452
|
promises.push((async () => {
|
|
@@ -456,8 +456,8 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
456
456
|
return [];
|
|
457
457
|
}
|
|
458
458
|
let ctxVars = [
|
|
459
|
-
..._tsCodegen.scriptRanges()?.bindings.map(binding => vueCode.
|
|
460
|
-
..._tsCodegen.scriptSetupRanges()?.bindings.map(binding => vueCode.
|
|
459
|
+
..._tsCodegen.scriptRanges.get()?.bindings.map(binding => vueCode._sfc.script.content.substring(binding.start, binding.end)) ?? [],
|
|
460
|
+
..._tsCodegen.scriptSetupRanges.get()?.bindings.map(binding => vueCode._sfc.scriptSetup.content.substring(binding.start, binding.end)) ?? [],
|
|
461
461
|
...templateContextProps,
|
|
462
462
|
];
|
|
463
463
|
ctxVars = [...new Set(ctxVars)];
|
|
@@ -616,7 +616,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
616
616
|
}
|
|
617
617
|
}
|
|
618
618
|
}
|
|
619
|
-
completionList.items = completionList.items.filter(item => !specialTags.has(item.label));
|
|
619
|
+
completionList.items = completionList.items.filter(item => !specialTags.has(parseLabel(item.label).name));
|
|
620
620
|
const htmlDocumentations = new Map();
|
|
621
621
|
for (const item of completionList.items) {
|
|
622
622
|
const documentation = typeof item.documentation === 'string' ? item.documentation : item.documentation?.value;
|
|
@@ -628,7 +628,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
628
628
|
const resolvedLabelKey = resolveItemKey(item.label);
|
|
629
629
|
if (resolvedLabelKey) {
|
|
630
630
|
const name = resolvedLabelKey.tag;
|
|
631
|
-
item.label = name;
|
|
631
|
+
item.label = resolvedLabelKey.leadingSlash ? '/' + name : name;
|
|
632
632
|
if (item.textEdit) {
|
|
633
633
|
item.textEdit.newText = name;
|
|
634
634
|
}
|
|
@@ -678,6 +678,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
678
678
|
type: 'componentProp',
|
|
679
679
|
tag: '^',
|
|
680
680
|
prop: propName,
|
|
681
|
+
leadingSlash: false
|
|
681
682
|
};
|
|
682
683
|
}
|
|
683
684
|
if (tsDocumentations.has(propName)) {
|
|
@@ -809,6 +810,14 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
809
810
|
}
|
|
810
811
|
}
|
|
811
812
|
;
|
|
813
|
+
function parseLabel(label) {
|
|
814
|
+
const leadingSlash = label.startsWith('/');
|
|
815
|
+
const name = label.slice(leadingSlash ? 1 : 0);
|
|
816
|
+
return {
|
|
817
|
+
name,
|
|
818
|
+
leadingSlash
|
|
819
|
+
};
|
|
820
|
+
}
|
|
812
821
|
function parseItemKey(type, tag, prop) {
|
|
813
822
|
return '__VLS_data=' + type + ',' + tag + ',' + prop;
|
|
814
823
|
}
|
|
@@ -816,12 +825,14 @@ function isItemKey(key) {
|
|
|
816
825
|
return key.startsWith('__VLS_data=');
|
|
817
826
|
}
|
|
818
827
|
function resolveItemKey(key) {
|
|
819
|
-
|
|
820
|
-
|
|
828
|
+
const { leadingSlash, name } = parseLabel(key);
|
|
829
|
+
if (isItemKey(name)) {
|
|
830
|
+
const strs = name.slice('__VLS_data='.length).split(',');
|
|
821
831
|
return {
|
|
822
832
|
type: strs[0],
|
|
823
833
|
tag: strs[1],
|
|
824
834
|
prop: strs[2],
|
|
835
|
+
leadingSlash
|
|
825
836
|
};
|
|
826
837
|
}
|
|
827
838
|
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vue/language-service",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.8",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"files": [
|
|
6
6
|
"data",
|
|
7
7
|
"**/*.js",
|
|
8
8
|
"**/*.d.ts"
|
|
9
9
|
],
|
|
10
|
+
"sideEffects": false,
|
|
10
11
|
"repository": {
|
|
11
12
|
"type": "git",
|
|
12
13
|
"url": "https://github.com/vuejs/language-tools.git",
|
|
@@ -16,14 +17,14 @@
|
|
|
16
17
|
"update-html-data": "node ./scripts/update-html-data.js"
|
|
17
18
|
},
|
|
18
19
|
"dependencies": {
|
|
19
|
-
"@volar/language-core": "~2.4.
|
|
20
|
-
"@volar/language-service": "~2.4.
|
|
21
|
-
"@volar/typescript": "~2.4.
|
|
22
|
-
"@vue/compiler-dom": "^3.
|
|
23
|
-
"@vue/language-core": "2.1.
|
|
24
|
-
"@vue/shared": "^3.
|
|
25
|
-
"@vue/typescript-plugin": "2.1.
|
|
26
|
-
"
|
|
20
|
+
"@volar/language-core": "~2.4.8",
|
|
21
|
+
"@volar/language-service": "~2.4.8",
|
|
22
|
+
"@volar/typescript": "~2.4.8",
|
|
23
|
+
"@vue/compiler-dom": "^3.5.0",
|
|
24
|
+
"@vue/language-core": "2.1.8",
|
|
25
|
+
"@vue/shared": "^3.5.0",
|
|
26
|
+
"@vue/typescript-plugin": "2.1.8",
|
|
27
|
+
"alien-signals": "^0.2.0",
|
|
27
28
|
"path-browserify": "^1.0.1",
|
|
28
29
|
"volar-service-css": "0.0.62",
|
|
29
30
|
"volar-service-emmet": "0.0.62",
|
|
@@ -40,8 +41,8 @@
|
|
|
40
41
|
"devDependencies": {
|
|
41
42
|
"@types/node": "latest",
|
|
42
43
|
"@types/path-browserify": "latest",
|
|
43
|
-
"@volar/kit": "~2.4.
|
|
44
|
+
"@volar/kit": "~2.4.8",
|
|
44
45
|
"vscode-languageserver-protocol": "^3.17.5"
|
|
45
46
|
},
|
|
46
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "25cccedc53e7361ed4e34296d6ecd43d7de2a095"
|
|
47
48
|
}
|