@astrojs/language-server 0.9.2 → 0.12.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 (97) hide show
  1. package/CHANGELOG.md +22 -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 +6 -1
  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 +37 -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 +6 -2
  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 +8 -9
  34. package/dist/plugins/PluginHost.js +22 -36
  35. package/dist/plugins/astro/AstroPlugin.d.ts +11 -12
  36. package/dist/plugins/astro/AstroPlugin.js +17 -38
  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 -54
  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 +19 -11
  42. package/dist/plugins/css/CSSPlugin.js +63 -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 +15 -17
  52. package/dist/plugins/html/HTMLPlugin.js +33 -41
  53. package/dist/plugins/index.d.ts +2 -2
  54. package/dist/plugins/index.js +7 -3
  55. package/dist/plugins/interfaces.d.ts +35 -48
  56. package/dist/plugins/typescript/LanguageServiceManager.d.ts +33 -14
  57. package/dist/plugins/typescript/LanguageServiceManager.js +57 -32
  58. package/dist/plugins/typescript/TypeScriptPlugin.d.ts +16 -23
  59. package/dist/plugins/typescript/TypeScriptPlugin.js +48 -56
  60. package/dist/plugins/typescript/astro-sys.d.ts +5 -3
  61. package/dist/plugins/typescript/astro-sys.js +24 -41
  62. package/dist/plugins/typescript/features/CompletionsProvider.d.ts +6 -6
  63. package/dist/plugins/typescript/features/CompletionsProvider.js +17 -33
  64. package/dist/plugins/typescript/features/DiagnosticsProvider.d.ts +4 -4
  65. package/dist/plugins/typescript/features/DiagnosticsProvider.js +22 -61
  66. package/dist/plugins/typescript/features/HoverProvider.d.ts +4 -5
  67. package/dist/plugins/typescript/features/HoverProvider.js +9 -10
  68. package/dist/plugins/typescript/features/SignatureHelpProvider.d.ts +4 -5
  69. package/dist/plugins/typescript/features/SignatureHelpProvider.js +15 -11
  70. package/dist/plugins/typescript/features/utils.d.ts +1 -12
  71. package/dist/plugins/typescript/features/utils.js +2 -22
  72. package/dist/plugins/typescript/language-service.d.ts +38 -0
  73. package/dist/plugins/typescript/language-service.js +227 -0
  74. package/dist/plugins/typescript/module-loader.d.ts +5 -8
  75. package/dist/plugins/typescript/module-loader.js +43 -23
  76. package/dist/plugins/typescript/{DocumentSnapshot.d.ts → snapshots/DocumentSnapshot.d.ts} +45 -42
  77. package/dist/plugins/typescript/snapshots/DocumentSnapshot.js +135 -0
  78. package/dist/plugins/typescript/snapshots/SnapshotManager.d.ts +42 -0
  79. package/dist/plugins/typescript/snapshots/SnapshotManager.js +197 -0
  80. package/dist/plugins/typescript/snapshots/utils.d.ts +28 -0
  81. package/dist/plugins/typescript/snapshots/utils.js +84 -0
  82. package/dist/plugins/typescript/utils.d.ts +10 -11
  83. package/dist/plugins/typescript/utils.js +122 -151
  84. package/dist/server.d.ts +2 -4
  85. package/dist/server.js +88 -54
  86. package/dist/utils.d.ts +16 -8
  87. package/dist/utils.js +29 -14
  88. package/package.json +19 -13
  89. package/bin/server.js +0 -7
  90. package/dist/core/documents/Document.d.ts +0 -51
  91. package/dist/core/documents/Document.js +0 -135
  92. package/dist/plugins/typescript/DocumentSnapshot.js +0 -202
  93. package/dist/plugins/typescript/SnapshotManager.d.ts +0 -24
  94. package/dist/plugins/typescript/SnapshotManager.js +0 -97
  95. package/dist/plugins/typescript/languageService.d.ts +0 -17
  96. package/dist/plugins/typescript/languageService.js +0 -169
  97. package/types/index.d.ts +0 -4
@@ -1,12 +1,12 @@
1
1
  import type { AppCompletionList } from '../../interfaces';
