@astrojs/language-server 0.11.0 → 0.13.0

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 (103) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/bin/browserServer.js +3 -0
  3. package/bin/nodeServer.js +3 -0
  4. package/dist/browser.d.ts +1 -0
  5. package/dist/browser.js +8 -0
  6. package/dist/check.js +2 -5
  7. package/dist/core/DiagnosticsManager.d.ts +3 -3
  8. package/dist/core/DiagnosticsManager.js +2 -2
  9. package/dist/core/config/ConfigManager.d.ts +19 -164
  10. package/dist/core/config/ConfigManager.js +62 -101
  11. package/dist/core/config/index.d.ts +1 -0
  12. package/dist/core/config/index.js +1 -0
  13. package/dist/core/config/interfaces.d.ts +123 -0
  14. package/dist/core/config/interfaces.js +2 -0
  15. package/dist/core/documents/AstroDocument.d.ts +18 -0
  16. package/dist/core/documents/AstroDocument.js +42 -0
  17. package/dist/core/documents/DocumentBase.d.ts +10 -2
  18. package/dist/core/documents/DocumentBase.js +15 -50
  19. package/dist/core/documents/DocumentManager.d.ts +12 -16
  20. package/dist/core/documents/DocumentManager.js +32 -26
  21. package/dist/core/documents/DocumentMapper.js +3 -1
  22. package/dist/core/documents/index.d.ts +1 -1
  23. package/dist/core/documents/index.js +1 -1
  24. package/dist/core/documents/parseAstro.d.ts +2 -2
  25. package/dist/core/documents/parseHtml.d.ts +2 -2
  26. package/dist/core/documents/parseHtml.js +4 -1
  27. package/dist/core/documents/utils.d.ts +22 -26
  28. package/dist/core/documents/utils.js +96 -134
  29. package/dist/index.d.ts +0 -1
  30. package/dist/index.js +1 -3
  31. package/dist/node.d.ts +1 -0
  32. package/dist/node.js +29 -0
  33. package/dist/plugins/PluginHost.d.ts +11 -9
  34. package/dist/plugins/PluginHost.js +34 -36
  35. package/dist/plugins/astro/AstroPlugin.d.ts +11 -12
  36. package/dist/plugins/astro/AstroPlugin.js +17 -42
  37. package/dist/plugins/astro/features/{CompletionProvider.d.ts → CompletionsProvider.d.ts} +5 -5
  38. package/dist/plugins/astro/features/{CompletionProvider.js → CompletionsProvider.js} +33 -58
  39. package/dist/plugins/css/CSSDocument.d.ts +3 -3
  40. package/dist/plugins/css/CSSDocument.js +7 -16
  41. package/dist/plugins/css/CSSPlugin.d.ts +31 -12
  42. package/dist/plugins/css/CSSPlugin.js +174 -41
  43. package/dist/plugins/css/StyleAttributeDocument.d.ts +2 -2
  44. package/dist/plugins/css/StyleAttributeDocument.js +2 -2
  45. package/dist/plugins/css/features/astro-selectors.d.ts +2 -0
  46. package/dist/plugins/css/features/astro-selectors.js +16 -0
  47. package/dist/plugins/css/features/{getIdClassCompletion.d.ts → getIdClassCompletions.d.ts} +3 -3
  48. package/dist/plugins/css/features/{getIdClassCompletion.js → getIdClassCompletions.js} +10 -9
  49. package/dist/plugins/css/{service.d.ts → language-service.d.ts} +0 -0
  50. package/dist/plugins/css/{service.js → language-service.js} +2 -1
  51. package/dist/plugins/html/HTMLPlugin.d.ts +18 -17
  52. package/dist/plugins/html/HTMLPlugin.js +69 -41
  53. package/dist/plugins/html/features/astro-attributes.d.ts +2 -0
  54. package/dist/plugins/html/features/astro-attributes.js +126 -0
  55. package/dist/plugins/index.d.ts +2 -2
  56. package/dist/plugins/index.js +2 -2
  57. package/dist/plugins/interfaces.d.ts +35 -48
  58. package/dist/plugins/typescript/LanguageServiceManager.d.ts +33 -14
  59. package/dist/plugins/typescript/LanguageServiceManager.js +57 -32
  60. package/dist/plugins/typescript/TypeScriptPlugin.d.ts +18 -23
  61. package/dist/plugins/typescript/TypeScriptPlugin.js +58 -55
  62. package/dist/plugins/typescript/astro-sys.d.ts +5 -3
  63. package/dist/plugins/typescript/astro-sys.js +24 -45
  64. package/dist/plugins/typescript/features/CompletionsProvider.d.ts +6 -6
  65. package/dist/plugins/typescript/features/CompletionsProvider.js +18 -38
  66. package/dist/plugins/typescript/features/DiagnosticsProvider.d.ts +4 -4
  67. package/dist/plugins/typescript/features/DiagnosticsProvider.js +27 -87
  68. package/dist/plugins/typescript/features/DocumentSymbolsProvider.d.ts +10 -0
  69. package/dist/plugins/typescript/features/DocumentSymbolsProvider.js +69 -0
  70. package/dist/plugins/typescript/features/HoverProvider.d.ts +4 -5
  71. package/dist/plugins/typescript/features/HoverProvider.js +9 -10
  72. package/dist/plugins/typescript/features/SignatureHelpProvider.d.ts +4 -5
  73. package/dist/plugins/typescript/features/SignatureHelpProvider.js +15 -11
  74. package/dist/plugins/typescript/features/utils.d.ts +1 -12
  75. package/dist/plugins/typescript/features/utils.js +2 -22
  76. package/dist/plugins/typescript/language-service.d.ts +38 -0
  77. package/dist/plugins/typescript/language-service.js +230 -0
  78. package/dist/plugins/typescript/module-loader.d.ts +5 -8
  79. package/dist/plugins/typescript/module-loader.js +43 -23
  80. package/dist/plugins/typescript/snapshots/DocumentSnapshot.d.ts +90 -0
  81. package/dist/plugins/typescript/snapshots/DocumentSnapshot.js +135 -0
  82. package/dist/plugins/typescript/snapshots/SnapshotManager.d.ts +42 -0
  83. package/dist/plugins/typescript/snapshots/SnapshotManager.js +197 -0
  84. package/dist/plugins/typescript/snapshots/utils.d.ts +28 -0
  85. package/dist/plugins/typescript/snapshots/utils.js +84 -0
  86. package/dist/plugins/typescript/utils.d.ts +10 -13
  87. package/dist/plugins/typescript/utils.js +154 -158
  88. package/dist/server.d.ts +2 -4
  89. package/dist/server.js +93 -54
  90. package/dist/utils.d.ts +20 -16
  91. package/dist/utils.js +35 -24
  92. package/package.json +18 -12
  93. package/types/astro-jsx.d.ts +1077 -0
  94. package/bin/server.js +0 -7
  95. package/dist/core/documents/Document.d.ts +0 -51
  96. package/dist/core/documents/Document.js +0 -135
  97. package/dist/plugins/typescript/DocumentSnapshot.d.ts +0 -99
  98. package/dist/plugins/typescript/DocumentSnapshot.js +0 -259
  99. package/dist/plugins/typescript/SnapshotManager.d.ts +0 -24
  100. package/dist/plugins/typescript/SnapshotManager.js +0 -103
  101. package/dist/plugins/typescript/languageService.d.ts +0 -17
  102. package/dist/plugins/typescript/languageService.js +0 -173
  103. package/types/index.d.ts +0 -4
