@vue/language-service 2.2.0 → 2.2.2

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.
@@ -8,7 +8,7 @@
8
8
  "name": "src",
9
9
  "description": {
10
10
  "kind": "markdown",
11
- "value": "如果你更喜欢将 `*.vue` 组件分散到多个文件中,可以为一个语块使用 `src` 这个 attribute 来导入一个外部文件:\n\n```vue\n<template src=\"./template.html\"></template>\n<style src=\"./style.css\"></style>\n<script src=\"./script.js\"></script>\n```\n\n请注意 `src` 导入和 JS 模块导入遵循相同的路径解析规则,这意味着:\n\n- 相对路径需要以 `./` 开头\n- 你也可以从 npm 依赖中导入资源\n\n```vue\n<!-- 从所安装的 \"todomvc-app-css\" npm 包中导入一个文件 -->\n<style src=\"todomvc-app-css/index.css\" />\n```\n\n`src` 导入对自定义语块也同样适用:\n\n```vue\n<unit-test src=\"./unit-test.js\">\n</unit-test>\n```"
11
+ "value": "如果你更喜欢将 `*.vue` 组件分散到多个文件中,可以为一个语块使用 `src` 这个 attribute 来导入一个外部文件:\n\n```vue\n<template src=\"./template.html\"></template>\n<style src=\"./style.css\"></style>\n<script src=\"./script.js\"></script>\n```\n\n请注意 `src` 导入和 JS 模块导入遵循相同的路径解析规则,这意味着:\n\n- 相对路径需要以 `./` 开头\n- 你也可以从 npm 依赖中导入资源\n\n```vue\n<!-- 从所安装的 \"todomvc-app-css\" npm 包中导入一个文件 -->\n<style src=\"todomvc-app-css/index.css\" />\n```\n\n`src` 导入对自定义语块也同样适用:\n\n```vue\n<unit-test src=\"./unit-test.js\">\n</unit-test>\n```\n\n:::warning 注意\n在 `src` 中使用别名时,不要以 `~` 开头,后面的任何内容都会被解释为模块请求。这意味着你可以引用 node 模块中的资源:\n```vue\n<img src=\"~some-npm-package/foo.png\">\n```\n:::"
12
12
  },
13
13
  "references": "api/sfc-spec.html#src-imports"
14
14
  },
@@ -42,7 +42,7 @@
42
42
  "name": "src",
43
43
  "description": {
44
44
  "kind": "markdown",
45
- "value": "如果你更喜欢将 `*.vue` 组件分散到多个文件中,可以为一个语块使用 `src` 这个 attribute 来导入一个外部文件:\n\n```vue\n<template src=\"./template.html\"></template>\n<style src=\"./style.css\"></style>\n<script src=\"./script.js\"></script>\n```\n\n请注意 `src` 导入和 JS 模块导入遵循相同的路径解析规则,这意味着:\n\n- 相对路径需要以 `./` 开头\n- 你也可以从 npm 依赖中导入资源\n\n```vue\n<!-- 从所安装的 \"todomvc-app-css\" npm 包中导入一个文件 -->\n<style src=\"todomvc-app-css/index.css\" />\n```\n\n`src` 导入对自定义语块也同样适用:\n\n```vue\n<unit-test src=\"./unit-test.js\">\n</unit-test>\n```"
45
+ "value": "如果你更喜欢将 `*.vue` 组件分散到多个文件中,可以为一个语块使用 `src` 这个 attribute 来导入一个外部文件:\n\n```vue\n<template src=\"./template.html\"></template>\n<style src=\"./style.css\"></style>\n<script src=\"./script.js\"></script>\n```\n\n请注意 `src` 导入和 JS 模块导入遵循相同的路径解析规则,这意味着:\n\n- 相对路径需要以 `./` 开头\n- 你也可以从 npm 依赖中导入资源\n\n```vue\n<!-- 从所安装的 \"todomvc-app-css\" npm 包中导入一个文件 -->\n<style src=\"todomvc-app-css/index.css\" />\n```\n\n`src` 导入对自定义语块也同样适用:\n\n```vue\n<unit-test src=\"./unit-test.js\">\n</unit-test>\n```\n\n:::warning 注意\n在 `src` 中使用别名时,不要以 `~` 开头,后面的任何内容都会被解释为模块请求。这意味着你可以引用 node 模块中的资源:\n```vue\n<img src=\"~some-npm-package/foo.png\">\n```\n:::"
46
46
  },
47
47
  "references": "api/sfc-spec.html#src-imports"
48
48
  },
@@ -103,7 +103,7 @@
103
103
  "name": "src",
104
104
  "description": {
105
105
  "kind": "markdown",
106
- "value": "如果你更喜欢将 `*.vue` 组件分散到多个文件中,可以为一个语块使用 `src` 这个 attribute 来导入一个外部文件:\n\n```vue\n<template src=\"./template.html\"></template>\n<style src=\"./style.css\"></style>\n<script src=\"./script.js\"></script>\n```\n\n请注意 `src` 导入和 JS 模块导入遵循相同的路径解析规则,这意味着:\n\n- 相对路径需要以 `./` 开头\n- 你也可以从 npm 依赖中导入资源\n\n```vue\n<!-- 从所安装的 \"todomvc-app-css\" npm 包中导入一个文件 -->\n<style src=\"todomvc-app-css/index.css\" />\n```\n\n`src` 导入对自定义语块也同样适用:\n\n```vue\n<unit-test src=\"./unit-test.js\">\n</unit-test>\n```"
106
+ "value": "如果你更喜欢将 `*.vue` 组件分散到多个文件中,可以为一个语块使用 `src` 这个 attribute 来导入一个外部文件:\n\n```vue\n<template src=\"./template.html\"></template>\n<style src=\"./style.css\"></style>\n<script src=\"./script.js\"></script>\n```\n\n请注意 `src` 导入和 JS 模块导入遵循相同的路径解析规则,这意味着:\n\n- 相对路径需要以 `./` 开头\n- 你也可以从 npm 依赖中导入资源\n\n```vue\n<!-- 从所安装的 \"todomvc-app-css\" npm 包中导入一个文件 -->\n<style src=\"todomvc-app-css/index.css\" />\n```\n\n`src` 导入对自定义语块也同样适用:\n\n```vue\n<unit-test src=\"./unit-test.js\">\n</unit-test>\n```\n\n:::warning 注意\n在 `src` 中使用别名时,不要以 `~` 开头,后面的任何内容都会被解释为模块请求。这意味着你可以引用 node 模块中的资源:\n```vue\n<img src=\"~some-npm-package/foo.png\">\n```\n:::"
107
107
  },
108
108
  "references": "api/sfc-spec.html#src-imports"
109
109
  },
@@ -149,7 +149,7 @@
149
149
  "valueSet": "v",
