@vue/language-service 2.1.5 → 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 +3 -3
- package/data/template/en.json +4 -4
- package/data/template/ru.json +4 -4
- package/lib/ideFeatures/nameCasing.js +9 -9
- package/lib/plugins/vue-document-drop.js +3 -3
- 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 +112 -63
- package/package.json +12 -11
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
|
{
|
|
@@ -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
|
@@ -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
|
{
|
|
@@ -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
|
}
|
|
@@ -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) {
|
|
@@ -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
|
|
@@ -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");
|
|
@@ -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;
|
|
@@ -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;
|
|
@@ -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',
|
|
@@ -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(),
|
|
@@ -279,7 +280,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
279
280
|
return;
|
|
280
281
|
}
|
|
281
282
|
const templateErrors = [];
|
|
282
|
-
const { template } = code.
|
|
283
|
+
const { template } = code._sfc;
|
|
283
284
|
if (template) {
|
|
284
285
|
for (const error of template.errors) {
|
|
285
286
|
onCompilerError(error, 1);
|
|
@@ -326,10 +327,10 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
326
327
|
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
|
|
327
328
|
if (!sourceScript
|
|
328
329
|
|| !(sourceScript.generated?.root instanceof language_core_1.VueVirtualCode)
|
|
329
|
-
|| !sourceScript.generated.root.
|
|
330
|
+
|| !sourceScript.generated.root._sfc.template) {
|
|
330
331
|
return [];
|
|
331
332
|
}
|
|
332
|
-
const { template } = sourceScript.generated.root.
|
|
333
|
+
const { template } = sourceScript.generated.root._sfc;
|
|
333
334
|
const spans = common_1.getComponentSpans.call({
|
|
334
335
|
files: context.language.scripts,
|
|
335
336
|
languageService,
|
|
@@ -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
|
{
|
|
@@ -395,8 +397,8 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
395
397
|
})());
|
|
396
398
|
return [];
|
|
397
399
|
}
|
|
398
|
-
const scriptSetupRanges = vueCode.
|
|
399
|
-
? (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)
|
|
400
402
|
: undefined;
|
|
401
403
|
const names = new Set();
|
|
402
404
|
const tags = [];
|
|
@@ -409,7 +411,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
409
411
|
}
|
|
410
412
|
}
|
|
411
413
|
for (const binding of scriptSetupRanges?.bindings ?? []) {
|
|
412
|
-
const name = vueCode.
|
|
414
|
+
const name = vueCode._sfc.scriptSetup.content.substring(binding.start, binding.end);
|
|
413
415
|
if (casing.tag === types_1.TagNameCasing.Kebab) {
|
|
414
416
|
names.add((0, language_core_1.hyphenateTag)(name));
|
|
415
417
|
}
|
|
@@ -430,20 +432,21 @@ 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
|
-
const _tsCodegen = language_core_1.tsCodegen.get(vueCode.
|
|
449
|
+
const _tsCodegen = language_core_1.tsCodegen.get(vueCode._sfc);
|
|
447
450
|
if (_tsCodegen) {
|
|
448
451
|
if (!templateContextProps) {
|
|
449
452
|
promises.push((async () => {
|
|
@@ -453,8 +456,8 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
453
456
|
return [];
|
|
454
457
|
}
|
|
455
458
|
let ctxVars = [
|
|
456
|
-
..._tsCodegen.scriptRanges()?.bindings.map(binding => vueCode.
|
|
457
|
-
..._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)) ?? [],
|
|
458
461
|
...templateContextProps,
|
|
459
462
|
];
|
|
460
463
|
ctxVars = [...new Set(ctxVars)];
|
|
@@ -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,15 +616,19 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
606
616
|
}
|
|
607
617
|
}
|
|
608
618
|
}
|
|
609
|
-
|
|
619
|
+
completionList.items = completionList.items.filter(item => !specialTags.has(parseLabel(item.label).name));
|
|
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
|
-
|
|
617
|
-
|
|
626
|
+
}
|
|
627
|
+
for (const item of completionList.items) {
|
|
628
|
+
const resolvedLabelKey = resolveItemKey(item.label);
|
|
629
|
+
if (resolvedLabelKey) {
|
|
630
|
+
const name = resolvedLabelKey.tag;
|
|
631
|
+
item.label = resolvedLabelKey.leadingSlash ? '/' + name : name;
|
|
618
632
|
if (item.textEdit) {
|
|
619
633
|
item.textEdit.newText = name;
|
|
620
634
|
}
|
|
@@ -626,32 +640,56 @@ 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,
|
|
681
|
+
leadingSlash: false
|
|
651
682
|
};
|
|
652
683
|
}
|
|
653
|
-
|
|
654
|
-
|
|
684
|
+
if (tsDocumentations.has(propName)) {
|
|
685
|
+
const originalDocumentation = typeof item.documentation === 'string' ? item.documentation : item.documentation?.value;
|
|
686
|
+
item.documentation = {
|
|
687
|
+
kind: 'markdown',
|
|
688
|
+
value: [
|
|
689
|
+
tsDocumentations.get(propName),
|
|
690
|
+
originalDocumentation,
|
|
691
|
+
].filter(str => !!str).join('\n\n'),
|
|
692
|
+
};
|
|
655
693
|
}
|
|
656
694
|
}
|
|
657
695
|
const tokens = [];
|
|
@@ -659,23 +697,23 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
659
697
|
item.kind = 6;
|
|
660
698
|
tokens.push('\u0000');
|
|
661
699
|
}
|
|
662
|
-
else if (
|
|
663
|
-
const isComponent =
|
|
664
|
-
const
|
|
665
|
-
if (
|
|
666
|
-
if (isComponent || specialProps.has(
|
|
700
|
+
else if (resolvedKey) {
|
|
701
|
+
const isComponent = resolvedKey.tag !== '*';
|
|
702
|
+
const { isEvent, propName } = getPropName(resolvedKey);
|
|
703
|
+
if (resolvedKey.type === 'componentProp') {
|
|
704
|
+
if (isComponent || specialProps.has(propName)) {
|
|
667
705
|
item.kind = 5;
|
|
668
706
|
}
|
|
669
707
|
}
|
|
670
708
|
else if (isEvent) {
|
|
671
709
|
item.kind = 23;
|
|
672
|
-
if (
|
|
710
|
+
if (propName.startsWith('vnode-')) {
|
|
673
711
|
tokens.push('\u0004');
|
|
674
712
|
}
|
|
675
713
|
}
|
|
676
714
|
if (isComponent
|
|
677
715
|
|| (isComponent && isEvent)
|
|
678
|
-
|| specialProps.has(
|
|
716
|
+
|| specialProps.has(propName)) {
|
|
679
717
|
tokens.push('\u0000');
|
|
680
718
|
if (item.label.startsWith(':')) {
|
|
681
719
|
tokens.push('\u0001');
|
|
@@ -692,7 +730,7 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
692
730
|
else {
|
|
693
731
|
tokens.push('\u0000');
|
|
694
732
|
}
|
|
695
|
-
if (specialProps.has(
|
|
733
|
+
if (specialProps.has(propName)) {
|
|
696
734
|
tokens.push('\u0001');
|
|
697
735
|
}
|
|
698
736
|
else {
|
|
@@ -772,18 +810,29 @@ function create(mode, ts, getTsPluginClient) {
|
|
|
772
810
|
}
|
|
773
811
|
}
|
|
774
812
|
;
|
|
775
|
-
function
|
|
776
|
-
|
|
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
|
+
}
|
|
821
|
+
function parseItemKey(type, tag, prop) {
|
|
822
|
+
return '__VLS_data=' + type + ',' + tag + ',' + prop;
|
|
777
823
|
}
|
|
778
|
-
function
|
|
779
|
-
return key.startsWith('
|
|
824
|
+
function isItemKey(key) {
|
|
825
|
+
return key.startsWith('__VLS_data=');
|
|
780
826
|
}
|
|
781
|
-
function
|
|
782
|
-
|
|
783
|
-
|
|
827
|
+
function resolveItemKey(key) {
|
|
828
|
+
const { leadingSlash, name } = parseLabel(key);
|
|
829
|
+
if (isItemKey(name)) {
|
|
830
|
+
const strs = name.slice('__VLS_data='.length).split(',');
|
|
784
831
|
return {
|
|
785
|
-
type: strs[
|
|
786
|
-
|
|
832
|
+
type: strs[0],
|
|
833
|
+
tag: strs[1],
|
|
834
|
+
prop: strs[2],
|
|
835
|
+
leadingSlash
|
|
787
836
|
};
|
|
788
837
|
}
|
|
789
838
|
}
|
|
@@ -798,14 +847,14 @@ function getReplacement(list, doc) {
|
|
|
798
847
|
}
|
|
799
848
|
}
|
|
800
849
|
}
|
|
801
|
-
function
|
|
802
|
-
const name = (0, language_core_1.hyphenateAttr)(
|
|
850
|
+
function getPropName(itemKey) {
|
|
851
|
+
const name = (0, language_core_1.hyphenateAttr)(itemKey.prop);
|
|
803
852
|
if (name.startsWith('on-')) {
|
|
804
|
-
return
|
|
853
|
+
return { isEvent: true, propName: name.slice('on-'.length) };
|
|
805
854
|
}
|
|
806
|
-
else if (
|
|
807
|
-
return
|
|
855
|
+
else if (itemKey.type === 'componentEvent') {
|
|
856
|
+
return { isEvent: true, propName: name };
|
|
808
857
|
}
|
|
809
|
-
return
|
|
858
|
+
return { isEvent: false, propName: name };
|
|
810
859
|
}
|
|
811
860
|
//# sourceMappingURL=vue-template.js.map
|
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
|
}
|