2
- import type { Document, DocumentManager } from '../../../core/documents';
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 CompletionProvider {
5
+ export declare class CompletionsProviderImpl {
6
6
  private readonly docManager;
7
- private readonly tsLanguageServiceManager;
8
- constructor(docManager: DocumentManager, tsLanguageServiceManager: TypeScriptLanguageServiceManager);
9
- getCompletions(document: Document, position: Position, completionContext?: CompletionContext): Promise<AppCompletionList | null>;
7
+ private readonly languageServiceManager;
8
+ constructor(docManager: DocumentManager, languageServiceManager: TypeScriptLanguageServiceManager);
9
+ getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext): Promise<AppCompletionList | null>;
10
10
  private getClientHintCompletion;
11
11
  private getComponentScriptCompletion;
12
12
  private getPropCompletions;
@@ -1,34 +1,18 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
- }) : (function(o, m, k, k2) {
6
- if (k2 === undefined) k2 = k;
7
- o[k2] = m[k];
8
- }));
9
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
- Object.defineProperty(o, "default", { enumerable: true, value: v });
11
- }) : function(o, v) {
12
- o["default"] = v;
13
- });
14
- var __importStar = (this && this.__importStar) || function (mod) {
15
- if (mod && mod.__esModule) return mod;
16
- var result = {};
17
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
- __setModuleDefault(result, mod);
19
- return result;
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
20
4
  };
21
5
  Object.defineProperty(exports, "__esModule", { value: true });
22
- exports.CompletionProvider = void 0;
6
+ exports.CompletionsProviderImpl = void 0;
23
7
  const vscode_languageserver_1 = require("vscode-languageserver");
24
- const ts = __importStar(require("typescript"));
8
+ const typescript_1 = __importDefault(require("typescript"));
25
9
  const utils_1 = require("../../../core/documents/utils");
26
10
  const utils_2 = require("../../../utils");
27
11
  const utils_3 = require("../../typescript/utils");