150
150
  "description": {
151
151
  "kind": "markdown",
152
- "value": "一个 `<style module>` 标签会被编译为 [CSS Modules](https://github.com/css-modules/css-modules) 并且将生成的 CSS class 作为 `$style` 对象暴露给组件:\n\n```vue\n<template>\n <p :class=\"$style.red\">This should be red</p>\n</template>\n\n<style module>\n.red {\n color: red;\n}\n</style>\n```\n\n得出的 class 将被哈希化以避免冲突,实现了同样的将 CSS 仅作用于当前组件的效果。\n\n参考 [CSS Modules spec](https://github.com/css-modules/css-modules) 以查看更多详情,例如 [global exceptions](https://github.com/css-modules/css-modules/blob/master/docs/composition.md#exceptions) 和 [composition](https://github.com/css-modules/css-modules/blob/master/docs/composition.md#composition)。\n\n### 自定义注入名称 \n\n你可以通过给 `module` attribute 一个值来自定义注入 class 对象的属性名:\n\n```vue\n<template>\n <p :class=\"classes.red\">red</p>\n</template>\n\n<style module=\"classes\">\n.red {\n color: red;\n}\n</style>\n```\n\n### 与组合式 API 一同使用 \n\n可以通过 `useCssModule` API 在 `setup()` 和 `<script setup>` 中访问注入的 class。对于使用了自定义注入名称的 `<style module>` 块,`useCssModule` 接收一个匹配的 `module` attribute 值作为第一个参数:\n\n```js\nimport { useCssModule } from 'vue'\n\n// 在 setup() 作用域中...\n// 默认情况下,返回 <style module> 的 class\nuseCssModule()\n\n// 具名情况下,返回 <style module=\"classes\"> 的 class\nuseCssModule('classes')\n```"
152
+ "value": "一个 `<style module>` 标签会被编译为 [CSS Modules](https://github.com/css-modules/css-modules) 并且将生成的 CSS class 作为 `$style` 对象暴露给组件:\n\n```vue\n<template>\n <p :class=\"$style.red\">This should be red</p>\n</template>\n\n<style module>\n.red {\n color: red;\n}\n</style>\n```\n\n得出的 class 将被哈希化以避免冲突,实现了同样的将 CSS 仅作用于当前组件的效果。\n\n参考 [CSS Modules spec](https://github.com/css-modules/css-modules) 以查看更多详情,例如 [global exceptions](https://github.com/css-modules/css-modules/blob/master/docs/composition.md#exceptions) 和 [composition](https://github.com/css-modules/css-modules/blob/master/docs/composition.md#composition)。\n\n### 自定义注入名称 \n\n你可以通过给 `module` attribute 一个值来自定义注入 class 对象的属性名:\n\n```vue\n<template>\n <p :class=\"classes.red\">red</p>\n</template>\n\n<style module=\"classes\">\n.red {\n color: red;\n}\n</style>\n```\n\n### 与组合式 API 一同使用 \n\n可以通过 `useCssModule` API 在 `setup()` 和 `<script setup>` 中访问注入的 class。对于使用了自定义注入名称的 `<style module>` 块,`useCssModule` 接收一个匹配的 `module` attribute 值作为第一个参数:\n\n```js\nimport { useCssModule } from 'vue'\n\n// 在 setup() 作用域中...\n// 默认情况下,返回 <style module> 的 class\nuseCssModule()\n\n// 具名情况下,返回 <style module=\"classes\"> 的 class\nuseCssModule('classes')\n```\n\n- **示例**\n\n```vue\n<script setup lang=\"ts\">\nimport { useCssModule } from 'vue'\n\nconst classes = useCssModule()\n</script>\n\n<template>\n <p :class=\"classes.red\">red</p>\n</template>\n\n<style module>\n.red {\n color: red;\n}\n</style>\n```"
153
153
  },
154
154
  "references": "api/sfc-css-features.html#css-modules"
155
155
  }
@@ -167,7 +167,7 @@
167
167
  "name": "src",
168
168
  "description": {
169
169
  "kind": "markdown",
170
- "value": "如果你更喜欢将 `*.vue` 组件分散到多个文件中,可以为一个语块使用 `src` 这个 attribute 来导入一个外部文件:\n\n```vue\n<template src=\"./template.html\"></template>\n<style src=\"./style.css\"></style>\n<script src=\"./script.js\"></script>\n```\n\n请注意 `src` 导入和 JS 模块导入遵循相同的路径解析规则,这意味着:\n\n- 相对路径需要以 `./` 开头\n- 你也可以从 npm 依赖中导入资源\n\n```vue\n<!-- 从所安装的 \"todomvc-app-css\" npm 包中导入一个文件 -->\n<style src=\"todomvc-app-css/index.css\" />\n```\n\n`src` 导入对自定义语块也同样适用:\n\n```vue\n<unit-test src=\"./unit-test.js\">\n</unit-test>\n```"
170
+ "value": "如果你更喜欢将 `*.vue` 组件分散到多个文件中,可以为一个语块使用 `src` 这个 attribute 来导入一个外部文件:\n\n```vue\n<template src=\"./template.html\"></template>\n<style src=\"./style.css\"></style>\n<script src=\"./script.js\"></script>\n```\n\n请注意 `src` 导入和 JS 模块导入遵循相同的路径解析规则,这意味着:\n\n- 相对路径需要以 `./` 开头\n- 你也可以从 npm 依赖中导入资源\n\n```vue\n<!-- 从所安装的 \"todomvc-app-css\" npm 包中导入一个文件 -->\n<style src=\"todomvc-app-css/index.css\" />\n```\n\n`src` 导入对自定义语块也同样适用:\n\n```vue\n<unit-test src=\"./unit-test.js\">\n</unit-test>\n```\n\n:::warning 注意\n在 `src` 中使用别名时,不要以 `~` 开头,后面的任何内容都会被解释为模块请求。这意味着你可以引用 node 模块中的资源:\n```vue\n<img src=\"~some-npm-package/foo.png\">\n```\n:::"
171
171
  },
172
172
  "references": "api/sfc-spec.html#src-imports"
173
173
  }
@@ -193,7 +193,7 @@
193
193
  "name": "src",
194
194
  "description": {
195
195
  "kind": "markdown",
196
- "value": "如果你更喜欢将 `*.vue` 组件分散到多个文件中,可以为一个语块使用 `src` 这个 attribute 来导入一个外部文件:\n\n```vue\n<template src=\"./template.html\"></template>\n<style src=\"./style.css\"></style>\n<script src=\"./script.js\"></script>\n```\n\n请注意 `src` 导入和 JS 模块导入遵循相同的路径解析规则,这意味着:\n\n- 相对路径需要以 `./` 开头\n- 你也可以从 npm 依赖中导入资源\n\n```vue\n<!-- 从所安装的 \"todomvc-app-css\" npm 包中导入一个文件 -->\n<style src=\"todomvc-app-css/index.css\" />\n```\n\n`src` 导入对自定义语块也同样适用:\n\n```vue\n<unit-test src=\"./unit-test.js\">\n</unit-test>\n```"
196
+ "value": "如果你更喜欢将 `*.vue` 组件分散到多个文件中,可以为一个语块使用 `src` 这个 attribute 来导入一个外部文件:\n\n```vue\n<template src=\"./template.html\"></template>\n<style src=\"./style.css\"></style>\n<script src=\"./script.js\"></script>\n```\n\n请注意 `src` 导入和 JS 模块导入遵循相同的路径解析规则,这意味着:\n\n- 相对路径需要以 `./` 开头\n- 你也可以从 npm 依赖中导入资源\n\n```vue\n<!-- 从所安装的 \"todomvc-app-css\" npm 包中导入一个文件 -->\n<style src=\"todomvc-app-css/index.css\" />\n```\n\n`src` 导入对自定义语块也同样适用:\n\n```vue\n<unit-test src=\"./unit-test.js\">\n</unit-test>\n```\n\n:::warning 注意\n在 `src` 中使用别名时,不要以 `~` 开头,后面的任何内容都会被解释为模块请求。这意味着你可以引用 node 模块中的资源:\n```vue\n<img src=\"~some-npm-package/foo.png\">\n```\n:::"
197
197
  },
198
198
  "references": "api/sfc-spec.html#src-imports"
199
199
  }
@@ -13,7 +13,7 @@
13
13
  "name": "number",
14
14
  "description": {
15
15
  "kind": "markdown",
16
- "value": "如果你想让用户输入自动转换为数字,你可以在 `v-model` 后添加 `.number` 修饰符来管理输入:\n\n```html\n<input v-model.number=\"age\" />\n```\n\n如果该值无法被 `parseFloat()` 处理,那么将返回原始值。\n\n`number` 修饰符会在输入框有 `type=\"number\"` 时自动启用。"
16
+ "value": "如果你想让用户输入自动转换为数字,你可以在 `v-model` 后添加 `.number` 修饰符来管理输入:\n\n```html\n<input v-model.number=\"age\" />\n```\n\n如果该值无法被 `parseFloat()` 处理,那么将返回原始值。特别是当输入为空时 (例如用户清空输入字段之后),会返回一个空字符串。这种行为与 [DOM 属性 valueAsNumber](https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLInputElement#valueasnumber) 有所不同。\n\n`number` 修饰符会在输入框有 `type=\"number\"` 时自动启用。"
17
17
  },
18
18
  "references": "guide/essentials/forms.html#number"
19
19
  },
@@ -5,7 +5,7 @@
5
5
  "name": "Transition",
