@vue/language-service 2.1.4 → 2.1.6
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
CHANGED
|
@@ -992,7 +992,7 @@
|
|
|
992
992
|
"name": "v-bind",
|
|
993
993
|
"description": {
|
|
994
994
|
"kind": "markdown",
|
|
995
|
-
"value": "\nDynamicky váže jeden nebo více atributů nebo vlastností (props) komponenty na výraz.\n\n- **Zkratka:** \n - `:` nebo `.` (pokud se používá modifikátor `.prop`)\n - Vynechání hodnoty (pokud mají atribut a vázaná hodnota stejný název)
|
|
995
|
+
"value": "\nDynamicky váže jeden nebo více atributů nebo vlastností (props) komponenty na výraz.\n\n- **Zkratka:** \n - `:` nebo `.` (pokud se používá modifikátor `.prop`)\n - Vynechání hodnoty (pokud mají atribut a vázaná hodnota stejný název), podporováno až od verze 3.4+\n\n- **Očekává:** `libovolný (s parametrem) | Objekt (bez parametru)`\n\n- **Parametr:** `attrOrProp (volitelné)`\n\n- **Modifikátory**\n\n - `.camel` - převede název atributu z kebab-case na camelCase.\n - `.prop` - vynutí binding jako vlastnost (prop) DOM (3.2+).\n - `.attr` - vynutí binding jako atribut DOM (3.2+).\n\n- **Použití**\n\n Pokud se používá pro binding atributu `class` nebo `style`, `v-bind` podporuje další typy hodnot, jako jsou pole nebo objekty. Podrobnosti naleznete v příslušné části průvodce níže.\n\n Při nastavování bindingu na element Vue ve výchozím nastavení kontroluje, zda má element klíč definovaný jako vlastnost pomocí operátoru `in`. Pokud je vlastnost definována, Vue nastaví hodnotu jako vlastnost DOM místo atributu. To by mělo fungovat ve většině případů, ale toto chování můžete přepsat explicitním použitím modifikátorů `.prop` nebo `.attr`. To je někdy nutné, zejména při [práci s custom elementy](https://cs.vuejs.org/guide/extras/web-components.html#passing-dom-properties).\n\n Při použití pro binding vlastností (props) komponenty musí být vlastnost v komponentě potomka správně deklarována.\n\n Pokud se používá bez parametru, může být použito pro binding objektu obsahujícího páry název-hodnota atributu.\n\n- **Příklad**\n\n ```html\n <!-- binding atributu -->\n <img v-bind:src=\"imageSrc\" />\n\n <!-- dynamický název atributu -->\n <button v-bind:[key]=\"value\"></button>\n\n <!-- zkratka -->\n <img :src=\"imageSrc\" />\n\n <!-- zkratka stejného názvu (3.4+), bude rozšířeno na :src=\"src\" -->\n <img :src />\n\n <!-- zkratka s dynamickým názvem atributu -->\n <button :[key]=\"value\"></button>\n\n <!-- se spojením řetězců -->\n <img :src=\"'/path/to/images/' + fileName\" />\n\n <!-- binding třídy -->\n <div :class=\"{ red: isRed }\"></div>\n <div :class=\"[classA, classB]\"></div>\n <div :class=\"[classA, { classB: isB, classC: isC }]\"></div>\n\n <!-- binding stylů -->\n <div :style=\"{ fontSize: size + 'px' }\"></div>\n <div :style=\"[styleObjectA, styleObjectB]\"></div>\n\n <!-- binding objektu attributů -->\n <div v-bind=\"{ id: someProp, 'other-attr': otherProp }\"></div>\n\n <!-- binding vlastnosti, `prop` musí být deklarována v komponentě potomka -->\n <MyComponent :prop=\"someThing\" />\n\n <!-- předání props z rodiče, které jsou společné s komponentnou potomka -->\n <MyComponent v-bind=\"$props\" />\n\n <!-- XLink -->\n <svg><a :xlink:special=\"foo\"></a></svg>\n ```\n\nModifikátor `.prop` má také zkrácenou formu, `.`:\n\n```html\n<div :someProperty.prop=\"someObject\"></div>\n\n<!-- ekvivalentní zápis -->\n<div .someProperty=\"someObject\"></div>\n```\n\nModifikátor `.camel` umožňuje převést jméno atributu `v-bind` na camelCase, například atribut `viewBox` ve SVG:\n\n```html\n<svg :view-box.camel=\"viewBox\"></svg>\n```\n\n`.camel` není potřeba, pokud používáte řetězcové šablony nebo předkompilujete šablonu pomocí build fáze.\n\n- **Viz také:**\n - [Binding tříd a stylů](https://cs.vuejs.org/guide/essentials/class-and-style.html)\n - [Vlastnosti (Props) - Detaily předávání vlastností](https://cs.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- **Očekává:** `any[]`\n\n- **Podrobnosti**\n\n Uloží si (memoize) podstrom šablony. Může být použito jak na elementech, tak na komponentách. Direktiva očekává pole hodnot závislostí pevné délky, které se porovnávají pro zapamatování. Pokud každá hodnota v poli byla stejná jako při posledním vykreslení, aktualizace pro celý podstrom bude přeskočena. Například:\n\n ```html\n <div v-memo=\"[hodnotaA, hodnotaB]\">\n ...\n </div>\n ```\n\n Pokud při opětovném vykreslení komponenty zůstanou jak `hodnotaA`, tak `hodnotaB` stejné, všechny aktualizace pro tento `<div>` a jeho potomky budou přeskočeny. Ve skutečnosti bude přeskočeno i vytváření Virtual DOM VNode, protože memoizovaná kopie podstromu může být znovu použita.\n\n Je důležité správně specifikovat pole pro zapamatování, jinak můžeme přeskočit aktualizace, které by aplikovány být měly. `v-memo` s prázdným polem závislostí (`v-memo=\"[]\"`) by bylo funkčně ekvivalentní `v-once`.\n\n **Použití s `v-for`**\n\n `v-memo` je poskytováno výhradně pro mikrooptimalizace výkonu a je potřeba jen zřídka. Nejběžnější případ, kdy se to může hodit, je při vykreslování velkých seznamů `v-for` (kde `length > 1000`):\n\n ```html\n <div v-for=\"prvek in seznam\" :key=\"prvek.id\" v-memo=\"[prvek.id === vybrano]\">\n <p>ID: {{ prvek.id }} - vybráno: {{ prvek.id === vybrano }}</p>\n <p>...další potomci</p>\n </div>\n ```\n\n Při změně stavu `vybrano` komponenty bude vytvořeno velké množství VNodes, i když většina položek zůstala přesně stejná. Použití `v-memo` zde znamená _„aktualizujte tuto položku pouze tehdy, pokud se změnila z nevybrané na vybranou nebo naopak“_. To umožňuje každé neovlivněné položce znovu použít její předchozí VNode a úplně přeskočit porovnávání rozdílů. Poznamenejme, že zde do pole závislostí pro zapamatování nemusíme zahrnout `prvek.id`, protože Vue ji automaticky odvodí z `:key` položky.\n\n :::warning Varování\n Při použití `v-memo` s `v-for` se ujistěte, že jsou použity na stejném elementu. **`v-memo` nefunguje uvnitř `v-for`.**\n :::\n\n `v-memo` lze také použít na komponentách k manuálnímu zabránění nechtěným aktualizacím v určitých okrajových případech, kdy byla kontrola aktualizace potomka de-optimalizována. Ale opět je zodpovědností vývojáře specifikovat správné pole závislostí, aby se zabránilo vynechání nutných aktualizací.\n\n- **Viz také:**\n - [v-once](#v-once)\n"
|
|
1302
|
+
"value": "\n- Podporováno až od verze 3.2+\n\n- **Očekává:** `any[]`\n\n- **Podrobnosti**\n\n Uloží si (memoize) podstrom šablony. Může být použito jak na elementech, tak na komponentách. Direktiva očekává pole hodnot závislostí pevné délky, které se porovnávají pro zapamatování. Pokud každá hodnota v poli byla stejná jako při posledním vykreslení, aktualizace pro celý podstrom bude přeskočena. Například:\n\n ```html\n <div v-memo=\"[hodnotaA, hodnotaB]\">\n ...\n </div>\n ```\n\n Pokud při opětovném vykreslení komponenty zůstanou jak `hodnotaA`, tak `hodnotaB` stejné, všechny aktualizace pro tento `<div>` a jeho potomky budou přeskočeny. Ve skutečnosti bude přeskočeno i vytváření Virtual DOM VNode, protože memoizovaná kopie podstromu může být znovu použita.\n\n Je důležité správně specifikovat pole pro zapamatování, jinak můžeme přeskočit aktualizace, které by aplikovány být měly. `v-memo` s prázdným polem závislostí (`v-memo=\"[]\"`) by bylo funkčně ekvivalentní `v-once`.\n\n **Použití s `v-for`**\n\n `v-memo` je poskytováno výhradně pro mikrooptimalizace výkonu a je potřeba jen zřídka. Nejběžnější případ, kdy se to může hodit, je při vykreslování velkých seznamů `v-for` (kde `length > 1000`):\n\n ```html\n <div v-for=\"prvek in seznam\" :key=\"prvek.id\" v-memo=\"[prvek.id === vybrano]\">\n <p>ID: {{ prvek.id }} - vybráno: {{ prvek.id === vybrano }}</p>\n <p>...další potomci</p>\n </div>\n ```\n\n Při změně stavu `vybrano` komponenty bude vytvořeno velké množství VNodes, i když většina položek zůstala přesně stejná. Použití `v-memo` zde znamená _„aktualizujte tuto položku pouze tehdy, pokud se změnila z nevybrané na vybranou nebo naopak“_. To umožňuje každé neovlivněné položce znovu použít její předchozí VNode a úplně přeskočit porovnávání rozdílů. Poznamenejme, že zde do pole závislostí pro zapamatování nemusíme zahrnout `prvek.id`, protože Vue ji automaticky odvodí z `:key` položky.\n\n :::warning Varování\n Při použití `v-memo` s `v-for` se ujistěte, že jsou použity na stejném elementu. **`v-memo` nefunguje uvnitř `v-for`.**\n :::\n\n `v-memo` lze také použít na komponentách k manuálnímu zabránění nechtěným aktualizacím v určitých okrajových případech, kdy byla kontrola aktualizace potomka de-optimalizována. Ale opět je zodpovědností vývojáře specifikovat správné pole závislostí, aby se zabránilo vynechání nutných aktualizací.\n\n- **Viz také:**\n - [v-once](#v-once)\n"
|
|
1303
1303
|
},
|
|
1304
1304
|
"references": [
|
|
1305
1305
|
{
|
package/data/template/en.json
CHANGED
|
@@ -191,7 +191,7 @@
|
|
|
191
191
|
"name": "Teleport",
|
|
192
192
|
"description": {
|
|
193
193
|
"kind": "markdown",
|
|
194
|
-
"value": "\nRenders its slot content to another part of the DOM.\n\n- **Props**\n\n ```ts\n interface TeleportProps {\n /**\n * Required. Specify target container.\n * Can either be a selector or an actual element.\n */\n to: string | HTMLElement\n /**\n * When `true`, the content will remain in its original\n * location instead of moved into the target container.\n * Can be changed dynamically.\n */\n disabled?: boolean\n }\n ```\n\n- **Example**\n\n Specifying target container:\n\n ```html\n <Teleport to=\"#some-id\" />\n <Teleport to=\".some-class\" />\n <Teleport to=\"[data-teleport]\" />\n ```\n\n Conditionally disabling:\n\n ```html\n <Teleport to=\"#popup\" :disabled=\"displayVideoInline\">\n <video src=\"./my-movie.mp4\">\n </Teleport>\n ```\n\n- **See also** [Guide - Teleport](https://vuejs.org/guide/built-ins/teleport.html)\n"
|
|
194
|
+
"value": "\nRenders its slot content to another part of the DOM.\n\n- **Props**\n\n ```ts\n interface TeleportProps {\n /**\n * Required. Specify target container.\n * Can either be a selector or an actual element.\n */\n to: string | HTMLElement\n /**\n * When `true`, the content will remain in its original\n * location instead of moved into the target container.\n * Can be changed dynamically.\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- **Example**\n\n Specifying target container:\n\n ```html\n <Teleport to=\"#some-id\" />\n <Teleport to=\".some-class\" />\n <Teleport to=\"[data-teleport]\" />\n ```\n\n Conditionally disabling:\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- **See also** [Guide - Teleport](https://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": "\nDynamically bind one or more attributes, or a component prop to an expression.\n\n- **Shorthand:**\n - `:` or `.` (when using `.prop` modifier)\n - Omitting value (when attribute and bound value has the same name
|
|
995
|
+
"value": "\nDynamically bind one or more attributes, or a component prop to an expression.\n\n- **Shorthand:**\n - `:` or `.` (when using `.prop` modifier)\n - Omitting value (when attribute and bound value has the same name, requires 3.4+)\n\n- **Expects:** `any (with argument) | Object (without argument)`\n\n- **Argument:** `attrOrProp (optional)`\n\n- **Modifiers**\n\n - `.camel` - transform the kebab-case attribute name into camelCase.\n - `.prop` - force a binding to be set as a DOM property (3.2+).\n - `.attr` - force a binding to be set as a DOM attribute (3.2+).\n\n- **Usage**\n\n When used to bind the `class` or `style` attribute, `v-bind` supports additional value types such as Array or Objects. See linked guide section below for more details.\n\n When setting a binding on an element, Vue by default checks whether the element has the key defined as a property using an `in` operator check. If the property is defined, Vue will set the value as a DOM property instead of an attribute. This should work in most cases, but you can override this behavior by explicitly using `.prop` or `.attr` modifiers. This is sometimes necessary, especially when [working with custom elements](https://vuejs.org/guide/extras/web-components.html#passing-dom-properties).\n\n When used for component prop binding, the prop must be properly declared in the child component.\n\n When used without an argument, can be used to bind an object containing attribute name-value pairs.\n\n- **Example**\n\n ```html\n <!-- bind an attribute -->\n <img v-bind:src=\"imageSrc\" />\n\n <!-- dynamic attribute name -->\n <button v-bind:[key]=\"value\"></button>\n\n <!-- shorthand -->\n <img :src=\"imageSrc\" />\n\n <!-- same-name shorthand (3.4+), expands to :src=\"src\" -->\n <img :src />\n\n <!-- shorthand dynamic attribute name -->\n <button :[key]=\"value\"></button>\n\n <!-- with inline string concatenation -->\n <img :src=\"'/path/to/images/' + fileName\" />\n\n <!-- class binding -->\n <div :class=\"{ red: isRed }\"></div>\n <div :class=\"[classA, classB]\"></div>\n <div :class=\"[classA, { classB: isB, classC: isC }]\"></div>\n\n <!-- style binding -->\n <div :style=\"{ fontSize: size + 'px' }\"></div>\n <div :style=\"[styleObjectA, styleObjectB]\"></div>\n\n <!-- binding an object of attributes -->\n <div v-bind=\"{ id: someProp, 'other-attr': otherProp }\"></div>\n\n <!-- prop binding. \"prop\" must be declared in the child component. -->\n <MyComponent :prop=\"someThing\" />\n\n <!-- pass down parent props in common with a child component -->\n <MyComponent v-bind=\"$props\" />\n\n <!-- XLink -->\n <svg><a :xlink:special=\"foo\"></a></svg>\n ```\n\n The `.prop` modifier also has a dedicated shorthand, `.`:\n\n ```html\n <div :someProperty.prop=\"someObject\"></div>\n\n <!-- equivalent to -->\n <div .someProperty=\"someObject\"></div>\n ```\n\n The `.camel` modifier allows camelizing a `v-bind` attribute name when using in-DOM templates, e.g. the SVG `viewBox` attribute:\n\n ```html\n <svg :view-box.camel=\"viewBox\"></svg>\n ```\n\n `.camel` is not needed if you are using string templates, or pre-compiling the template with a build step.\n\n- **See also**\n - [Class and Style Bindings](https://vuejs.org/guide/essentials/class-and-style.html)\n - [Components - Prop Passing Details](https://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- **Expects:** `any[]`\n\n- **Details**\n\n Memoize a sub-tree of the template. Can be used on both elements and components. The directive expects a fixed-length array of dependency values to compare for the memoization. If every value in the array was the same as last render, then updates for the entire sub-tree will be skipped. For example:\n\n ```html\n <div v-memo=\"[valueA, valueB]\">\n ...\n </div>\n ```\n\n When the component re-renders, if both `valueA` and `valueB` remain the same, all updates for this `<div>` and its children will be skipped. In fact, even the Virtual DOM VNode creation will also be skipped since the memoized copy of the sub-tree can be reused.\n\n It is important to specify the memoization array correctly, otherwise we may skip updates that should indeed be applied. `v-memo` with an empty dependency array (`v-memo=\"[]\"`) would be functionally equivalent to `v-once`.\n\n **Usage with `v-for`**\n\n `v-memo` is provided solely for micro optimizations in performance-critical scenarios and should be rarely needed. The most common case where this may prove helpful is when rendering large `v-for` lists (where `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 }} - selected: {{ item.id === selected }}</p>\n <p>...more child nodes</p>\n </div>\n ```\n\n When the component's `selected` state changes, a large amount of VNodes will be created even though most of the items remained exactly the same. The `v-memo` usage here is essentially saying \"only update this item if it went from non-selected to selected, or the other way around\". This allows every unaffected item to reuse its previous VNode and skip diffing entirely. Note we don't need to include `item.id` in the memo dependency array here since Vue automatically infers it from the item's `:key`.\n\n :::warning\n When using `v-memo` with `v-for`, make sure they are used on the same element. **`v-memo` does not work inside `v-for`.**\n :::\n\n `v-memo` can also be used on components to manually prevent unwanted updates in certain edge cases where the child component update check has been de-optimized. But again, it is the developer's responsibility to specify correct dependency arrays to avoid skipping necessary updates.\n\n- **See also**\n - [v-once](#v-once)\n"
|
|
1302
|
+
"value": "\n- Only supported in 3.2+\n\n- **Expects:** `any[]`\n\n- **Details**\n\n Memoize a sub-tree of the template. Can be used on both elements and components. The directive expects a fixed-length array of dependency values to compare for the memoization. If every value in the array was the same as last render, then updates for the entire sub-tree will be skipped. For example:\n\n ```html\n <div v-memo=\"[valueA, valueB]\">\n ...\n </div>\n ```\n\n When the component re-renders, if both `valueA` and `valueB` remain the same, all updates for this `<div>` and its children will be skipped. In fact, even the Virtual DOM VNode creation will also be skipped since the memoized copy of the sub-tree can be reused.\n\n It is important to specify the memoization array correctly, otherwise we may skip updates that should indeed be applied. `v-memo` with an empty dependency array (`v-memo=\"[]\"`) would be functionally equivalent to `v-once`.\n\n **Usage with `v-for`**\n\n `v-memo` is provided solely for micro optimizations in performance-critical scenarios and should be rarely needed. The most common case where this may prove helpful is when rendering large `v-for` lists (where `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 }} - selected: {{ item.id === selected }}</p>\n <p>...more child nodes</p>\n </div>\n ```\n\n When the component's `selected` state changes, a large amount of VNodes will be created even though most of the items remained exactly the same. The `v-memo` usage here is essentially saying \"only update this item if it went from non-selected to selected, or the other way around\". This allows every unaffected item to reuse its previous VNode and skip diffing entirely. Note we don't need to include `item.id` in the memo dependency array here since Vue automatically infers it from the item's `:key`.\n\n :::warning\n When using `v-memo` with `v-for`, make sure they are used on the same element. **`v-memo` does not work inside `v-for`.**\n :::\n\n `v-memo` can also be used on components to manually prevent unwanted updates in certain edge cases where the child component update check has been de-optimized. But again, it is the developer's responsibility to specify correct dependency arrays to avoid skipping necessary updates.\n\n- **See also**\n - [v-once](#v-once)\n"
|
|
1303
1303
|
},
|
|
1304
1304
|
"references": [
|
|
1305
1305
|
{
|
|
@@ -65,7 +65,7 @@ async function convertAttrName(context, uri, casing, tsPluginClient) {
|
|
|
65
65
|
for (const [tagName, { attrs }] of tags) {
|
|
66
66
|
const componentName = components.find(component => component === tagName || (0, language_core_1.hyphenateTag)(component) === tagName);
|
|
67
67
|
if (componentName) {
|
|
68
|
-
const props = await tsPluginClient?.getComponentProps(rootCode.fileName, componentName) ?? [];
|
|
68
|
+
const props = (await tsPluginClient?.getComponentProps(rootCode.fileName, componentName) ?? []).map(prop => prop.name);
|
|
69
69
|
for (const [attrName, { offsets }] of attrs) {
|
|
70
70
|
const propName = props.find(prop => prop === attrName || (0, language_core_1.hyphenateAttr)(prop) === attrName);
|
|
71
71
|
if (propName) {
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.create = create;
|
|
4
4
|
const language_core_1 = require("@vue/language-core");
|
|
5
5
|
const shared_1 = require("@vue/shared");
|
|
6
|
-
const
|
|
6
|
+
const path_browserify_1 = require("path-browserify");
|
|
7
7
|
const getUserPreferences_1 = require("volar-service-typescript/lib/configs/getUserPreferences");
|
|
8
8
|
const vscode_uri_1 = require("vscode-uri");
|
|
9
9
|
const vue_extract_file_1 = require("../plugins/vue-extract-file");
|
|
@@ -67,7 +67,7 @@ function create(ts, getTsPluginClient) {
|
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
if (!importPath) {
|
|
70
|
-
importPath =
|
|
70
|
+
importPath = path_browserify_1.posix.relative(path_browserify_1.posix.dirname(vueVirtualCode.fileName), incomingFileName)
|
|
71
71
|
|| importUri.substring(importUri.lastIndexOf('/') + 1);
|
|
72
72
|
if (!importPath.startsWith('./') && !importPath.startsWith('../')) {
|
|
73
73
|
importPath = './' + importPath;
|
|
@@ -19,6 +19,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
19
19
|
let customData = [];
|
|
20
20
|
let extraCustomData = [];
|
|
21
21
|
let lastCompletionComponentNames = new Set();
|
|
22
|
+
const tsDocumentations = new Map();
|
|
22
23
|
const onDidChangeCustomDataListeners = new Set();
|
|
23
24
|
const onDidChangeCustomData = (listener) => {
|
|
24
25
|
onDidChangeCustomDataListeners.add(listener);
|
|
@@ -182,7 +183,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
182
183
|
? tagName
|
|
183
184
|
: components.find(component => component === tagName || (0, language_core_1.hyphenateTag)(component) === tagName);
|
|
184
185
|
if (checkTag) {
|
|
185
|
-
componentProps[checkTag] ??= await tsPluginClient?.getComponentProps(code.fileName, checkTag, true) ?? [];
|
|
186
|
+
componentProps[checkTag] ??= (await tsPluginClient?.getComponentProps(code.fileName, checkTag, true) ?? []).map(prop => prop.name);
|
|
186
187
|
current = {
|
|
187
188
|
unburnedRequiredProps: [...componentProps[checkTag]],
|
|
188
189
|
labelOffset: scanner.getTokenOffset() + scanner.getTokenLength(),
|
|
@@ -357,11 +358,11 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
357
358
|
const casing = await (0, nameCasing_1.getNameCasing)(context, sourceDocumentUri);
|
|
358
359
|
if (builtInData.tags) {
|
|
359
360
|
for (const tag of builtInData.tags) {
|
|
360
|
-
if (
|
|
361
|
+
if (isItemKey(tag.name)) {
|
|
361
362
|
continue;
|
|
362
363
|
}
|
|
363
364
|
if (specialTags.has(tag.name)) {
|
|
364
|
-
tag.name =
|
|
365
|
+
tag.name = parseItemKey('specialTag', tag.name, '');
|
|
365
366
|
}
|
|
366
367
|
else if (casing.tag === types_1.TagNameCasing.Kebab) {
|
|
367
368
|
tag.name = (0, language_core_1.hyphenateTag)(tag.name);
|
|
@@ -376,6 +377,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
376
377
|
let version = 0;
|
|
377
378
|
let components;
|
|
378
379
|
let templateContextProps;
|
|
380
|
+
tsDocumentations.clear();
|
|
379
381
|
updateExtraCustomData([
|
|
380
382
|
html.newHTMLDataProvider('vue-template-built-in', builtInData),
|
|
381
383
|
{
|
|
@@ -430,18 +432,19 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
430
432
|
if (!tagInfo) {
|
|
431
433
|
promises.push((async () => {
|
|
432
434
|
const attrs = await tsPluginClient?.getElementAttrs(vueCode.fileName, tag) ?? [];
|
|
433
|
-
const
|
|
435
|
+
const propsInfo = await tsPluginClient?.getComponentProps(vueCode.fileName, tag) ?? [];
|
|
434
436
|
const events = await tsPluginClient?.getComponentEvents(vueCode.fileName, tag) ?? [];
|
|
435
437
|
tagInfos.set(tag, {
|
|
436
438
|
attrs,
|
|
437
|
-
|
|
439
|
+
propsInfo: propsInfo.filter(prop => !prop.name.startsWith('ref_')),
|
|
438
440
|
events,
|
|
439
441
|
});
|
|
440
442
|
version++;
|
|
441
443
|
})());
|
|
442
444
|
return [];
|
|
443
445
|
}
|
|
444
|
-
const { attrs,
|
|
446
|
+
const { attrs, propsInfo, events } = tagInfo;
|
|
447
|
+
const props = propsInfo.map(prop => prop.name);
|
|
445
448
|
const attributes = [];
|
|
446
449
|
const _tsCodegen = language_core_1.tsCodegen.get(vueCode.sfc);
|
|
447
450
|
if (_tsCodegen) {
|
|
@@ -474,7 +477,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
474
477
|
const propNameBase = name.startsWith('on-')
|
|
475
478
|
? name.slice('on-'.length)
|
|
476
479
|
: (name['on'.length].toLowerCase() + name.slice('onX'.length));
|
|
477
|
-
const propKey =
|
|
480
|
+
const propKey = parseItemKey('componentEvent', isGlobal ? '*' : tag, propNameBase);
|
|
478
481
|
attributes.push({
|
|
479
482
|
name: 'v-on:' + propNameBase,
|
|
480
483
|
description: propKey,
|
|
@@ -485,7 +488,14 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
485
488
|
}
|
|
486
489
|
else {
|
|
487
490
|
const propName = name;
|
|
488
|
-
const propKey =
|
|
491
|
+
const propKey = parseItemKey('componentProp', isGlobal ? '*' : tag, propName);
|
|
492
|
+
const propDescription = propsInfo.find(prop => {
|
|
493
|
+
const name = casing.attr === types_1.AttrNameCasing.Camel ? prop.name : (0, language_core_1.hyphenateAttr)(prop.name);
|
|
494
|
+
return name === propName;
|
|
495
|
+
})?.commentMarkdown;
|
|
496
|
+
if (propDescription) {
|
|
497
|
+
tsDocumentations.set(propName, propDescription);
|
|
498
|
+
}
|
|
489
499
|
attributes.push({
|
|
490
500
|
name: propName,
|
|
491
501
|
description: propKey,
|
|
@@ -500,7 +510,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
500
510
|
}
|
|
501
511
|
for (const event of events) {
|
|
502
512
|
const name = casing.attr === types_1.AttrNameCasing.Camel ? event : (0, language_core_1.hyphenateAttr)(event);
|
|
503
|
-
const propKey =
|
|
513
|
+
const propKey = parseItemKey('componentEvent', tag, name);
|
|
504
514
|
attributes.push({
|
|
505
515
|
name: 'v-on:' + name,
|
|
506
516
|
description: propKey,
|
|
@@ -523,7 +533,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
523
533
|
}
|
|
524
534
|
for (const [isGlobal, model] of models) {
|
|
525
535
|
const name = casing.attr === types_1.AttrNameCasing.Camel ? model : (0, language_core_1.hyphenateAttr)(model);
|
|
526
|
-
const propKey =
|
|
536
|
+
const propKey = parseItemKey('componentProp', isGlobal ? '*' : tag, name);
|
|
527
537
|
attributes.push({
|
|
528
538
|
name: 'v-model:' + name,
|
|
529
539
|
description: propKey,
|
|
@@ -606,14 +616,18 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
606
616
|
}
|
|
607
617
|
}
|
|
608
618
|
}
|
|
609
|
-
|
|
619
|
+
completionList.items = completionList.items.filter(item => !specialTags.has(item.label));
|
|
620
|
+
const htmlDocumentations = new Map();
|
|
610
621
|
for (const item of completionList.items) {
|
|
611
|
-
|
|
612
|
-
|
|
622
|
+
const documentation = typeof item.documentation === 'string' ? item.documentation : item.documentation?.value;
|
|
623
|
+
if (documentation && !isItemKey(documentation) && item.documentation) {
|
|
624
|
+
htmlDocumentations.set(item.label, documentation);
|
|
613
625
|
}
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
626
|
+
}
|
|
627
|
+
for (const item of completionList.items) {
|
|
628
|
+
const resolvedLabelKey = resolveItemKey(item.label);
|
|
629
|
+
if (resolvedLabelKey) {
|
|
630
|
+
const name = resolvedLabelKey.tag;
|
|
617
631
|
item.label = name;
|
|
618
632
|
if (item.textEdit) {
|
|
619
633
|
item.textEdit.newText = name;
|
|
@@ -626,32 +640,55 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
626
640
|
item.sortText = name;
|
|
627
641
|
}
|
|
628
642
|
}
|
|
629
|
-
const
|
|
630
|
-
let
|
|
631
|
-
if (
|
|
632
|
-
|
|
643
|
+
const itemKeyStr = typeof item.documentation === 'string' ? item.documentation : item.documentation?.value;
|
|
644
|
+
let resolvedKey = itemKeyStr ? resolveItemKey(itemKeyStr) : undefined;
|
|
645
|
+
if (resolvedKey) {
|
|
646
|
+
const documentations = [];
|
|
647
|
+
if (tsDocumentations.has(resolvedKey.prop)) {
|
|
648
|
+
documentations.push(tsDocumentations.get(resolvedKey.prop));
|
|
649
|
+
}
|
|
650
|
+
let { isEvent, propName } = getPropName(resolvedKey);
|
|
633
651
|
if (isEvent) {
|
|
634
|
-
|
|
652
|
+
// click -> onclick
|
|
653
|
+
propName = 'on' + propName;
|
|
654
|
+
}
|
|
655
|
+
if (htmlDocumentations.has(propName)) {
|
|
656
|
+
documentations.push(htmlDocumentations.get(propName));
|
|
657
|
+
}
|
|
658
|
+
if (documentations.length) {
|
|
659
|
+
item.documentation = {
|
|
660
|
+
kind: 'markdown',
|
|
661
|
+
value: documentations.join('\n\n'),
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
else {
|
|
665
|
+
item.documentation = undefined;
|
|
635
666
|
}
|
|
636
|
-
const original = originals.get(name);
|
|
637
|
-
item.documentation = original?.documentation;
|
|
638
667
|
}
|
|
639
668
|
else {
|
|
640
|
-
let
|
|
641
|
-
const isVBind =
|
|
642
|
-
const isVBindAbbr =
|
|
669
|
+
let propName = item.label;
|
|
670
|
+
const isVBind = propName.startsWith('v-bind:') ? (propName = propName.slice('v-bind:'.length), true) : false;
|
|
671
|
+
const isVBindAbbr = propName.startsWith(':') && propName !== ':' ? (propName = propName.slice(':'.length), true) : false;
|
|
643
672
|
/**
|
|
644
673
|
* for `is`, `key` and `ref` starting with `v-bind:` or `:`
|
|
645
674
|
* that without `internalItemId`.
|
|
646
675
|
*/
|
|
647
676
|
if (isVBind || isVBindAbbr) {
|
|
648
|
-
|
|
677
|
+
resolvedKey = {
|
|
649
678
|
type: 'componentProp',
|
|
650
|
-
|
|
679
|
+
tag: '^',
|
|
680
|
+
prop: propName,
|
|
651
681
|
};
|
|
652
682
|
}
|
|
653
|
-
|
|
654
|
-
|
|
683
|
+
if (tsDocumentations.has(propName)) {
|
|
684
|
+
const originalDocumentation = typeof item.documentation === 'string' ? item.documentation : item.documentation?.value;
|
|
685
|
+
item.documentation = {
|
|
686
|
+
kind: 'markdown',
|
|
687
|
+
value: [
|
|
688
|
+
tsDocumentations.get(propName),
|
|
689
|
+
originalDocumentation,
|
|
690
|
+
].filter(str => !!str).join('\n\n'),
|
|
691
|
+
};
|
|
655
692
|
}
|
|
656
693
|
}
|
|
657
694
|
const tokens = [];
|
|
@@ -659,23 +696,23 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
659
696
|
item.kind = 6;
|
|
660
697
|
tokens.push('\u0000');
|
|
661
698
|
}
|
|
662
|
-
else if (
|
|
663
|
-
const isComponent =
|
|
664
|
-
const
|
|
665
|
-
if (
|
|
666
|
-
if (isComponent || specialProps.has(
|
|
699
|
+
else if (resolvedKey) {
|
|
700
|
+
const isComponent = resolvedKey.tag !== '*';
|
|
701
|
+
const { isEvent, propName } = getPropName(resolvedKey);
|
|
702
|
+
if (resolvedKey.type === 'componentProp') {
|
|
703
|
+
if (isComponent || specialProps.has(propName)) {
|
|
667
704
|
item.kind = 5;
|
|
668
705
|
}
|
|
669
706
|
}
|
|
670
707
|
else if (isEvent) {
|
|
671
708
|
item.kind = 23;
|
|
672
|
-
if (
|
|
709
|
+
if (propName.startsWith('vnode-')) {
|
|
673
710
|
tokens.push('\u0004');
|
|
674
711
|
}
|
|
675
712
|
}
|
|
676
713
|
if (isComponent
|
|
677
714
|
|| (isComponent && isEvent)
|
|
678
|
-
|| specialProps.has(
|
|
715
|
+
|| specialProps.has(propName)) {
|
|
679
716
|
tokens.push('\u0000');
|
|
680
717
|
if (item.label.startsWith(':')) {
|
|
681
718
|
tokens.push('\u0001');
|
|
@@ -692,7 +729,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
692
729
|
else {
|
|
693
730
|
tokens.push('\u0000');
|
|
694
731
|
}
|
|
695
|
-
if (specialProps.has(
|
|
732
|
+
if (specialProps.has(propName)) {
|
|
696
733
|
tokens.push('\u0001');
|
|
697
734
|
}
|
|
698
735
|
else {
|
|
@@ -772,18 +809,19 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
772
809
|
}
|
|
773
810
|
}
|
|
774
811
|
;
|
|
775
|
-
function
|
|
776
|
-
return '
|
|
812
|
+
function parseItemKey(type, tag, prop) {
|
|
813
|
+
return '__VLS_data=' + type + ',' + tag + ',' + prop;
|
|
777
814
|
}
|
|
778
|
-
function
|
|
779
|
-
return key.startsWith('
|
|
815
|
+
function isItemKey(key) {
|
|
816
|
+
return key.startsWith('__VLS_data=');
|
|
780
817
|
}
|
|
781
|
-
function
|
|
782
|
-
if (
|
|
783
|
-
const strs = key.split('
|
|
818
|
+
function resolveItemKey(key) {
|
|
819
|
+
if (isItemKey(key)) {
|
|
820
|
+
const strs = key.slice('__VLS_data='.length).split(',');
|
|
784
821
|
return {
|
|
785
|
-
type: strs[
|
|
786
|
-
|
|
822
|
+
type: strs[0],
|
|
823
|
+
tag: strs[1],
|
|
824
|
+
prop: strs[2],
|
|
787
825
|
};
|
|
788
826
|
}
|
|
789
827
|
}
|
|
@@ -798,14 +836,14 @@ function getReplacement(list, doc) {
|
|
|
798
836
|
}
|
|
799
837
|
}
|
|
800
838
|
}
|
|
801
|
-
function
|
|
802
|
-
const name = (0, language_core_1.hyphenateAttr)(
|
|
839
|
+
function getPropName(itemKey) {
|
|
840
|
+
const name = (0, language_core_1.hyphenateAttr)(itemKey.prop);
|
|
803
841
|
if (name.startsWith('on-')) {
|
|
804
|
-
return
|
|
842
|
+
return { isEvent: true, propName: name.slice('on-'.length) };
|
|
805
843
|
}
|
|
806
|
-
else if (
|
|
807
|
-
return
|
|
844
|
+
else if (itemKey.type === 'componentEvent') {
|
|
845
|
+
return { isEvent: true, propName: name };
|
|
808
846
|
}
|
|
809
|
-
return
|
|
847
|
+
return { isEvent: false, propName: name };
|
|
810
848
|
}
|
|
811
849
|
//# sourceMappingURL=vue-template.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vue/language-service",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.6",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"files": [
|
|
6
6
|
"data",
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
"@volar/language-service": "~2.4.1",
|
|
21
21
|
"@volar/typescript": "~2.4.1",
|
|
22
22
|
"@vue/compiler-dom": "^3.4.0",
|
|
23
|
-
"@vue/language-core": "2.1.
|
|
23
|
+
"@vue/language-core": "2.1.6",
|
|
24
24
|
"@vue/shared": "^3.4.0",
|
|
25
|
-
"@vue/typescript-plugin": "2.1.
|
|
25
|
+
"@vue/typescript-plugin": "2.1.6",
|
|
26
26
|
"computeds": "^0.0.1",
|
|
27
27
|
"path-browserify": "^1.0.1",
|
|
28
28
|
"volar-service-css": "0.0.62",
|
|
@@ -43,5 +43,5 @@
|
|
|
43
43
|
"@volar/kit": "~2.4.1",
|
|
44
44
|
"vscode-languageserver-protocol": "^3.17.5"
|
|
45
45
|
},
|
|
46
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "fd61953ce9eb924eeaf4df0bf8d2237267321194"
|
|
47
47
|
}
|