@astrojs/language-server 0.13.0 → 0.13.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @astrojs/language-server
2
2
 
3
+ ## 0.13.3
4
+
5
+ ### Patch Changes
6
+
7
+ - 1fb21ff: Add support for folding CSS
8
+ - 99d7536: Add support for semantic tokens
9
+ - b363c00: Improve completions for components
10
+
11
+ ## 0.13.2
12
+
13
+ ### Patch Changes
14
+
15
+ - aff8b76: Fix error caused by malformed Svelte components
16
+ - Updated dependencies [aff8b76]
17
+ - @astrojs/svelte-language-integration@0.1.2
18
+
19
+ ## 0.13.1
20
+
21
+ ### Patch Changes
22
+
23
+ - ea74fdb: Publish failed
24
+
3
25
  ## 0.13.0
4
26
 
5
27
  ### Minor Changes
@@ -1,4 +1,4 @@
1
- import { Position, Range, CompletionItem, Hover, Diagnostic, ColorPresentation, SymbolInformation, LocationLink, TextDocumentEdit, CodeAction, SelectionRange, TextEdit, InsertReplaceEdit } from 'vscode-languageserver';
1
+ import { Position, Range, CompletionItem, Hover, Diagnostic, ColorPresentation, SymbolInformation, LocationLink, TextDocumentEdit, CodeAction, SelectionRange, TextEdit, InsertReplaceEdit, FoldingRange } from 'vscode-languageserver';
2
2
  import { TagInformation } from './utils';
3
3
  import { SourceMapConsumer } from 'source-map';