6
6
  "description": {
7
7
  "kind": "markdown",
8
- "value": "\nProvides animated transition effects to a **single** element or component.\n\n- **Props**\n\n ```ts\n interface TransitionProps {\n /**\n * Used to automatically generate transition CSS class names.\n * e.g. `name: 'fade'` will auto expand to `.fade-enter`,\n * `.fade-enter-active`, etc.\n */\n name?: string\n /**\n * Whether to apply CSS transition classes.\n * Default: true\n */\n css?: boolean\n /**\n * Specifies the type of transition events to wait for to\n * determine transition end timing.\n * Default behavior is auto detecting the type that has\n * longer duration.\n */\n type?: 'transition' | 'animation'\n /**\n * Specifies explicit durations of the transition.\n * Default behavior is wait for the first `transitionend`\n * or `animationend` event on the root transition element.\n */\n duration?: number | { enter: number; leave: number }\n /**\n * Controls the timing sequence of leaving/entering transitions.\n * Default behavior is simultaneous.\n */\n mode?: 'in-out' | 'out-in' | 'default'\n /**\n * Whether to apply transition on initial render.\n * Default: false\n */\n appear?: boolean\n\n /**\n * Props for customizing transition classes.\n * Use kebab-case in templates, e.g. enter-from-class=\"xxx\"\n */\n enterFromClass?: string\n enterActiveClass?: string\n enterToClass?: string\n appearFromClass?: string\n appearActiveClass?: string\n appearToClass?: string\n leaveFromClass?: string\n leaveActiveClass?: string\n leaveToClass?: string\n }\n ```\n\n- **Events**\n\n - `@before-enter`\n - `@before-leave`\n - `@enter`\n - `@leave`\n - `@appear`\n - `@after-enter`\n - `@after-leave`\n - `@after-appear`\n - `@enter-cancelled`\n - `@leave-cancelled` (`v-show` only)\n - `@appear-cancelled`\n\n- **Example**\n\n Simple element:\n\n ```html\n <Transition>\n <div v-if=\"ok\">toggled content</div>\n </Transition>\n ```\n\n Forcing a transition by changing the `key` attribute:\n\n ```html\n <Transition>\n <div :key=\"text\">{{ text }}</div>\n </Transition>\n ```\n\n Dynamic component, with transition mode + animate on appear:\n\n ```html\n <Transition name=\"fade\" mode=\"out-in\" appear>\n <component :is=\"view\"></component>\n </Transition>\n ```\n\n Listening to transition events:\n\n ```html\n <Transition @after-enter=\"onTransitionComplete\">\n <div v-show=\"ok\">toggled content</div>\n </Transition>\n ```\n\n- **See also** [`<Transition>` Guide](https://it.vuejs.org/guide/built-ins/transition.html)\n"
8
+ "value": "\nFornisce un'animazione di transizione a un **solo** elemento o componente.\n\n- **Props**\n\n ```ts\n interface TransitionProps {\n /**\n * Usato per generare automaticamente classi CSS per le transizioni.\n * Per esempio `name: 'fade'` verrà automaticamente espanso in `.fade-enter`,\n * `.fade-enter-active`, etc.\n */\n name?: string\n /**\n * Definisce se applicare le classi di transizione CSS.\n * Predefinito: true\n */\n css?: boolean\n /**\n * Specifica il tipo di evento di transizione da attendere\n * per determinare la tempistica della fine della transizione.\n * Il comportamento predefinito rileva automaticamente il tipo che ha\n * la durata maggiore.\n */\n type?: 'transition' | 'animation'\n /**\n * Specifica esplicitamente la durata della transizione.\n * Il comportamento predefinito è di attendere il primo evento\n * `transitionend` o `animationend` nel root dell'elemento transition.\n */\n duration?: number | { enter: number; leave: number }\n /**\n * Controlla la sequenza temporale delle transizioni di uscita/entrata.\n * Il comportamento predefinito è simultaneo\n */\n mode?: 'in-out' | 'out-in' | 'default'\n /**\n * Definisce se applicare la transizione al rendering iniziale.\n * Predefinito: false\n */\n appear?: boolean\n\n /**\n * Props per personalizzare le classi di transizione.\n * Usa il kebab-case nei template, per esempio enter-from-class=\"xxx\"\n */\n enterFromClass?: string\n enterActiveClass?: string\n enterToClass?: string\n appearFromClass?: string\n appearActiveClass?: string\n appearToClass?: string\n leaveFromClass?: string\n leaveActiveClass?: string\n leaveToClass?: string\n }\n ```\n\n- **Eventi**\n\n - `@before-enter`\n - `@before-leave`\n - `@enter`\n - `@leave`\n - `@appear`\n - `@after-enter`\n - `@after-leave`\n - `@after-appear`\n - `@enter-cancelled`\n - `@leave-cancelled` (solo `v-show`)\n - `@appear-cancelled`\n\n- **Esempio**\n\n Elemento semplice:\n\n ```html\n <Transition>\n <div v-if=\"ok\">contenuto attivato</div>\n </Transition>\n ```\n\n Forzare una transizione cambiando l'attributo `key`:\n\n ```html\n <Transition>\n <div :key=\"text\">{{ text }}</div>\n </Transition>\n ```\n\n Componente dinamico, con modalità di transizione + animazione in entrata:\n\n ```html\n <Transition name=\"fade\" mode=\"out-in\" appear>\n <component :is=\"view\"></component>\n </Transition>\n ```\n\n Ascolto eventi transizione:\n\n ```html\n <Transition @after-enter=\"onTransitionComplete\">\n <div v-show=\"ok\">toggled content</div>\n </Transition>\n ```\n\n- **Vedi anche** [Guida `<Transition>`](https://it.vuejs.org/guide/built-ins/transition.html)\n"
9
9
  },
10
10
  "attributes": [],
11
11
  "references": "api/built-in-components.html#transition"
@@ -14,7 +14,7 @@
14
14
  "name": "TransitionGroup",
15
15
  "description": {
16
16
  "kind": "markdown",
17
- "value": "\nProvides transition effects for **multiple** elements or components in a list.\n\n- **Props**\n\n `<TransitionGroup>` accepts the same props as `<Transition>` except `mode`, plus two additional props:\n\n ```ts\n interface TransitionGroupProps extends Omit<TransitionProps, 'mode'> {\n /**\n * If not defined, renders as a fragment.\n */\n tag?: string\n /**\n * For customizing the CSS class applied during move transitions.\n * Use kebab-case in templates, e.g. move-class=\"xxx\"\n */\n moveClass?: string\n }\n ```\n\n- **Events**\n\n `<TransitionGroup>` emits the same events as `<Transition>`.\n\n- **Details**\n\n By default, `<TransitionGroup>` doesn't render a wrapper DOM element, but one can be defined via the `tag` prop.\n\n Note that every child in a `<transition-group>` must be [**uniquely keyed**](https://it.vuejs.org/guide/essentials/list.html#maintaining-state-with-key) for the animations to work properly.\n\n `<TransitionGroup>` supports moving transitions via CSS transform. When a child's position on screen has changed after an update, it will get applied a moving CSS class (auto generated from the `name` attribute or configured with the `move-class` prop). If the CSS `transform` property is \"transition-able\" when the moving class is applied, the element will be smoothly animated to its destination using the [FLIP technique](https://aerotwist.com/blog/flip-your-animations/).\n\n- **Example**\n\n ```html\n <TransitionGroup tag=\"ul\" name=\"slide\">\n <li v-for=\"item in items\" :key=\"item.id\">\n {{ item.text }}\n </li>\n </TransitionGroup>\n ```\n\n- **See also** [Guide - TransitionGroup](https://it.vuejs.org/guide/built-ins/transition-group.html)\n"
17
+ "value": "\nFornisce effetti di transizione per elementi **multipli** o componenti in un elenco.\n\n- **Props**\n\n `<TransitionGroup>` accetta le stesse props di `<Transition>` tranne `mode`, più due prop aggiuntive:\n\n ```ts\n interface TransitionGroupProps extends Omit<TransitionProps, 'mode'> {\n /**\n * Se non definito, renderizza come un fragment\n */\n tag?: string\n /**\n * Per personalizzare la classe CSS applicata durante la transizione.\n * Usa il kebab-case nel template, per esempio move-class=\"xxx\"\n */\n moveClass?: string\n }\n ```\n\n- **Eventi**\n\n `<TransitionGroup>` emette gli stessi eventi di `<Transition>`.\n\n- **Dettagli**\n\n Di default, `<TransitionGroup>` non renderizza un elemento DOM wrapper, ma uno può essere definito attraverso la prop `tag`.\n\n Nota che ogni figlio in `<transition-group>` deve avere una [**chiave univoca**](https://it.vuejs.org/guide/essentials/list.html#maintaining-state-with-key) per l'animazione per funzionare correttamente.\n\n `<TransitionGroup>` supporta le transizioni tramite trasformazione CSS. Quando la posizione di un figlio nello schermo cambia dopo un aggiornamento, gli verrà applicata una classe CSS di movimento (generata automaticamente dall'attributo `name` o configurato con la prop `move-class`). Se la proprietà CSS `transform` è \"transition-able\" quando la classe di movimento è applicata, l'elemento verrà animato fluidamente alla sua destinazione usando la [tecnica FLIP](https://aerotwist.com/blog/flip-your-animations/).\n\n- **Esempio**\n\n ```html\n <TransitionGroup tag=\"ul\" name=\"slide\">\n <li v-for=\"item in items\" :key=\"item.id\">\n {{ item.text }}\n </li>\n </TransitionGroup>\n ```\n\n- **Vedi anche** [Guida - TransitionGroup](https://it.vuejs.org/guide/built-ins/transition-group.html)\n"
18
18
  },
