@astrojs/language-server 0.13.1 → 0.13.4

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.
Files changed (34) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/dist/core/documents/DocumentMapper.d.ts +2 -1
  3. package/dist/core/documents/DocumentMapper.js +8 -1
  4. package/dist/core/documents/utils.d.ts +1 -0
  5. package/dist/core/documents/utils.js +2 -0
  6. package/dist/plugins/PluginHost.d.ts +2 -1
  7. package/dist/plugins/PluginHost.js +4 -0
  8. package/dist/plugins/astro/AstroPlugin.d.ts +1 -1
  9. package/dist/plugins/astro/AstroPlugin.js +1 -1
  10. package/dist/plugins/astro/features/CompletionsProvider.d.ts +5 -6
  11. package/dist/plugins/astro/features/CompletionsProvider.js +50 -59
  12. package/dist/plugins/css/CSSPlugin.d.ts +2 -1
  13. package/dist/plugins/css/CSSPlugin.js +27 -28
  14. package/dist/plugins/css/features/astro-selectors.js +1 -2
  15. package/dist/plugins/html/HTMLPlugin.d.ts +1 -0
  16. package/dist/plugins/html/HTMLPlugin.js +8 -3
  17. package/dist/plugins/html/features/astro-attributes.d.ts +1 -0
  18. package/dist/plugins/html/features/astro-attributes.js +67 -3
  19. package/dist/plugins/html/utils.d.ts +6 -0
  20. package/dist/plugins/html/utils.js +11 -0
  21. package/dist/plugins/typescript/TypeScriptPlugin.d.ts +3 -1
  22. package/dist/plugins/typescript/TypeScriptPlugin.js +8 -0
  23. package/dist/plugins/typescript/features/DocumentSymbolsProvider.js +6 -3
  24. package/dist/plugins/typescript/features/SemanticTokenProvider.d.ts +15 -0
  25. package/dist/plugins/typescript/features/SemanticTokenProvider.js +81 -0
  26. package/dist/plugins/typescript/language-service.js +1 -1
  27. package/dist/plugins/typescript/snapshots/SnapshotManager.js +2 -1
  28. package/dist/plugins/typescript/utils.d.ts +24 -1
  29. package/dist/plugins/typescript/utils.js +32 -1
  30. package/dist/server.js +11 -2
  31. package/dist/utils.d.ts +0 -5
  32. package/dist/utils.js +1 -16
  33. package/package.json +3 -3
  34. package/types/astro-jsx.d.ts +112 -113
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @astrojs/language-server
2
2
 
3
+ ## 0.13.4
4
+
5
+ ### Patch Changes
6
+
7
+ - 5874655: Add support for Astro 0.26.0 attributes
8
+
9
+ ## 0.13.3
10
+
11
+ ### Patch Changes
12
+
13
+ - 1fb21ff: Add support for folding CSS
14
+ - 99d7536: Add support for semantic tokens
15
+ - b363c00: Improve completions for components
16
+
17
+ ## 0.13.2
18
+
19
+ ### Patch Changes
20
+
21
+ - aff8b76: Fix error caused by malformed Svelte components
22
+ - Updated dependencies [aff8b76]
23
+ - @astrojs/svelte-language-integration@0.1.2
24
+
3
25
  ## 0.13.1
4
26
 
5
27
  ### Patch 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));
@@ -11,6 +11,7 @@ export interface TagInformation {
11
11
  start: number;
12
12
  end: number;
13
13
  };
14
+ closed: boolean;
14
15
  }
15
16
  export declare function walk(node: Node): Generator<Node, void, unknown>;
16
17
  export declare function extractStyleTags(source: string, html?: HTMLDocument): TagInformation[];
@@ -48,6 +48,8 @@ function extractTags(text, tag, html) {
48
48
  startPos,
49
49
  endPos,
50
50
  container,
51
+ // vscode-html-languageservice types does not contain this, despite it existing. Annoying
52
+ closed: matchedNode.closed,
51
53
  };
52
54
  }
53
55
  }