4
4
  export interface DocumentMapper {
@@ -82,4 +82,5 @@ export declare function mapSymbolInformationToOriginal(fragment: Pick<DocumentMa
82
82
  export declare function mapLocationLinkToOriginal(fragment: DocumentMapper, def: LocationLink): LocationLink;
83
83
  export declare function mapTextDocumentEditToOriginal(fragment: DocumentMapper, edit: TextDocumentEdit): TextDocumentEdit;
84
84
  export declare function mapCodeActionToOriginal(fragment: DocumentMapper, codeAction: CodeAction): CodeAction;
85
+ export declare function mapFoldingRangeToParent(fragment: DocumentMapper, foldingRange: FoldingRange): FoldingRange;
85
86
  export declare function mapSelectionRangeToParent(fragment: Pick<DocumentMapper, 'getOriginalPosition'>, selectionRange: SelectionRange): SelectionRange;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.mapSelectionRangeToParent = exports.mapCodeActionToOriginal = exports.mapTextDocumentEditToOriginal = exports.mapLocationLinkToOriginal = exports.mapSymbolInformationToOriginal = exports.mapColorPresentationToOriginal = exports.mapDiagnosticToGenerated = exports.mapEditToOriginal = exports.mapInsertReplaceEditToOriginal = exports.mapObjWithRangeToOriginal = exports.mapHoverToParent = exports.mapCompletionItemToOriginal = exports.mapRangeToGenerated = exports.mapRangeToOriginal = exports.SourceMapDocumentMapper = exports.FragmentMapper = exports.IdentityMapper = void 0;
3
+ exports.mapSelectionRangeToParent = exports.mapFoldingRangeToParent = exports.mapCodeActionToOriginal = exports.mapTextDocumentEditToOriginal = exports.mapLocationLinkToOriginal = exports.mapSymbolInformationToOriginal = exports.mapColorPresentationToOriginal = exports.mapDiagnosticToGenerated = exports.mapEditToOriginal = exports.mapInsertReplaceEditToOriginal = exports.mapObjWithRangeToOriginal = exports.mapHoverToParent = exports.mapCompletionItemToOriginal = exports.mapRangeToGenerated = exports.mapRangeToOriginal = exports.SourceMapDocumentMapper = exports.FragmentMapper = exports.IdentityMapper = void 0;
4
4
  const vscode_languageserver_1 = require("vscode-languageserver");
5
5
  const utils_1 = require("./utils");
6
6
  /**
@@ -231,6 +231,13 @@ function mapCodeActionToOriginal(fragment, codeAction) {
231
231
  }, codeAction.kind);
232
232
  }
233
233
  exports.mapCodeActionToOriginal = mapCodeActionToOriginal;
234
+ function mapFoldingRangeToParent(fragment, foldingRange) {
235
+ // Despite FoldingRange asking for a start and end line and a start and end character, FoldingRanges
236
+ // don't use the Range type, instead asking for 4 number. Not sure why, but it's not convenient
237
+ const range = mapRangeToOriginal(fragment, vscode_languageserver_1.Range.create(foldingRange.startLine, foldingRange.startCharacter || 0, foldingRange.endLine, foldingRange.endCharacter || 0));
238
+ return vscode_languageserver_1.FoldingRange.create(range.start.line, range.end.line, foldingRange.startCharacter ? range.start.character : undefined, foldingRange.endCharacter ? range.end.character : undefined, foldingRange.kind);
239
+ }
240
+ exports.mapFoldingRangeToParent = mapFoldingRangeToParent;
234
241
  function mapSelectionRangeToParent(fragment, selectionRange) {
235
242
  const { range, parent } = selectionRange;
236
243
  return vscode_languageserver_1.SelectionRange.create(mapRangeToOriginal(fragment, range), parent && mapSelectionRangeToParent(fragment, parent));
@@ -1,4 +1,4 @@
1
- import { CancellationToken, Color, ColorInformation, ColorPresentation, CompletionContext, CompletionItem, CompletionList, DefinitionLink, Diagnostic, FoldingRange, Hover, Position, Range, Location, SignatureHelp, SignatureHelpContext, TextDocumentContentChangeEvent, TextDocumentIdentifier, WorkspaceEdit, SymbolInformation } from 'vscode-languageserver';
1
+ import { CancellationToken, Color, ColorInformation, ColorPresentation, CompletionContext, CompletionItem, CompletionList, DefinitionLink, Diagnostic, FoldingRange, Hover, Position, Range, Location, SignatureHelp, SignatureHelpContext, TextDocumentContentChangeEvent, TextDocumentIdentifier, WorkspaceEdit, SymbolInformation, SemanticTokens } from 'vscode-languageserver';
2
2
  import type { AppCompletionItem, Plugin } from './interfaces';
3
3
  import { DocumentManager } from '../core/documents/DocumentManager';
4
4
  interface PluginHostConfig {
@@ -19,6 +19,7 @@ export declare class PluginHost {
19
19
  doTagComplete(textDocument: TextDocumentIdentifier, position: Position): Promise<string | null>;
20
20
  getFoldingRanges(textDocument: TextDocumentIdentifier): Promise<FoldingRange[] | null>;
21
21
  getDocumentSymbols(textDocument: TextDocumentIdentifier, cancellationToken: CancellationToken): Promise<SymbolInformation[]>;
22
+ getSemanticTokens(textDocument: TextDocumentIdentifier, range?: Range, cancellationToken?: CancellationToken): Promise<SemanticTokens | null>;
22
23
  getDefinitions(textDocument: TextDocumentIdentifier, position: Position): Promise<DefinitionLink[] | Location[]>;
23
24
  rename(textDocument: TextDocumentIdentifier, position: Position, newName: string): Promise<WorkspaceEdit | null>;
24
25
  getDocumentColors(textDocument: TextDocumentIdentifier): Promise<ColorInformation[]>;
@@ -57,6 +57,10 @@ class PluginHost {
57
57
  const document = this.getDocument(textDocument.uri);
58
58
  return (0, lodash_1.flatten)(await this.execute('getDocumentSymbols', [document, cancellationToken], ExecuteMode.Collect));
59
59
  }
60
+ async getSemanticTokens(textDocument, range, cancellationToken) {
61
+ const document = this.getDocument(textDocument.uri);
62
+ return await this.execute('getSemanticTokens', [document, range, cancellationToken], ExecuteMode.FirstNonNull);
63
+ }
60
64
  async getDefinitions(textDocument, position) {
61
65
  const document = this.getDocument(textDocument.uri);
62
66
  const definitions = (0, lodash_1.flatten)(await this.execute('getDefinitions', [document, position], ExecuteMode.Collect));
@@ -5,14 +5,13 @@ import { LanguageServiceManager as TypeScriptLanguageServiceManager } from '../.
5
5
  export declare class CompletionsProviderImpl {
6
6
  private readonly docManager;
7
7
  private readonly languageServiceManager;
8
+ directivesHTMLLang: import("vscode-html-languageservice").LanguageService;
8
9
  constructor(docManager: DocumentManager, languageServiceManager: TypeScriptLanguageServiceManager);
9
10
  getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext): Promise<AppCompletionList | null>;
10
- private getClientHintCompletion;
11
11
  private getComponentScriptCompletion;
12
12
  private getPropCompletions;
13
13
  private getImportedSymbol;
14
14
  private getPropType;
15
- private getCompletionItemForTypeMember;
16
- private isComponentTag;
17
- private isInsideFrontmatter;
15
+ private getCompletionItemForProperty;
16
+ private isAstroComponent;
18
17
  }
@@ -9,8 +9,15 @@ const typescript_1 = __importDefault(require("typescript"));
9
9
  const utils_1 = require("../../../core/documents/utils");
10
10
  const utils_2 = require("../../../utils");
11
11
  const utils_3 = require("../../typescript/utils");
12
+ const vscode_html_languageservice_1 = require("vscode-html-languageservice");
13
+ const astro_attributes_1 = require("../../html/features/astro-attributes");
14
+ const utils_4 = require("../../html/utils");
12
15
  class CompletionsProviderImpl {
13
16
  constructor(docManager, languageServiceManager) {
17
+ this.directivesHTMLLang = (0, vscode_html_languageservice_1.getLanguageService)({
18
+ customDataProviders: [astro_attributes_1.astroDirectives],
19
+ useDefaultDataProvider: false,
20
+ });
14
21
  this.docManager = docManager;
15
22
  this.languageServiceManager = languageServiceManager;
16
23
  }
@@ -24,46 +31,23 @@ class CompletionsProviderImpl {
24
31
  if (frontmatter)
25
32
  items.push(frontmatter);
26
33
  }
27
- if ((completionContext === null || completionContext === void 0 ? void 0 : completionContext.triggerCharacter) === ':') {
28
- const clientHint = this.getClientHintCompletion(doc, position, completionContext);
29
- if (clientHint)
30
- items.push(...clientHint);
31
- }
32
- if (!this.isInsideFrontmatter(document, position)) {
34
+ const offset = document.offsetAt(position);
35
+ if (!(0, utils_1.isInsideFrontmatter)(document.getText(), offset)) {
33
36
  const props = await this.getPropCompletions(document, position, completionContext);
34
37
  if (props.length) {
35
38
  items.push(...props);
36
39
  }
37
40
  }
41
+ const html = document.html;
42
+ if ((0, utils_1.isInComponentStartTag)(html, offset)) {
43
+ const node = html.findNodeAt(offset);
44
+ const isAstro = await this.isAstroComponent(document, node);
45
+ if (!isAstro) {
46
+ items.push(...(0, utils_4.removeDataAttrCompletion)(this.directivesHTMLLang.doComplete(document, position, html).items));
47
+ }
48
+ }
38
49
  return vscode_languageserver_1.CompletionList.create(items, true);
39
50
  }
40
- getClientHintCompletion(document, position, completionContext) {
41
- const node = document.html.findNodeAt(document.offsetAt(position));
42
- if (!(0, utils_2.isPossibleClientComponent)(node))
43
- return null;
44
- return [
45
- {
46
- label: ':load',
47
- insertText: 'load',
48
- commitCharacters: ['l'],
49
- },
50
- {
51
- label: ':idle',
52
- insertText: 'idle',
53
- commitCharacters: ['i'],
54
- },
55
- {
56
- label: ':visible',
57
- insertText: 'visible',
58
- commitCharacters: ['v'],
59
- },
60
- {
61
- label: ':media',
62
- insertText: 'media',
63
- commitCharacters: ['m'],
64
- },
65
- ];
66
- }
67
51
  getComponentScriptCompletion(document, position, completionContext) {
68
52
  const base = {
69
53
  kind: vscode_languageserver_1.CompletionItemKind.Snippet,
@@ -96,11 +80,10 @@ class CompletionsProviderImpl {
96
80
  return null;
97
81
  }
98
82
  async getPropCompletions(document, position, completionContext) {
99
- var _a, _b;
100
83
  const offset = document.offsetAt(position);
101
84
  const html = document.html;
102
85
  const node = html.findNodeAt(offset);
103
- if (!this.isComponentTag(node)) {
86
+ if (!(0, utils_2.isPossibleComponent)(node)) {
104
87
  return [];
105
88
  }
106
89
  const inAttribute = node.start + node.tag.length < offset;
@@ -119,8 +102,7 @@ class CompletionsProviderImpl {
119
102
  const componentName = node.tag;
120
103
  const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
121
104
  // Get the source file
122
- const filePath = (0, utils_2.urlToPath)(document.uri);
123
- const tsFilePath = (0, utils_3.toVirtualAstroFilePath)(filePath);
105
+ const tsFilePath = (0, utils_3.toVirtualAstroFilePath)(tsDoc.filePath);
124
106
  const program = lang.getProgram();
125
107
  const sourceFile = program === null || program === void 0 ? void 0 : program.getSourceFile(tsFilePath);
126
108
  const typeChecker = program === null || program === void 0 ? void 0 : program.getTypeChecker();
@@ -133,26 +115,22 @@ class CompletionsProviderImpl {
133
115
  if (!importType) {
134
116
  return [];
135
117
  }
136
- // Get the import's type
118
+ // Get the component's props type
137
119
  const componentType = this.getPropType(importType, typeChecker);
138
120
  if (!componentType) {
139
121
  return [];
140
122
  }
141
- const completionItems = [];
142
- // Add completions for this types props
143
- for (let baseType of componentType.getBaseTypes() || []) {
144
- const members = ((_a = baseType.getSymbol()) === null || _a === void 0 ? void 0 : _a.members) || [];
145
- members.forEach((mem) => {
146
- let completionItem = this.getCompletionItemForTypeMember(mem, typeChecker);
147
- completionItems.push(completionItem);
148
- });
149
- }
150
- // Add completions for this types base members
151
- const members = ((_b = componentType.getSymbol()) === null || _b === void 0 ? void 0 : _b.members) || [];
152
- members.forEach((mem) => {
153
- let completionItem = this.getCompletionItemForTypeMember(mem, typeChecker);
123
+ let completionItems = [];
124
+ // Add completions for this component's props type properties
125
+ const properties = componentType.getProperties().filter((property) => property.name !== 'children') || [];
126
+ properties.forEach((property) => {
127
+ let completionItem = this.getCompletionItemForProperty(property, typeChecker);
154
128
  completionItems.push(completionItem);
155
129
  });
130
+ // Ensure that props shows up first as a completion, despite this plugin being ran after the HTML one
131
+ completionItems = completionItems.map((item) => {
132
+ return { ...item, sortText: '_' };
133
+ });
156
134
  return completionItems;
157
135
  }
158
136
  getImportedSymbol(sourceFile, identifier) {
@@ -203,7 +181,7 @@ class CompletionsProviderImpl {
203
181
  }
204
182
  return null;
205
183
  }
206
- getCompletionItemForTypeMember(mem, typeChecker) {
184
+ getCompletionItemForProperty(mem, typeChecker) {
207
185
  let item = {
208
186
  label: mem.name,
209
187
  insertText: mem.name,
@@ -223,15 +201,29 @@ class CompletionsProviderImpl {
223
201
  }
224
202
  return item;
225
203
  }
226
- isComponentTag(node) {
227
- if (!node.tag) {
204
+ async isAstroComponent(document, node) {
205
+ var _a;
206
+ const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
207
+ // Get the source file
208
+ const tsFilePath = (0, utils_3.toVirtualAstroFilePath)(tsDoc.filePath);
209
+ const program = lang.getProgram();
210
+ const sourceFile = program === null || program === void 0 ? void 0 : program.getSourceFile(tsFilePath);
211
+ const typeChecker = program === null || program === void 0 ? void 0 : program.getTypeChecker();
212
+ if (!sourceFile || !typeChecker) {
228
213
  return false;
229
214
  }
230
- const firstChar = node.tag[0];
231
- return /[A-Z]/.test(firstChar);
232
- }
233
- isInsideFrontmatter(document, position) {
234
- return (0, utils_1.isInsideFrontmatter)(document.getText(), document.offsetAt(position));
215
+ const componentName = node.tag;
216
+ const imp = this.getImportedSymbol(sourceFile, componentName);
217
+ const importType = imp && typeChecker.getTypeAtLocation(imp);
218
+ if (!importType) {
219
+ return false;
220
+ }
221
+ const symbolDeclaration = (_a = importType.getSymbol()) === null || _a === void 0 ? void 0 : _a.declarations;
222
+ if (symbolDeclaration) {
223
+ const fileName = symbolDeclaration[0].getSourceFile().fileName;
224
+ return fileName.endsWith('.astro');
225
+ }
226
+ return false;
235
227
  }
236
228
  }
237
229
  exports.CompletionsProviderImpl = CompletionsProviderImpl;
@@ -1,4 +1,4 @@
1
- import { Color, ColorInformation, ColorPresentation, CompletionContext, CompletionList, Hover, Position, Range, SymbolInformation } from 'vscode-languageserver';
1
+ import { Color, ColorInformation, ColorPresentation, CompletionContext, CompletionList, FoldingRange, Hover, Position, Range, SymbolInformation } from 'vscode-languageserver';
2
2
  import { ConfigManager } from '../../core/config/ConfigManager';
3
3
  import { AstroDocument } from '../../core/documents';
4
4
  import type { Plugin } from '../interfaces';
@@ -14,6 +14,7 @@ export declare class CSSPlugin implements Plugin {
14
14
  private getCompletionsInternal;
15
15
  getDocumentColors(document: AstroDocument): ColorInformation[];
16
16
  getColorPresentations(document: AstroDocument, range: Range, color: Color): ColorPresentation[];
17
+ getFoldingRanges(document: AstroDocument): FoldingRange[] | null;
17
18
  getDocumentSymbols(document: AstroDocument): SymbolInformation[];
18
19
  private inStyleAttributeWithoutInterpolation;
19
20
  /**
@@ -37,7 +37,8 @@ class CSSPlugin {
37
37
  return null;
38
38
  }
39
39
  const cssDocument = this.getCSSDocumentForStyleTag(styleTag, document);
40
- if (shouldExcludeHover(cssDocument)) {
40
+ const cssLang = extractLanguage(cssDocument);
41
+ if (!isSupportedByLangService(cssLang)) {
41
42
  return null;
42
43
  }
43
44
  return this.doHoverInternal(cssDocument, position);
@@ -104,7 +105,7 @@ class CSSPlugin {
104
105
  const allColorInfo = this.getCSSDocumentsForDocument(document).map((cssDoc) => {
105
106
  const cssLang = extractLanguage(cssDoc);
106
107
  const langService = (0, language_service_1.getLanguageService)(cssLang);
107
- if (shouldExcludeColor(cssLang)) {
108
+ if (!isSupportedByLangService(cssLang)) {
108
109
  return [];
109
110
  }
110
111
  return langService
@@ -120,7 +121,8 @@ class CSSPlugin {
120
121
  const allColorPres = this.getCSSDocumentsForDocument(document).map((cssDoc) => {
121
122
  const cssLang = extractLanguage(cssDoc);
122
123
  const langService = (0, language_service_1.getLanguageService)(cssLang);
123
- if ((!cssDoc.isInGenerated(range.start) && !cssDoc.isInGenerated(range.end)) || shouldExcludeColor(cssLang)) {
124
+ if ((!cssDoc.isInGenerated(range.start) && !cssDoc.isInGenerated(range.end)) ||
125
+ !isSupportedByLangService(cssLang)) {
124
126
  return [];
125
127
  }
126
128
  return langService
@@ -129,6 +131,14 @@ class CSSPlugin {
129
131
  });
130
132
  return (0, lodash_1.flatten)(allColorPres);
131
133
  }
134
+ getFoldingRanges(document) {
135
+ const allFoldingRanges = this.getCSSDocumentsForDocument(document).map((cssDoc) => {
136
+ const cssLang = extractLanguage(cssDoc);
137
+ const langService = (0, language_service_1.getLanguageService)(cssLang);
138
+ return langService.getFoldingRanges(cssDoc).map((foldingRange) => (0, documents_1.mapFoldingRangeToParent)(cssDoc, foldingRange));
139
+ });
140
+ return (0, lodash_1.flatten)(allFoldingRanges);
141
+ }
132
142
  getDocumentSymbols(document) {
133
143
  if (!this.featureEnabled('documentSymbols')) {
134
144
  return [];
@@ -182,32 +192,13 @@ class CSSPlugin {
182
192
  }
183
193
  exports.CSSPlugin = CSSPlugin;
184
194
  /**
185
- * Exclude certain language when getting hover info
186
- * The CSS language service only supports CSS, LESS and SCSS,
187
- * which mean that we cannot support hover info in other languages
195
+ * Check is a CSSDocument's language is supported by the CSS language service
188
196
  */
189
- function shouldExcludeHover(document) {
190
- const language = typeof document === 'string' ? document : extractLanguage(document);
197
+ function isSupportedByLangService(language) {
191
198
  switch (language) {
192
- case 'sass':
193
- case 'stylus':
194
- case 'styl':
195
- return true;
196
- default:
197
- return false;
198
- }
199
- }
200
- /**
201
- * Exclude certain language when getting colors
202
- * The CSS language service only supports CSS, LESS and SCSS,
203
- * which mean that we cannot support colors in other languages
204
- */
205
- function shouldExcludeColor(document) {
206
- const language = typeof document === 'string' ? document : extractLanguage(document);
207
- switch (language) {
208
- case 'sass':
209
- case 'stylus':
210
- case 'styl':
199
+ case 'css':
200
+ case 'scss':
201
+ case 'less':
211
202
  return true;
212
203
  default:
213
204
  return false;
@@ -5,6 +5,7 @@ import { AstroDocument } from '../../core/documents/AstroDocument';
5
5
  export declare class HTMLPlugin implements Plugin {
6
6
  __name: string;
7
7
  private lang;
8
+ private attributeOnlyLang;
8
9
  private componentLang;
9
10
  private styleScriptTemplate;
10
11
  private configManager;
@@ -7,11 +7,16 @@ const vscode_html_languageservice_1 = require("vscode-html-languageservice");
7
7
  const utils_1 = require("../../core/documents/utils");
8
8
  const utils_2 = require("../../utils");
9
9
  const astro_attributes_1 = require("./features/astro-attributes");
10
+ const utils_3 = require("./utils");
10
11
  class HTMLPlugin {
11
12
  constructor(configManager) {
12
13
  this.__name = 'html';
13
14
  this.lang = (0, vscode_html_languageservice_1.getLanguageService)({
15
+ customDataProviders: [astro_attributes_1.astroAttributes, astro_attributes_1.classListAttribute],
16
+ });
17
+ this.attributeOnlyLang = (0, vscode_html_languageservice_1.getLanguageService)({
14
18
  customDataProviders: [astro_attributes_1.astroAttributes],
19
+ useDefaultDataProvider: false,
15
20
  });
16
21
  this.componentLang = (0, vscode_html_languageservice_1.getLanguageService)({
17
22
  customDataProviders: [astro_attributes_1.astroAttributes, astro_attributes_1.astroDirectives],
@@ -66,9 +71,9 @@ class HTMLPlugin {
66
71
  // If we're in a component starting tag, we do not want HTML language completions
67
72
  // as HTML attributes are not valid for components
68
73
  const results = (0, utils_1.isInComponentStartTag)(html, document.offsetAt(position))
69
- ? vscode_languageserver_1.CompletionList.create([])
70
- : this.lang.doComplete(document, position, html);
71
- return vscode_languageserver_1.CompletionList.create([...results.items, ...this.getLangCompletions(results.items), ...emmetResults.items],
74
+ ? (0, utils_3.removeDataAttrCompletion)(this.attributeOnlyLang.doComplete(document, position, html).items)
75
+ : this.lang.doComplete(document, position, html).items;
76
+ return vscode_languageserver_1.CompletionList.create([...results, ...this.getLangCompletions(results), ...emmetResults.items],
72
77
  // Emmet completions change on every keystroke, so they are never complete
73
78
  emmetResults.items.length > 0);
74
79
  }
@@ -1,2 +1,3 @@
1
+ export declare const classListAttribute: import("vscode-html-languageservice").IHTMLDataProvider;
1
2
  export declare const astroAttributes: import("vscode-html-languageservice").IHTMLDataProvider;
2
3
  export declare const astroDirectives: import("vscode-html-languageservice").IHTMLDataProvider;
@@ -1,14 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.astroDirectives = exports.astroAttributes = void 0;
3
+ exports.astroDirectives = exports.astroAttributes = exports.classListAttribute = void 0;
4
4
  const vscode_html_languageservice_1 = require("vscode-html-languageservice");
5
- exports.astroAttributes = (0, vscode_html_languageservice_1.newHTMLDataProvider)('astro-attributes', {
5
+ exports.classListAttribute = (0, vscode_html_languageservice_1.newHTMLDataProvider)('class-list', {
6
6
  version: 1,
7
7
  globalAttributes: [
8
8
  {
9
9
  name: 'class:list',
10
10
  description: 'Utility to provide a list of class',
11
11
  },
12
+ ],
13
+ });
14
+ exports.astroAttributes = (0, vscode_html_languageservice_1.newHTMLDataProvider)('astro-attributes', {
15
+ version: 1,
16
+ globalAttributes: [
12
17
  {
13
18
  name: 'set:html',
14
19
  description: 'Inject unescaped HTML into this tag',
@@ -75,6 +80,7 @@ exports.astroDirectives = (0, vscode_html_languageservice_1.newHTMLDataProvider)
75
80
  {
76
81
  name: 'client:load',
77
82
  description: 'Start importing the component JS at page load. Hydrate the component when import completes.',
83
+ valueSet: 'v',
78
84
  references: [
79
85
  {
80
86
  name: 'Astro documentation',
@@ -85,6 +91,7 @@ exports.astroDirectives = (0, vscode_html_languageservice_1.newHTMLDataProvider)
85
91
  {
86
92
  name: 'client:idle',
87
93
  description: 'Start importing the component JS as soon as main thread is free (uses requestIdleCallback()). Hydrate the component when import completes.',
94
+ valueSet: 'v',
88
95
  references: [
89
96
  {
90
97
  name: 'Astro documentation',
@@ -95,6 +102,7 @@ exports.astroDirectives = (0, vscode_html_languageservice_1.newHTMLDataProvider)
95
102
  {
96
103
  name: 'client:visible',
97
104
  description: 'Start importing the component JS as soon as the element enters the viewport (uses IntersectionObserver). Hydrate the component when import completes. Useful for content lower down on the page.',
105
+ valueSet: 'v',
98
106
  references: [
99
107
  {
100
108
  name: 'Astro documentation',
@@ -115,6 +123,7 @@ exports.astroDirectives = (0, vscode_html_languageservice_1.newHTMLDataProvider)
115
123
  {
116
124
  name: 'client:only',
117
125
  description: 'Start importing the component JS at page load and hydrate when the import completes, similar to client:load. The component will be skipped at build time, useful for components that are entirely dependent on client-side APIs. This is best avoided unless absolutely needed, in most cases it is best to render placeholder content on the server and delay any browser API calls until the component hydrates in the browser.',
126
+ valueSet: 'v',
118
127
  references: [
119
128
  {
120
129
  name: 'Astro documentation',
@@ -0,0 +1,6 @@
1
+ import { CompletionItem } from 'vscode-languageserver-types';
2
+ /**
3
+ * The VS Code HTML language service provides a completion for data attributes that is independent from
4
+ * data providers, which mean that you can't disable it, so this function removes them from a completionList
5
+ */
6
+ export declare function removeDataAttrCompletion(items: CompletionItem[]): CompletionItem[];
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.removeDataAttrCompletion = void 0;
4
+ /**
5
+ * The VS Code HTML language service provides a completion for data attributes that is independent from
6
+ * data providers, which mean that you can't disable it, so this function removes them from a completionList
7
+ */
8
+ function removeDataAttrCompletion(items) {
9
+ return items.filter((item) => !item.label.startsWith('data-'));
10
+ }
11
+ exports.removeDataAttrCompletion = removeDataAttrCompletion;
@@ -1,4 +1,4 @@
1
- import { CancellationToken, CompletionContext, DefinitionLink, Diagnostic, Hover, Position, SignatureHelp, SignatureHelpContext, SymbolInformation, TextDocumentContentChangeEvent, WorkspaceEdit } from 'vscode-languageserver';
1
+ import { CancellationToken, CompletionContext, DefinitionLink, Diagnostic, Hover, Position, Range, SemanticTokens, SignatureHelp, SignatureHelpContext, SymbolInformation, TextDocumentContentChangeEvent, WorkspaceEdit } from 'vscode-languageserver';
2
2
  import { ConfigManager } from '../../core/config';
3
3
  import { AstroDocument, DocumentManager } from '../../core/documents';
4
4
  import { AppCompletionItem, AppCompletionList, OnWatchFileChangesParam, Plugin } from '../interfaces';
@@ -12,9 +12,11 @@ export declare class TypeScriptPlugin implements Plugin {
12
12
  private readonly signatureHelpProvider;
13
13
  private readonly diagnosticsProvider;
14
14
  private readonly documentSymbolsProvider;
15
+ private readonly semanticTokensProvider;
15
16
  constructor(docManager: DocumentManager, configManager: ConfigManager, workspaceUris: string[]);
16
17
  doHover(document: AstroDocument, position: Position): Promise<Hover | null>;
17
18
  rename(document: AstroDocument, position: Position, newName: string): Promise<WorkspaceEdit | null>;
19
+ getSemanticTokens(textDocument: AstroDocument, range?: Range, cancellationToken?: CancellationToken): Promise<SemanticTokens | null>;
18
20
  getDocumentSymbols(document: AstroDocument): Promise<SymbolInformation[]>;
19
21
  getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext): Promise<AppCompletionList<CompletionEntryWithIdentifer> | null>;
20
22
  resolveCompletion(document: AstroDocument, completionItem: AppCompletionItem<CompletionEntryWithIdentifer>): Promise<AppCompletionItem<CompletionEntryWithIdentifer>>;
@@ -36,6 +36,7 @@ const utils_2 = require("./features/utils");
36
36
  const LanguageServiceManager_1 = require("./LanguageServiceManager");
37
37
  const utils_3 = require("./utils");
38
38
  const DocumentSymbolsProvider_1 = require("./features/DocumentSymbolsProvider");
39
+ const SemanticTokenProvider_1 = require("./features/SemanticTokenProvider");
39
40
  class TypeScriptPlugin {
40
41
  constructor(docManager, configManager, workspaceUris) {
41
42
  this.__name = 'typescript';
@@ -46,6 +47,7 @@ class TypeScriptPlugin {
46
47
  this.signatureHelpProvider = new SignatureHelpProvider_1.SignatureHelpProviderImpl(this.languageServiceManager);
47
48
  this.diagnosticsProvider = new DiagnosticsProvider_1.DiagnosticsProviderImpl(this.languageServiceManager);
48
49
  this.documentSymbolsProvider = new DocumentSymbolsProvider_1.DocumentSymbolsProviderImpl(this.languageServiceManager);
50
+ this.semanticTokensProvider = new SemanticTokenProvider_1.SemanticTokensProviderImpl(this.languageServiceManager);
49
51
  }
50
52
  async doHover(document, position) {
51
53
  if (!this.featureEnabled('hover')) {
@@ -76,6 +78,9 @@ class TypeScriptPlugin {
76
78
  });
77
79
  return edit;
78
80
  }
81
+ async getSemanticTokens(textDocument, range, cancellationToken) {
82
+ return this.semanticTokensProvider.getSemanticTokens(textDocument, range, cancellationToken);
83
+ }
79
84
  async getDocumentSymbols(document) {
80
85
  if (!this.featureEnabled('documentSymbols')) {
81
86
  return [];
@@ -0,0 +1,15 @@
1
+ import { CancellationToken, Range, SemanticTokens } from 'vscode-languageserver';
2
+ import { AstroDocument } from '../../../core/documents';
3
+ import { SemanticTokensProvider } from '../../interfaces';
4
+ import { LanguageServiceManager } from '../LanguageServiceManager';
5
+ export declare class SemanticTokensProviderImpl implements SemanticTokensProvider {
6
+ private languageServiceManager;
7
+ constructor(languageServiceManager: LanguageServiceManager);
8
+ getSemanticTokens(document: AstroDocument, range?: Range, cancellationToken?: CancellationToken): Promise<SemanticTokens | null>;
9
+ private mapToOrigin;
10
+ /**
11
+ * TSClassification = (TokenType + 1) << TokenEncodingConsts.typeOffset + TokenModifier
12
+ */
13
+ private getTokenTypeFromClassification;
14
+ private getTokenModifierFromClassification;
15
+ }
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.SemanticTokensProviderImpl = void 0;
7
+ const typescript_1 = __importDefault(require("typescript"));
8
+ const vscode_languageserver_1 = require("vscode-languageserver");
9
+ const documents_1 = require("../../../core/documents");
10
+ const utils_1 = require("../utils");
11
+ class SemanticTokensProviderImpl {
12
+ constructor(languageServiceManager) {
13
+ this.languageServiceManager = languageServiceManager;
14
+ }
15
+ async getSemanticTokens(document, range, cancellationToken) {
16
+ const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
17
+ const fragment = (await tsDoc.createFragment());
18
+ if (cancellationToken === null || cancellationToken === void 0 ? void 0 : cancellationToken.isCancellationRequested) {
19
+ return null;
20
+ }
21
+ const filePath = (0, utils_1.toVirtualAstroFilePath)(tsDoc.filePath);
22
+ const start = range ? fragment.offsetAt(fragment.getGeneratedPosition(range.start)) : 0;
23
+ const { spans } = lang.getEncodedSemanticClassifications(filePath, {
24
+ start,
25
+ length: range ? fragment.offsetAt(fragment.getGeneratedPosition(range.end)) - start : fragment.text.length,
26
+ }, typescript_1.default.SemanticClassificationFormat.TwentyTwenty);
27
+ const tokens = [];
28
+ let i = 0;
29
+ while (i < spans.length) {
30
+ const offset = spans[i++];
31
+ const generatedLength = spans[i++];
32
+ const classification = spans[i++];
33
+ const originalPosition = this.mapToOrigin(document, fragment, offset, generatedLength);
34
+ if (!originalPosition) {
35
+ continue;
36
+ }
37
+ const [line, character, length] = originalPosition;
38
+ const classificationType = this.getTokenTypeFromClassification(classification);
39
+ if (classificationType < 0) {
40
+ continue;
41
+ }
42
+ const modifier = this.getTokenModifierFromClassification(classification);
43
+ tokens.push([line, character, length, classificationType, modifier]);
44
+ }
45
+ const sorted = tokens.sort((a, b) => {
46
+ const [lineA, charA] = a;
47
+ const [lineB, charB] = b;
48
+ return lineA - lineB || charA - charB;
49
+ });
50
+ const builder = new vscode_languageserver_1.SemanticTokensBuilder();
51
+ sorted.forEach((tokenData) => builder.push(...tokenData));
52
+ const build = builder.build();
53
+ return build;
54
+ }
55
+ mapToOrigin(document, fragment, generatedOffset, generatedLength) {
56
+ const range = {
57
+ start: fragment.positionAt(generatedOffset),
58
+ end: fragment.positionAt(generatedOffset + generatedLength),
59
+ };
60
+ const { start: startPosition, end: endPosition } = (0, documents_1.mapRangeToOriginal)(fragment, range);
61
+ if (startPosition.line < 0 || endPosition.line < 0) {
62
+ return;
63
+ }
64
+ const startOffset = document.offsetAt(startPosition);
65
+ const endOffset = document.offsetAt(endPosition);
66
+ return [startPosition.line, startPosition.character, endOffset - startOffset, startOffset];
67
+ }
68
+ /**
69
+ * TSClassification = (TokenType + 1) << TokenEncodingConsts.typeOffset + TokenModifier
70
+ */
71
+ getTokenTypeFromClassification(tsClassification) {
72
+ return (tsClassification >> 8 /* typeOffset */) - 1;
73
+ }
74
+ getTokenModifierFromClassification(tsClassification) {
75
+ return tsClassification & 255 /* modifierMask */;
76
+ }
77
+ }
78
+ exports.SemanticTokensProviderImpl = SemanticTokensProviderImpl;
@@ -1,6 +1,29 @@
1
1
  import ts from 'typescript';
2
- import { CompletionItemKind, DiagnosticSeverity, Position, Range, SymbolKind } from 'vscode-languageserver';
2
+ import { CompletionItemKind, DiagnosticSeverity, Position, Range, SymbolKind, SemanticTokensLegend } from 'vscode-languageserver';
3
3
  import { SnapshotFragment } from './snapshots/DocumentSnapshot';
4
+ export declare const enum TokenType {
5
+ class = 0,
6
+ enum = 1,
7
+ interface = 2,
8
+ namespace = 3,
9
+ typeParameter = 4,
10
+ type = 5,
11
+ parameter = 6,
12
+ variable = 7,
13
+ enumMember = 8,
14
+ property = 9,
15
+ function = 10,
16
+ method = 11
17
+ }
18
+ export declare const enum TokenModifier {
19
+ declaration = 0,
20
+ static = 1,
21
+ async = 2,
22
+ readonly = 3,
23
+ defaultLibrary = 4,
24
+ local = 5
25
+ }
26
+ export declare function getSemanticTokenLegend(): SemanticTokensLegend;
4
27
  export declare function symbolKindFromString(kind: string): SymbolKind;
5
28
  export declare function scriptElementKindToCompletionItemKind(kind: ts.ScriptElementKind): CompletionItemKind;
6
29
  export declare function getCommitCharactersForScriptElement(kind: ts.ScriptElementKind): string[] | undefined;
@@ -3,12 +3,43 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ensureRealFilePath = exports.ensureRealAstroFilePath = exports.toRealAstroFilePath = exports.toVirtualFilePath = exports.toVirtualAstroFilePath = exports.isVirtualFilePath = exports.isVirtualSvelteFilePath = exports.isVirtualVueFilePath = exports.isVirtualAstroFilePath = exports.isFrameworkFilePath = exports.isAstroFilePath = exports.isVirtualFrameworkFilePath = exports.getFrameworkFromFilePath = exports.convertToLocationRange = exports.convertRange = exports.mapSeverity = exports.getScriptKindFromFileName = exports.isSubPath = exports.findTsConfigPath = exports.getExtensionFromScriptKind = exports.getCommitCharactersForScriptElement = exports.scriptElementKindToCompletionItemKind = exports.symbolKindFromString = void 0;
6
+ exports.ensureRealFilePath = exports.ensureRealAstroFilePath = exports.toRealAstroFilePath = exports.toVirtualFilePath = exports.toVirtualAstroFilePath = exports.isVirtualFilePath = exports.isVirtualSvelteFilePath = exports.isVirtualVueFilePath = exports.isVirtualAstroFilePath = exports.isFrameworkFilePath = exports.isAstroFilePath = exports.isVirtualFrameworkFilePath = exports.getFrameworkFromFilePath = exports.convertToLocationRange = exports.convertRange = exports.mapSeverity = exports.getScriptKindFromFileName = exports.isSubPath = exports.findTsConfigPath = exports.getExtensionFromScriptKind = exports.getCommitCharactersForScriptElement = exports.scriptElementKindToCompletionItemKind = exports.symbolKindFromString = exports.getSemanticTokenLegend = void 0;
7
7
  const typescript_1 = __importDefault(require("typescript"));
8
8
  const path_1 = require("path");
9
9
  const utils_1 = require("../../utils");
10
10
  const vscode_languageserver_1 = require("vscode-languageserver");
11
11
  const documents_1 = require("../../core/documents");
12
+ function getSemanticTokenLegend() {
13
+ const tokenModifiers = [];
14
+ [
15
+ [0 /* declaration */, vscode_languageserver_1.SemanticTokenModifiers.declaration],
16
+ [1 /* static */, vscode_languageserver_1.SemanticTokenModifiers.static],
17
+ [2 /* async */, vscode_languageserver_1.SemanticTokenModifiers.async],
18
+ [3 /* readonly */, vscode_languageserver_1.SemanticTokenModifiers.readonly],
19
+ [4 /* defaultLibrary */, vscode_languageserver_1.SemanticTokenModifiers.defaultLibrary],
20
+ [5 /* local */, 'local'],
21
+ ].forEach(([tsModifier, legend]) => (tokenModifiers[tsModifier] = legend));
22
+ const tokenTypes = [];
23
+ [
24
+ [0 /* class */, vscode_languageserver_1.SemanticTokenTypes.class],
25
+ [1 /* enum */, vscode_languageserver_1.SemanticTokenTypes.enum],
26
+ [2 /* interface */, vscode_languageserver_1.SemanticTokenTypes.interface],
27
+ [3 /* namespace */, vscode_languageserver_1.SemanticTokenTypes.namespace],
28
+ [4 /* typeParameter */, vscode_languageserver_1.SemanticTokenTypes.typeParameter],
29
+ [5 /* type */, vscode_languageserver_1.SemanticTokenTypes.type],
30
+ [6 /* parameter */, vscode_languageserver_1.SemanticTokenTypes.parameter],
31
+ [7 /* variable */, vscode_languageserver_1.SemanticTokenTypes.variable],
32
+ [8 /* enumMember */, vscode_languageserver_1.SemanticTokenTypes.enumMember],
33
+ [9 /* property */, vscode_languageserver_1.SemanticTokenTypes.property],
34
+ [10 /* function */, vscode_languageserver_1.SemanticTokenTypes.function],
35
+ [11 /* method */, vscode_languageserver_1.SemanticTokenTypes.method],
36
+ ].forEach(([tokenType, legend]) => (tokenTypes[tokenType] = legend));
37
+ return {
38
+ tokenModifiers,
39
+ tokenTypes,
40
+ };
41
+ }
42
+ exports.getSemanticTokenLegend = getSemanticTokenLegend;
12
43
  function symbolKindFromString(kind) {
13
44
  switch (kind) {
14
45
  case 'module':
package/dist/server.js CHANGED
@@ -25,6 +25,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
25
25
  Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.startLanguageServer = void 0;
27
27
  const vscode = __importStar(require("vscode-languageserver"));
28
+ const vscode_languageserver_1 = require("vscode-languageserver");
28
29
  const ConfigManager_1 = require("./core/config/ConfigManager");
29
30
  const DocumentManager_1 = require("./core/documents/DocumentManager");
30
31
  const DiagnosticsManager_1 = require("./core/DiagnosticsManager");
@@ -32,8 +33,9 @@ const AstroPlugin_1 = require("./plugins/astro/AstroPlugin");
32
33
  const CSSPlugin_1 = require("./plugins/css/CSSPlugin");
33
34
  const HTMLPlugin_1 = require("./plugins/html/HTMLPlugin");
34
35
  const PluginHost_1 = require("./plugins/PluginHost");
35
- const TypeScriptPlugin_1 = require("./plugins/typescript/TypeScriptPlugin");
36
+ const plugins_1 = require("./plugins");
36
37
  const utils_1 = require("./utils");
38
+ const utils_2 = require("./plugins/typescript/utils");
37
39
  const TagCloseRequest = new vscode.RequestType('html/tag');
38
40
  // Start the language server
39
41
  function startLanguageServer(connection) {
@@ -54,7 +56,7 @@ function startLanguageServer(connection) {
54
56
  // We don't currently support running the TypeScript and Astro plugin in the browser
55
57
  if (params.initializationOptions.environment !== 'browser') {
56
58
  pluginHost.registerPlugin(new AstroPlugin_1.AstroPlugin(documentManager, configManager, workspaceUris));
57
- pluginHost.registerPlugin(new TypeScriptPlugin_1.TypeScriptPlugin(documentManager, configManager, workspaceUris));
59
+ pluginHost.registerPlugin(new plugins_1.TypeScriptPlugin(documentManager, configManager, workspaceUris));
58
60
  }
59
61
  // Update language-server config with what the user supplied to us at launch
60
62
  configManager.updateConfig(params.initializationOptions.configuration.astro);
@@ -97,6 +99,11 @@ function startLanguageServer(connection) {
97
99
  colorProvider: true,
98
100
  hoverProvider: true,
99
101
  documentSymbolProvider: true,
102
+ semanticTokensProvider: {
103
+ legend: (0, utils_2.getSemanticTokenLegend)(),
104
+ range: true,
105
+ full: true,
106
+ },
100
107
  signatureHelpProvider: {
101
108
  triggerCharacters: ['(', ',', '<'],
102
109
  retriggerCharacters: [')'],
@@ -146,6 +153,8 @@ function startLanguageServer(connection) {
146
153
  return pluginHost.resolveCompletion(data, completionItem);
147
154
  });
148
155
  connection.onDocumentSymbol((params, cancellationToken) => pluginHost.getDocumentSymbols(params.textDocument, cancellationToken));
156
+ connection.onRequest(vscode_languageserver_1.SemanticTokensRequest.type, (evt, cancellationToken) => pluginHost.getSemanticTokens(evt.textDocument, undefined, cancellationToken));
157
+ connection.onRequest(vscode_languageserver_1.SemanticTokensRangeRequest.type, (evt, cancellationToken) => pluginHost.getSemanticTokens(evt.textDocument, evt.range, cancellationToken));
149
158
  connection.onDocumentColor((params) => pluginHost.getDocumentColors(params.textDocument));
150
159
  connection.onColorPresentation((params) => pluginHost.getColorPresentations(params.textDocument, params.range, params.color));
151
160
  connection.onRequest(TagCloseRequest, (evt) => pluginHost.doTagComplete(evt.textDocument, evt.position));
package/dist/utils.d.ts CHANGED
@@ -21,11 +21,6 @@ export declare function getLastPartOfPath(path: string): string;
21
21
  * This is not a 100% sure test as it'll return false for any component that does not match the standard format for a component
22
22
  */
23
23
  export declare function isPossibleComponent(node: Node): boolean;
24
- /**
25
- * Return true if a specific node could be a component with a client directive on it.
26
- * This is not a 100% sure test as it'll return false for any component that does not match the standard format for a component
27
- */
28
- export declare function isPossibleClientComponent(node: Node): boolean;
29
24
  /** Flattens an array */
30
25
  export declare function flatten<T>(arr: T[][]): T[];
31
26
  /** Clamps a number between min and max */
package/dist/utils.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.debounceThrottle = exports.debounceSameArg = exports.isBeforeOrEqualToPosition = exports.isInRange = exports.isNotNullOrUndefined = exports.clamp = exports.flatten = exports.isPossibleClientComponent = exports.isPossibleComponent = exports.getLastPartOfPath = exports.pathToUrl = exports.urlToPath = exports.normalizePath = exports.normalizeUri = void 0;
3
+ exports.debounceThrottle = exports.debounceSameArg = exports.isBeforeOrEqualToPosition = exports.isInRange = exports.isNotNullOrUndefined = exports.clamp = exports.flatten = exports.isPossibleComponent = exports.getLastPartOfPath = exports.pathToUrl = exports.urlToPath = exports.normalizePath = exports.normalizeUri = void 0;
4
4
  const vscode_uri_1 = require("vscode-uri");
5
5
  /** Normalizes a document URI */
6
6
  function normalizeUri(uri) {
@@ -46,21 +46,6 @@ function isPossibleComponent(node) {
46
46
  return !!((_a = node.tag) === null || _a === void 0 ? void 0 : _a[0].match(/[A-Z]/)) || !!((_b = node.tag) === null || _b === void 0 ? void 0 : _b.match(/.+[.][A-Z]/));
47
47
  }
48
48
  exports.isPossibleComponent = isPossibleComponent;
49
- /**
50
- * Return true if a specific node could be a component with a client directive on it.
51
- * This is not a 100% sure test as it'll return false for any component that does not match the standard format for a component
52
- */
53
- function isPossibleClientComponent(node) {
54
- if (isPossibleComponent(node) && node.attributes) {
55
- for (let [name] of Object.entries(node.attributes)) {
56
- if (name.startsWith('client:')) {
57
- return true;
58
- }
59
- }
60
- }
61
- return false;
62
- }
63
- exports.isPossibleClientComponent = isPossibleClientComponent;
64
49
  /** Flattens an array */
65
50
  function flatten(arr) {
66
51
  return arr.reduce((all, item) => [...all, ...item], []);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrojs/language-server",
3
- "version": "0.13.0",
3
+ "version": "0.13.3",
4
4
  "author": "withastro",
5
5
  "license": "MIT",
6
6
  "type": "commonjs",
@@ -19,7 +19,7 @@
19
19
  "test": "cross-env TS_NODE_TRANSPILE_ONLY=true mocha --require ts-node/register \"test/**/*.ts\" --exclude \"test/**/*.d.ts\""
20
20
  },
21
21
  "dependencies": {
22
- "@astrojs/svelte-language-integration": "^0.1.0",
22
+ "@astrojs/svelte-language-integration": "^0.1.2",
23
23
  "@vscode/emmet-helper": "^2.8.4",
24
24
  "lodash": "^4.17.21",
25
25
  "source-map": "^0.7.3",