19
19
  "attributes": [],
20
20
  "references": "api/built-in-components.html#transitiongroup"
@@ -23,7 +23,7 @@
23
23
  "name": "KeepAlive",
24
24
  "description": {
25
25
  "kind": "markdown",
26
- "value": "\nCaches dynamically toggled components wrapped inside.\n\n- **Props**\n\n ```ts\n interface KeepAliveProps {\n /**\n * If specified, only components with names matched by\n * `include` will be cached.\n */\n include?: MatchPattern\n /**\n * Any component with a name matched by `exclude` will\n * not be cached.\n */\n exclude?: MatchPattern\n /**\n * The maximum number of component instances to cache.\n */\n max?: number | string\n }\n\n type MatchPattern = string | RegExp | (string | RegExp)[]\n ```\n\n- **Details**\n\n When wrapped around a dynamic component, `<KeepAlive>` caches the inactive component instances without destroying them.\n\n There can only be one active component instance as the direct child of `<KeepAlive>` at any time.\n\n When a component is toggled inside `<KeepAlive>`, its `activated` and `deactivated` lifecycle hooks will be invoked accordingly, providing an alternative to `mounted` and `unmounted`, which are not called. This applies to the direct child of `<KeepAlive>` as well as to all of its descendants.\n\n- **Example**\n\n Utilizzo Base:\n\n ```html\n <KeepAlive>\n <component :is=\"view\"></component>\n </KeepAlive>\n ```\n\n When used with `v-if` / `v-else` branches, there must be only one component rendered at a time:\n\n ```html\n <KeepAlive>\n <comp-a v-if=\"a > 1\"></comp-a>\n <comp-b v-else></comp-b>\n </KeepAlive>\n ```\n\n Used together with `<Transition>`:\n\n ```html\n <Transition>\n <KeepAlive>\n <component :is=\"view\"></component>\n </KeepAlive>\n </Transition>\n ```\n\n Using `include` / `exclude`:\n\n ```html\n <!-- comma-delimited string -->\n <KeepAlive include=\"a,b\">\n <component :is=\"view\"></component>\n </KeepAlive>\n\n <!-- regex (use `v-bind`) -->\n <KeepAlive :include=\"/a|b/\">\n <component :is=\"view\"></component>\n </KeepAlive>\n\n <!-- Array (use `v-bind`) -->\n <KeepAlive :include=\"['a', 'b']\">\n <component :is=\"view\"></component>\n </KeepAlive>\n ```\n\n Usage with `max`:\n\n ```html\n <KeepAlive :max=\"10\">\n <component :is=\"view\"></component>\n </KeepAlive>\n ```\n\n- **See also** [Guide - KeepAlive](https://it.vuejs.org/guide/built-ins/keep-alive.html)\n"
26
+ "value": "\nMemorizza nella cache i componenti attivati/disattivati ​​dinamicamente racchiusi all'interno.\n\n- **Props**\n\n ```ts\n interface KeepAliveProps {\n /**\n * Se specificata, solo i componenti con gli stessi nomi corrispondenti a \n * `include` saranno memorizzati nella cache.\n */\n include?: MatchPattern\n /**\n * Qualsiasi componente con un nome corrispondente a `exclude`\n * non verrà memorizzato nella cache.\n */\n exclude?: MatchPattern\n /**\n * Il numero massimo di istanze del componente da memorizzare nella cache.\n */\n max?: number | string\n }\n\n type MatchPattern = string | RegExp | (string | RegExp)[]\n ```\n\n- **Dettagli**\n\n Quando racchiuso in un componente dinamico, `<KeepAlive>` memorizza nella cache le istanze dei componenti inattivi senza distruggerle.\n\n Ci può essere solo un'istanza di un componente come figlio diretto di `<KeepAlive>` in qualsiasi momento.\n\n Quando un componente è azionato dentro `<KeepAlive>`, i suoi lifecycle hooks `activated` e `deactivated` verranno richiamati di conseguenza, offrendo un alternativa a `mounted` e `unmounted`, che non sono chiamati. Questo si applica ai figli diretti di `<KeepAlive>` e anche a tutti i suoi discendenti.\n\n- **Esempio**\n\n Utilizzo Base:\n\n ```html\n <KeepAlive>\n <component :is=\"view\"></component>\n </KeepAlive>\n ```\n Quando usato con `v-if` / `v-else`, ci deve essere solo un componente renderizzato alla volta:\n\n ```html\n <KeepAlive>\n <comp-a v-if=\"a > 1\"></comp-a>\n <comp-b v-else></comp-b>\n </KeepAlive>\n ```\n Usato insieme a `<Transition>`:\n\n ```html\n <Transition>\n <KeepAlive>\n <component :is=\"view\"></component>\n </KeepAlive>\n </Transition>\n ```\n Usando `include` / `exclude`: \n\n ```html\n <!-- stringa con delimitatore virgola -->\n <KeepAlive include=\"a,b\">\n <component :is=\"view\"></component>\n </KeepAlive>\n\n <!-- regex (usando `v-bind`) -->\n <KeepAlive :include=\"/a|b/\">\n <component :is=\"view\"></component>\n </KeepAlive>\n\n <!-- Array (usando `v-bind`) -->\n <KeepAlive :include=\"['a', 'b']\">\n <component :is=\"view\"></component>\n </KeepAlive>\n ```\n Utilizzo con `max`:\n\n ```html\n <KeepAlive :max=\"10\">\n <component :is=\"view\"></component>\n </KeepAlive>\n ```\n\n- **Vedi anche** [Guida - KeepAlive](https://it.vuejs.org/guide/built-ins/keep-alive.html)\n"
27
27
  },
28
28
  "attributes": [],
29
29
  "references": "api/built-in-components.html#keepalive"
@@ -32,7 +32,7 @@
32
32
  "name": "Teleport",
33
33
  "description": {
34
34
  "kind": "markdown",
35
- "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://it.vuejs.org/guide/built-ins/teleport.html)\n"
35
+ "value": "\nRenderizza il contenuto dello slot in un' altra parte del DOM.\n\n- **Props**\n\n ```ts\n interface TeleportProps {\n /**\n * Obbligatoria. Specifica il container di destinazione.\n * Può essere sia un selettore o un elemento reale.\n */\n to: string | HTMLElement\n /**\n * Quando `true`, il contenuto resterà nella posizione\n * originale invece di essere spostato nel container di destinazione.\n * Può essere cambiato dinamicamente.\n */\n disabled?: boolean\n }\n ```\n\n- **Esempio**\n\n Specificando un container di destinazione\n\n ```html\n <teleport to=\"#some-id\" />\n <teleport to=\".some-class\" />\n <teleport to=\"[data-teleport]\" />\n ```\n Disabilitazione condizionale:\n\n ```html\n <teleport to=\"#popup\" :disabled=\"displayVideoInline\">\n <video src=\"./my-movie.mp4\">\n </teleport>\n ```\n\n- **Vedi anche** [Guida - Teleport](https://it.vuejs.org/guide/built-ins/teleport.html)\n"
36
36
  },
37
37
  "attributes": [],
38
38
  "references": "api/built-in-components.html#teleport"
@@ -41,7 +41,7 @@
41
41
  "name": "Suspense",