@@ -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));
@@ -9,7 +9,7 @@ export declare class AstroPlugin implements Plugin {
9
9
  private readonly completionProvider;
10
10
  constructor(docManager: DocumentManager, configManager: ConfigManager, workspaceUris: string[]);
11
11
  getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext): Promise<AppCompletionList | null>;
12
- getFoldingRanges(document: AstroDocument): Promise<FoldingRange[]>;
12
+ getFoldingRanges(document: AstroDocument): FoldingRange[];
13
13
  getDefinitions(document: AstroDocument, position: Position): Promise<DefinitionLink[]>;
14
14
  private isInsideFrontmatter;
15
15
  private isComponentTag;
@@ -22,7 +22,7 @@ class AstroPlugin {
22
22
  const completions = this.completionProvider.getCompletions(document, position, completionContext);
23
23
  return completions;
24
24
  }
25
- async getFoldingRanges(document) {
25
+ getFoldingRanges(document) {
26
26
  const foldingRanges = [];
27
27
  const { frontmatter } = document.astroMeta;
28
28
  // Currently editing frontmatter, don't fold
@@ -1,18 +1,17 @@
1
- import type { AppCompletionList } from '../../interfaces';
1
+ import type { AppCompletionList, CompletionsProvider } from '../../interfaces';
2
2
  import type { AstroDocument, DocumentManager } from '../../../core/documents';
3
3
  import { CompletionContext, Position } from 'vscode-languageserver';
4
4
  import { LanguageServiceManager as TypeScriptLanguageServiceManager } from '../../typescript/LanguageServiceManager';
5
- export declare class CompletionsProviderImpl {
5
+ export declare class CompletionsProviderImpl implements CompletionsProvider {
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,22 @@ 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 html = document.html;
35
+ const offset = document.offsetAt(position);
36
+ if ((0, utils_1.isInComponentStartTag)(html, offset)) {
33
37
  const props = await this.getPropCompletions(document, position, completionContext);
34
38
  if (props.length) {
35
39
  items.push(...props);
36
40
  }
41
+ const node = html.findNodeAt(offset);
42
+ const isAstro = await this.isAstroComponent(document, node);
43
+ if (!isAstro) {
44
+ const directives = (0, utils_4.removeDataAttrCompletion)(this.directivesHTMLLang.doComplete(document, position, html).items);
45
+ items.push(...directives);
46
+ }
37
47
  }
38
48
  return vscode_languageserver_1.CompletionList.create(items, true);
39
49
  }
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
50
  getComponentScriptCompletion(document, position, completionContext) {
68
51
  const base = {
69
52
  kind: vscode_languageserver_1.CompletionItemKind.Snippet,
@@ -96,11 +79,10 @@ class CompletionsProviderImpl {
96
79
  return null;
97
80
  }
98
81
  async getPropCompletions(document, position, completionContext) {
99
- var _a, _b;
100
82
  const offset = document.offsetAt(position);
101
83
  const html = document.html;
102
84
  const node = html.findNodeAt(offset);
103
- if (!this.isComponentTag(node)) {
85
+ if (!(0, utils_2.isPossibleComponent)(node)) {
104
86
  return [];
105
87
  }
106
88
  const inAttribute = node.start + node.tag.length < offset;
@@ -119,8 +101,7 @@ class CompletionsProviderImpl {
119
101
  const componentName = node.tag;
120
102
  const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
121
103
  // Get the source file
122
- const filePath = (0, utils_2.urlToPath)(document.uri);
123
- const tsFilePath = (0, utils_3.toVirtualAstroFilePath)(filePath);
104
+ const tsFilePath = (0, utils_3.toVirtualAstroFilePath)(tsDoc.filePath);
124
105
  const program = lang.getProgram();
125
106
  const sourceFile = program === null || program === void 0 ? void 0 : program.getSourceFile(tsFilePath);
126
107
  const typeChecker = program === null || program === void 0 ? void 0 : program.getTypeChecker();
@@ -133,26 +114,22 @@ class CompletionsProviderImpl {
133
114
  if (!importType) {
134
115
  return [];
135
116
  }
136
- // Get the import's type
117
+ // Get the component's props type
137
118
  const componentType = this.getPropType(importType, typeChecker);
138
119
  if (!componentType) {
139
120
  return [];
140
121
  }
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);
122
+ let completionItems = [];
123
+ // Add completions for this component's props type properties
124
+ const properties = componentType.getProperties().filter((property) => property.name !== 'children') || [];
125
+ properties.forEach((property) => {
126
+ let completionItem = this.getCompletionItemForProperty(property, typeChecker);
154
127
  completionItems.push(completionItem);
155
128
  });
129
+ // Ensure that props shows up first as a completion, despite this plugin being ran after the HTML one
130
+ completionItems = completionItems.map((item) => {
131
+ return { ...item, sortText: '_' };
132
+ });
156
133
  return completionItems;
157
134
  }
158
135
  getImportedSymbol(sourceFile, identifier) {
@@ -203,7 +180,7 @@ class CompletionsProviderImpl {
203
180
  }
204
181
  return null;
205
182
  }
206
- getCompletionItemForTypeMember(mem, typeChecker) {
183
+ getCompletionItemForProperty(mem, typeChecker) {
207
184
  let item = {
208
185
  label: mem.name,
209
186
  insertText: mem.name,
@@ -223,15 +200,29 @@ class CompletionsProviderImpl {
223
200
  }
224
201
  return item;
225
202
  }
226
- isComponentTag(node) {
227
- if (!node.tag) {
203
+ async isAstroComponent(document, node) {
204
+ var _a;
205
+ const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
206
+ // Get the source file
207
+ const tsFilePath = (0, utils_3.toVirtualAstroFilePath)(tsDoc.filePath);
208
+ const program = lang.getProgram();
209
+ const sourceFile = program === null || program === void 0 ? void 0 : program.getSourceFile(tsFilePath);
210
+ const typeChecker = program === null || program === void 0 ? void 0 : program.getTypeChecker();
211
+ if (!sourceFile || !typeChecker) {
228
212
  return false;
229
213
  }
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));
214
+ const componentName = node.tag;
215
+ const imp = this.getImportedSymbol(sourceFile, componentName);
216
+ const importType = imp && typeChecker.getTypeAtLocation(imp);
217
+ if (!importType) {
218
+ return false;
219
+ }
220
+ const symbolDeclaration = (_a = importType.getSymbol()) === null || _a === void 0 ? void 0 : _a.declarations;
221
+ if (symbolDeclaration) {
222
+ const fileName = symbolDeclaration[0].getSourceFile().fileName;
223
+ return fileName.endsWith('.astro');
224
+ }
225
+ return false;
235
226
  }
236
227
  }
237
228
  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
  /**
@@ -25,6 +25,12 @@ class CSSPlugin {
25
25
  return null;
26
26
  }
27
27
  const styleTag = this.getStyleTagForPosition(document, position);
28
+ // We technically can return results even for open tags, however, a lot of the info returned is not valid
29
+ // Since most editors will automatically close the tag before the user start working in them, this shouldn't be a problem
30
+ if (styleTag && !styleTag.closed) {
31
+ return null;
32
+ }
33
+ // If we don't have a style tag at this position, we might be in a style property instead, let's check
28
34
  if (!styleTag) {
29
35
  const attributeContext = (0, parseHtml_1.getAttributeContextAtPosition)(document, position);
30
36
  if (!attributeContext) {
@@ -37,7 +43,8 @@ class CSSPlugin {
37
43
  return null;
38
44
  }
39
45
  const cssDocument = this.getCSSDocumentForStyleTag(styleTag, document);
40
- if (shouldExcludeHover(cssDocument)) {
46
+ const cssLang = extractLanguage(cssDocument);
47
+ if (!isSupportedByLangService(cssLang)) {
41
48
  return null;
42
49
  }
43
50
  return this.doHoverInternal(cssDocument, position);
@@ -60,7 +67,9 @@ class CSSPlugin {
60
67
  return null;
61
68
  }
62
69
  const styleTag = this.getStyleTagForPosition(document, position);
63
- // If we don't have a style tag at this position, we might be in a style property instead, let's check
70
+ if (styleTag && !styleTag.closed) {
71
+ return null;
72
+ }
64
73
  if (!styleTag) {
65
74
  const attributeContext = (0, parseHtml_1.getAttributeContextAtPosition)(document, position);
66
75
  if (!attributeContext) {
@@ -104,7 +113,7 @@ class CSSPlugin {
104
113
  const allColorInfo = this.getCSSDocumentsForDocument(document).map((cssDoc) => {
105
114
  const cssLang = extractLanguage(cssDoc);
106
115
  const langService = (0, language_service_1.getLanguageService)(cssLang);
107
- if (shouldExcludeColor(cssLang)) {
116
+ if (!isSupportedByLangService(cssLang)) {
108
117
  return [];
109
118
  }
110
119
  return langService
@@ -120,7 +129,8 @@ class CSSPlugin {
120
129
  const allColorPres = this.getCSSDocumentsForDocument(document).map((cssDoc) => {
121
130
  const cssLang = extractLanguage(cssDoc);
122
131
  const langService = (0, language_service_1.getLanguageService)(cssLang);
123
- if ((!cssDoc.isInGenerated(range.start) && !cssDoc.isInGenerated(range.end)) || shouldExcludeColor(cssLang)) {
132
+ if ((!cssDoc.isInGenerated(range.start) && !cssDoc.isInGenerated(range.end)) ||
133
+ !isSupportedByLangService(cssLang)) {
124
134
  return [];
125
135
  }
126
136
  return langService
@@ -129,6 +139,14 @@ class CSSPlugin {
129
139
  });
130
140
  return (0, lodash_1.flatten)(allColorPres);
131
141
  }
142
+ getFoldingRanges(document) {
143
+ const allFoldingRanges = this.getCSSDocumentsForDocument(document).map((cssDoc) => {
144
+ const cssLang = extractLanguage(cssDoc);
145
+ const langService = (0, language_service_1.getLanguageService)(cssLang);
146
+ return langService.getFoldingRanges(cssDoc).map((foldingRange) => (0, documents_1.mapFoldingRangeToParent)(cssDoc, foldingRange));
147
+ });
148
+ return (0, lodash_1.flatten)(allFoldingRanges);
149
+ }
132
150
  getDocumentSymbols(document) {
133
151
  if (!this.featureEnabled('documentSymbols')) {
134
152
  return [];
@@ -182,32 +200,13 @@ class CSSPlugin {
182
200
  }
183
201
  exports.CSSPlugin = CSSPlugin;
184
202
  /**
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
203
+ * Check is a CSSDocument's language is supported by the CSS language service
188
204
  */
189
- function shouldExcludeHover(document) {
190
- const language = typeof document === 'string' ? document : extractLanguage(document);
205
+ function isSupportedByLangService(language) {
191
206
  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':
207
+ case 'css':
208
+ case 'scss':
209
+ case 'less':
211
210
  return true;
212
211
  default:
213
212
  return false;
@@ -4,8 +4,7 @@ exports.pseudoClass = void 0;
4
4
  exports.pseudoClass = [
5
5
  {
6
6
  name: ':global()',
7
- description: `[astro] :global modifier
8
- Apply styles to a selector globally`,
7
+ description: 'Apply styles to a selector globally',
9
8
  references: [
10
9
  {
11
10
  name: 'Astro documentation',
@@ -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',
@@ -38,7 +43,7 @@ exports.astroAttributes = (0, vscode_html_languageservice_1.newHTMLDataProvider)
38
43
  // The VS Code tag definitions does not provide a description for the deprecated `charset` attribute on script tags
39
44
  // Which mean that since we get no hover info for this, we instead get JSX hover info. So we'll just specify a description ourselves for this specific case
40
45
  name: 'charset',
41
- description: "(Deprecated) It's unnecessary to specify the charset attribute, because documents must use UTF-8, and the script element inherits its character encoding from the document.",
46
+ description: "**Deprecated**\n\nIt's unnecessary to specify the charset attribute, because documents must use UTF-8, and the script element inherits its character encoding from the document.",
42
47
  },
43
48
  {
44
49
  name: 'define:vars',
@@ -50,6 +55,28 @@ exports.astroAttributes = (0, vscode_html_languageservice_1.newHTMLDataProvider)
50
55
  },
51
56
  ],
52
57
  },
58
+ {
59
+ name: 'hoist',
60
+ description: '**Deprecated in Astro >= 0.26.0**\n\nBuilds, optimizes, and bundles your script with the other JavaScript on the page',
61
+ valueSet: 'v',
62
+ references: [
63
+ {
64
+ name: 'Astro documentation',
65
+ url: 'https://docs.astro.build/en/core-concepts/astro-components/#using-hoisted-scripts',
66
+ },
67
+ ],
68
+ },
69
+ {
70
+ name: 'is:inline',
71
+ description: 'Leave a script tag inline in the page template. No processing will be done on its content',
72
+ valueSet: 'v',
73
+ references: [
74
+ {
75
+ name: 'Astro documentation',
76
+ url: 'https://docs.astro.build/en/migrate/#new-default-script-behavior',
77
+ },
78
+ ],
79
+ },
53
80
  ],
54
81
  },
55
82
  {
@@ -65,6 +92,39 @@ exports.astroAttributes = (0, vscode_html_languageservice_1.newHTMLDataProvider)
65
92
  },
66
93
  ],
67
94
  },
95
+ {
96
+ name: 'global',
97
+ description: '**Deprecated in favor of `is:global` in >= Astro 0.26.0**\n\nOpts-out of automatic CSS scoping, all contents will be available globally',
98
+ valueSet: 'v',
99
+ references: [
100
+ {
101
+ name: 'Astro documentation',
102
+ url: 'https://docs.astro.build/en/guides/styling/#global-styles',
103
+ },
104
+ ],
105
+ },
106
+ {
107
+ name: 'is:global',
108
+ description: 'Opts-out of automatic CSS scoping, all contents will be available globally',
109
+ valueSet: 'v',
110
+ references: [
111
+ {
112
+ name: 'Astro documentation',
113
+ url: 'https://docs.astro.build/en/guides/styling/#global-styles',
114
+ },
115
+ ],
116
+ },
117
+ {
118
+ name: 'is:inline',
119
+ description: 'Leave a style tag inline in the page template. No processing will be done on its content',
120
+ valueSet: 'v',
121
+ references: [
122
+ {
123
+ name: 'Astro documentation',
124
+ url: 'https://docs.astro.build/en/migrate/#new-default-script-behavior',
125
+ },
126
+ ],
127
+ },
68
128
  ],
69
129
  },
70
130
  ],
@@ -75,6 +135,7 @@ exports.astroDirectives = (0, vscode_html_languageservice_1.newHTMLDataProvider)
75
135
  {
76
136
  name: 'client:load',
77
137
  description: 'Start importing the component JS at page load. Hydrate the component when import completes.',
138
+ valueSet: 'v',
78
139
  references: [
79
140
  {
80
141
  name: 'Astro documentation',
@@ -85,6 +146,7 @@ exports.astroDirectives = (0, vscode_html_languageservice_1.newHTMLDataProvider)
85
146
  {
86
147
  name: 'client:idle',
87
148
  description: 'Start importing the component JS as soon as main thread is free (uses requestIdleCallback()). Hydrate the component when import completes.',
149
+ valueSet: 'v',
88
150
  references: [
89
151
  {
90
152
  name: 'Astro documentation',
@@ -95,6 +157,7 @@ exports.astroDirectives = (0, vscode_html_languageservice_1.newHTMLDataProvider)
95
157
  {
96
158
  name: 'client:visible',
97
159
  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.',
160
+ valueSet: 'v',
98
161
  references: [
99
162
  {
100
163
  name: 'Astro documentation',
@@ -115,6 +178,7 @@ exports.astroDirectives = (0, vscode_html_languageservice_1.newHTMLDataProvider)
115
178
  {
116
179
  name: 'client:only',
117
180
  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.',
181
+ valueSet: 'v',
118
182
  references: [
119
183
  {
120
184
  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 completions
5
+ */
6
+ export declare function removeDataAttrCompletion(items: CompletionItem[]): CompletionItem[];