@vue/language-service 3.1.4 → 3.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -79,7 +79,7 @@
79
79
  "name": "v-text",
80
80
  "description": {
81
81
  "kind": "markdown",
82
- "value": "Обновление текстового содержимого элемента.\n\n- **Ожидает:** `string`\n\n- **Подробности**\n\n `v-text` работает путём установки свойства [textContent](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent) элемента, поэтому он будет перезаписывать всё существующее содержимое внутри элемента. Если необходимо обновить часть `textContent`, то вместо этого следует использовать [текстовые интерполяции](https://ru.vuejs.org/guide/essentials/template-syntax.html#text-interpolation).\n\n- **Пример**\n\n ```html\n <span v-text=\"msg\"></span>\n <!-- тоже самое -->\n <span>{{msg}}</span>\n ```\n\n- **См. также** [Синтаксис шаблонов - Текстовые интерполяции](https://ru.vuejs.org/guide/essentials/template-syntax.html#text-interpolation)"
82
+ "value": "Обновление текстового содержимого элемента.\n\n- **Ожидает:** `string`\n\n- **Подробности**\n\n `v-text` работает путём установки свойства [textContent](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent) элемента, поэтому он будет перезаписывать всё существующее содержимое внутри элемента. Если необходимо обновить только часть `textContent`, то вместо этого следует использовать [текстовые интерполяции](https://ru.vuejs.org/guide/essentials/template-syntax.html#text-interpolation) (то есть <span v-pre>`<span>Оставьте это, но обновите {{dynamicPortion}}</span>`</span>).\n\n- **Пример**\n\n ```html\n <span v-text=\"msg\"></span>\n <!-- тоже самое -->\n <span>{{msg}}</span>\n ```\n\n- **См. также** [Синтаксис шаблонов - Текстовые интерполяции](https://ru.vuejs.org/guide/essentials/template-syntax.html#text-interpolation)"
83
83
  },
84
84
  "references": "api/built-in-directives.html#v-text"
85
85
  },
package/index.js CHANGED
@@ -34,6 +34,7 @@ const vue_directive_comments_1 = require("./lib/plugins/vue-directive-comments")
34
34
  const vue_document_drop_1 = require("./lib/plugins/vue-document-drop");
35
35
  const vue_document_highlights_1 = require("./lib/plugins/vue-document-highlights");
36
36
  const vue_extract_file_1 = require("./lib/plugins/vue-extract-file");
37
+ const vue_format_per_block_1 = require("./lib/plugins/vue-format-per-block");
37
38
  const vue_global_types_error_1 = require("./lib/plugins/vue-global-types-error");
38
39
  const vue_inlayhints_1 = require("./lib/plugins/vue-inlayhints");
39
40
  const vue_missing_props_hints_1 = require("./lib/plugins/vue-missing-props-hints");