42
42
  "description": {
43
43
  "kind": "markdown",
44
- "value": "\nUsed for orchestrating nested async dependencies in a component tree.\n\n- **Props**\n\n ```ts\n interface SuspenseProps {\n timeout?: string | number\n }\n ```\n\n- **Events**\n\n - `@resolve`\n - `@pending`\n - `@fallback`\n\n- **Details**\n\n `<Suspense>` accepts two slots: the `#default` slot and the `#fallback` slot. It will display the content of the fallback slot while rendering the default slot in memory.\n\n If it encounters async dependencies ([Async Components](https://it.vuejs.org/guide/components/async.html) and components with [`async setup()`](https://it.vuejs.org/guide/built-ins/suspense.html#async-setup)) while rendering the default slot, it will wait until all of them are resolved before displaying the default slot.\n\n- **See also** [Guide - Suspense](https://it.vuejs.org/guide/built-ins/suspense.html)\n"
44
+ "value": "\nUsato per orchestrare dipendenze asincrone annidate in un albero di componenti.\n\n- **Props**\n\n ```ts\n interface SuspenseProps {\n timeout?: string | number\n }\n ```\n\n- **Eventi**\n\n - `@resolve`\n - `@pending`\n - `@fallback`\n\n- **Dettagli**\n\n `<Suspense>` accetta due slots: lo slot di `#default` e lo slot `#fallback`. Mostrerà il contenuto dello slot di fallback mentre renderizza lo slot default in memoria.\n\n Se incontra dipendenze asincrone ([Componente asincrono](https://it.vuejs.org/guide/components/async.html) e componenti con [`async setup()`](https://it.vuejs.org/guide/built-ins/suspense.html#async-setup)) mentre renderizza lo slot di default, aspetterà fino a quando tutti sono risolti prima di visualizzare lo slot di default.\n\n- **Vedi anche** [Guida - Suspense](https://it.vuejs.org/guide/built-ins/suspense.html)\n"
45
45
  },
46
46
  "attributes": [],
47
47
  "references": "api/built-in-components.html#suspense"
package/index.js CHANGED
@@ -44,7 +44,11 @@ const vue_twoslash_queries_1 = require("./lib/plugins/vue-twoslash-queries");
44
44
  const language_core_1 = require("@vue/language-core");
45
45
  const common_1 = require("@vue/typescript-plugin/lib/common");
46
46
  const collectExtractProps_1 = require("@vue/typescript-plugin/lib/requests/collectExtractProps");
47
- const componentInfos_1 = require("@vue/typescript-plugin/lib/requests/componentInfos");
47
+ const getComponentDirectives_1 = require("@vue/typescript-plugin/lib/requests/getComponentDirectives");
48
+ const getComponentEvents_1 = require("@vue/typescript-plugin/lib/requests/getComponentEvents");
49
+ const getComponentNames_1 = require("@vue/typescript-plugin/lib/requests/getComponentNames");
50
+ const getComponentProps_1 = require("@vue/typescript-plugin/lib/requests/getComponentProps");
51
+ const getElementAttrs_1 = require("@vue/typescript-plugin/lib/requests/getElementAttrs");
48
52
  const getImportPathForFile_1 = require("@vue/typescript-plugin/lib/requests/getImportPathForFile");
49
53
  const getPropertiesAtLocation_1 = require("@vue/typescript-plugin/lib/requests/getPropertiesAtLocation");
50
54
  const vscode_uri_1 = require("vscode-uri");
@@ -106,19 +110,19 @@ function getFullLanguageServicePlugins(ts, { disableAutoImportCache } = {}) {
106
110
  return await getImportPathForFile_1.getImportPathForFile.apply(requestContext, args);
107
111
  },
108
112
  async getComponentEvents(...args) {
109
- return await componentInfos_1.getComponentEvents.apply(requestContext, args);
113
+ return await getComponentEvents_1.getComponentEvents.apply(requestContext, args);
114
+ },
115
+ async getComponentDirectives(...args) {
116
+ return await getComponentDirectives_1.getComponentDirectives.apply(requestContext, args);
110
117
  },
111
118
  async getComponentNames(...args) {
112
- return await componentInfos_1.getComponentNames.apply(requestContext, args);
119
+ return await getComponentNames_1.getComponentNames.apply(requestContext, args);
113
120
  },
114
121
  async getComponentProps(...args) {
115
- return await componentInfos_1.getComponentProps.apply(requestContext, args);
122
+ return await getComponentProps_1.getComponentProps.apply(requestContext, args);
116
123
  },
117
124
  async getElementAttrs(...args) {
118
- return await componentInfos_1.getElementAttrs.apply(requestContext, args);
119
- },
120
- async getTemplateContextProps(...args) {
121
- return await componentInfos_1.getTemplateContextProps.apply(requestContext, args);
125
+ return await getElementAttrs_1.getElementAttrs.apply(requestContext, args);
122
126
  },
123
127
  async getQuickInfoAtPosition(fileName, position) {
124
128
  const languageService = context.getLanguageService();
@@ -197,6 +197,6 @@ function getTemplateTagsAndAttrs(sourceFile) {
197
197
  });
198
198
  map.set(sourceFile, getter);
199
199
  }
200
- return map.get(sourceFile).get() ?? new Map();
200
+ return map.get(sourceFile)() ?? new Map();
201
201
  }
202
202
  //# sourceMappingURL=nameCasing.js.map
@@ -0,0 +1,3 @@
1
+ import type { TextDocument } from 'vscode-languageserver-textdocument';
2
+ export declare function sleep(ms: number): Promise<unknown>;
3
+ export declare function isTsDocument(document: TextDocument): boolean;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sleep = sleep;
4
+ exports.isTsDocument = isTsDocument;
5
+ function sleep(ms) {
6
+ return new Promise(resolve => setTimeout(resolve, ms));
7
+ }
8
+ function isTsDocument(document) {
9
+ return document.languageId === 'javascript' ||
10
+ document.languageId === 'typescript' ||
11
+ document.languageId === 'javascriptreact' ||
12
+ document.languageId === 'typescriptreact';
13
+ }
14
+ //# sourceMappingURL=utils.js.map
@@ -1,11 +1,2 @@
1
1
  import type { LanguageServiceContext, LanguageServicePlugin } from '@volar/language-service';
2
- import type * as ts from 'typescript';
3
- import type { TextDocument } from 'vscode-languageserver-textdocument';
4
2
  export declare function create(ts: typeof import('typescript'), getTsPluginClient?: (context: LanguageServiceContext) => typeof import('@vue/typescript-plugin/lib/client') | undefined): LanguageServicePlugin;
5
- export declare function isTsDocument(document: TextDocument): boolean;
6
- export declare function isCharacterTyping(document: TextDocument, change: {
7
- text: string;
8
- rangeOffset: number;
9
- rangeLength: number;
10
- }): boolean;
11
- export declare function isBlacklistNode(ts: typeof import('typescript'), node: ts.Node, pos: number, allowAccessDotValue: boolean): boolean;
@@ -1,20 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.create = create;
4
- exports.isTsDocument = isTsDocument;
5
- exports.isCharacterTyping = isCharacterTyping;
6
- exports.isBlacklistNode = isBlacklistNode;
7
4
  const language_core_1 = require("@vue/language-core");
8
5
  const vscode_uri_1 = require("vscode-uri");
