@astrojs/language-server 2.5.1 → 2.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/check.js CHANGED
@@ -72,9 +72,9 @@ class AstroCheck {
72
72
  // Filter diagnostics based on the logErrors level
73
73
  const fileDiagnosticsToPrint = fileDiagnostics.filter((diag) => {
74
74
  const severity = diag.severity ?? language_server_1.DiagnosticSeverity.Error;
75
- switch (logErrors?.level ?? 'error') {
75
+ switch (logErrors?.level ?? 'hint') {
76
76
  case 'error':
77
- return true;
77
+ return severity <= language_server_1.DiagnosticSeverity.Error;
78
78
  case 'warning':
79
79
  return severity <= language_server_1.DiagnosticSeverity.Warning;
80
80
  case 'hint':
@@ -106,9 +106,10 @@ class AstroCheck {
106
106
  initialize() {
107
107
  this.ts = this.typescriptPath ? require(this.typescriptPath) : require('typescript');
108
108
  const tsconfigPath = this.getTsconfig();
109
+ const astroInstall = (0, utils_js_1.getAstroInstall)([this.workspacePath]);
109
110
  const config = {
110
111
  languages: {
111
- astro: (0, index_js_1.getLanguageModule)((0, utils_js_1.getAstroInstall)([this.workspacePath]), this.ts),
112
+ astro: (0, index_js_1.getLanguageModule)(typeof astroInstall === 'string' ? undefined : astroInstall, this.ts),
112
113
  svelte: (0, svelte_js_1.getSvelteLanguageModule)(),
113
114
  vue: (0, vue_js_1.getVueLanguageModule)(),
114
115
  },
@@ -28,7 +28,7 @@ function safeConvertToTSX(content, options) {
28
28
  code: 1000,
29
29
  location: { file: options.filename, line: 1, column: 1, length: content.length },
30
30
  severity: 1,
31
- text: `The Astro compiler encountered an unknown error while parsing this file. Please create an issue with your code and the error shown in the server's logs: https://github.com/withastro/language-tools/issues`,
31
+ text: `The Astro compiler encountered an unknown error while transform this file to TSX. Please create an issue with your code and the error shown in the server's logs: https://github.com/withastro/language-tools/issues`,
32
32
  },
33
33
  ],
34
34
  };
@@ -111,7 +111,11 @@ class AstroFile {
111
111
  data: language_core_1.FileRangeCapabilities.full,
112
112
  },
113
113
  ];
114
- this.astroMeta = (0, parseAstro_1.getAstroMetadata)(this.snapshot.getText(0, this.snapshot.getLength()));
114
+ this.compilerDiagnostics = [];
115
+ this.astroMeta = (0, parseAstro_1.getAstroMetadata)(this.fileName, this.snapshot.getText(0, this.snapshot.getLength()));
116
+ if (this.astroMeta.diagnostics.length > 0) {
117
+ this.compilerDiagnostics.push(...this.astroMeta.diagnostics);
118
+ }
115
119
  const { htmlDocument, virtualFile: htmlVirtualFile } = (0, parseHTML_1.parseHTML)(this.fileName, this.snapshot, this.astroMeta.frontmatter.status === 'closed'
116
120
  ? this.astroMeta.frontmatter.position.end.offset
117
121
  : 0);
@@ -122,7 +126,7 @@ class AstroFile {
122
126
  this.embeddedFiles = [];
123
127
  this.embeddedFiles.push(htmlVirtualFile);
124
128
  const tsx = (0, astro2tsx_1.astro2tsx)(this.snapshot.getText(0, this.snapshot.getLength()), this.fileName, this.ts, htmlDocument);
125
- this.compilerDiagnostics = tsx.diagnostics;
129
+ this.compilerDiagnostics.push(...tsx.diagnostics);
126
130
  this.embeddedFiles.push(tsx.virtualFile);
127
131
  }
128
132
  }
@@ -1,8 +1,8 @@
1
- import type { ParseResult, Point } from '@astrojs/compiler/types';
1
+ import type { ParseOptions, ParseResult, Point } from '@astrojs/compiler/types';
2
2
  type AstroMetadata = ParseResult & {
3
3
  frontmatter: FrontmatterStatus;
4
4
  };
5
- export declare function getAstroMetadata(input: string, position?: boolean): AstroMetadata;
5
+ export declare function getAstroMetadata(fileName: string, input: string, options?: ParseOptions): AstroMetadata;
6
6
  interface FrontmatterOpen {
7
7
  status: 'open';
8
8
  position: {
@@ -2,14 +2,37 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getAstroMetadata = void 0;
4
4
  const sync_1 = require("@astrojs/compiler/sync");
5
- function getAstroMetadata(input, position = true) {
6
- const parseResult = (0, sync_1.parse)(input, { position: position });
5
+ function getAstroMetadata(fileName, input, options = { position: true }) {
6
+ const parseResult = safeParseAst(fileName, input, options);
7
7
  return {
8
8
  ...parseResult,
9
9
  frontmatter: getFrontmatterStatus(parseResult.ast, input),
10
10
  };
11
11
  }
12
12
  exports.getAstroMetadata = getAstroMetadata;
13
+ function safeParseAst(fileName, input, parseOptions) {
14
+ try {
15
+ const parseResult = (0, sync_1.parse)(input, parseOptions);
16
+ return parseResult;
17
+ }
18
+ catch (e) {
19
+ console.error(`There was an error parsing ${fileName}'s AST. An empty AST will be returned instead to avoid breaking the server. Please create an issue: https://github.com/withastro/language-tools/issues\nError: ${e}.`);
20
+ return {
21
+ ast: {
22
+ type: 'root',
23
+ children: [],
24
+ },
25
+ diagnostics: [
26
+ {
27
+ code: 1000,
28
+ location: { file: fileName, line: 1, column: 1, length: input.length },
29
+ severity: 1,
30
+ text: `The Astro compiler encountered an unknown error while parsing this file's AST. Please create an issue with your code and the error shown in the server's logs: https://github.com/withastro/language-tools/issues`,
31
+ },
32
+ ],
33
+ };
34
+ }
35
+ }
13
36
  function getFrontmatterStatus(ast, text) {
14
37
  if (!ast.children || (ast.children && ast.children.length === 0)) {
15
38
  return {
@@ -29,32 +29,35 @@ const language_core_1 = require("@volar/language-core");
29
29
  const SourceMap = __importStar(require("@volar/source-map"));
30
30
  const muggle = __importStar(require("muggle-string"));
31
31
  function extractScriptTags(fileName, snapshot, htmlDocument, ast) {
32
- const embeddedJSFiles = findIsolatedScripts(fileName, snapshot, htmlDocument.roots);
32
+ const embeddedJSFiles = findModuleScripts(fileName, snapshot, htmlDocument.roots);
33
33
  const javascriptContexts = [
34
- ...findInlineScripts(htmlDocument, snapshot),
34
+ ...findClassicScripts(htmlDocument, snapshot),
35
35
  ...findEventAttributes(ast),
36
36
  ].sort((a, b) => a.startOffset - b.startOffset);
37
37
  if (javascriptContexts.length > 0) {
38
+ // classic scripts share the same scope
39
+ // merging them brings about redeclaration errors
38
40
  embeddedJSFiles.push(mergeJSContexts(fileName, javascriptContexts));
39
41
  }
40
42
  return embeddedJSFiles;
41
43
  }
42
44
  exports.extractScriptTags = extractScriptTags;
43
- function isIsolatedScriptTag(scriptTag) {
44
- // Using any kind of attributes on the script tag will disable hoisting
45
- if (!scriptTag.attributes ||
46
- (scriptTag.attributes && Object.entries(scriptTag.attributes).length === 0) ||
47
- scriptTag.attributes['type']?.includes('module')) {
48
- return true;
49
- }
50
- return false;
45
+ function getScriptType(scriptTag) {
46
+ // script tags without attributes are processed and converted into module scripts
47
+ if (!scriptTag.attributes || Object.entries(scriptTag.attributes).length === 0)
48
+ return 'processed module';
49
+ // even when it is not processed by vite, scripts with type=module remain modules
50
+ if (scriptTag.attributes['type']?.includes('module') === true)
51
+ return 'module';
52
+ // whenever there are attributes, is:inline is implied and in the absence of type=module, the script is classic
53
+ return 'classic';
51
54
  }
52
55
  /**
53
56
  * Get all the isolated scripts in the HTML document
54
57
  * Isolated scripts are scripts that are hoisted by Astro and as such, are isolated from the rest of the code because of the implicit `type="module"`
55
58
  * All the isolated scripts are passed to the TypeScript language server as separate `.mts` files.
56
59
  */
57
- function findIsolatedScripts(fileName, snapshot, roots) {
60
+ function findModuleScripts(fileName, snapshot, roots) {
58
61
  const embeddedScripts = [];
59
62
  let scriptIndex = 0;
60
63
  getEmbeddedScriptsInNodes(roots);
@@ -63,10 +66,11 @@ function findIsolatedScripts(fileName, snapshot, roots) {
63
66
  if (node.tag === 'script' &&
64
67
  node.startTagEnd !== undefined &&
65
68
  node.endTagStart !== undefined &&
66
- isIsolatedScriptTag(node)) {
69
+ getScriptType(node) !== 'classic') {
67
70
  const scriptText = snapshot.getText(node.startTagEnd, node.endTagStart);
71
+ const extension = getScriptType(node) === 'processed module' ? 'mts' : 'mjs';
68
72
  embeddedScripts.push({
69
- fileName: fileName + `.${scriptIndex}.mts`,
73
+ fileName: fileName + `.${scriptIndex}.${extension}`,
70
74
  kind: language_core_1.FileKind.TypeScriptHostFile,
71
75
  snapshot: {
72
76
  getText: (start, end) => scriptText.substring(start, end),
@@ -104,7 +108,7 @@ function findIsolatedScripts(fileName, snapshot, roots) {
104
108
  * Inline scripts are scripts that are not hoisted by Astro and as such, are not isolated from the rest of the code.
105
109
  * All the inline scripts are concatenated into a single `.mjs` file and passed to the TypeScript language server.
106
110
  */
107
- function findInlineScripts(htmlDocument, snapshot) {
111
+ function findClassicScripts(htmlDocument, snapshot) {
108
112
  const inlineScripts = [];
109
113
  getInlineScriptsInNodes(htmlDocument.roots);
110
114
  function getInlineScriptsInNodes(nodes) {
@@ -113,7 +117,7 @@ function findInlineScripts(htmlDocument, snapshot) {
113
117
  node.startTagEnd !== undefined &&
114
118
  node.endTagStart !== undefined &&
115
119
  !isJSON(node.attributes?.type) &&
116
- !isIsolatedScriptTag(node)) {
120
+ getScriptType(node) === 'classic') {
117
121
  const scriptText = snapshot.getText(node.startTagEnd, node.endTagStart);
118
122
  inlineScripts.push({
119
123
  startOffset: node.startTagEnd,
@@ -189,7 +193,14 @@ function mergeJSContexts(fileName, javascriptContexts) {
189
193
  getLength: () => text.length,
190
194
  getChangeRange: () => undefined,
191
195
  },
192
- capabilities: language_core_1.FileCapabilities.full,
196
+ capabilities: {
197
+ codeAction: true,
198
+ diagnostic: true,
199
+ documentFormatting: false,
200
+ documentSymbol: true,
201
+ foldingRange: true,
202
+ inlayHint: true,
203
+ },
193
204
  embeddedFiles: [],
194
205
  kind: language_core_1.FileKind.TypeScriptHostFile,
195
206
  mappings,
@@ -39,14 +39,18 @@ const plugin = (initOptions, modules) => ({
39
39
  resolveConfig(config, ctx) {
40
40
  config.languages ??= {};
41
41
  if (ctx) {
42
- const astroInstall = (0, utils_js_1.getAstroInstall)([ctx.project.rootUri.fsPath]);
43
- if (!astroInstall) {
42
+ const nearestPackageJson = modules.typescript?.findConfigFile(ctx.project.rootUri.fsPath, modules.typescript.sys.fileExists, 'package.json');
43
+ const astroInstall = (0, utils_js_1.getAstroInstall)([ctx.project.rootUri.fsPath], {
44
+ nearestPackageJson: nearestPackageJson,
45
+ readDirectory: modules.typescript.sys.readDirectory,
46
+ });
47
+ if (astroInstall === 'not-found') {
44
48
  ctx.server.connection.sendNotification(node_1.ShowMessageNotification.type, {
45
49
  message: `Couldn't find Astro in workspace "${ctx.project.rootUri.fsPath}". Experience might be degraded. For the best experience, please make sure Astro is installed into your project and restart the language server.`,
46
50
  type: node_1.MessageType.Warning,
47
51
  });
48
52
  }
49
- config.languages.astro = (0, core_1.getLanguageModule)(astroInstall, modules.typescript);
53
+ config.languages.astro = (0, core_1.getLanguageModule)(typeof astroInstall === 'string' ? undefined : astroInstall, modules.typescript);
50
54
  config.languages.vue = (0, vue_js_1.getVueLanguageModule)();
51
55
  config.languages.svelte = (0, svelte_js_1.getSvelteLanguageModule)();
52
56
  }
package/dist/utils.d.ts CHANGED
@@ -7,4 +7,7 @@ export interface AstroInstall {
7
7
  patch: number;
8
8
  };
9
9
  }
10
- export declare function getAstroInstall(basePaths: string[]): AstroInstall | undefined;
10
+ export declare function getAstroInstall(basePaths: string[], checkForAstro?: {
11
+ nearestPackageJson: string | undefined;
12
+ readDirectory: typeof import('typescript/lib/tsserverlibrary.js').sys.readDirectory;
13
+ }): AstroInstall | 'not-an-astro-project' | 'not-found';
package/dist/utils.js CHANGED
@@ -26,9 +26,28 @@ Object.defineProperty(exports, "__esModule", { value: true });
26
26
  exports.getAstroInstall = void 0;
27
27
  const path = __importStar(require("node:path"));
28
28
  const importPackage_js_1 = require("./importPackage.js");
29
- function getAstroInstall(basePaths) {
29
+ function getAstroInstall(basePaths, checkForAstro) {
30
30
  let astroPath;
31
31
  let version;
32
+ if (checkForAstro && checkForAstro.nearestPackageJson) {
33
+ basePaths.push(path.dirname(checkForAstro.nearestPackageJson));
34
+ let deps = new Set();
35
+ try {
36
+ const packageJSON = require(checkForAstro.nearestPackageJson);
37
+ [
38
+ ...Object.keys(packageJSON.dependencies ?? {}),
39
+ ...Object.keys(packageJSON.devDependencies ?? {}),
40
+ ...Object.keys(packageJSON.peerDependencies ?? {}),
41
+ ].forEach((dep) => deps.add(dep));
42
+ }
43
+ catch { }
44
+ if (!deps.has('astro')) {
45
+ const directoryContent = checkForAstro.readDirectory(path.dirname(checkForAstro.nearestPackageJson), ['.js', '.mjs', '.cjs', '.ts', '.mts', '.cts'], undefined, undefined, 1);
46
+ if (!directoryContent.some((file) => path.basename(file).startsWith('astro.config'))) {
47
+ return 'not-an-astro-project';
48
+ }
49
+ }
50
+ }
32
51
  try {
33
52
  astroPath = (0, importPackage_js_1.getPackagePath)('astro', basePaths);
34
53
  if (!astroPath) {
@@ -48,9 +67,12 @@ function getAstroInstall(basePaths) {
48
67
  catch (e) {
49
68
  // If we still couldn't find it, it probably just doesn't exist
50
69
  console.error(`${basePaths[0]} seems to be an Astro project, but we couldn't find Astro or Astro is not installed`);
51
- return undefined;
70
+ return 'not-found';
52
71
  }
53
72
  }
73
+ if (!version) {
74
+ return 'not-found';
75
+ }
54
76
  let [major, minor, patch] = version.split('.');
55
77
  if (patch.includes('-')) {
56
78
  const patchParts = patch.split('-');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astrojs/language-server",
3
- "version": "2.5.1",
3
+ "version": "2.5.3",
4
4
  "author": "withastro",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -20,22 +20,22 @@
20
20
  "astro-ls": "./bin/nodeServer.js"
21
21
  },
22
22
  "dependencies": {
23
- "@astrojs/compiler": "^2.2.1",
23
+ "@astrojs/compiler": "^2.2.2",
24
24
  "@jridgewell/sourcemap-codec": "^1.4.15",
25
- "@volar/kit": "~1.10.3",
26
- "@volar/language-core": "~1.10.3",
27
- "@volar/language-server": "~1.10.3",
28
- "@volar/language-service": "~1.10.3",
29
- "@volar/source-map": "~1.10.3",
30
- "@volar/typescript": "~1.10.3",
25
+ "@volar/kit": "~1.10.9",
26
+ "@volar/language-core": "~1.10.9",
27
+ "@volar/language-server": "~1.10.9",
28
+ "@volar/language-service": "~1.10.9",
29
+ "@volar/source-map": "~1.10.9",
30
+ "@volar/typescript": "~1.10.9",
31
31
  "fast-glob": "^3.2.12",
32
32
  "muggle-string": "^0.3.1",
33
- "volar-service-css": "0.0.14",
34
- "volar-service-emmet": "0.0.14",
35
- "volar-service-html": "0.0.14",
36
- "volar-service-prettier": "0.0.14",
37
- "volar-service-typescript": "0.0.14",
38
- "volar-service-typescript-twoslash-queries": "0.0.14",
33
+ "volar-service-css": "0.0.16",
34
+ "volar-service-emmet": "0.0.16",
35
+ "volar-service-html": "0.0.16",
36
+ "volar-service-prettier": "0.0.16",
37
+ "volar-service-typescript": "0.0.16",
38
+ "volar-service-typescript-twoslash-queries": "0.0.16",
39
39
  "vscode-html-languageservice": "^5.1.0",
40
40
  "vscode-uri": "^3.0.8"
41
41
  },
@@ -44,14 +44,14 @@
44
44
  "@astrojs/vue": "^3.0.1",
45
45
  "@types/chai": "^4.3.5",
46
46
  "@types/mocha": "^10.0.1",
47
- "@types/node": "^16.18.26",
47
+ "@types/node": "^18.17.8",
48
48
  "astro": "^3.3.0",
49
49
  "chai": "^4.3.7",
50
50
  "mocha": "^10.2.0",
51
51
  "tsx": "^3.12.7",
52
- "typescript": "~5.1.3",
53
52
  "vscode-languageserver-protocol": "^3.17.5",
54
- "vscode-languageserver-textdocument": "^1.0.11"
53
+ "vscode-languageserver-textdocument": "^1.0.11",
54
+ "typescript": "^5.2.2"
55
55
  },
56
56
  "peerDependencies": {
57
57
  "prettier": "^3.0.0",