@@ -50,16 +51,15 @@ function createVueLanguageServicePlugins(ts, client = new Proxy({}, {
50
51
  },
51
52
  })) {
52
53
  return [
53
- (0, css_1.create)(),
54
54
  (0, volar_service_json_1.create)(),
55
55
  (0, volar_service_pug_beautify_1.create)(),
56
+ (0, vue_format_per_block_1.create)(),
56
57
  (0, vue_autoinsert_space_1.create)(),
57
58
  (0, vue_compiler_dom_errors_1.create)(),
58
59
  (0, vue_directive_comments_1.create)(),
59
60
  (0, vue_global_types_error_1.create)(),
60
61
  (0, vue_scoped_class_links_1.create)(),
61
62
  (0, vue_sfc_1.create)(),
62
- (0, vue_suggest_define_assignment_1.create)(),
63
63
  (0, vue_template_ref_links_1.create)(),
64
64
  (0, volar_service_emmet_1.create)({
65
65
  mappedLanguages: {
@@ -68,10 +68,12 @@ function createVueLanguageServicePlugins(ts, client = new Proxy({}, {
68
68
  },
69
69
  }),
70
70
  // TS related plugins
71
+ (0, vue_suggest_define_assignment_1.create)(ts),
71
72
  (0, docCommentTemplate_1.create)(ts),
72
73
  (0, syntactic_1.create)(ts),
73
74
  (0, vue_inlayhints_1.create)(ts),
74
75
  // type aware plugins
76
+ (0, css_1.create)(client),
75
77
  (0, typescript_semantic_tokens_1.create)(client),
76
78
  (0, vue_autoinsert_dotvalue_1.create)(ts, client),
77
79
  (0, vue_component_semantic_tokens_1.create)(client),
@@ -79,8 +81,8 @@ function createVueLanguageServicePlugins(ts, client = new Proxy({}, {
79
81
  (0, vue_document_highlights_1.create)(client),
80
82
  (0, vue_extract_file_1.create)(ts, client),
81
83
  (0, vue_missing_props_hints_1.create)(client),
82
- (0, vue_template_1.create)('html', client),
83
- (0, vue_template_1.create)('jade', client),
84
+ (0, vue_template_1.create)(ts, 'html', client),
85
+ (0, vue_template_1.create)(ts, 'jade', client),
84
86
  (0, vue_twoslash_queries_1.create)(client),
85
87
  ];
86
88
  }
@@ -0,0 +1,2 @@
1
+ import { type HTMLFormatConfiguration, Range, type TextDocument, type TextEdit } from 'vscode-html-languageservice';
2
+ export declare function format(document: TextDocument, range: Range | undefined, options: HTMLFormatConfiguration, voidElements?: string[]): TextEdit[];
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.format = format;
4
+ // @ts-expect-error
5
+ const beautify = require("vscode-html-languageservice/lib/umd/beautify/beautify-html.js");
6
+ // @ts-expect-error
7
+ const strings = require("vscode-html-languageservice/lib/umd/utils/strings.js");
8
+ /*
9
+ * original file: https://github.com/microsoft/vscode-html-languageservice/blob/main/src/services/htmlFormatter.ts
10
+ * commit: a134f3050c22fe80954241467cd429811792a81d (2024-03-22)
11
+ * purpose: override to add void_elements option
12
+ */
13
+ /*---------------------------------------------------------------------------------------------
14
+ * Copyright (c) Microsoft Corporation. All rights reserved.
15
+ * Licensed under the MIT License. See License.txt in the project root for license information.
16
+ *--------------------------------------------------------------------------------------------*/
17
+ const vscode_html_languageservice_1 = require("vscode-html-languageservice");
18
+ function format(document, range, options, voidElements) {
19
+ let value = document.getText();
20
+ let includesEnd = true;
21
+ let initialIndentLevel = 0;
22
+ const tabSize = options.tabSize || 4;
23
+ if (range) {
24
+ let startOffset = document.offsetAt(range.start);
25
+ // include all leading whitespace iff at the beginning of the line
26
+ let extendedStart = startOffset;
27
+ while (extendedStart > 0 && isWhitespace(value, extendedStart - 1)) {
28
+ extendedStart--;
29
+ }
30
+ if (extendedStart === 0 || isEOL(value, extendedStart - 1)) {
31
+ startOffset = extendedStart;
32
+ }
33
+ else {
34
+ // else keep at least one whitespace
35
+ if (extendedStart < startOffset) {
36
+ startOffset = extendedStart + 1;
37
+ }
38
+ }
39
+ // include all following whitespace until the end of the line
40
+ let endOffset = document.offsetAt(range.end);
41
+ let extendedEnd = endOffset;
42
+ while (extendedEnd < value.length && isWhitespace(value, extendedEnd)) {
43
+ extendedEnd++;
44
+ }
45
+ if (extendedEnd === value.length || isEOL(value, extendedEnd)) {
46
+ endOffset = extendedEnd;
47
+ }
48
+ range = vscode_html_languageservice_1.Range.create(document.positionAt(startOffset), document.positionAt(endOffset));
49
+ // Do not modify if substring starts in inside an element
50
+ // Ending inside an element is fine as it doesn't cause formatting errors
51
+ const firstHalf = value.substring(0, startOffset);
52
+ if (new RegExp(/.*[<][^>]*$/).test(firstHalf)) {
53
+ // return without modification
54
+ value = value.substring(startOffset, endOffset);
55
+ return [{
56
+ range: range,
57
+ newText: value,
58
+ }];
59
+ }
60
+ includesEnd = endOffset === value.length;
61
+ value = value.substring(startOffset, endOffset);
62
+ if (startOffset !== 0) {
63
+ const startOfLineOffset = document.offsetAt(vscode_html_languageservice_1.Position.create(range.start.line, 0));
64
+ initialIndentLevel = computeIndentLevel(document.getText(), startOfLineOffset, options);
65
+ }
66
+ }
67
+ else {
68
+ range = vscode_html_languageservice_1.Range.create(vscode_html_languageservice_1.Position.create(0, 0), document.positionAt(value.length));
69
+ }
70
+ const htmlOptions = {
71
+ indent_size: tabSize,
72
+ indent_char: options.insertSpaces ? ' ' : '\t',
73
+ indent_empty_lines: getFormatOption(options, 'indentEmptyLines', false),
74
+ wrap_line_length: getFormatOption(options, 'wrapLineLength', 120),
75
+ unformatted: getTagsFormatOption(options, 'unformatted', void 0),
76
+ content_unformatted: getTagsFormatOption(options, 'contentUnformatted', void 0),
77
+ indent_inner_html: getFormatOption(options, 'indentInnerHtml', false),
78
+ preserve_newlines: getFormatOption(options, 'preserveNewLines', true),
79
+ max_preserve_newlines: getFormatOption(options, 'maxPreserveNewLines', 32786),
80
+ indent_handlebars: getFormatOption(options, 'indentHandlebars', false),
81
+ end_with_newline: includesEnd && getFormatOption(options, 'endWithNewline', false),
82
+ extra_liners: getTagsFormatOption(options, 'extraLiners', void 0),
83
+ wrap_attributes: getFormatOption(options, 'wrapAttributes', 'auto'),
84
+ wrap_attributes_indent_size: getFormatOption(options, 'wrapAttributesIndentSize', void 0),
85
+ eol: '\n',
86
+ indent_scripts: getFormatOption(options, 'indentScripts', 'normal'),
87
+ templating: getTemplatingFormatOption(options, 'all'),
88
+ unformatted_content_delimiter: getFormatOption(options, 'unformattedContentDelimiter', ''),
89
+ ...voidElements !== undefined && { void_elements: voidElements },
90
+ };
91
+ let result = beautify.html_beautify(trimLeft(value), htmlOptions);
92
+ if (initialIndentLevel > 0) {
93
+ const indent = options.insertSpaces
94
+ ? strings.repeat(' ', tabSize * initialIndentLevel)
95
+ : strings.repeat('\t', initialIndentLevel);
96
+ result = result.split('\n').join('\n' + indent);
97
+ if (range.start.character === 0) {
98
+ result = indent + result; // keep the indent
99
+ }
100
+ }
101
+ return [{
102
+ range: range,
103
+ newText: result,
104
+ }];
105
+ }
106
+ function trimLeft(str) {
107
+ return str.replace(/^\s+/, '');
108
+ }
109
+ function getFormatOption(options, key, dflt) {
110
+ if (options && options.hasOwnProperty(key)) {
111
+ const value = options[key];
112
+ if (value !== null) {
113
+ return value;
114
+ }
115
+ }
116
+ return dflt;
117
+ }
118
+ function getTagsFormatOption(options, key, dflt) {
119
+ const list = getFormatOption(options, key, null);
120
+ if (typeof list === 'string') {
121
+ if (list.length > 0) {
122
+ return list.split(',').map(t => t.trim().toLowerCase());
123
+ }
124
+ return [];
125
+ }
126
+ return dflt;
127
+ }
128
+ function getTemplatingFormatOption(options, dflt) {
129
+ const value = getFormatOption(options, 'templating', dflt);
130
+ if (value === true) {
131
+ return ['auto'];
132
+ }
133
+ if (value === false || value === dflt || Array.isArray(value) === false) {
134
+ return ['none'];
135
+ }
136
+ return value;
137
+ }
138
+ function computeIndentLevel(content, offset, options) {
139
+ let i = offset;
140
+ let nChars = 0;
141
+ const tabSize = options.tabSize || 4;
142
+ while (i < content.length) {
143
+ const ch = content.charAt(i);
144
+ if (ch === ' ') {
145
+ nChars++;
146
+ }
147
+ else if (ch === '\t') {
148
+ nChars += tabSize;
149
+ }
150
+ else {
151
+ break;
152
+ }
153
+ i++;
154
+ }
155
+ return Math.floor(nChars / tabSize);
156
+ }
157
+ function isEOL(text, offset) {
158
+ return '\r\n'.indexOf(text.charAt(offset)) !== -1;
159
+ }
160
+ function isWhitespace(text, offset) {
161
+ return ' \t'.indexOf(text.charAt(offset)) !== -1;
162
+ }
163
+ //# sourceMappingURL=htmlFormatter.js.map
@@ -1,14 +1,12 @@
1
1
  import type { LanguageServiceContext } from '@volar/language-service';
2
2
  import type { URI } from 'vscode-uri';
3
- export declare enum TagNameCasing {
3
+ export declare const enum TagNameCasing {
4
4
  Kebab = 0,
5
5
  Pascal = 1
6
6
  }
7
- export declare enum AttrNameCasing {
7
+ export declare const enum AttrNameCasing {
8
8
  Kebab = 0,
9
9
  Camel = 1
10
10
  }
11
- export declare function checkCasing(context: LanguageServiceContext, uri: URI): Promise<{
12
- tag: TagNameCasing | undefined;
13
- attr: AttrNameCasing | undefined;
14
- }>;
11
+ export declare function getTagNameCasing(context: LanguageServiceContext, uri: URI): Promise<TagNameCasing | undefined>;
12
+ export declare function getAttrNameCasing(context: LanguageServiceContext, uri: URI): Promise<AttrNameCasing | undefined>;
package/lib/nameCasing.js CHANGED
@@ -1,71 +1,62 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AttrNameCasing = exports.TagNameCasing = void 0;
4
- exports.checkCasing = checkCasing;
3
+ exports.getTagNameCasing = getTagNameCasing;
4
+ exports.getAttrNameCasing = getAttrNameCasing;
5
5
  const language_core_1 = require("@vue/language-core");
6
- var TagNameCasing;
7
- (function (TagNameCasing) {
8
- TagNameCasing[TagNameCasing["Kebab"] = 0] = "Kebab";
9
- TagNameCasing[TagNameCasing["Pascal"] = 1] = "Pascal";
10
- })(TagNameCasing || (exports.TagNameCasing = TagNameCasing = {}));
11
- var AttrNameCasing;
12
- (function (AttrNameCasing) {
13
- AttrNameCasing[AttrNameCasing["Kebab"] = 0] = "Kebab";
14
- AttrNameCasing[AttrNameCasing["Camel"] = 1] = "Camel";
15
- })(AttrNameCasing || (exports.AttrNameCasing = AttrNameCasing = {}));
16
- async function checkCasing(context, uri) {
17
- const detected = detect(context, uri);
18
- const [attr, tag] = await Promise.all([
19
- context.env.getConfiguration?.('vue.suggest.propNameCasing', uri.toString()),
20
- context.env.getConfiguration?.('vue.suggest.componentNameCasing', uri.toString()),
21
- ]);
22
- const tagNameCasing = detected.tag.length === 1 && (tag === 'preferPascalCase' || tag === 'preferKebabCase')
23
- ? detected.tag[0]
24
- : (tag === 'preferKebabCase' || tag === 'alwaysKebabCase')
25
- ? TagNameCasing.Kebab
26
- : TagNameCasing.Pascal;
27
- const attrNameCasing = detected.attr.length === 1 && (attr === 'preferCamelCase' || attr === 'preferKebabCase')
28
- ? detected.attr[0]
29
- : (attr === 'preferCamelCase' || attr === 'alwaysCamelCase')
30
- ? AttrNameCasing.Camel
31
- : AttrNameCasing.Kebab;
32
- return {
33
- tag: tagNameCasing,
34
- attr: attrNameCasing,
35
- };
36
- }
37
- const cache = new WeakMap();
38
- function detect(context, uri) {
6
+ const collectCache = new WeakMap();
7
+ async function getTagNameCasing(context, uri) {
8
+ const config = await context.env.getConfiguration?.('vue.suggest.componentNameCasing', uri.toString());
9
+ if (config === 'alwaysKebabCase') {
10
+ return 0 /* TagNameCasing.Kebab */;
11
+ }
12
+ if (config === 'alwaysPascalCase') {
13
+ return 1 /* TagNameCasing.Pascal */;
14
+ }
39
15
  const root = context.language.scripts.get(uri)?.generated?.root;
40
- if (!(root instanceof language_core_1.VueVirtualCode)) {
41
- return { tag: [], attr: [] };
16
+ if (root instanceof language_core_1.VueVirtualCode) {
17
+ const detectedCasings = detectTagCasing(root);
18
+ if (detectedCasings.length === 1) {
19
+ return detectedCasings[0];
20
+ }
21
+ }
22
+ if (config === 'preferKebabCase') {
23
+ return 0 /* TagNameCasing.Kebab */;
42
24
  }
43
- return {
44
- tag: detectTagCasing(root),
45
- attr: detectAttrCasing(root),
46
- };
25
+ return 1 /* TagNameCasing.Pascal */;
47
26
  }
48
- function detectAttrCasing(code) {
49
- let tags;
50
- if (cache.has(code)) {
51
- tags = cache.get(code);
27
+ async function getAttrNameCasing(context, uri) {
28
+ const config = await context.env.getConfiguration?.('vue.suggest.propNameCasing', uri.toString());
29
+ if (config === 'alwaysKebabCase') {
30
+ return 0 /* AttrNameCasing.Kebab */;
31
+ }
32
+ if (config === 'alwaysCamelCase') {
33
+ return 1 /* AttrNameCasing.Camel */;
52
34
  }
53
- else {
54
- cache.set(code, tags = collectTags(code));
35
+ const root = context.language.scripts.get(uri)?.generated?.root;
36
+ if (root instanceof language_core_1.VueVirtualCode) {
37
+ const detectedCasings = detectAttrCasing(root);
38
+ if (detectedCasings.length === 1) {
39
+ return detectedCasings[0];
40
+ }
55
41
  }
42
+ if (config === 'preferKebabCase') {
43
+ return 0 /* AttrNameCasing.Kebab */;
44
+ }
45
+ return 1 /* AttrNameCasing.Camel */;
46
+ }
47
+ function detectAttrCasing(code) {
48
+ const tags = collectTagsWithCache(code);
56
49
  const result = new Set();
57
- for (const [, attrs] of tags ?? []) {
50
+ for (const [, [_, attrs]] of tags) {
58
51
  for (const attr of attrs) {
59
- // attrName
60
52
  if (attr !== (0, language_core_1.hyphenateTag)(attr)) {
61
- result.add(AttrNameCasing.Camel);
53
+ result.add(1 /* AttrNameCasing.Camel */);
62
54
  break;
63
55
  }
64
56
  }
65
57
  for (const attr of attrs) {
66
- // attr-name
67
58
  if (attr.includes('-')) {
68
- result.add(AttrNameCasing.Kebab);
59
+ result.add(0 /* AttrNameCasing.Kebab */);
69
60
  break;
70
61
  }
71
62
  }
@@ -73,39 +64,37 @@ function detectAttrCasing(code) {
73
64
  return [...result];
74
65
  }
75
66
  function detectTagCasing(code) {
76
- let tags;
77
- if (cache.has(code)) {
78
- tags = cache.get(code);
79
- }
80
- else {
81
- cache.set(code, tags = collectTags(code));
82
- }
67
+ const tags = collectTagsWithCache(code);
83
68
  const result = new Set();
84
- for (const [tag] of tags ?? []) {
69
+ for (const [tag, [tagType]] of tags) {
70
+ if (tagType === 0
71
+ || tagType === 3) {
72
+ continue;
73
+ }
85
74
  if (tag !== (0, language_core_1.hyphenateTag)(tag)) {
86
- // TagName
87
- result.add(TagNameCasing.Pascal);
75
+ result.add(1 /* TagNameCasing.Pascal */);
88
76
  }
89
77
  else {
90
- // tag-name
91
- result.add(TagNameCasing.Kebab);
78
+ result.add(0 /* TagNameCasing.Kebab */);
92
79
  }
93
80
  }
94
81
  return [...result];
95
82
  }
96
- function collectTags(root) {
97
- if (!(root instanceof language_core_1.VueVirtualCode)) {
98
- return undefined;
99
- }
100
- const ast = root.sfc.template?.ast;
101
- if (!ast) {
102
- return undefined;
83
+ function collectTagsWithCache(code) {
84
+ let cache = collectCache.get(code);
85
+ if (!cache) {
86
+ const ast = code.sfc.template?.ast;
87
+ cache = ast ? collectTags(ast) : new Map();
88
+ collectCache.set(code, cache);
103
89
  }
90
+ return cache;
91
+ }
92
+ function collectTags(ast) {
104
93
  const tags = new Map();
105
94
  for (const node of (0, language_core_1.forEachElementNode)(ast)) {
106
95
  let tag = tags.get(node.tag);
107
96
  if (!tag) {
108
- tags.set(node.tag, tag = []);
97
+ tags.set(node.tag, tag = [node.tagType, []]);
109
98
  }
110
99
  for (const prop of node.props) {
111
100
  let name;
@@ -118,7 +107,7 @@ function collectTags(root) {
118
107
  name = prop.name;
119
108
  }
120
109
  if (name !== undefined) {
121
- tag.push(name);
110
+ tag[1].push(name);
122
111
  }
123
112
  }
124
113
  }
@@ -1,2 +1,2 @@
1
1
  import type { LanguageServicePlugin } from '@volar/language-service';
2
- export declare function create(): LanguageServicePlugin;
2
+ export declare function create({ resolveModuleName }: import('@vue/typescript-plugin/lib/requests').Requests): LanguageServicePlugin;
@@ -3,18 +3,55 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.create = create;
4
4
  const language_core_1 = require("@vue/language-core");
5
5
  const volar_service_css_1 = require("volar-service-css");
6
+ const vscode_uri_1 = require("vscode-uri");
6
7
  const utils_1 = require("../utils");
7
- function create() {
8
- const base = (0, volar_service_css_1.create)({ scssDocumentSelector: ['scss', 'postcss'] });
8
+ function create({ resolveModuleName }) {
9
+ let modulePathCache;
10
+ const baseService = (0, volar_service_css_1.create)({
11
+ getDocumentContext(context) {
12
+ return {
13
+ resolveReference(ref, base) {
14
+ let baseUri = vscode_uri_1.URI.parse(base);
15
+ const decoded = context.decodeEmbeddedDocumentUri(baseUri);
16
+ if (decoded) {
17
+ baseUri = decoded[0];
18
+ }
19
+ if (modulePathCache
20
+ && baseUri.scheme === 'file'
21
+ && !ref.startsWith('./')
22
+ && !ref.startsWith('../')) {
23
+ const map = modulePathCache;
24
+ if (!map.has(ref)) {
25
+ const fileName = baseUri.fsPath.replace(/\\/g, '/');
26
+ const promise = resolveModuleName(fileName, ref);
27
+ map.set(ref, promise);
28
+ if (promise instanceof Promise) {
29
+ promise.then(res => map.set(ref, res));
30
+ }
31
+ }
32
+ const cached = modulePathCache.get(ref);
33
+ if (cached instanceof Promise) {
34
+ throw cached;
35
+ }
36
+ if (cached) {
37
+ return cached;
38
+ }
39
+ }
40
+ return (0, volar_service_css_1.resolveReference)(ref, baseUri, context.env.workspaceFolders);
41
+ },
42
+ };
43
+ },
44
+ scssDocumentSelector: ['scss', 'postcss'],
45
+ });
9
46
  return {
10
- ...base,
47
+ ...baseService,
11
48
  create(context) {
12
- const baseInstance = base.create(context);
13
- const { 'css/languageService': getCssLs, 'css/stylesheet': getStylesheet, } = baseInstance.provide;
49
+ const baseServiceInstance = baseService.create(context);
50
+ const { 'css/languageService': getCssLs, 'css/stylesheet': getStylesheet, } = baseServiceInstance.provide;
14
51
  return {
15
- ...baseInstance,
52
+ ...baseServiceInstance,
16
53
  async provideDiagnostics(document, token) {
17
- let diagnostics = await baseInstance.provideDiagnostics?.(document, token) ?? [];
54
+ let diagnostics = await baseServiceInstance.provideDiagnostics?.(document, token) ?? [];
18
55
  if (document.languageId === 'postcss') {
19
56
  diagnostics = diagnostics.filter(diag => diag.code !== 'css-semicolonexpected'
20
57
  && diag.code !== 'css-ruleorselectorexpected'
@@ -42,6 +79,24 @@ function create() {
42
79
  return cssLs.prepareRename(document, position, stylesheet);
43
80
  });
44
81
  },
82
+ async provideDocumentLinks(document, token) {
83
+ modulePathCache = new Map();
84
+ while (true) {
85
+ try {
86
+ const result = await baseServiceInstance.provideDocumentLinks?.(document, token);
87
+ modulePathCache = undefined;
88
+ return result;
89
+ }
90
+ catch (e) {
91
+ if (e instanceof Promise) {
92
+ await e;
93
+ }
94
+ else {
95
+ throw e;
96
+ }
97
+ }
98
+ }
99
+ },
45
100
  };
46
101
  function isWithinNavigationVirtualCode(document, position) {
47
102
  const info = (0, utils_1.resolveEmbeddedCode)(context, document.uri);
@@ -44,7 +44,7 @@ function create(ts, { isRefAtPosition }) {
44
44
  if (sourceOffset < startTagEnd || sourceOffset > endTagStart) {
45
45
  continue;
46
46
  }
47
- if (isBlacklistNode(ts, ast, sourceOffset - startTagEnd, false)) {
47
+ if (shouldSkip(ts, ast, sourceOffset - startTagEnd, false)) {
48
48
  return;
49
49
  }
50
50
  }
@@ -68,7 +68,7 @@ function isCharacterTyping(document, change) {
68
68
  }
69
69
  return charReg.test(lastCharacter) && !charReg.test(nextCharacter);
70
70
  }
71
- function isBlacklistNode(ts, node, pos, allowAccessDotValue) {
71
+ function shouldSkip(ts, node, pos, allowAccessDotValue) {
72
72
  if (ts.isVariableDeclaration(node) && pos >= node.name.getFullStart() && pos <= node.name.getEnd()) {
73
73
  return true;
74
74
  }
@@ -100,45 +100,45 @@ function isBlacklistNode(ts, node, pos, allowAccessDotValue) {
100
100
  else if (ts.isCallExpression(node)
101
101
  && ts.isIdentifier(node.expression)
102
102
  && isWatchOrUseFunction(node.expression.text)
103
- && isTopLevelArgOrArrayTopLevelItemItem(node)) {
103
+ && isTopLevelArgOrArrayTopLevelItemItem(ts, node, pos)) {
104
104
  return true;
105
105
  }
106
106
  else {
107
- let _isBlacklistNode = false;
107
+ let _shouldSkip = false;
108
108
  node.forEachChild(node => {
109
- if (_isBlacklistNode) {
109
+ if (_shouldSkip) {
110
110
  return;
111
111
  }
112
112
  if (pos >= node.getFullStart() && pos <= node.getEnd()) {
113
- if (isBlacklistNode(ts, node, pos, allowAccessDotValue)) {
114
- _isBlacklistNode = true;
113
+ if (shouldSkip(ts, node, pos, allowAccessDotValue)) {
114
+ _shouldSkip = true;
115
115
  }
116
116
  }
117
117
  });
118
- return _isBlacklistNode;
118
+ return _shouldSkip;
119
119
  }
120
- function isWatchOrUseFunction(fnName) {
121
- return fnName === 'watch'
122
- || fnName === 'unref'
123
- || fnName === 'triggerRef'
124
- || fnName === 'isRef'
125
- || (0, language_core_1.hyphenateAttr)(fnName).startsWith('use-');
126
- }
127
- function isTopLevelArgOrArrayTopLevelItemItem(node) {
128
- for (const arg of node.arguments) {
129
- if (pos >= arg.getFullStart() && pos <= arg.getEnd()) {
130
- if (ts.isIdentifier(arg)) {
131
- return true;
132
- }
133
- if (ts.isArrayLiteralExpression(arg)) {
134
- for (const el of arg.elements) {
135
- if (pos >= el.getFullStart() && pos <= el.getEnd()) {
136
- return ts.isIdentifier(el);
137
- }
120
+ }
121
+ function isWatchOrUseFunction(fnName) {
122
+ return fnName === 'watch'
123
+ || fnName === 'unref'
124
+ || fnName === 'triggerRef'
125
+ || fnName === 'isRef'
126
+ || (0, language_core_1.hyphenateAttr)(fnName).startsWith('use-');
127
+ }
128
+ function isTopLevelArgOrArrayTopLevelItemItem(ts, node, pos) {
129
+ for (const arg of node.arguments) {
130
+ if (pos >= arg.getFullStart() && pos <= arg.getEnd()) {
131
+ if (ts.isIdentifier(arg)) {
132
+ return true;
133
+ }
134
+ if (ts.isArrayLiteralExpression(arg)) {
135
+ for (const el of arg.elements) {
136
+ if (pos >= el.getFullStart() && pos <= el.getEnd()) {
137
+ return ts.isIdentifier(el);
138
138
  }
139
139
  }
140
- return false;
141
140
  }
141
+ return false;
142
142
  }
143
143
  }
144
144
  }
@@ -39,7 +39,7 @@ function create(ts, { getImportPathForFile }) {
39
39
  if (!script) {
40
40
  return;
41
41
  }
42
- const casing = await (0, nameCasing_1.checkCasing)(context, info.script.id);
42
+ const tagNameCasing = await (0, nameCasing_1.getTagNameCasing)(context, info.script.id);
43
43
  const baseName = path_browserify_1.posix.basename(importUri);
44
44
  const newName = (0, shared_1.capitalize)((0, shared_1.camelize)(baseName.slice(0, baseName.lastIndexOf('.'))));
45
45
  const additionalEdit = {};
@@ -90,7 +90,7 @@ function create(ts, { getImportPathForFile }) {
90
90
  }
91
91
  }
92
92
  return {
93
- insertText: `<${casing.tag === nameCasing_1.TagNameCasing.Kebab ? (0, shared_1.hyphenate)(newName) : newName}$0 />`,
93
+ insertText: `<${tagNameCasing === 0 /* TagNameCasing.Kebab */ ? (0, shared_1.hyphenate)(newName) : newName}$0 />`,
94
94
  insertTextFormat: 2,
95
95
  additionalEdit,
96
96
  };
@@ -0,0 +1,2 @@
1
+ import type { LanguageServicePlugin } from '@volar/language-service';
2
+ export declare function create(): LanguageServicePlugin;
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.create = create;
4
+ const vscode_uri_1 = require("vscode-uri");
5
+ function create() {
6
+ return {
7
+ name: 'vue-format-per-block',
8
+ capabilities: {
9
+ documentFormattingProvider: true,
10
+ documentOnTypeFormattingProvider: {
11
+ triggerCharacters: [],
12
+ },
13
+ },
14
+ create(context) {
15
+ return {
16
+ async provideDocumentFormattingEdits(document) {
17
+ if (await shouldSkip(document)) {
18
+ return [];
19
+ }
20
+ return undefined;
21
+ },
22
+ async provideOnTypeFormattingEdits(document) {
23
+ if (await shouldSkip(document)) {
24
+ return [];
25
+ }
26
+ return undefined;
27
+ },
28
+ };
29
+ async function shouldSkip(document) {
30
+ const decoded = context.decodeEmbeddedDocumentUri(vscode_uri_1.URI.parse(document.uri));
31
+ if (!decoded) {
32
+ return false;
33
+ }
34
+ const [, embeddedCodeId] = decoded;
35
+ if (embeddedCodeId === 'script_raw' || embeddedCodeId === 'scriptsetup_raw') {
36
+ return await context.env.getConfiguration?.('vue.format.script.enabled') === false;
37
+ }
38
+ if (embeddedCodeId.startsWith('style_')) {
39
+ return await context.env.getConfiguration?.('vue.format.style.enabled') === false;
40
+ }
41
+ if (embeddedCodeId === 'template'
42
+ || embeddedCodeId.startsWith('template_inline_ts_')
43
+ || embeddedCodeId === 'root_tags') {
44
+ return await context.env.getConfiguration?.('vue.format.template.enabled') === false;
45
+ }
46
+ return false;
47
+ }
48
+ },
49
+ };
50
+ }
51
+ //# sourceMappingURL=vue-format-per-block.js.map
@@ -28,7 +28,7 @@ function create({ getComponentNames, getElementNames, getComponentProps }) {
28
28
  return;
29
29
  }
30
30
  const result = [];
31
- const casing = await (0, nameCasing_1.checkCasing)(context, info.script.id);
31
+ const attrNameCasing = await (0, nameCasing_1.getAttrNameCasing)(context, info.script.id);
32
32
  const components = await getComponentNames(info.root.fileName) ?? [];
33
33
  const componentProps = new Map();
34
34
  intrinsicElementNames ??= new Set(await getElementNames(info.root.fileName) ?? []);
@@ -113,7 +113,7 @@ function create({ getComponentNames, getElementNames, getComponentProps }) {
113
113
  start: document.positionAt(current.labelOffset),
114
114
  end: document.positionAt(current.labelOffset),
115
115
  },
116
- newText: ` :${casing.attr === nameCasing_1.AttrNameCasing.Kebab ? (0, language_core_1.hyphenateAttr)(requiredProp) : requiredProp}=`,
116
+ newText: ` :${attrNameCasing === 0 /* AttrNameCasing.Kebab */ ? (0, language_core_1.hyphenateAttr)(requiredProp) : requiredProp}=`,
117
117
  }],
118
118
  });
119
119
  }
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.create = create;
4
- const language_core_1 = require("@vue/language-core");
4
+ const styleScopedClasses_1 = require("@vue/language-core/lib/codegen/template/styleScopedClasses");
5
5
  const utils_1 = require("../utils");
6
6
  function create() {
7
7
  return {
@@ -17,17 +17,21 @@ function create() {
17
17
  return;
18
18
  }
19
19
  const { sfc } = info.root;
20
- const codegen = language_core_1.tsCodegen.get(sfc);
21
- const option = info.root.vueCompilerOptions.resolveStyleClassNames;
22
- const scopedClasses = codegen?.getGeneratedTemplate()?.scopedClasses ?? [];
20
+ if (!sfc.template) {
21
+ return;
22
+ }
23
+ const { resolveStyleClassNames } = info.root.vueCompilerOptions;
24
+ if (!resolveStyleClassNames) {
25
+ return;
26
+ }
27
+ const scopedClasses = styleScopedClasses_1.references.get(sfc.template)?.[1] ?? [];
23
28
  const styleClasses = new Map();
24
- for (let i = 0; i < sfc.styles.length; i++) {
25
- const style = sfc.styles[i];
26
- if (option !== true && !(option === 'scoped' && style.scoped)) {
29
+ for (const style of sfc.styles) {
30
+ if (!(resolveStyleClassNames === true || style.scoped)) {
27
31
  continue;
28
32
  }
29
- const styleDocumentUri = context.encodeEmbeddedDocumentUri(info.script.id, 'style_' + i);
30
- const styleVirtualCode = info.script.generated.embeddedCodes.get('style_' + i);
33
+ const styleDocumentUri = context.encodeEmbeddedDocumentUri(info.script.id, style.name);
34
+ const styleVirtualCode = info.script.generated.embeddedCodes.get(style.name);
31
35
  if (!styleVirtualCode) {
32
36
  continue;
33
37
  }
@@ -43,7 +47,7 @@ function create() {
43
47
  styleClasses.get(text).push(target);
44
48
  }
45
49
  }
46
- return scopedClasses.flatMap(({ className, offset }) => {
50
+ return scopedClasses.flatMap(([className, offset]) => {
47
51
  const range = {
48
52
  start: document.positionAt(offset),
49
53
  end: document.positionAt(offset + className.length),
@@ -1,2 +1,2 @@
1
1
  import type { LanguageServicePlugin } from '@volar/language-service';
2
- export declare function create(): LanguageServicePlugin;
2
+ export declare function create(ts: typeof import('typescript')): LanguageServicePlugin;
@@ -2,8 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.create = create;
4
4
  const language_core_1 = require("@vue/language-core");
5
+ const vscode_uri_1 = require("vscode-uri");
5
6
  const utils_1 = require("../utils");
6
- function create() {
7
+ const documentToSourceFile = new WeakMap();
8
+ function create(ts) {
7
9
  return {
8
10
  name: 'vue-suggest-define-assignment',
9
11
  capabilities: {
@@ -12,7 +14,7 @@ function create() {
12
14
  create(context) {
13
15
  return {
14
16
  isAdditionalCompletion: true,
15
- async provideCompletionItems(document) {
17
+ async provideCompletionItems(document, position) {
16
18
  const info = (0, utils_1.resolveEmbeddedCode)(context, document.uri);
17
19
  if (!info?.code.id.startsWith('script_')) {
18
20
  return;
@@ -28,6 +30,10 @@ function create() {
28
30
  if (!scriptSetup || !scriptSetupRanges) {
29
31
  return;
30
32
  }
33
+ const sourceFile = getSourceFile(ts, document);
34
+ if (shouldSkip(ts, sourceFile, document.offsetAt(position))) {
35
+ return;
36
+ }
31
37
  const result = [];
32
38
  const mappings = [...context.language.maps.forEach(info.code)];
33
39
  addDefineCompletionItem(scriptSetupRanges.defineProps?.statement, scriptSetupRanges.withDefaults?.exp ?? scriptSetupRanges.defineProps?.exp, 'props');
@@ -70,4 +76,34 @@ function create() {
70
76
  },
71
77
  };
72
78
  }
79
+ function shouldSkip(ts, node, pos) {
80
+ if (ts.isStringLiteral(node) && pos >= node.getFullStart() && pos <= node.getEnd()) {
81
+ return true;
82
+ }
83
+ else if (ts.isTemplateLiteral(node) && pos >= node.getFullStart() && pos <= node.getEnd()) {
84
+ return true;
85
+ }
86
+ else {
87
+ let _shouldSkip = false;
88
+ node.forEachChild(node => {
89
+ if (_shouldSkip) {
90
+ return;
91
+ }
92
+ if (pos >= node.getFullStart() && pos <= node.getEnd()) {
93
+ if (shouldSkip(ts, node, pos)) {
94
+ _shouldSkip = true;
95
+ }
96
+ }
97
+ });
98
+ return _shouldSkip;
99
+ }
100
+ }
101
+ function getSourceFile(ts, document) {
102
+ let sourceFile = documentToSourceFile.get(document);
103
+ if (!sourceFile) {
104
+ sourceFile = ts.createSourceFile(vscode_uri_1.URI.parse(document.uri).path, document.getText(), ts.ScriptTarget.Latest);
105
+ documentToSourceFile.set(document, sourceFile);
106
+ }
107
+ return sourceFile;
108
+ }
73
109
  //# sourceMappingURL=vue-suggest-define-assignment.js.map
@@ -1,2 +1,2 @@
1
- import type { LanguageServicePlugin } from '@volar/language-service';
2
- export declare function create(languageId: 'html' | 'jade', { getComponentNames, getElementAttrs, getComponentProps, getComponentEvents, getComponentDirectives, getComponentSlots, }: import('@vue/typescript-plugin/lib/requests').Requests): LanguageServicePlugin;
1
+ import { type LanguageServicePlugin } from '@volar/language-service';
2
+ export declare function create(ts: typeof import('typescript'), languageId: 'html' | 'jade', { getComponentNames, getComponentProps, getComponentEvents, getComponentDirectives, getComponentSlots, getElementAttrs, resolveModuleName, getAutoImportSuggestions, resolveAutoImportCompletionEntry, }: import('@vue/typescript-plugin/lib/requests').Requests): LanguageServicePlugin;
@@ -1,13 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.create = create;
4
+ const language_service_1 = require("@volar/language-service");
5
+ const featureWorkers_1 = require("@volar/language-service/lib/utils/featureWorkers");
4
6
  const language_core_1 = require("@vue/language-core");
5
7
  const shared_1 = require("@vue/shared");
6
8
  const volar_service_html_1 = require("volar-service-html");
7
9
  const volar_service_pug_1 = require("volar-service-pug");
10
+ const getFormatCodeSettings_js_1 = require("volar-service-typescript/lib/configs/getFormatCodeSettings.js");
11
+ const getUserPreferences_js_1 = require("volar-service-typescript/lib/configs/getUserPreferences.js");
12
+ const lspConverters_js_1 = require("volar-service-typescript/lib/utils/lspConverters.js");
8
13
  const html = require("vscode-html-languageservice");
9
14
  const vscode_uri_1 = require("vscode-uri");
10
15
  const data_1 = require("../data");
16
+ const htmlFormatter_1 = require("../htmlFormatter");
11
17
  const nameCasing_1 = require("../nameCasing");
12
18
  const utils_1 = require("../utils");
13
19
  const specialTags = new Set([
@@ -23,11 +29,19 @@ const specialProps = new Set([
23
29
  'ref',
24
30
  'style',
25
31
  ]);
32
+ const builtInComponents = new Set([
33
+ 'Transition',
34
+ 'TransitionGroup',
35
+ 'KeepAlive',
36
+ 'Suspense',
37
+ 'Teleport',
38
+ ]);
26
39
  let builtInData;
27
40
  let modelData;
28
- function create(languageId, { getComponentNames, getElementAttrs, getComponentProps, getComponentEvents, getComponentDirectives, getComponentSlots, }) {
41
+ function create(ts, languageId, { getComponentNames, getComponentProps, getComponentEvents, getComponentDirectives, getComponentSlots, getElementAttrs, resolveModuleName, getAutoImportSuggestions, resolveAutoImportCompletionEntry, }) {
29
42
  let customData = [];
30
43
  let extraCustomData = [];
44
+ let modulePathCache;
31
45
  const onDidChangeCustomDataListeners = new Set();
32
46
  const onDidChangeCustomData = (listener) => {
33
47
  onDidChangeCustomDataListeners.add(listener);
@@ -51,6 +65,39 @@ function create(languageId, { getComponentNames, getElementAttrs, getComponentPr
51
65
  : (0, volar_service_html_1.create)({
52
66
  documentSelector: ['html', 'markdown'],
53
67
  useDefaultDataProvider: false,
68
+ getDocumentContext(context) {
69
+ return {
70
+ resolveReference(ref, base) {
71
+ let baseUri = vscode_uri_1.URI.parse(base);
72
+ const decoded = context.decodeEmbeddedDocumentUri(baseUri);
73
+ if (decoded) {
74
+ baseUri = decoded[0];
75
+ }
76
+ if (modulePathCache
77
+ && baseUri.scheme === 'file'
78
+ && !ref.startsWith('./')
79
+ && !ref.startsWith('../')) {
80
+ const map = modulePathCache;
81
+ if (!map.has(ref)) {
82
+ const fileName = baseUri.fsPath.replace(/\\/g, '/');
83
+ const promise = resolveModuleName(fileName, ref);
84
+ map.set(ref, promise);
85
+ if (promise instanceof Promise) {
86
+ promise.then(res => map.set(ref, res));
87
+ }
88
+ }
89
+ const cached = modulePathCache.get(ref);
90
+ if (cached instanceof Promise) {
91
+ throw cached;
92
+ }
93
+ if (cached) {
94
+ return cached;
95
+ }
96
+ }
97
+ return (0, volar_service_html_1.resolveReference)(ref, baseUri, context.env.workspaceFolders);
98
+ },
99
+ };
100
+ },
54
101
  getCustomData() {
55
102
  return [
56
103
  ...customData,
@@ -96,6 +143,43 @@ function create(languageId, { getComponentNames, getElementAttrs, getComponentPr
96
143
  }
97
144
  return parseHTMLDocument(document);
98
145
  };
146
+ htmlService.format = (document, range, options) => {
147
+ let voidElements;
148
+ const info = (0, utils_1.resolveEmbeddedCode)(context, document.uri);
149
+ const codegen = info && language_core_1.tsCodegen.get(info.root.sfc);
150
+ if (codegen) {
151
+ const componentNames = new Set([
152
+ ...codegen.getImportComponentNames(),
153
+ ...codegen.getSetupExposed(),
154
+ ]);
155
+ // copied from https://github.com/microsoft/vscode-html-languageservice/blob/10daf45dc16b4f4228987cf7cddf3a7dbbdc7570/src/beautify/beautify-html.js#L2746-L2761
156
+ voidElements = [
157
+ 'area',
158
+ 'base',
159
+ 'br',
160
+ 'col',
161
+ 'embed',
162
+ 'hr',
163
+ 'img',
164
+ 'input',
165
+ 'keygen',
166
+ 'link',
167
+ 'menuitem',
168
+ 'meta',
169
+ 'param',
170
+ 'source',
171
+ 'track',
172
+ 'wbr',
173
+ '!doctype',
174
+ '?xml',
175
+ 'basefont',
176
+ 'isindex',
177
+ ].filter(tag => tag
178
+ && !componentNames.has(tag)
179
+ && !componentNames.has((0, shared_1.capitalize)((0, shared_1.camelize)(tag))));
180
+ }
181
+ return (0, htmlFormatter_1.format)(document, range, options, voidElements);
182
+ };
99
183
  }
100
184
  builtInData ??= (0, data_1.loadTemplateData)(context.env.locale ?? 'en');
101
185
  modelData ??= (0, data_1.loadModelModifiersData)(context.env.locale ?? 'en');
@@ -143,13 +227,24 @@ function create(languageId, { getComponentNames, getElementAttrs, getComponentPr
143
227
  }
144
228
  }
145
229
  const disposable = context.env.onDidChangeConfiguration?.(() => initializing = undefined);
230
+ const transformedItems = new WeakSet();
146
231
  let initializing;
232
+ let formattingOptions;
233
+ let lastCompletionDocument;
147
234
  return {
148
235
  ...baseServiceInstance,
149
236
  dispose() {
150
237
  baseServiceInstance.dispose?.();
151
238
  disposable?.dispose();
152
239
  },
240
+ provideDocumentFormattingEdits(document, range, options, ...rest) {
241
+ formattingOptions = options;
242
+ return baseServiceInstance.provideDocumentFormattingEdits?.(document, range, options, ...rest);
243
+ },
244
+ provideOnTypeFormattingEdits(document, position, key, options, ...rest) {
245
+ formattingOptions = options;
246
+ return baseServiceInstance.provideOnTypeFormattingEdits?.(document, position, key, options, ...rest);
247
+ },
153
248
  async provideCompletionItems(document, position, completionContext, token) {
154
249
  if (document.languageId !== languageId) {
155
250
  return;
@@ -158,23 +253,62 @@ function create(languageId, { getComponentNames, getElementAttrs, getComponentPr
158
253
  if (info?.code.id !== 'template') {
159
254
  return;
160
255
  }
161
- const { result: completionList, target, info: { components, propMap, }, } = await runWithVueData(info.script.id, info.root, () => baseServiceInstance.provideCompletionItems(document, position, completionContext, token));
162
- if (!completionList) {
256
+ const { result: htmlCompletion, target, info: { tagNameCasing, components, propMap, }, } = await runWithVueData(info.script.id, info.root, () => baseServiceInstance.provideCompletionItems(document, position, completionContext, token));
257
+ if (!htmlCompletion) {
163
258
  return;
164
259
  }
260
+ const autoImportPlaceholderIndex = htmlCompletion.items.findIndex(item => item.label === 'AutoImportsPlaceholder');
261
+ if (autoImportPlaceholderIndex !== -1) {
262
+ const offset = document.offsetAt(position);
263
+ const map = context.language.maps.get(info.code, info.script);
264
+ let spliced = false;
265
+ for (const [sourceOffset] of map.toSourceLocation(offset)) {
266
+ const [formatOptions, preferences] = await Promise.all([
267
+ (0, getFormatCodeSettings_js_1.getFormatCodeSettings)(context, document, formattingOptions),
268
+ (0, getUserPreferences_js_1.getUserPreferences)(context, document),
269
+ ]);
270
+ const autoImport = await getAutoImportSuggestions(info.root.fileName, sourceOffset, preferences, formatOptions);
271
+ if (!autoImport) {
272
+ continue;
273
+ }
274
+ const tsCompletion = (0, lspConverters_js_1.convertCompletionInfo)(ts, autoImport, document, position, entry => entry.data);
275
+ const placeholder = htmlCompletion.items[autoImportPlaceholderIndex];
276
+ for (const tsItem of tsCompletion.items) {
277
+ if (placeholder.textEdit) {
278
+ const newText = tsItem.textEdit?.newText ?? tsItem.label;
279
+ tsItem.textEdit = {
280
+ ...placeholder.textEdit,
281
+ newText: tagNameCasing === 0 /* TagNameCasing.Kebab */
282
+ ? (0, language_core_1.hyphenateTag)(newText)
283
+ : newText,
284
+ };
285
+ }
286
+ else {
287
+ tsItem.textEdit = undefined;
288
+ }
289
+ }
290
+ htmlCompletion.items.splice(autoImportPlaceholderIndex, 1, ...tsCompletion.items);
291
+ spliced = true;
292
+ lastCompletionDocument = document;
293
+ break;
294
+ }
295
+ if (!spliced) {
296
+ htmlCompletion.items.splice(autoImportPlaceholderIndex, 1);
297
+ }
298
+ }
165
299
  switch (target) {
166
300
  case 'tag': {
167
- completionList.items.forEach(transformTag);
301
+ htmlCompletion.items.forEach(transformTag);
168
302
  break;
169
303
  }
170
304
  case 'attribute': {
171
- addDirectiveModifiers(completionList, document);
172
- completionList.items.forEach(transformAttribute);
305
+ addDirectiveModifiers(htmlCompletion, document);
306
+ htmlCompletion.items.forEach(transformAttribute);
173
307
  break;
174
308
  }
175
309
  }
176
310
  updateExtraCustomData([]);
177
- return completionList;
311
+ return htmlCompletion;
178
312
  function transformTag(item) {
179
313
  const tagName = (0, shared_1.capitalize)((0, shared_1.camelize)(item.label));
180
314
  if (components?.includes(tagName)) {
@@ -272,6 +406,39 @@ function create(languageId, { getComponentNames, getElementAttrs, getComponentPr
272
406
  }
273
407
  }
274
408
  },
409
+ async resolveCompletionItem(item) {
410
+ if (item.data?.__isAutoImport || item.data?.__isComponentAutoImport) {
411
+ const embeddedUri = vscode_uri_1.URI.parse(lastCompletionDocument.uri);
412
+ const decoded = context.decodeEmbeddedDocumentUri(embeddedUri);
413
+ if (!decoded) {
414
+ return item;
415
+ }
416
+ const sourceScript = context.language.scripts.get(decoded[0]);
417
+ if (!sourceScript) {
418
+ return item;
419
+ }
420
+ const [formatOptions, preferences] = await Promise.all([
421
+ (0, getFormatCodeSettings_js_1.getFormatCodeSettings)(context, lastCompletionDocument, formattingOptions),
422
+ (0, getUserPreferences_js_1.getUserPreferences)(context, lastCompletionDocument),
423
+ ]);
424
+ const details = await resolveAutoImportCompletionEntry(item.data, preferences, formatOptions);
425
+ if (details) {
426
+ const virtualCode = sourceScript.generated.embeddedCodes.get(decoded[1]);
427
+ const sourceDocument = context.documents.get(sourceScript.id, sourceScript.languageId, sourceScript.snapshot);
428
+ const embeddedDocument = context.documents.get(embeddedUri, virtualCode.languageId, virtualCode.snapshot);
429
+ const map = context.language.maps.get(virtualCode, sourceScript);
430
+ item = (0, language_service_1.transformCompletionItem)(item, embeddedRange => (0, featureWorkers_1.getSourceRange)([sourceDocument, embeddedDocument, map], embeddedRange), embeddedDocument, context);
431
+ (0, lspConverters_js_1.applyCompletionEntryDetails)(ts, item, details, sourceDocument, fileName => vscode_uri_1.URI.file(fileName), () => undefined);
432
+ transformedItems.add(item);
433
+ }
434
+ }
435
+ return item;
436
+ },
437
+ transformCompletionItem(item) {
438
+ if (transformedItems.has(item)) {
439
+ return item;
440
+ }
441
+ },
275
442
  provideHover(document, position, token) {
276
443
  if (document.languageId !== languageId) {
277
444
  return;
@@ -287,6 +454,24 @@ function create(languageId, { getComponentNames, getElementAttrs, getComponentPr
287
454
  }
288
455
  return baseServiceInstance.provideHover?.(document, position, token);
289
456
  },
457
+ async provideDocumentLinks(document, token) {
458
+ modulePathCache = new Map();
459
+ while (true) {
460
+ try {
461
+ const result = await baseServiceInstance.provideDocumentLinks?.(document, token);
462
+ modulePathCache = undefined;
463
+ return result;
464
+ }
465
+ catch (e) {
466
+ if (e instanceof Promise) {
467
+ await e;
468
+ }
469
+ else {
470
+ throw e;
471
+ }
472
+ }
473
+ }
474
+ },
290
475
  };
291
476
  async function runWithVueData(sourceDocumentUri, root, fn) {
292
477
  // #4298: Precompute HTMLDocument before provideHtmlData to avoid parseHTMLDocument requesting component names from tsserver
@@ -301,12 +486,13 @@ function create(languageId, { getComponentNames, getElementAttrs, getComponentPr
301
486
  }
302
487
  async function provideHtmlData(sourceDocumentUri, root) {
303
488
  await (initializing ??= initialize());
304
- const casing = await (0, nameCasing_1.checkCasing)(context, sourceDocumentUri);
489
+ const tagNameCasing = await (0, nameCasing_1.getTagNameCasing)(context, sourceDocumentUri);
490
+ const attrNameCasing = await (0, nameCasing_1.getAttrNameCasing)(context, sourceDocumentUri);
305
491
  for (const tag of builtInData.tags ?? []) {
306
492
  if (specialTags.has(tag.name)) {
307
493
  continue;
308
494
  }
309
- if (casing.tag === nameCasing_1.TagNameCasing.Kebab) {
495
+ if (tagNameCasing === 0 /* TagNameCasing.Kebab */) {
310
496
  tag.name = (0, language_core_1.hyphenateTag)(tag.name);
311
497
  }
312
498
  else {
@@ -354,11 +540,7 @@ function create(languageId, { getComponentNames, getElementAttrs, getComponentPr
354
540
  components = [];
355
541
  tasks.push((async () => {
356
542
  components = (await getComponentNames(root.fileName) ?? [])
357
- .filter(name => name !== 'Transition'
358
- && name !== 'TransitionGroup'
359
- && name !== 'KeepAlive'
360
- && name !== 'Suspense'
361
- && name !== 'Teleport');
543
+ .filter(name => !builtInComponents.has(name));
362
544
  version++;
363
545
  })());
364
546
  }
@@ -366,7 +548,7 @@ function create(languageId, { getComponentNames, getElementAttrs, getComponentPr
366
548
  const names = new Set();
367
549
  const tags = [];
368
550
  for (const tag of components) {
369
- if (casing.tag === nameCasing_1.TagNameCasing.Kebab) {
551
+ if (tagNameCasing === 0 /* TagNameCasing.Kebab */) {
370
552
  names.add((0, language_core_1.hyphenateTag)(tag));
371
553
  }
372
554
  else {
@@ -375,7 +557,7 @@ function create(languageId, { getComponentNames, getElementAttrs, getComponentPr
375
557
  }
376
558
  for (const binding of scriptSetupRanges?.bindings ?? []) {
377
559
  const name = root.sfc.scriptSetup.content.slice(binding.range.start, binding.range.end);
378
- if (casing.tag === nameCasing_1.TagNameCasing.Kebab) {
560
+ if (tagNameCasing === 0 /* TagNameCasing.Kebab */) {
379
561
  names.add((0, language_core_1.hyphenateTag)(name));
380
562
  }
381
563
  else {
@@ -429,10 +611,10 @@ function create(languageId, { getComponentNames, getElementAttrs, getComponentPr
429
611
  ...attrs.map(attr => ({ name: attr })),
430
612
  ]) {
431
613
  const isGlobal = prop.isAttribute || !propNameSet.has(prop.name);
432
- const propName = casing.attr === nameCasing_1.AttrNameCasing.Camel ? prop.name : (0, language_core_1.hyphenateAttr)(prop.name);
614
+ const propName = attrNameCasing === 1 /* AttrNameCasing.Camel */ ? prop.name : (0, language_core_1.hyphenateAttr)(prop.name);
433
615
  const isEvent = (0, language_core_1.hyphenateAttr)(propName).startsWith('on-');
434
616
  if (isEvent) {
435
- const eventName = casing.attr === nameCasing_1.AttrNameCasing.Camel
617
+ const eventName = attrNameCasing === 1 /* AttrNameCasing.Camel */
436
618
  ? propName['on'.length].toLowerCase() + propName.slice('onX'.length)
437
619
  : propName.slice('on-'.length);
438
620
  for (const name of [
@@ -450,7 +632,7 @@ function create(languageId, { getComponentNames, getElementAttrs, getComponentPr
450
632
  }
451
633
  else {
452
634
  const propInfo = propInfos.find(prop => {
453
- const name = casing.attr === nameCasing_1.AttrNameCasing.Camel ? prop.name : (0, language_core_1.hyphenateAttr)(prop.name);
635
+ const name = attrNameCasing === 1 /* AttrNameCasing.Camel */ ? prop.name : (0, language_core_1.hyphenateAttr)(prop.name);
454
636
  return name === propName;
455
637
  });
456
638
  for (const name of [
@@ -472,7 +654,7 @@ function create(languageId, { getComponentNames, getElementAttrs, getComponentPr
472
654
  }
473
655
  }
474
656
  for (const event of events) {
475
- const eventName = casing.attr === nameCasing_1.AttrNameCasing.Camel ? event : (0, language_core_1.hyphenateAttr)(event);
657
+ const eventName = attrNameCasing === 1 /* AttrNameCasing.Camel */ ? event : (0, language_core_1.hyphenateAttr)(event);
476
658
  for (const name of [
477
659
  'v-on:' + eventName,
478
660
  '@' + eventName,
@@ -505,7 +687,7 @@ function create(languageId, { getComponentNames, getElementAttrs, getComponentPr
505
687
  }
506
688
  }
507
689
  for (const model of models) {
508
- const name = casing.attr === nameCasing_1.AttrNameCasing.Camel ? model : (0, language_core_1.hyphenateAttr)(model);
690
+ const name = attrNameCasing === 1 /* AttrNameCasing.Camel */ ? model : (0, language_core_1.hyphenateAttr)(model);
509
691
  attributes.push({ name: 'v-model:' + name });
510
692
  propMap.set('v-model:' + name, {
511
693
  name,
@@ -535,6 +717,19 @@ function create(languageId, { getComponentNames, getElementAttrs, getComponentPr
535
717
  }));
536
718
  },
537
719
  },
720
+ {
721
+ getId: () => 'vue-auto-imports',
722
+ isApplicable: () => true,
723
+ provideTags() {
724
+ return [{ name: 'AutoImportsPlaceholder', attributes: [] }];
725
+ },
726
+ provideAttributes() {
727
+ return [];
728
+ },
729
+ provideValues() {
730
+ return [];
731
+ },
732
+ },
538
733
  ]);
539
734
  return {
540
735
  async sync() {
@@ -543,6 +738,7 @@ function create(languageId, { getComponentNames, getElementAttrs, getComponentPr
543
738
  version,
544
739
  target,
545
740
  info: {
741
+ tagNameCasing,
546
742
  components,
547
743
  propMap,
548
744
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vue/language-service",
3
- "version": "3.1.4",
3
+ "version": "3.1.6",
4
4
  "license": "MIT",
5
5
  "files": [
6
6
  "data",
@@ -17,8 +17,8 @@
17
17
  "update-html-data": "node ./scripts/update-html-data.js"
18
18
  },
19
19
  "dependencies": {
20
- "@volar/language-service": "2.4.23",
21
- "@vue/language-core": "3.1.4",
20
+ "@volar/language-service": "2.4.26",
21
+ "@vue/language-core": "3.1.6",
22
22
  "@vue/shared": "^3.5.0",
23
23
  "path-browserify": "^1.0.1",
24
24
  "volar-service-css": "0.0.67",
@@ -34,11 +34,11 @@
34
34
  "devDependencies": {
35
35
  "@types/node": "^22.10.4",
36
36
  "@types/path-browserify": "^1.0.1",
37
- "@volar/kit": "2.4.23",
38
- "@volar/typescript": "2.4.23",
37
+ "@volar/kit": "2.4.26",
38
+ "@volar/typescript": "2.4.26",
39
39
  "@vue/compiler-dom": "^3.5.0",
40
- "@vue/typescript-plugin": "3.1.4",
40
+ "@vue/typescript-plugin": "3.1.6",
41
41
  "vscode-css-languageservice": "^6.3.1"
42
42
  },
43
- "gitHead": "9670176c727993d16f9224f48406077e20972353"
43
+ "gitHead": "341c06897f7f46606dddb8dd6d9e74e9c7844f02"
44
44
  }