9
- const asts = new WeakMap();
10
- function getAst(ts, fileName, snapshot, scriptKind) {
11
- let ast = asts.get(snapshot);
12
- if (!ast) {
13
- ast = ts.createSourceFile(fileName, snapshot.getText(0, snapshot.getLength()), ts.ScriptTarget.Latest, undefined, scriptKind);
14
- asts.set(snapshot, ast);
15
- }
16
- return ast;
17
- }
6
+ const utils_1 = require("./utils");
18
7
  function create(ts, getTsPluginClient) {
19
8
  return {
20
9
  name: 'vue-autoinsert-dotvalue',
@@ -33,7 +22,7 @@ function create(ts, getTsPluginClient) {
33
22
  if (document.offsetAt(selection) !== change.rangeOffset + change.text.length) {
34
23
  return;
35
24
  }
36
- if (!isTsDocument(document)) {
25
+ if (!(0, utils_1.isTsDocument)(document)) {
37
26
  return;
38
27
  }
39
28
  if (!isCharacterTyping(document, change)) {
@@ -41,7 +30,7 @@ function create(ts, getTsPluginClient) {
41
30
  }
42
31
  const req = ++currentReq;
43
32
  // Wait for tsserver to sync
44
- await sleep(250);
33
+ await (0, utils_1.sleep)(250);
45
34
  if (req !== currentReq) {
46
35
  return;
47
36
  }
@@ -53,41 +42,44 @@ function create(ts, getTsPluginClient) {
53
42
  const decoded = context.decodeEmbeddedDocumentUri(uri);
54
43
  const sourceScript = decoded && context.language.scripts.get(decoded[0]);
55
44
  const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
56
- if (!sourceScript) {
45
+ if (!sourceScript?.generated || !virtualCode) {
46
+ return;
47
+ }
48
+ const root = sourceScript.generated.root;
49
+ if (!(root instanceof language_core_1.VueVirtualCode)) {
50
+ return;
51
+ }
52
+ const blocks = [
53
+ root._sfc.script,
54
+ root._sfc.scriptSetup,
55
+ ].filter(block => !!block);
56
+ if (!blocks.length) {
57
57
  return;
58
58
  }
59
- let ast;
60
59
  let sourceCodeOffset = document.offsetAt(selection);
61
- const fileName = context.project.typescript?.uriConverter.asFileName(sourceScript.id)
62
- ?? sourceScript.id.fsPath.replace(/\\/g, '/');
63
- if (sourceScript.generated) {
64
- const serviceScript = sourceScript.generated.languagePlugin.typescript?.getServiceScript(sourceScript.generated.root);
65
- if (!serviceScript || serviceScript?.code !== virtualCode) {
66
- return;
67
- }
68
- ast = getAst(ts, fileName, virtualCode.snapshot, serviceScript.scriptKind);
69
- let mapped = false;
70
- for (const [_sourceScript, map] of context.language.maps.forEach(virtualCode)) {
71
- for (const [sourceOffset] of map.toSourceLocation(document.offsetAt(selection))) {
72
- sourceCodeOffset = sourceOffset;
73
- mapped = true;
74
- break;
75
- }
76
- if (mapped) {
77
- break;
78
- }
60
+ let mapped = false;
61
+ for (const [, map] of context.language.maps.forEach(virtualCode)) {
62
+ for (const [sourceOffset] of map.toSourceLocation(sourceCodeOffset)) {
63
+ sourceCodeOffset = sourceOffset;
64
+ mapped = true;
65
+ break;
79
66
  }
80
- if (!mapped) {
81
- return;
67
+ if (mapped) {
68
+ break;
82
69
  }
83
70
  }
84
- else {
85
- ast = getAst(ts, fileName, sourceScript.snapshot);
86
- }
87
- if (isBlacklistNode(ts, ast, document.offsetAt(selection), false)) {
71
+ if (!mapped) {
88
72
  return;
89
73
  }
90
- const props = await tsPluginClient?.getPropertiesAtLocation(fileName, sourceCodeOffset) ?? [];
74
+ for (const { ast, startTagEnd, endTagStart } of blocks) {
75
+ if (sourceCodeOffset < startTagEnd || sourceCodeOffset > endTagStart) {
76
+ continue;
77
+ }
78
+ if (isBlacklistNode(ts, ast, sourceCodeOffset - startTagEnd, false)) {
79
+ return;
80
+ }
81
+ }
82
+ const props = await tsPluginClient?.getPropertiesAtLocation(root.fileName, sourceCodeOffset) ?? [];
91
83
  if (props.some(prop => prop === 'value')) {
92
84
  return '${1:.value}';
93
85
  }
@@ -96,15 +88,6 @@ function create(ts, getTsPluginClient) {
96
88
  },
97
89
  };
98
90
  }
99
- function sleep(ms) {
100
- return new Promise(resolve => setTimeout(resolve, ms));
101
- }
102
- function isTsDocument(document) {
103
- return document.languageId === 'javascript' ||
104
- document.languageId === 'typescript' ||
105
- document.languageId === 'javascriptreact' ||
106
- document.languageId === 'typescriptreact';
107
- }
108
91
  const charReg = /\w/;
109
92
  function isCharacterTyping(document, change) {
110
93
  const lastCharacter = change.text[change.text.length - 1];
@@ -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 vscode_uri_1 = require("vscode-uri");
6
- const vue_autoinsert_dotvalue_1 = require("./vue-autoinsert-dotvalue");
6
+ const utils_1 = require("./utils");
7
7
  function create() {
8
8
  return {
9
9
  name: 'vue-complete-define-assignment',
@@ -14,7 +14,7 @@ function create() {
14
14
  return {
15
15
  isAdditionalCompletion: true,
16
16
  async provideCompletionItems(document) {
17
- if (!(0, vue_autoinsert_dotvalue_1.isTsDocument)(document)) {
17
+ if (!(0, utils_1.isTsDocument)(document)) {
18
18
  return;
19
19
  }
20
20
  const enabled = await context.env.getConfiguration?.('vue.complete.defineAssignment') ?? true;
@@ -34,7 +34,7 @@ function create() {
34
34
  }
35
35
  const codegen = language_core_1.tsCodegen.get(root._sfc);
36
36
  const scriptSetup = root._sfc.scriptSetup;
37
- const scriptSetupRanges = codegen?.scriptSetupRanges.get();
37
+ const scriptSetupRanges = codegen?.getScriptSetupRanges();
38
38
  if (!scriptSetup || !scriptSetupRanges) {
39
39
  return;
40
40
  }
@@ -91,7 +91,7 @@ function create(ts, getTsPluginClient) {
91
91
  + (lastImportNode ? '' : '\n'),
92
92
  });
93
93
  if (sfc.script) {
94
- const edit = (0, vue_extract_file_1.createAddComponentToOptionEdit)(ts, sfc.script.ast, newName);
94
+ const edit = (0, vue_extract_file_1.createAddComponentToOptionEdit)(ts, sfc, sfc.script.ast, newName);
95
95
  if (edit) {
96
96
  additionalEdit.changes[embeddedDocumentUriStr].push({
97
97
  range: {
@@ -25,7 +25,7 @@ function create() {
25
25
  }
26
26
  const result = [];
27
27
  const codegen = language_core_1.tsCodegen.get(root._sfc);
28
- const scopedClasses = codegen?.generatedTemplate.get()?.scopedClasses ?? [];
28
+ const scopedClasses = codegen?.getGeneratedTemplate()?.scopedClasses ?? [];
29
29
  const styleClasses = new Map();
30
30
  const option = root.vueCompilerOptions.experimentalResolveStyleCssClasses;
31
31
  for (let i = 0; i < root._sfc.styles.length; i++) {
@@ -1,8 +1,9 @@
1
1
  import type { LanguageServiceContext, LanguageServicePlugin } from '@volar/language-service';
2
+ import { Sfc } from '@vue/language-core';
2
3
  import type * as ts from 'typescript';
3
4
  export declare function create(ts: typeof import('typescript'), getTsPluginClient?: (context: LanguageServiceContext) => typeof import('@vue/typescript-plugin/lib/client') | undefined): LanguageServicePlugin;
4
5
  export declare function getLastImportNode(ts: typeof import('typescript'), sourceFile: ts.SourceFile): ts.Node | undefined;
5
- export declare function createAddComponentToOptionEdit(ts: typeof import('typescript'), ast: ts.SourceFile, componentName: string): {
6
+ export declare function createAddComponentToOptionEdit(ts: typeof import('typescript'), sfc: Sfc, ast: ts.SourceFile, componentName: string): {
6
7
  range: import("@vue/language-core").TextRange;
7
8
  newText: string;
8
9
  } | undefined;
@@ -11,13 +11,17 @@ function create(ts, getTsPluginClient) {
11
11
  name: 'vue-extract-file',
12
12
  capabilities: {
13
13
  codeActionProvider: {
14
+ codeActionKinds: ['refactor'],
14
15
  resolveProvider: true,
15
16
  },
16
17
  },
17
18
  create(context) {
18
19
  const tsPluginClient = getTsPluginClient?.(context);
19
20
  return {
20
- provideCodeActions(document, range, _context) {
21
+ provideCodeActions(document, range, ctx) {
22
+ if (ctx.only && !ctx.only.includes('refactor')) {
23
+ return;
24
+ }
21
25
  const startOffset = document.offsetAt(range.start);
22
26
  const endOffset = document.offsetAt(range.end);
23
27
  if (startOffset === endOffset) {
@@ -118,7 +122,7 @@ function create(ts, getTsPluginClient) {
118
122
  },
119
123
  ];
120
124
  if (sfc.script) {
121
- const edit = createAddComponentToOptionEdit(ts, sfc.script.ast, newName);
125
+ const edit = createAddComponentToOptionEdit(ts, sfc, sfc.script.ast, newName);
122
126
  if (edit) {
123
127
  sfcEdits.push({
124
128
  range: {
@@ -247,11 +251,12 @@ function getLastImportNode(ts, sourceFile) {
247
251
  }
248
252
  return lastImportNode;
249
253
  }
250
- function createAddComponentToOptionEdit(ts, ast, componentName) {
251
- const exportDefault = language_core_1.scriptRanges.parseScriptRanges(ts, ast, false, true).exportDefault;
252
- if (!exportDefault) {
254
+ function createAddComponentToOptionEdit(ts, sfc, ast, componentName) {
255
+ const scriptRanges = language_core_1.tsCodegen.get(sfc)?.getScriptRanges();
256
+ if (!scriptRanges?.exportDefault) {
253
257
  return;
254
258
  }
259
+ const { exportDefault } = scriptRanges;
255
260
  // https://github.com/microsoft/TypeScript/issues/36174
256
261
  const printer = ts.createPrinter();
257
262
  if (exportDefault.componentsOption && exportDefault.componentsOptionNode) {
@@ -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: Set<string>): [ts.Identifier, boolean][];
7
+ export declare function findDestructuredProps(ts: typeof import('typescript'), ast: ts.SourceFile, props: MapIterator<string>): [ts.Identifier, boolean][];
@@ -28,15 +28,15 @@ function create(ts) {
28
28
  const result = [];
29
29
  const codegen = language_core_1.tsCodegen.get(virtualCode._sfc);
30
30
  const inlayHints = [
31
- ...codegen?.generatedTemplate.get()?.inlayHints ?? [],
32
- ...codegen?.generatedScript.get()?.inlayHints ?? [],
31
+ ...codegen?.getGeneratedTemplate()?.inlayHints ?? [],
32
+ ...codegen?.getGeneratedScript()?.inlayHints ?? [],
33
33
  ];
34
- const scriptSetupRanges = codegen?.scriptSetupRanges.get();
34
+ const scriptSetupRanges = codegen?.getScriptSetupRanges();
35
35
  if (scriptSetupRanges?.defineProps?.destructured && virtualCode._sfc.scriptSetup?.ast) {
36
36
  const setting = 'vue.inlayHints.destructuredProps';
37
37
  const enabled = await getSettingEnabled(setting);
38
38
  if (enabled) {
39
- for (const [prop, isShorthand] of findDestructuredProps(ts, virtualCode._sfc.scriptSetup.ast, scriptSetupRanges.defineProps.destructured)) {
39
+ for (const [prop, isShorthand] of findDestructuredProps(ts, virtualCode._sfc.scriptSetup.ast, scriptSetupRanges.defineProps.destructured.keys())) {
40
40
  const name = prop.text;
41
41
  const end = prop.getEnd();
42
42
  const pos = isShorthand ? end : end - name.length;
@@ -148,7 +148,7 @@ function findDestructuredProps(ts, ast, props) {
148
148
  && initializer
149
149
  && ts.isCallExpression(initializer)
150
150
  && initializer.expression.getText(ast) === 'defineProps';
151
- for (const [id] of (0, index_1.collectIdentifiers)(ts, name)) {
151
+ for (const { id } of (0, index_1.collectIdentifiers)(ts, name)) {
152
152
  if (isDefineProps) {
153
153
  excludedIds.add(id);
154
154
  }
@@ -163,7 +163,7 @@ function findDestructuredProps(ts, ast, props) {
163
163
  registerLocalBinding(name);
164
164
  }
165
165
  for (const p of parameters) {
166
- for (const [id] of (0, index_1.collectIdentifiers)(ts, p)) {
166
+ for (const { id } of (0, index_1.collectIdentifiers)(ts, p)) {
167
167
  registerLocalBinding(id);
168
168
  }
169
169
  }
@@ -30,7 +30,7 @@ function create(mode, ts, getTsPluginClient) {
30
30
  let customData = [];
31
31
  let extraCustomData = [];
32
32
  let lastCompletionComponentNames = new Set();
33
- const tsDocumentations = new Map();
33
+ const cachedPropInfos = new Map();
34
34
  const onDidChangeCustomDataListeners = new Set();
35
35
  const onDidChangeCustomData = (listener) => {
36
36
  onDidChangeCustomDataListeners.add(listener);
@@ -131,7 +131,6 @@ function create(mode, ts, getTsPluginClient) {
131
131
  if (!context.project.vue) {
132
132
  return;
133
133
  }
134
- const vueCompilerOptions = context.project.vue.compilerOptions;
135
134
  let sync;
136
135
  let currentVersion;
137
136
  const uri = vscode_uri_1.URI.parse(document.uri);
@@ -141,7 +140,7 @@ function create(mode, ts, getTsPluginClient) {
141
140
  if (root instanceof language_core_1.VueVirtualCode) {
142
141
  // #4298: Precompute HTMLDocument before provideHtmlData to avoid parseHTMLDocument requesting component names from tsserver
143
142
  baseServiceInstance.provideCompletionItems?.(document, position, completionContext, token);
144
- sync = (await provideHtmlData(vueCompilerOptions, sourceScript.id, root)).sync;
143
+ sync = (await provideHtmlData(sourceScript.id, root)).sync;
145
144
  currentVersion = await sync();
146
145
  }
147
146
  let htmlComplete = await baseServiceInstance.provideCompletionItems?.(document, position, completionContext, token);
@@ -378,7 +377,7 @@ function create(mode, ts, getTsPluginClient) {
378
377
  });
379
378
  },
380
379
  };
381
- async function provideHtmlData(vueCompilerOptions, sourceDocumentUri, vueCode) {
380
+ async function provideHtmlData(sourceDocumentUri, vueCode) {
382
381
  await (initializing ??= initialize());
383
382
  const casing = await (0, nameCasing_1.getNameCasing)(context, sourceDocumentUri);
384
383
  if (builtInData.tags) {
@@ -401,8 +400,7 @@ function create(mode, ts, getTsPluginClient) {
401
400
  const tagInfos = new Map();
402
401
  let version = 0;
403
402
  let components;
404
- let templateContextProps;
405
- tsDocumentations.clear();
403
+ cachedPropInfos.clear();
406
404
  updateExtraCustomData([
407
405
  html.newHTMLDataProvider('vue-template-built-in', builtInData),
408
406
  {
@@ -422,9 +420,7 @@ function create(mode, ts, getTsPluginClient) {
422
420
  })());
423
421
  return [];
424
422
  }
425
- const scriptSetupRanges = vueCode._sfc.scriptSetup
426
- ? (0, language_core_1.parseScriptSetupRanges)(ts, vueCode._sfc.scriptSetup.ast, vueCompilerOptions)
427
- : undefined;
423
+ const scriptSetupRanges = language_core_1.tsCodegen.get(vueCode._sfc)?.getScriptSetupRanges();
428
424
  const names = new Set();
429
425
  const tags = [];
430
426
  for (const tag of components) {
@@ -457,44 +453,24 @@ function create(mode, ts, getTsPluginClient) {
457
453
  if (!tagInfo) {
458
454
  promises.push((async () => {
459
455
  const attrs = await tsPluginClient?.getElementAttrs(vueCode.fileName, tag) ?? [];
460
- const propsInfo = await tsPluginClient?.getComponentProps(vueCode.fileName, tag) ?? [];
456
+ const propInfos = await tsPluginClient?.getComponentProps(vueCode.fileName, tag) ?? [];
461
457
  const events = await tsPluginClient?.getComponentEvents(vueCode.fileName, tag) ?? [];
458
+ const directives = await tsPluginClient?.getComponentDirectives(vueCode.fileName) ?? [];
462
459
  tagInfos.set(tag, {
463
460
  attrs,
464
- propsInfo: propsInfo.filter(prop => !prop.name.startsWith('ref_')),
461
+ propInfos: propInfos.filter(prop => !prop.name.startsWith('ref_')),
465
462
  events,
463
+ directives,
466
464
  });
467
465
  version++;
468
466
  })());
469
467
  return [];
470
468
  }
471
- const { attrs, propsInfo, events } = tagInfo;
472
- const props = propsInfo.map(prop => (0, language_core_1.hyphenateTag)(prop.name).startsWith('on-vnode-')
469
+ const { attrs, propInfos, events, directives } = tagInfo;
470
+ const props = propInfos.map(prop => (0, language_core_1.hyphenateTag)(prop.name).startsWith('on-vnode-')
473
471
  ? 'onVue:' + prop.name.slice('onVnode'.length)
474
472
  : prop.name);
475
473
  const attributes = [];
476
- const _tsCodegen = language_core_1.tsCodegen.get(vueCode._sfc);
477
- if (_tsCodegen) {
478
- if (!templateContextProps) {
479
- promises.push((async () => {
480
- templateContextProps = await tsPluginClient?.getTemplateContextProps(vueCode.fileName) ?? [];
481
- version++;
482
- })());
483
- return [];
484
- }
485
- let ctxVars = [
486
- ..._tsCodegen.scriptRanges.get()?.bindings.map(({ range }) => vueCode._sfc.script.content.slice(range.start, range.end)) ?? [],
487
- ..._tsCodegen.scriptSetupRanges.get()?.bindings.map(({ range }) => vueCode._sfc.scriptSetup.content.slice(range.start, range.end)) ?? [],
488
- ...templateContextProps,
489
- ];
490
- ctxVars = [...new Set(ctxVars)];
491
- const dirs = ctxVars.map(language_core_1.hyphenateAttr).filter(v => v.startsWith('v-'));
492
- for (const dir of dirs) {
493
- attributes.push({
494
- name: dir,
495
- });
496
- }
497
- }
498
474
  const propsSet = new Set(props);
499
475
  for (const prop of [...props, ...attrs]) {
500
476
  const isGlobal = !propsSet.has(prop);
@@ -515,13 +491,13 @@ function create(mode, ts, getTsPluginClient) {
515
491
  }
516
492
  else {
517
493
  const propName = name;
518
- const propKey = generateItemKey('componentProp', isGlobal ? '*' : tag, propName);
519
- const propDescription = propsInfo.find(prop => {
494
+ const propInfo = propInfos.find(prop => {
520
495
  const name = casing.attr === types_1.AttrNameCasing.Camel ? prop.name : (0, language_core_1.hyphenateAttr)(prop.name);
521
496
  return name === propName;
522
- })?.commentMarkdown;
523
- if (propDescription) {
524
- tsDocumentations.set(propName, propDescription);
497
+ });
498
+ const propKey = generateItemKey('componentProp', isGlobal ? '*' : tag, propName, propInfo?.deprecated);
499
+ if (propInfo) {
500
+ cachedPropInfos.set(propName, propInfo);
525
501
  }
526
502
  attributes.push({
527
503
  name: propName,
@@ -546,6 +522,12 @@ function create(mode, ts, getTsPluginClient) {
546
522
  description: propKey,
547
523
  });
548
524
  }
525
+ for (const directive of directives) {
526
+ const name = (0, language_core_1.hyphenateAttr)(directive);
527
+ attributes.push({
528
+ name
529
+ });
530
+ }
549
531
  const models = [];
550
532
  for (const prop of [...props, ...attrs]) {
551
533
  if (prop.startsWith('onUpdate:')) {
@@ -652,7 +634,7 @@ function create(mode, ts, getTsPluginClient) {
652
634
  const htmlDocumentations = new Map();
653
635
  for (const item of completionList.items) {
654
636
  const documentation = typeof item.documentation === 'string' ? item.documentation : item.documentation?.value;
655
- if (documentation && !isItemKey(documentation) && item.documentation) {
637
+ if (documentation && !isItemKey(documentation)) {
656
638
  htmlDocumentations.set(item.label, documentation);
657
639
  }
658
640
  }
@@ -675,10 +657,12 @@ function create(mode, ts, getTsPluginClient) {
675
657
  }
676
658
  const itemKeyStr = typeof item.documentation === 'string' ? item.documentation : item.documentation?.value;
677
659
  let parsedItemKey = itemKeyStr ? parseItemKey(itemKeyStr) : undefined;
660
+ let propInfo;
678
661
  if (parsedItemKey) {
679
662
  const documentations = [];
680
- if (tsDocumentations.has(parsedItemKey.prop)) {
681
- documentations.push(tsDocumentations.get(parsedItemKey.prop));
663
+ propInfo = cachedPropInfos.get(parsedItemKey.prop);
664
+ if (propInfo?.commentMarkdown) {
665
+ documentations.push(propInfo.commentMarkdown);
682
666
  }
683
667
  let { isEvent, propName } = getPropName(parsedItemKey);
684
668
  if (isEvent) {
@@ -712,20 +696,25 @@ function create(mode, ts, getTsPluginClient) {
712
696
  type: 'componentProp',
713
697
  tag: '^',
714
698
  prop: propName,
699
+ deprecated: false,
715
700
  leadingSlash: false
716
701
  };
717
702
  }
718
- if (tsDocumentations.has(propName)) {
703
+ propInfo = cachedPropInfos.get(propName);
704
+ if (propInfo?.commentMarkdown) {
719
705
  const originalDocumentation = typeof item.documentation === 'string' ? item.documentation : item.documentation?.value;
720
706
  item.documentation = {
721
707
  kind: 'markdown',
722
708
  value: [
723
- tsDocumentations.get(propName),
709
+ propInfo.commentMarkdown,
724
710
  originalDocumentation,
725
711
  ].filter(str => !!str).join('\n\n'),
726
712
  };
727
713
  }
728
714
  }
715
+ if (propInfo?.deprecated) {
716
+ item.tags = [1];
717
+ }
729
718
  const tokens = [];
730
719
  if (item.kind === 10
731
720
  && lastCompletionComponentNames.has((0, language_core_1.hyphenateTag)(item.label))) {
@@ -850,8 +839,8 @@ function parseLabel(label) {
850
839
  leadingSlash
851
840
  };
852
841
  }
853
- function generateItemKey(type, tag, prop) {
854
- return '__VLS_data=' + type + ',' + tag + ',' + prop;
842
+ function generateItemKey(type, tag, prop, deprecated) {
843
+ return `__VLS_data=${type},${tag},${prop},${Number(deprecated)}`;
855
844
  }
856
845
  function isItemKey(key) {
857
846
  return key.startsWith('__VLS_data=');
@@ -864,6 +853,7 @@ function parseItemKey(key) {
864
853
  type: strs[0],
865
854
  tag: strs[1],
866
855
  prop: strs[2],
856
+ deprecated: strs[3] === '1',
867
857
  leadingSlash
868
858
  };
869
859
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vue/language-service",
3
- "version": "2.2.0",
3
+ "version": "2.2.2",
4
4
  "license": "MIT",
5
5
  "files": [
6
6
  "data",
@@ -21,10 +21,10 @@
21
21
  "@volar/language-service": "~2.4.11",
22
22
  "@volar/typescript": "~2.4.11",
23
23
  "@vue/compiler-dom": "^3.5.0",
24
- "@vue/language-core": "2.2.0",
24
+ "@vue/language-core": "2.2.2",
25
25
  "@vue/shared": "^3.5.0",
26
- "@vue/typescript-plugin": "2.2.0",
27
- "alien-signals": "^0.4.9",
26
+ "@vue/typescript-plugin": "2.2.2",
27
+ "alien-signals": "^1.0.3",
28
28
  "path-browserify": "^1.0.1",
29
29
  "volar-service-css": "0.0.62",
30
30
  "volar-service-emmet": "0.0.62",
@@ -39,10 +39,10 @@
39
39
  "vscode-uri": "^3.0.8"
40
40
  },
41
41
  "devDependencies": {
42
- "@types/node": "latest",
43
- "@types/path-browserify": "latest",
42
+ "@types/node": "^22.10.4",
43
+ "@types/path-browserify": "^1.0.1",
44
44
  "@volar/kit": "~2.4.11",
45
45
  "vscode-languageserver-protocol": "^3.17.5"
46
46
  },
47
- "gitHead": "5babca774658d4b9afbe877ac7c8cafdaecf2c3e"
47
+ "gitHead": "30757908b67f40f779c36795665163634fb81868"
48
48
  }