@@ -1,85 +1,218 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CSSPlugin = void 0;
4
- const emmet_helper_1 = require("@vscode/emmet-helper");
5
4
  const vscode_languageserver_1 = require("vscode-languageserver");
6
- const utils_1 = require("../../core/documents/utils");
7
- const CSSDocument_1 = require("./CSSDocument");
8
- const service_1 = require("./service");
9
- const StyleAttributeDocument_1 = require("./StyleAttributeDocument");
10
5
  const documents_1 = require("../../core/documents");
6
+ const emmet_helper_1 = require("@vscode/emmet-helper");
7
+ const CSSDocument_1 = require("./CSSDocument");
8
+ const language_service_1 = require("./language-service");
11
9
  const parseHtml_1 = require("../../core/documents/parseHtml");
12
- const getIdClassCompletion_1 = require("./features/getIdClassCompletion");
10
+ const StyleAttributeDocument_1 = require("./StyleAttributeDocument");
11
+ const getIdClassCompletions_1 = require("./features/getIdClassCompletions");
12
+ const lodash_1 = require("lodash");
13
13
  class CSSPlugin {
14
- constructor(docManager, configManager) {
15
- this.documents = new WeakMap();
14
+ constructor(configManager) {
15
+ this.__name = 'css';
16
+ this.cssDocuments = new WeakMap();
16
17
  this.triggerCharacters = new Set(['.', ':', '-', '/']);
17
- this.pluginName = 'CSS';
18
- this.docManager = docManager;
19
18
  this.configManager = configManager;
20
- this.docManager.on('documentChange', (document) => {
21
- this.documents.set(document, new CSSDocument_1.CSSDocument(document));
22
- });
23
19
  }
24
- getCompletions(document, position, completionContext) {
25
- const triggerCharacter = completionContext === null || completionContext === void 0 ? void 0 : completionContext.triggerCharacter;
26
- const triggerKind = completionContext === null || completionContext === void 0 ? void 0 : completionContext.triggerKind;
27
- const isCustomTriggerCharacter = triggerKind === vscode_languageserver_1.CompletionTriggerKind.TriggerCharacter;
28
- if (isCustomTriggerCharacter && triggerCharacter && !this.triggerCharacters.has(triggerCharacter)) {
20
+ doHover(document, position) {
21
+ if (!this.featureEnabled('hover')) {
22
+ return null;
23
+ }
24
+ if ((0, documents_1.isInsideFrontmatter)(document.getText(), document.offsetAt(position))) {
29
25
  return null;
30
26
  }
31
- if (this.isInsideFrontmatter(document, position)) {
27
+ const styleTag = this.getStyleTagForPosition(document, position);
28
+ if (!styleTag) {
29
+ const attributeContext = (0, parseHtml_1.getAttributeContextAtPosition)(document, position);
30
+ if (!attributeContext) {
31
+ return null;
32
+ }
33
+ if (this.inStyleAttributeWithoutInterpolation(attributeContext, document.getText())) {
34
+ const [start, end] = attributeContext.valueRange;
35
+ return this.doHoverInternal(new StyleAttributeDocument_1.StyleAttributeDocument(document, start, end), position);
36
+ }
32
37
  return null;
33
38
  }
34
- const cssDocument = this.getCSSDoc(document);
35
- if (cssDocument.isInGenerated(position)) {
36
- return this.getCompletionsInternal(document, position, cssDocument);
39
+ const cssDocument = this.getCSSDocumentForStyleTag(styleTag, document);
40
+ if (shouldExcludeHover(cssDocument)) {
41
+ return null;
37
42
  }
38
- const attributeContext = (0, parseHtml_1.getAttributeContextAtPosition)(document, position);
39
- if (!attributeContext) {
43
+ return this.doHoverInternal(cssDocument, position);
44
+ }
45
+ doHoverInternal(cssDocument, position) {
46
+ const hoverInfo = (0, language_service_1.getLanguageService)(extractLanguage(cssDocument)).doHover(cssDocument, cssDocument.getGeneratedPosition(position), cssDocument.stylesheet);
47
+ return hoverInfo ? (0, documents_1.mapHoverToParent)(cssDocument, hoverInfo) : hoverInfo;
48
+ }
49
+ getCompletions(document, position, completionContext) {
50
+ if (!this.featureEnabled('completions')) {
40
51
  return null;
41
52
  }
42
- if (this.inStyleAttributeWithoutInterpolation(attributeContext, document.getText())) {
43
- const [start, end] = attributeContext.valueRange;
44
- return this.getCompletionsInternal(document, position, new StyleAttributeDocument_1.StyleAttributeDocument(document, start, end));
53
+ if ((0, documents_1.isInsideFrontmatter)(document.getText(), document.offsetAt(position))) {
54
+ return null;
45
55
  }
46
- else {
47
- return (0, getIdClassCompletion_1.getIdClassCompletion)(cssDocument, attributeContext);
56
+ const triggerCharacter = completionContext === null || completionContext === void 0 ? void 0 : completionContext.triggerCharacter;
57
+ const triggerKind = completionContext === null || completionContext === void 0 ? void 0 : completionContext.triggerKind;
58
+ const isCustomTriggerCharacter = triggerKind === vscode_languageserver_1.CompletionTriggerKind.TriggerCharacter;
59
+ if (isCustomTriggerCharacter && triggerCharacter && !this.triggerCharacters.has(triggerCharacter)) {
60
+ return null;
61
+ }
62
+ 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
64
+ if (!styleTag) {
65
+ const attributeContext = (0, parseHtml_1.getAttributeContextAtPosition)(document, position);
66
+ if (!attributeContext) {
67
+ return null;
68
+ }
69
+ if (this.inStyleAttributeWithoutInterpolation(attributeContext, document.getText())) {
70
+ const [start, end] = attributeContext.valueRange;
71
+ return this.getCompletionsInternal(document, position, new StyleAttributeDocument_1.StyleAttributeDocument(document, start, end));
72
+ }
73
+ // If we're not in a style attribute, instead give completions for ids and classes used in the current document
74
+ else if ((attributeContext.name == 'id' || attributeContext.name == 'class') && attributeContext.inValue) {
75
+ const stylesheets = this.getStylesheetsForDocument(document);
76
+ return (0, getIdClassCompletions_1.getIdClassCompletion)(stylesheets, attributeContext);
77
+ }
78
+ return null;
48
79
  }
80
+ const cssDocument = this.getCSSDocumentForStyleTag(styleTag, document);
81
+ return this.getCompletionsInternal(document, position, cssDocument);
49
82
  }
50
83
  getCompletionsInternal(document, position, cssDocument) {
51
84
  if (isSASS(cssDocument)) {
52
- // the css language service does not support sass, still we can use
53
- // the emmet helper directly to at least get emmet completions
85
+ // The CSS language service does not support SASS (not to be confused with SCSS)
86
+ // however we can at least still at least provide Emmet completions in SASS blocks
54
87
  return (0, emmet_helper_1.doComplete)(document, position, 'sass', this.configManager.getEmmetConfig()) || null;
55
88
  }
56
- const type = extractLanguage(cssDocument);
57
- const lang = (0, service_1.getLanguageService)(type);
89
+ const cssLang = extractLanguage(cssDocument);
90
+ const langService = (0, language_service_1.getLanguageService)(cssLang);
58
91
  const emmetResults = {
59
92
  isIncomplete: true,
60
93
  items: [],
61
94
  };
62
- const results = lang.doComplete(cssDocument, cssDocument.getGeneratedPosition(position), cssDocument.stylesheet);
95
+ const results = langService.doComplete(cssDocument, cssDocument.getGeneratedPosition(position), cssDocument.stylesheet);
63
96
  return vscode_languageserver_1.CompletionList.create([...(results ? results.items : []), ...emmetResults.items].map((completionItem) => (0, documents_1.mapCompletionItemToOriginal)(cssDocument, completionItem)),
64
97
  // Emmet completions change on every keystroke, so they are never complete
65
98
  emmetResults.items.length > 0);
66
99
  }
100
+ getDocumentColors(document) {
101
+ if (!this.featureEnabled('documentColors')) {
102
+ return [];
103
+ }
104
+ const allColorInfo = this.getCSSDocumentsForDocument(document).map((cssDoc) => {
105
+ const cssLang = extractLanguage(cssDoc);
106
+ const langService = (0, language_service_1.getLanguageService)(cssLang);
107
+ if (shouldExcludeColor(cssLang)) {
108
+ return [];
109
+ }
110
+ return langService
111
+ .findDocumentColors(cssDoc, cssDoc.stylesheet)
112
+ .map((colorInfo) => (0, documents_1.mapObjWithRangeToOriginal)(cssDoc, colorInfo));
113
+ });
114
+ return (0, lodash_1.flatten)(allColorInfo);
115
+ }
116
+ getColorPresentations(document, range, color) {
117
+ if (!this.featureEnabled('colorPresentations')) {
118
+ return [];
119
+ }
120
+ const allColorPres = this.getCSSDocumentsForDocument(document).map((cssDoc) => {
121
+ const cssLang = extractLanguage(cssDoc);
122
+ const langService = (0, language_service_1.getLanguageService)(cssLang);
123
+ if ((!cssDoc.isInGenerated(range.start) && !cssDoc.isInGenerated(range.end)) || shouldExcludeColor(cssLang)) {
124
+ return [];
125
+ }
126
+ return langService
127
+ .getColorPresentations(cssDoc, cssDoc.stylesheet, color, (0, documents_1.mapRangeToGenerated)(cssDoc, range))
128
+ .map((colorPres) => (0, documents_1.mapColorPresentationToOriginal)(cssDoc, colorPres));
129
+ });
130
+ return (0, lodash_1.flatten)(allColorPres);
131
+ }
132
+ getDocumentSymbols(document) {
133
+ if (!this.featureEnabled('documentSymbols')) {
134
+ return [];
135
+ }
136
+ const allDocumentSymbols = this.getCSSDocumentsForDocument(document).map((cssDoc) => {
137
+ return (0, language_service_1.getLanguageService)(extractLanguage(cssDoc))
138
+ .findDocumentSymbols(cssDoc, cssDoc.stylesheet)
139
+ .map((symbol) => (0, documents_1.mapSymbolInformationToOriginal)(cssDoc, symbol));
140
+ });
141
+ return (0, lodash_1.flatten)(allDocumentSymbols);
142
+ }
67
143
  inStyleAttributeWithoutInterpolation(attrContext, text) {
68
- return attrContext.name === 'style' && !!attrContext.valueRange && !text.substring(attrContext.valueRange[0], attrContext.valueRange[1]).includes('{');
144
+ return (attrContext.name === 'style' &&
145
+ !!attrContext.valueRange &&
146
+ !text.substring(attrContext.valueRange[0], attrContext.valueRange[1]).includes('{'));
69
147
  }
70
- getCSSDoc(document) {
71
- let cssDoc = this.documents.get(document);
148
+ /**
149
+ * Get the associated CSS Document for a style tag
150
+ */
151
+ getCSSDocumentForStyleTag(tag, document) {
152
+ let cssDoc = this.cssDocuments.get(tag);
72
153
  if (!cssDoc || cssDoc.version < document.version) {
73
- cssDoc = new CSSDocument_1.CSSDocument(document);
74
- this.documents.set(document, cssDoc);
154
+ cssDoc = new CSSDocument_1.CSSDocument(document, tag);
155
+ this.cssDocuments.set(tag, cssDoc);
75
156
  }
76
157
  return cssDoc;
77
158
  }
78
- isInsideFrontmatter(document, position) {
79
- return (0, utils_1.isInsideFrontmatter)(document.getText(), document.offsetAt(position));
159
+ /**
160
+ * Get all the CSSDocuments in a document
161
+ */
162
+ getCSSDocumentsForDocument(document) {
163
+ return document.styleTags.map((tag) => this.getCSSDocumentForStyleTag(tag, document));
164
+ }
165
+ /**
166
+ * Get all the stylesheets (Stylesheet type) in a document
167
+ */
168
+ getStylesheetsForDocument(document) {
169
+ return this.getCSSDocumentsForDocument(document).map((cssDoc) => cssDoc.stylesheet);
170
+ }
171
+ /**
172
+ * Get style tag at position for a document
173
+ */
174
+ getStyleTagForPosition(document, position) {
175
+ return document.styleTags.find((styleTag) => {
176
+ return (0, documents_1.isInTag)(position, styleTag);
177
+ });
178
+ }
179
+ featureEnabled(feature) {
180
+ return this.configManager.enabled('css.enabled') && this.configManager.enabled(`css.${feature}.enabled`);
80
181
  }
81
182
  }
82
183
  exports.CSSPlugin = CSSPlugin;
184
+ /**
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
188
+ */
189
+ function shouldExcludeHover(document) {
190
+ const language = typeof document === 'string' ? document : extractLanguage(document);
191
+ 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':
211
+ return true;
212
+ default:
213
+ return false;
214
+ }
215
+ }
83
216
  function isSASS(document) {
84
217
  switch (extractLanguage(document)) {
85
218
  case 'sass':
@@ -1,6 +1,6 @@
1
1
  import { Stylesheet } from 'vscode-css-languageservice';
2
2
  import { Position } from 'vscode-languageserver';
3
- import { Document, DocumentMapper, ReadableDocument } from '../../core/documents';
3
+ import { AstroDocument, DocumentMapper, ReadableDocument } from '../../core/documents';
4
4
  export declare class StyleAttributeDocument extends ReadableDocument implements DocumentMapper {
5
5
  private readonly parent;
6
6
  private readonly attrStart;
@@ -8,7 +8,7 @@ export declare class StyleAttributeDocument extends ReadableDocument implements
8
8
  readonly version: number;
9
9
  stylesheet: Stylesheet;
10
10
  languageId: string;
11
- constructor(parent: Document, attrStart: number, attrEnd: number);
11
+ constructor(parent: AstroDocument, attrStart: number, attrEnd: number);
12
12
  /**
13
13
  * Get the fragment position relative to the parent
14
14
  * @param pos Position in fragment
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.StyleAttributeDocument = void 0;
4
- const service_1 = require("./service");
4
+ const language_service_1 = require("./language-service");
5
5
  const documents_1 = require("../../core/documents");
6
6
  const PREFIX = '__ {';
7
7
  const SUFFIX = '}';
@@ -13,7 +13,7 @@ class StyleAttributeDocument extends documents_1.ReadableDocument {
13
13
  this.attrEnd = attrEnd;
14
14
  this.version = this.parent.version;
15
15
  this.languageId = 'css';
16
- this.stylesheet = (0, service_1.getLanguageService)(this.languageId).parseStylesheet(this);
16
+ this.stylesheet = (0, language_service_1.getLanguageService)(this.languageId).parseStylesheet(this);
17
17
  }
18
18
  /**
19
19
  * Get the fragment position relative to the parent
@@ -0,0 +1,2 @@
1
+ import { IPseudoClassData } from 'vscode-css-languageservice';
2
+ export declare const pseudoClass: IPseudoClassData[];
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pseudoClass = void 0;
4
+ exports.pseudoClass = [
5
+ {
6
+ name: ':global()',
7
+ description: `[astro] :global modifier
8
+ Apply styles to a selector globally`,
9
+ references: [
10
+ {
11
+ name: 'Astro documentation',
12
+ url: 'https://docs.astro.build/en/guides/styling/#global-styles-within-style-tag',
13
+ },
14
+ ],
15
+ },
16
+ ];
@@ -1,7 +1,7 @@
1
1
  import { CompletionItem, CompletionList } from 'vscode-languageserver';
2
2
  import { AttributeContext } from '../../../core/documents/parseHtml';
3
- import { CSSDocument } from '../CSSDocument';
4
- export declare function getIdClassCompletion(cssDoc: CSSDocument, attributeContext: AttributeContext): CompletionList | null;
3
+ import { Stylesheet } from 'vscode-css-languageservice';
4
+ export declare function getIdClassCompletion(stylesheets: Stylesheet[], attributeContext: AttributeContext): CompletionList | null;
5
5
  /**
6
6
  * incomplete see
7
7
  * https://github.com/microsoft/vscode-css-languageservice/blob/master/src/parser/cssNodes.ts#L14
@@ -16,4 +16,4 @@ export declare type CSSNode = {
16
16
  children: CSSNode[] | undefined;
17
17
  getText(): string;
18
18
  };
19
- export declare function collectSelectors(stylesheet: CSSNode, type: number): CompletionItem[];
19
+ export declare function collectSelectors(stylesheets: CSSNode[], type: number): CompletionItem[];
@@ -2,13 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.collectSelectors = exports.NodeType = exports.getIdClassCompletion = void 0;
4
4
  const vscode_languageserver_1 = require("vscode-languageserver");
5
- function getIdClassCompletion(cssDoc, attributeContext) {
5
+ function getIdClassCompletion(stylesheets, attributeContext) {
6
6
  const collectingType = getCollectingType(attributeContext);
7
7
  if (!collectingType) {
8
8
  return null;
9
9
  }
10
- const items = collectSelectors(cssDoc.stylesheet, collectingType);
11
- console.log('getIdClassCompletion items', items.length);
10
+ const items = collectSelectors(stylesheets, collectingType);
12
11
  return vscode_languageserver_1.CompletionList.create(items);
13
12
  }
14
13
  exports.getIdClassCompletion = getIdClassCompletion;
@@ -35,12 +34,14 @@ var NodeType;
35
34
  NodeType[NodeType["ClassSelector"] = 14] = "ClassSelector";
36
35
  NodeType[NodeType["IdentifierSelector"] = 15] = "IdentifierSelector";
37
36
  })(NodeType = exports.NodeType || (exports.NodeType = {}));
38
- function collectSelectors(stylesheet, type) {
37
+ function collectSelectors(stylesheets, type) {
39
38
  const result = [];
40
- walk(stylesheet, (node) => {
41
- if (node.type === type) {
42
- result.push(node);
43
- }
39
+ stylesheets.forEach((stylesheet) => {
40
+ walk(stylesheet, (node) => {
41
+ if (node.type === type) {
42
+ result.push(node);
43
+ }
44
+ });
44
45
  });
45
46
  return result.map((node) => ({
46
47
  label: node.getText().substring(1),
@@ -51,6 +52,6 @@ exports.collectSelectors = collectSelectors;
51
52
  function walk(node, callback) {
52
53
  callback(node);
53
54
  if (node.children) {
54
- node.children.forEach((node) => walk(node, callback));
55
+ node.children.forEach((childrenNode) => walk(childrenNode, callback));
55
56
  }
56
57
  }
@@ -2,9 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getLanguageService = exports.getLanguage = void 0;
4
4
  const vscode_css_languageservice_1 = require("vscode-css-languageservice");
5
+ const astro_selectors_1 = require("./features/astro-selectors");
5
6
  const customDataProvider = {
6
7
  providePseudoClasses() {
7
- return [];
8
+ return astro_selectors_1.pseudoClass;
8
9
  },
9
10
  provideProperties() {
10
11
  return [];
@@ -1,24 +1,25 @@
1
- import { CompletionsProvider, FoldingRangeProvider } from '../interfaces';
2
- import { FoldingRange } from 'vscode-html-languageservice';
3
- import { CompletionList, Position } from 'vscode-languageserver';
4
- import type { Document, DocumentManager } from '../../core/documents';
5
- import type { ConfigManager } from '../../core/config';
6
- export declare class HTMLPlugin implements CompletionsProvider, FoldingRangeProvider {
1
+ import { CompletionList, Position, FoldingRange, Hover, SymbolInformation } from 'vscode-languageserver';
2
+ import type { Plugin } from '../interfaces';
3
+ import { ConfigManager } from '../../core/config/ConfigManager';
4
+ import { AstroDocument } from '../../core/documents/AstroDocument';
5
+ export declare class HTMLPlugin implements Plugin {
6
+ __name: string;
7
7
  private lang;
8
- private documents;
8
+ private componentLang;
9
9
  private styleScriptTemplate;
10
10
  private configManager;
11
- pluginName: string;
12
- constructor(docManager: DocumentManager, configManager: ConfigManager);
13
- getCompletions(document: Document, position: Position): CompletionList | null;
14
- getFoldingRanges(document: Document): FoldingRange[] | null;
15
- doTagComplete(document: Document, position: Position): string | null;
11
+ constructor(configManager: ConfigManager);
12
+ doHover(document: AstroDocument, position: Position): Hover | null;
16
13
  /**
17
- * The HTML language service uses newer types which clash
18
- * without the stable ones. Transform to the stable types.
14
+ * Get HTML completions
15
+ */
16
+ getCompletions(document: AstroDocument, position: Position): CompletionList | null;
17
+ getFoldingRanges(document: AstroDocument): FoldingRange[] | null;
18
+ doTagComplete(document: AstroDocument, position: Position): string | null;
19
+ getDocumentSymbols(document: AstroDocument): SymbolInformation[];
20
+ /**
21
+ * Get lang completions for style tags (ex: `<style lang="scss">`)
19
22
  */
20
- private toCompletionItems;
21
23
  private getLangCompletions;
22
- private isInsideExpression;
23
- private isInsideFrontmatter;
24
+ private featureEnabled;
24
25
  }
@@ -1,81 +1,114 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.HTMLPlugin = void 0;
4
+ const vscode_languageserver_1 = require("vscode-languageserver");
4
5
  const emmet_helper_1 = require("@vscode/emmet-helper");
5
6
  const vscode_html_languageservice_1 = require("vscode-html-languageservice");
6
- const vscode_languageserver_1 = require("vscode-languageserver");
7
7
  const utils_1 = require("../../core/documents/utils");
8
+ const utils_2 = require("../../utils");
9
+ const astro_attributes_1 = require("./features/astro-attributes");
8
10
  class HTMLPlugin {
9
- constructor(docManager, configManager) {
10
- this.lang = (0, vscode_html_languageservice_1.getLanguageService)();
11
- this.documents = new WeakMap();
12
- this.styleScriptTemplate = new Set(['template', 'style', 'script']);
13
- this.pluginName = 'HTML';
14
- docManager.on('documentChange', (document) => {
15
- this.documents.set(document, document.html);
11
+ constructor(configManager) {
12
+ this.__name = 'html';
13
+ this.lang = (0, vscode_html_languageservice_1.getLanguageService)({
14
+ customDataProviders: [astro_attributes_1.astroAttributes],
16
15
  });
16
+ this.componentLang = (0, vscode_html_languageservice_1.getLanguageService)({
17
+ customDataProviders: [astro_attributes_1.astroAttributes, astro_attributes_1.astroDirectives],
18
+ useDefaultDataProvider: false,
19
+ });
20
+ this.styleScriptTemplate = new Set(['style']);
17
21
  this.configManager = configManager;
18
22
  }
19
- getCompletions(document, position) {
20
- const html = this.documents.get(document);
23
+ doHover(document, position) {
24
+ if (!this.featureEnabled('hover')) {
25
+ return null;
26
+ }
27
+ const html = document.html;
21
28
  if (!html) {
22
29
  return null;
23
30
  }
24
- if (this.isInsideFrontmatter(document, position) || this.isInsideExpression(html, document, position)) {
31
+ const node = html.findNodeAt(document.offsetAt(position));
32
+ if (!node) {
33
+ return null;
34
+ }
35
+ // If the node we're hovering on is a component, instead only provide astro-specific hover info
36
+ if ((0, utils_2.isPossibleComponent)(node)) {
37
+ return this.componentLang.doHover(document, position, html);
38
+ }
39
+ return this.lang.doHover(document, position, html);
40
+ }
41
+ /**
42
+ * Get HTML completions
43
+ */
44
+ getCompletions(document, position) {
45
+ if (!this.featureEnabled('completions')) {
25
46
  return null;
26
47
  }
48
+ const html = document.html;
49
+ const offset = document.offsetAt(position);
50
+ if (!html ||
51
+ (0, utils_1.isInsideFrontmatter)(document.getText(), offset) ||
52
+ (0, utils_1.isInsideExpression)(document.getText(), html.findNodeAt(offset).start, offset)) {
53
+ return null;
54
+ }
55
+ // Get Emmet completions
27
56
  let emmetResults = {
28
57
  isIncomplete: true,
29
58
  items: [],
30
59
  };
31
60
  this.lang.setCompletionParticipants([
32
61
  {
33
- onHtmlContent: () => (emmetResults = (0, emmet_helper_1.doComplete)(document, position, 'html', this.configManager.getEmmetConfig()) || emmetResults),
62
+ onHtmlContent: () => (emmetResults =
63
+ (0, emmet_helper_1.doComplete)(document, position, 'html', this.configManager.getEmmetConfig()) || emmetResults),
34
64
  },
35
65
  ]);
36
- // For components, we only want Emmet completions inside the component (aka slots) because HTML properties are not necessarily valid for a component
37
- const results = (0, utils_1.isInComponentStartTag)(html, document.offsetAt(position)) ? vscode_languageserver_1.CompletionList.create([]) : this.lang.doComplete(document, position, html);
38
- const items = this.toCompletionItems(results.items);
39
- return vscode_languageserver_1.CompletionList.create([...this.toCompletionItems(items), ...this.getLangCompletions(items), ...emmetResults.items],
66
+ // If we're in a component starting tag, we do not want HTML language completions
67
+ // as HTML attributes are not valid for components
68
+ 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],
40
72
  // Emmet completions change on every keystroke, so they are never complete
41
73
  emmetResults.items.length > 0);
42
74
  }
43
75
  getFoldingRanges(document) {
44
- const html = this.documents.get(document);
76
+ const html = document.html;
45
77
  if (!html) {
46
78
  return null;
47
79
  }
48
80
  return this.lang.getFoldingRanges(document);
49
81
  }
50
82
  doTagComplete(document, position) {
51
- const html = this.documents.get(document);
52
- if (!html) {
83
+ if (!this.featureEnabled('tagComplete')) {
53
84
  return null;
54
85
  }
55
- if (this.isInsideFrontmatter(document, position) || this.isInsideExpression(html, document, position)) {
86
+ const html = document.html;
87
+ const offset = document.offsetAt(position);
88
+ if (!html ||
89
+ (0, utils_1.isInsideFrontmatter)(document.getText(), offset) ||
90
+ (0, utils_1.isInsideExpression)(document.getText(), html.findNodeAt(offset).start, offset)) {
56
91
  return null;
57
92
  }
58
93
  return this.lang.doTagComplete(document, position, html);
59
94
  }
95
+ getDocumentSymbols(document) {
96
+ if (!this.featureEnabled('documentSymbols')) {
97
+ return [];
98
+ }
99
+ const html = document.html;
100
+ if (!html) {
101
+ return [];
102
+ }
103
+ return this.lang.findDocumentSymbols(document, html);
104
+ }
60
105
  /**
61
- * The HTML language service uses newer types which clash
62
- * without the stable ones. Transform to the stable types.
106
+ * Get lang completions for style tags (ex: `<style lang="scss">`)
63
107
  */
64
- toCompletionItems(items) {
65
- return items.map((item) => {
66
- if (!item.textEdit || vscode_languageserver_1.TextEdit.is(item.textEdit)) {
67
- return item;
68
- }
69
- return {
70
- ...item,
71
- textEdit: vscode_languageserver_1.TextEdit.replace(item.textEdit.replace, item.textEdit.newText),
72
- };
73
- });
74
- }
75
108
  getLangCompletions(completions) {
76
109
  const styleScriptTemplateCompletions = completions.filter((completion) => completion.kind === vscode_languageserver_1.CompletionItemKind.Property && this.styleScriptTemplate.has(completion.label));
77
110
  const langCompletions = [];
78
- addLangCompletion('style', ['scss', 'sass']);
111
+ addLangCompletion('style', ['scss', 'sass', 'less', 'styl', 'stylus']);
79
112
  return langCompletions;
80
113
  /** Add language completions */
81
114
  function addLangCompletion(tag, languages) {
@@ -96,13 +129,8 @@ class HTMLPlugin {
96
129
  }));
97
130
  }
98
131
  }
99
- isInsideExpression(html, document, position) {
100
- const offset = document.offsetAt(position);
101
- const node = html.findNodeAt(offset);
102
- return (0, utils_1.isInsideExpression)(document.getText(), node.start, offset);
103
- }
104
- isInsideFrontmatter(document, position) {
105
- return (0, utils_1.isInsideFrontmatter)(document.getText(), document.offsetAt(position));
132
+ featureEnabled(feature) {
133
+ return this.configManager.enabled('html.enabled') && this.configManager.enabled(`html.${feature}.enabled`);
106
134
  }
107
135
  }
108
136
  exports.HTMLPlugin = HTMLPlugin;
@@ -0,0 +1,2 @@
1
+ export declare const astroAttributes: import("vscode-html-languageservice").IHTMLDataProvider;
2
+ export declare const astroDirectives: import("vscode-html-languageservice").IHTMLDataProvider;