28
- class CompletionProvider {
29
- constructor(docManager, tsLanguageServiceManager) {
12
+ class CompletionsProviderImpl {
13
+ constructor(docManager, languageServiceManager) {
30
14
  this.docManager = docManager;
31
- this.tsLanguageServiceManager = tsLanguageServiceManager;
15
+ this.languageServiceManager = languageServiceManager;
32
16
  }
33
17
  async getCompletions(document, position, completionContext) {
34
18
  const doc = this.docManager.get(document.uri);
@@ -76,8 +60,8 @@ class CompletionProvider {
76
60
  {
77
61
  label: ':media',
78
62
  insertText: 'media',
79
- commitCharacters: ['m']
80
- }
63
+ commitCharacters: ['m'],
64
+ },
81
65
  ];
82
66
  }
83
67
  getComponentScriptCompletion(document, position, completionContext) {
@@ -91,18 +75,22 @@ class CompletionProvider {
91
75
  commitCharacters: ['-'],
92
76
  };
93
77
  const prefix = document.getLineUntilOffset(document.offsetAt(position));
94
- if (document.astro.frontmatter.state === null) {
78
+ if (document.astroMeta.frontmatter.state === null) {
95
79
  return {
96
80
  ...base,
97
81
  insertText: '---\n$0\n---',
98
- textEdit: prefix.match(/^\s*\-+/) ? vscode_languageserver_1.TextEdit.replace({ start: { ...position, character: 0 }, end: position }, '---\n$0\n---') : undefined,
82
+ textEdit: prefix.match(/^\s*\-+/)
83
+ ? vscode_languageserver_1.TextEdit.replace({ start: { ...position, character: 0 }, end: position }, '---\n$0\n---')
84
+ : undefined,
99
85
  };
100
86
  }
101
- if (document.astro.frontmatter.state === 'open') {
87
+ if (document.astroMeta.frontmatter.state === 'open') {
102
88
  return {
103
89
  ...base,
104
90
  insertText: '---',
105
- textEdit: prefix.match(/^\s*\-+/) ? vscode_languageserver_1.TextEdit.replace({ start: { ...position, character: 0 }, end: position }, '---') : undefined,
91
+ textEdit: prefix.match(/^\s*\-+/)
92
+ ? vscode_languageserver_1.TextEdit.replace({ start: { ...position, character: 0 }, end: position }, '---')
93
+ : undefined,
106
94
  };
107
95
  }
108
96
  return null;
@@ -123,15 +111,17 @@ class CompletionProvider {
123
111
  return [];
124
112
  }
125
113
  // If inside of attribute value, skip.
126
- if (completionContext && completionContext.triggerKind === vscode_languageserver_1.CompletionTriggerKind.TriggerCharacter && completionContext.triggerCharacter === '"') {
114
+ if (completionContext &&
115
+ completionContext.triggerKind === vscode_languageserver_1.CompletionTriggerKind.TriggerCharacter &&
116
+ completionContext.triggerCharacter === '"') {
127
117
  return [];
128
118
  }
129
119
  const componentName = node.tag;
130
- const { lang: thisLang } = await this.tsLanguageServiceManager.getTypeScriptDoc(document);
120
+ const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
131
121
  // Get the source file
132
122
  const filePath = (0, utils_2.urlToPath)(document.uri);
133
123
  const tsFilePath = (0, utils_3.toVirtualAstroFilePath)(filePath);
134
- const program = thisLang.getProgram();
124
+ const program = lang.getProgram();
135
125
  const sourceFile = program === null || program === void 0 ? void 0 : program.getSourceFile(tsFilePath);
136
126
  const typeChecker = program === null || program === void 0 ? void 0 : program.getTypeChecker();
137
127
  if (!sourceFile || !typeChecker) {
@@ -152,14 +142,14 @@ class CompletionProvider {
152
142
  // Add completions for this types props
153
143
  for (let baseType of componentType.getBaseTypes() || []) {
154
144
  const members = ((_a = baseType.getSymbol()) === null || _a === void 0 ? void 0 : _a.members) || [];
155
- members.forEach(mem => {
145
+ members.forEach((mem) => {
156
146
  let completionItem = this.getCompletionItemForTypeMember(mem, typeChecker);
157
147
  completionItems.push(completionItem);
158
148
  });
159
149
  }
160
150
  // Add completions for this types base members
161
151
  const members = ((_b = componentType.getSymbol()) === null || _b === void 0 ? void 0 : _b.members) || [];
162
- members.forEach(mem => {
152
+ members.forEach((mem) => {
163
153
  let completionItem = this.getCompletionItemForTypeMember(mem, typeChecker);
164
154
  completionItems.push(completionItem);
165
155
  });
@@ -168,19 +158,20 @@ class CompletionProvider {
168
158
  getImportedSymbol(sourceFile, identifier) {
169
159
  for (let list of sourceFile.getChildren()) {
170
160
  for (let node of list.getChildren()) {
171
- if (ts.isImportDeclaration(node)) {
161
+ if (typescript_1.default.isImportDeclaration(node)) {
172
162
  let clauses = node.importClause;
173
163
  if (!clauses)
174
164
  return null;
175
165
  let namedImport = clauses.getChildAt(0);
176
- if (ts.isNamedImports(namedImport)) {
177
- for (let imp of namedImport.elements) { // Iterate the named imports
166
+ if (typescript_1.default.isNamedImports(namedImport)) {
167
+ for (let imp of namedImport.elements) {
168
+ // Iterate the named imports
178
169
  if (imp.name.getText() === identifier) {
179
170
  return imp;
180
171
  }
181
172
  }
182
173
  }
183
- else if (ts.isIdentifier(namedImport)) {
174
+ else if (typescript_1.default.isIdentifier(namedImport)) {
184
175
  if (namedImport.getText() === identifier) {
185
176
  return namedImport;
186
177
  }
@@ -196,21 +187,9 @@ class CompletionProvider {
196
187
  return null;
197
188
  }
198
189
  for (const decl of (sym === null || sym === void 0 ? void 0 : sym.getDeclarations()) || []) {
199
- const fileName = decl.getSourceFile().fileName;
200
- if ((0, utils_3.isVirtualAstroFilePath)(fileName)) {
201
- if (!ts.isFunctionDeclaration(decl)) {
202
- console.error(`Unexpected: .astro files should export a default function for the component definition.`);
203
- continue;
204
- }
205
- const fn = decl;
206
- if (!fn.parameters.length)
207
- continue;
208
- const param1 = fn.parameters[0];
209
- const type = typeChecker.getTypeAtLocation(param1);
210
- return type;
211
- }
212
- else if (fileName.endsWith('.tsx') || fileName.endsWith('.jsx')) {
213
- if (!ts.isFunctionDeclaration(decl)) {
190
+ const fileName = (0, utils_3.toVirtualFilePath)(decl.getSourceFile().fileName);
191
+ if (fileName.endsWith('.tsx') || fileName.endsWith('.jsx')) {
192
+ if (!typescript_1.default.isFunctionDeclaration(decl)) {
214
193
  console.error(`We only support function components for tsx/jsx at the moment.`);
215
194
  continue;
216
195
  }
@@ -255,4 +234,4 @@ class CompletionProvider {
255
234
  return (0, utils_1.isInsideFrontmatter)(document.getText(), document.offsetAt(position));
256
235
  }
257
236
  }
258
- exports.CompletionProvider = CompletionProvider;
237
+ exports.CompletionsProviderImpl = CompletionsProviderImpl;
@@ -1,6 +1,6 @@
1
1
  import { Stylesheet, TextDocument } from 'vscode-css-languageservice';
2
2
  import { Position } from 'vscode-languageserver';
3
- import { Document, DocumentMapper, ReadableDocument } from '../../core/documents/index';
3
+ import { AstroDocument, DocumentMapper, ReadableDocument, TagInformation } from '../../core/documents';
4
4
  export interface CSSDocumentBase extends DocumentMapper, TextDocument {
5
5
  languageId: string;
6
6
  stylesheet: Stylesheet;
@@ -11,7 +11,7 @@ export declare class CSSDocument extends ReadableDocument implements DocumentMap
11
11
  readonly version: number;
12
12
  stylesheet: Stylesheet;
13
13
  languageId: string;
14
- constructor(parent: Document);
14
+ constructor(parent: AstroDocument, styleInfo: Pick<TagInformation, 'attributes' | 'start' | 'end'>);
15
15
  /**
16
16
  * Get the fragment position relative to the parent
17
17
  * @param pos Position in fragment
@@ -32,7 +32,7 @@ export declare class CSSDocument extends ReadableDocument implements DocumentMap
32
32
  */
33
33
  getText(): string;
34
34
  /**
35
- * Returns the length of the fragment as calculated from the start and end positon
35
+ * Returns the length of the fragment as calculated from the start and end position
36
36
  */
37
37
  getTextLength(): number;
38
38
  /**
@@ -1,25 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CSSDocument = void 0;
4
- const service_1 = require("./service");
5
- const index_1 = require("../../core/documents/index");
6
- class CSSDocument extends index_1.ReadableDocument {
7
- constructor(parent) {
4
+ const language_service_1 = require("./language-service");
5
+ const documents_1 = require("../../core/documents");
6
+ class CSSDocument extends documents_1.ReadableDocument {
7
+ constructor(parent, styleInfo) {
8
8
  super();
9
9
  this.parent = parent;
10
+ this.styleInfo = styleInfo;
10
11
  this.version = this.parent.version;
11
- if (this.parent.styleInfo) {
12
- this.styleInfo = this.parent.styleInfo;
13
- }
14
- else {
15
- this.styleInfo = {
16
- attributes: {},
17
- start: -1,
18
- end: -1,
19
- };
20
- }
21
12
  this.languageId = this.language;
22
- this.stylesheet = (0, service_1.getLanguageService)(this.language).parseStylesheet(this);
13
+ this.stylesheet = (0, language_service_1.getLanguageService)(this.language).parseStylesheet(this);
23
14
  }
24
15
  /**
25
16
  * Get the fragment position relative to the parent
@@ -52,7 +43,7 @@ class CSSDocument extends index_1.ReadableDocument {
52
43
  return this.parent.getText().slice(this.styleInfo.start, this.styleInfo.end);
53
44
  }
54
45
  /**
55
- * Returns the length of the fragment as calculated from the start and end positon
46
+ * Returns the length of the fragment as calculated from the start and end position
56
47
  */
57
48
  getTextLength() {
58
49
  return this.styleInfo.end - this.styleInfo.start;
@@ -1,17 +1,25 @@
1
- import type { CompletionsProvider } from '../interfaces';
2
- import type { Document, DocumentManager } from '../../core/documents';
3
- import type { ConfigManager } from '../../core/config';
4
1
  import { CompletionContext, CompletionList, Position } from 'vscode-languageserver';
5
- export declare class CSSPlugin implements CompletionsProvider {
6
- private docManager;
2
+ import { ConfigManager } from '../../core/config/ConfigManager';
3
+ import { AstroDocument } from '../../core/documents';
4
+ import type { Plugin } from '../interfaces';
5
+ export declare class CSSPlugin implements Plugin {
6
+ __name: string;
7
7
  private configManager;
8
- private documents;
8
+ private cssDocuments;
9
9
  private triggerCharacters;
10
- pluginName: string;
11
- constructor(docManager: DocumentManager, configManager: ConfigManager);
12
- getCompletions(document: Document, position: Position, completionContext?: CompletionContext): CompletionList | null;
10
+ constructor(configManager: ConfigManager);
11
+ getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext): CompletionList | null;
13
12
  private getCompletionsInternal;
14
13
  private inStyleAttributeWithoutInterpolation;
15
- private getCSSDoc;
16
- private isInsideFrontmatter;
14
+ /**
15
+ * Get the associated CSS Document for a style tag
16
+ */
17
+ private getCSSDocumentForStyleTag;
18
+ private getCSSDocumentsForDocument;
19
+ private getStylesheetsForDocument;
20
+ /**
21
+ * Get style tag at position for a document
22
+ */
23
+ private getStyleTagForPosition;
24
+ private featureEnabled;
17
25
  }
@@ -1,82 +1,104 @@
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");
13
12
  class CSSPlugin {
14
- constructor(docManager, configManager) {
15
- this.documents = new WeakMap();
13
+ constructor(configManager) {
14
+ this.__name = 'css';
15
+ this.cssDocuments = new WeakMap();
16
16
  this.triggerCharacters = new Set(['.', ':', '-', '/']);
17
- this.pluginName = 'CSS';
18
- this.docManager = docManager;
19
17
  this.configManager = configManager;
20
- this.docManager.on('documentChange', (document) => {
21
- this.documents.set(document, new CSSDocument_1.CSSDocument(document));
22
- });
23
18
  }
24
19
  getCompletions(document, position, completionContext) {
20
+ if (!this.featureEnabled('completions')) {
21
+ return null;
22
+ }
23
+ if ((0, documents_1.isInsideFrontmatter)(document.getText(), document.offsetAt(position))) {
24
+ return null;
25
+ }
25
26
  const triggerCharacter = completionContext === null || completionContext === void 0 ? void 0 : completionContext.triggerCharacter;
26
27
  const triggerKind = completionContext === null || completionContext === void 0 ? void 0 : completionContext.triggerKind;
27
28
  const isCustomTriggerCharacter = triggerKind === vscode_languageserver_1.CompletionTriggerKind.TriggerCharacter;
28
29
  if (isCustomTriggerCharacter && triggerCharacter && !this.triggerCharacters.has(triggerCharacter)) {
29
30
  return null;
30
31
  }
31
- if (this.isInsideFrontmatter(document, position)) {
32
+ const styleTag = this.getStyleTagForPosition(document, position);
33
+ // If we don't have a style tag at this position, we might be in a style property instead, let's check
34
+ if (!styleTag) {
35
+ const attributeContext = (0, parseHtml_1.getAttributeContextAtPosition)(document, position);
36
+ if (!attributeContext) {
37
+ return null;
38
+ }
39
+ if (this.inStyleAttributeWithoutInterpolation(attributeContext, document.getText())) {
40
+ const [start, end] = attributeContext.valueRange;
41
+ return this.getCompletionsInternal(document, position, new StyleAttributeDocument_1.StyleAttributeDocument(document, start, end));
42
+ }
43
+ // If we're not in a style attribute, instead give completions for ids and classes used in the current document
44
+ else if ((attributeContext.name == 'id' || attributeContext.name == 'class') && attributeContext.inValue) {
45
+ const stylesheets = this.getStylesheetsForDocument(document);
46
+ return (0, getIdClassCompletions_1.getIdClassCompletion)(stylesheets, attributeContext);
47
+ }
32
48
  return null;
33
49
  }
34
- const cssDocument = this.getCSSDoc(document);
35
- if (cssDocument.isInGenerated(position)) {
36
- return this.getCompletionsInternal(document, position, cssDocument);
37
- }
38
- const attributeContext = (0, parseHtml_1.getAttributeContextAtPosition)(document, position);
39
- if (!attributeContext) {
40
- return null;
41
- }
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));
45
- }
46
- else {
47
- return (0, getIdClassCompletion_1.getIdClassCompletion)(cssDocument, attributeContext);
48
- }
50
+ const cssDocument = this.getCSSDocumentForStyleTag(styleTag, document);
51
+ return this.getCompletionsInternal(document, position, cssDocument);
49
52
  }
50
53
  getCompletionsInternal(document, position, cssDocument) {
51
54
  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
55
+ // The CSS language service does not support SASS (not to be confused with SCSS)
56
+ // however we can at least still at least provide Emmet completions in SASS blocks
54
57
  return (0, emmet_helper_1.doComplete)(document, position, 'sass', this.configManager.getEmmetConfig()) || null;
55
58
  }
56
- const type = extractLanguage(cssDocument);
57
- const lang = (0, service_1.getLanguageService)(type);
59
+ const cssLang = extractLanguage(cssDocument);
60
+ const langService = (0, language_service_1.getLanguageService)(cssLang);
58
61
  const emmetResults = {
59
62
  isIncomplete: true,
60
63
  items: [],
61
64
  };
62
- const results = lang.doComplete(cssDocument, cssDocument.getGeneratedPosition(position), cssDocument.stylesheet);
65
+ const results = langService.doComplete(cssDocument, cssDocument.getGeneratedPosition(position), cssDocument.stylesheet);
63
66
  return vscode_languageserver_1.CompletionList.create([...(results ? results.items : []), ...emmetResults.items].map((completionItem) => (0, documents_1.mapCompletionItemToOriginal)(cssDocument, completionItem)),
64
67
  // Emmet completions change on every keystroke, so they are never complete
65
68
  emmetResults.items.length > 0);
66
69
  }
67
70
  inStyleAttributeWithoutInterpolation(attrContext, text) {
68
- return attrContext.name === 'style' && !!attrContext.valueRange && !text.substring(attrContext.valueRange[0], attrContext.valueRange[1]).includes('{');
71
+ return (attrContext.name === 'style' &&
72
+ !!attrContext.valueRange &&
73
+ !text.substring(attrContext.valueRange[0], attrContext.valueRange[1]).includes('{'));
69
74
  }
70
- getCSSDoc(document) {
71
- let cssDoc = this.documents.get(document);
75
+ /**
76
+ * Get the associated CSS Document for a style tag
77
+ */
78
+ getCSSDocumentForStyleTag(tag, document) {
79
+ let cssDoc = this.cssDocuments.get(tag);
72
80
  if (!cssDoc || cssDoc.version < document.version) {
73
- cssDoc = new CSSDocument_1.CSSDocument(document);
74
- this.documents.set(document, cssDoc);
81
+ cssDoc = new CSSDocument_1.CSSDocument(document, tag);
82
+ this.cssDocuments.set(tag, cssDoc);
75
83
  }
76
84
  return cssDoc;
77
85
  }
78
- isInsideFrontmatter(document, position) {
79
- return (0, utils_1.isInsideFrontmatter)(document.getText(), document.offsetAt(position));
86
+ getCSSDocumentsForDocument(document) {
87
+ return document.styleTags.map((tag) => this.getCSSDocumentForStyleTag(tag, document));
88
+ }
89
+ getStylesheetsForDocument(document) {
90
+ return this.getCSSDocumentsForDocument(document).map((cssDoc) => cssDoc.stylesheet);
91
+ }
92
+ /**
93
+ * Get style tag at position for a document
94
+ */
95
+ getStyleTagForPosition(document, position) {
96
+ return document.styleTags.find((styleTag) => {
97
+ return (0, documents_1.isInTag)(position, styleTag);
98
+ });
99
+ }
100
+ featureEnabled(feature) {
101
+ return this.configManager.enabled('css.enabled') && this.configManager.enabled(`css.${feature}.enabled`);
80
102
  }
81
103
  }
82
104
  exports.CSSPlugin = CSSPlugin;
@@ -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
+ Applying styles to a selector globally`,
9
+ references: [
10
+ {
11
+ name: 'Astro Docs',
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,22 @@
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 } 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;
9
8
  private styleScriptTemplate;
10
9
  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;
10
+ constructor(configManager: ConfigManager);
16
11
  /**
17
- * The HTML language service uses newer types which clash
18
- * without the stable ones. Transform to the stable types.
12
+ * Get HTML completions
13
+ */
14
+ getCompletions(document: AstroDocument, position: Position): CompletionList | null;
15
+ getFoldingRanges(document: AstroDocument): FoldingRange[] | null;
16
+ doTagComplete(document: AstroDocument, position: Position): string | null;
17
+ /**
18
+ * Get lang completions for style tags (ex: `<style lang="scss">`)
19
19
  */
20
- private toCompletionItems;
21
20
  private getLangCompletions;
22
- private isInsideExpression;
23
- private isInsideFrontmatter;
21
+ private featureEnabled;
24
22
  }