@astrojs/language-server 2.0.0-next.7 → 2.0.0-next.9
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.d.ts +24 -0
- package/dist/check.js +117 -0
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.js +3 -1
- package/dist/core/parseCSS.d.ts +1 -0
- package/dist/core/parseCSS.js +23 -2
- package/dist/core/parseHTML.d.ts +4 -0
- package/dist/core/parseHTML.js +4 -3
- package/dist/core/utils.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4 -1
- package/dist/languageServerPlugin.js +6 -0
- package/dist/plugins/astro.js +1 -1
- package/dist/plugins/html.d.ts +1 -1
- package/dist/plugins/html.js +13 -2
- package/dist/plugins/typescript/codeActions.d.ts +1 -1
- package/dist/plugins/typescript/codeActions.js +6 -1
- package/dist/plugins/typescript/completions.js +13 -1
- package/dist/plugins/typescript/index.js +6 -2
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +16 -8
- package/package.json +4 -3
package/dist/check.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import * as kit from '@volar/kit';
|
|
2
|
+
export { DiagnosticSeverity, type Diagnostic } from '@volar/language-server';
|
|
3
|
+
export interface CheckResult {
|
|
4
|
+
errors: kit.Diagnostic[];
|
|
5
|
+
fileUrl: URL;
|
|
6
|
+
fileContent: string;
|
|
7
|
+
}
|
|
8
|
+
export declare class AstroCheck {
|
|
9
|
+
private readonly workspacePath;
|
|
10
|
+
private readonly typescriptPath;
|
|
11
|
+
private ts;
|
|
12
|
+
private project;
|
|
13
|
+
private linter;
|
|
14
|
+
constructor(workspacePath: string, typescriptPath: string | undefined);
|
|
15
|
+
/**
|
|
16
|
+
* Lint a list of files or the entire project and optionally log the errors found
|
|
17
|
+
* @param fileNames List of files to lint, if undefined, all files included in the project will be linted
|
|
18
|
+
* @param logErrors Whether to log errors by itself. This is disabled by default.
|
|
19
|
+
* @return {CheckResult} The result of the lint, including a list of errors, the file's content and its file path.
|
|
20
|
+
*/
|
|
21
|
+
lint(fileNames?: string[] | undefined, logErrors?: boolean): Promise<CheckResult[]>;
|
|
22
|
+
private initialize;
|
|
23
|
+
private getTsconfig;
|
|
24
|
+
}
|
package/dist/check.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.AstroCheck = exports.DiagnosticSeverity = void 0;
|
|
30
|
+
const kit = __importStar(require("@volar/kit"));
|
|
31
|
+
const fast_glob_1 = __importDefault(require("fast-glob"));
|
|
32
|
+
const node_url_1 = require("node:url");
|
|
33
|
+
const index_js_1 = require("./core/index.js");
|
|
34
|
+
const svelte_js_1 = require("./core/svelte.js");
|
|
35
|
+
const utils_js_1 = require("./core/utils.js");
|
|
36
|
+
const vue_js_1 = require("./core/vue.js");
|
|
37
|
+
const astro_js_1 = __importDefault(require("./plugins/astro.js"));
|
|
38
|
+
const index_js_2 = __importDefault(require("./plugins/typescript/index.js"));
|
|
39
|
+
// Export those for downstream consumers
|
|
40
|
+
var language_server_1 = require("@volar/language-server");
|
|
41
|
+
Object.defineProperty(exports, "DiagnosticSeverity", { enumerable: true, get: function () { return language_server_1.DiagnosticSeverity; } });
|
|
42
|
+
class AstroCheck {
|
|
43
|
+
constructor(workspacePath, typescriptPath) {
|
|
44
|
+
this.workspacePath = workspacePath;
|
|
45
|
+
this.typescriptPath = typescriptPath;
|
|
46
|
+
this.initialize();
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Lint a list of files or the entire project and optionally log the errors found
|
|
50
|
+
* @param fileNames List of files to lint, if undefined, all files included in the project will be linted
|
|
51
|
+
* @param logErrors Whether to log errors by itself. This is disabled by default.
|
|
52
|
+
* @return {CheckResult} The result of the lint, including a list of errors, the file's content and its file path.
|
|
53
|
+
*/
|
|
54
|
+
async lint(fileNames = undefined, logErrors = false) {
|
|
55
|
+
const files = fileNames !== undefined
|
|
56
|
+
? fileNames
|
|
57
|
+
: this.project.languageServiceHost
|
|
58
|
+
.getScriptFileNames()
|
|
59
|
+
.filter((file) => file.endsWith('.astro'));
|
|
60
|
+
const errors = [];
|
|
61
|
+
for (const file of files) {
|
|
62
|
+
const fileErrors = await this.linter.check(file);
|
|
63
|
+
if (logErrors) {
|
|
64
|
+
this.linter.logErrors(file, fileErrors);
|
|
65
|
+
}
|
|
66
|
+
if (fileErrors.length > 0) {
|
|
67
|
+
const fileSnapshot = this.project.languageServiceHost.getScriptSnapshot(file);
|
|
68
|
+
const fileContent = fileSnapshot?.getText(0, fileSnapshot.getLength());
|
|
69
|
+
errors.push({
|
|
70
|
+
errors: fileErrors,
|
|
71
|
+
fileContent: fileContent ?? '',
|
|
72
|
+
fileUrl: (0, node_url_1.pathToFileURL)(file),
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return errors;
|
|
77
|
+
}
|
|
78
|
+
initialize() {
|
|
79
|
+
this.ts = this.typescriptPath ? require(this.typescriptPath) : require('typescript');
|
|
80
|
+
const tsconfigPath = this.getTsconfig();
|
|
81
|
+
const config = {
|
|
82
|
+
languages: {
|
|
83
|
+
astro: (0, index_js_1.getLanguageModule)((0, utils_js_1.getAstroInstall)([this.workspacePath]), this.ts),
|
|
84
|
+
svelte: (0, svelte_js_1.getSvelteLanguageModule)(),
|
|
85
|
+
vue: (0, vue_js_1.getVueLanguageModule)(),
|
|
86
|
+
},
|
|
87
|
+
services: {
|
|
88
|
+
typescript: (0, index_js_2.default)(),
|
|
89
|
+
astro: (0, astro_js_1.default)(),
|
|
90
|
+
},
|
|
91
|
+
};
|
|
92
|
+
if (tsconfigPath) {
|
|
93
|
+
this.project = kit.createProject(tsconfigPath, [
|
|
94
|
+
{ extension: 'astro', isMixedContent: true, scriptKind: 7 },
|
|
95
|
+
{ extension: 'vue', isMixedContent: true, scriptKind: 7 },
|
|
96
|
+
{ extension: 'svelte', isMixedContent: true, scriptKind: 7 },
|
|
97
|
+
]);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
this.project = kit.createInferredProject(this.workspacePath, () => {
|
|
101
|
+
return fast_glob_1.default.sync('**/*.astro', {
|
|
102
|
+
cwd: this.workspacePath,
|
|
103
|
+
ignore: ['node_modules'],
|
|
104
|
+
absolute: true,
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
this.linter = kit.createLinter(config, this.project.languageServiceHost);
|
|
109
|
+
}
|
|
110
|
+
getTsconfig() {
|
|
111
|
+
const tsconfig = this.ts.findConfigFile(this.workspacePath, this.ts.sys.fileExists) ||
|
|
112
|
+
this.ts.findConfigFile(this.workspacePath, this.ts.sys.fileExists, 'jsconfig.json');
|
|
113
|
+
return tsconfig;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
exports.AstroCheck = AstroCheck;
|
|
117
|
+
//# sourceMappingURL=check.js.map
|
package/dist/core/index.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ export declare class AstroFile implements VirtualFile {
|
|
|
19
19
|
};
|
|
20
20
|
compilerDiagnostics: DiagnosticMessage[];
|
|
21
21
|
htmlDocument: HTMLDocument;
|
|
22
|
+
scriptFiles: string[];
|
|
22
23
|
codegenStacks: never[];
|
|
23
24
|
constructor(sourceFileName: string, snapshot: ts.IScriptSnapshot, ts: typeof import('typescript/lib/tsserverlibrary.js'));
|
|
24
25
|
get hasCompilationErrors(): boolean;
|
package/dist/core/index.js
CHANGED
|
@@ -107,7 +107,9 @@ class AstroFile {
|
|
|
107
107
|
? this.astroMeta.frontmatter.position.end.offset
|
|
108
108
|
: 0);
|
|
109
109
|
this.htmlDocument = htmlDocument;
|
|
110
|
-
|
|
110
|
+
const scriptTags = (0, parseJS_js_1.extractScriptTags)(this.fileName, this.snapshot, htmlDocument, this.astroMeta.ast);
|
|
111
|
+
this.scriptFiles = scriptTags.map((scriptTag) => scriptTag.fileName);
|
|
112
|
+
htmlVirtualFile.embeddedFiles.push(...(0, parseCSS_1.extractStylesheets)(this.fileName, this.snapshot, htmlDocument, this.astroMeta.ast), ...scriptTags);
|
|
111
113
|
this.embeddedFiles = [];
|
|
112
114
|
this.embeddedFiles.push(htmlVirtualFile);
|
|
113
115
|
const tsx = (0, astro2tsx_1.astro2tsx)(this.snapshot.getText(0, this.snapshot.getLength()), this.fileName, this.ts, htmlDocument);
|
package/dist/core/parseCSS.d.ts
CHANGED
|
@@ -4,4 +4,5 @@ import type ts from 'typescript/lib/tsserverlibrary';
|
|
|
4
4
|
import type { HTMLDocument } from 'vscode-html-languageservice';
|
|
5
5
|
import { AttributeNodeWithPosition } from './compilerUtils.js';
|
|
6
6
|
export declare function extractStylesheets(fileName: string, snapshot: ts.IScriptSnapshot, htmlDocument: HTMLDocument, ast: ParseResult['ast']): VirtualFile[];
|
|
7
|
+
export declare function collectClassesAndIds(ast: ParseResult['ast']): string[];
|
|
7
8
|
export declare function findInlineStyles(ast: ParseResult['ast']): AttributeNodeWithPosition[];
|
package/dist/core/parseCSS.js
CHANGED
|
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.findInlineStyles = exports.extractStylesheets = void 0;
|
|
26
|
+
exports.findInlineStyles = exports.collectClassesAndIds = exports.extractStylesheets = void 0;
|
|
27
27
|
const language_core_1 = require("@volar/language-core");
|
|
28
28
|
const SourceMap = __importStar(require("@volar/source-map"));
|
|
29
29
|
const muggle = __importStar(require("muggle-string"));
|
|
@@ -82,7 +82,7 @@ function extractStylesheets(fileName, snapshot, htmlDocument, ast) {
|
|
|
82
82
|
getLength: () => text.length,
|
|
83
83
|
getChangeRange: () => undefined,
|
|
84
84
|
},
|
|
85
|
-
capabilities: {},
|
|
85
|
+
capabilities: { documentSymbol: true },
|
|
86
86
|
embeddedFiles: [],
|
|
87
87
|
kind: language_core_1.FileKind.TextFile,
|
|
88
88
|
mappings,
|
|
@@ -91,6 +91,27 @@ function extractStylesheets(fileName, snapshot, htmlDocument, ast) {
|
|
|
91
91
|
return embeddedCSSFiles;
|
|
92
92
|
}
|
|
93
93
|
exports.extractStylesheets = extractStylesheets;
|
|
94
|
+
function collectClassesAndIds(ast) {
|
|
95
|
+
const classesAndIds = [];
|
|
96
|
+
function walkDown(parent) {
|
|
97
|
+
if (!parent.children)
|
|
98
|
+
return;
|
|
99
|
+
parent.children.forEach((child) => {
|
|
100
|
+
if (compilerUtils_js_1.is.element(child)) {
|
|
101
|
+
const classOrIDAttributes = child.attributes
|
|
102
|
+
.filter((attr) => attr.kind === 'quoted' && (attr.name === 'class' || attr.name === 'id'))
|
|
103
|
+
.flatMap((attr) => attr.value.split(' '));
|
|
104
|
+
classesAndIds.push(...classOrIDAttributes);
|
|
105
|
+
}
|
|
106
|
+
if (compilerUtils_js_1.is.parent(child)) {
|
|
107
|
+
walkDown(child);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
walkDown(ast);
|
|
112
|
+
return classesAndIds;
|
|
113
|
+
}
|
|
114
|
+
exports.collectClassesAndIds = collectClassesAndIds;
|
|
94
115
|
function findInlineStyles(ast) {
|
|
95
116
|
const styleAttrs = [];
|
|
96
117
|
// `@astrojs/compiler`'s `walk` method is async, so we can't use it here. Arf
|
package/dist/core/parseHTML.d.ts
CHANGED
|
@@ -5,3 +5,7 @@ export declare function parseHTML(fileName: string, snapshot: ts.IScriptSnapshot
|
|
|
5
5
|
virtualFile: VirtualFile;
|
|
6
6
|
htmlDocument: html.HTMLDocument;
|
|
7
7
|
};
|
|
8
|
+
/**
|
|
9
|
+
* scan the text and remove any `>` or `<` that cause the tag to end short
|
|
10
|
+
*/
|
|
11
|
+
export declare function preprocessHTML(text: string, frontmatterEnd?: number): string;
|
package/dist/core/parseHTML.js
CHANGED
|
@@ -23,13 +23,13 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.parseHTML = void 0;
|
|
26
|
+
exports.preprocessHTML = exports.parseHTML = void 0;
|
|
27
27
|
const language_core_1 = require("@volar/language-core");
|
|
28
28
|
const html = __importStar(require("vscode-html-languageservice"));
|
|
29
29
|
const utils_1 = require("../utils");
|
|
30
30
|
const htmlLs = html.getLanguageService();
|
|
31
31
|
function parseHTML(fileName, snapshot, frontmatterEnd) {
|
|
32
|
-
const htmlContent =
|
|
32
|
+
const htmlContent = preprocessHTML(snapshot.getText(0, snapshot.getLength()), frontmatterEnd);
|
|
33
33
|
return {
|
|
34
34
|
virtualFile: getHTMLVirtualFile(fileName, htmlContent),
|
|
35
35
|
htmlDocument: getHTMLDocument(htmlContent),
|
|
@@ -40,7 +40,7 @@ const createScanner = htmlLs.createScanner;
|
|
|
40
40
|
/**
|
|
41
41
|
* scan the text and remove any `>` or `<` that cause the tag to end short
|
|
42
42
|
*/
|
|
43
|
-
function
|
|
43
|
+
function preprocessHTML(text, frontmatterEnd) {
|
|
44
44
|
let content = text.split('').fill(' ', 0, frontmatterEnd).join('');
|
|
45
45
|
let scanner = createScanner(content);
|
|
46
46
|
let token = scanner.scan();
|
|
@@ -82,6 +82,7 @@ function preprocess(text, frontmatterEnd) {
|
|
|
82
82
|
scanner = createScanner(content, offset, state ?? html.ScannerState.WithinTag);
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
|
+
exports.preprocessHTML = preprocessHTML;
|
|
85
86
|
function getHTMLVirtualFile(fileName, preprocessedHTML) {
|
|
86
87
|
return {
|
|
87
88
|
fileName: fileName + `.html`,
|
package/dist/core/utils.js
CHANGED
|
@@ -82,7 +82,7 @@ function framework2tsx(fileName, filePath, sourceCode, framework) {
|
|
|
82
82
|
return {
|
|
83
83
|
fileName: fileName + '.tsx',
|
|
84
84
|
capabilities: language_core_1.FileCapabilities.full,
|
|
85
|
-
kind: language_core_1.FileKind.
|
|
85
|
+
kind: language_core_1.FileKind.TypeScriptHostFile,
|
|
86
86
|
snapshot: {
|
|
87
87
|
getText: (start, end) => content.substring(start, end),
|
|
88
88
|
getLength: () => content.length,
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -23,6 +23,9 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.protocol = void 0;
|
|
26
|
+
exports.DiagnosticSeverity = exports.AstroCheck = exports.protocol = void 0;
|
|
27
27
|
exports.protocol = __importStar(require("@volar/language-server/protocol"));
|
|
28
|
+
var check_js_1 = require("./check.js");
|
|
29
|
+
Object.defineProperty(exports, "AstroCheck", { enumerable: true, get: function () { return check_js_1.AstroCheck; } });
|
|
30
|
+
Object.defineProperty(exports, "DiagnosticSeverity", { enumerable: true, get: function () { return check_js_1.DiagnosticSeverity; } });
|
|
28
31
|
//# sourceMappingURL=index.js.map
|
|
@@ -52,6 +52,11 @@ const plugin = (initOptions, modules) => ({
|
|
|
52
52
|
config.services.astro ??= (0, astro_js_1.default)();
|
|
53
53
|
config.services.prettier ??= (0, volar_service_prettier_1.default)({
|
|
54
54
|
languages: ['astro'],
|
|
55
|
+
resolveConfigOptions: {
|
|
56
|
+
// Prettier's cache is a bit cumbersome, because you need to reload the config yourself on change
|
|
57
|
+
// TODO: Upstream a fix for this
|
|
58
|
+
useCache: false,
|
|
59
|
+
},
|
|
55
60
|
additionalOptions: (resolvedConfig) => {
|
|
56
61
|
function getAstroPrettierPlugin() {
|
|
57
62
|
if (!ctx?.project.rootUri)
|
|
@@ -66,6 +71,7 @@ const plugin = (initOptions, modules) => ({
|
|
|
66
71
|
return {
|
|
67
72
|
plugins: [...getAstroPrettierPlugin(), ...(resolvedConfig.plugins ?? [])],
|
|
68
73
|
parser: 'astro',
|
|
74
|
+
...resolvedConfig,
|
|
69
75
|
};
|
|
70
76
|
},
|
|
71
77
|
});
|
package/dist/plugins/astro.js
CHANGED
|
@@ -48,7 +48,7 @@ exports.default = () => (context, modules) => {
|
|
|
48
48
|
provideCodeLenses(document, token) {
|
|
49
49
|
if (token.isCancellationRequested)
|
|
50
50
|
return;
|
|
51
|
-
if (!modules?.typescript || !context?.typescript || !(0, utils_js_1.
|
|
51
|
+
if (!modules?.typescript || !context?.typescript || !(0, utils_js_1.isJSDocument)(document.languageId))
|
|
52
52
|
return;
|
|
53
53
|
const ts = modules?.typescript;
|
|
54
54
|
const tsProgram = context.typescript.languageService.getProgram();
|
package/dist/plugins/html.d.ts
CHANGED
package/dist/plugins/html.js
CHANGED
|
@@ -3,6 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const language_server_1 = require("@volar/language-server");
|
|
6
7
|
const volar_service_html_1 = __importDefault(require("volar-service-html"));
|
|
7
8
|
const index_js_1 = require("../core/index.js");
|
|
8
9
|
const utils_js_1 = require("../utils.js");
|
|
@@ -19,7 +20,7 @@ exports.default = () => (context, modules) => {
|
|
|
19
20
|
]);
|
|
20
21
|
return {
|
|
21
22
|
...htmlPlugin,
|
|
22
|
-
provideCompletionItems(document, position, completionContext, token) {
|
|
23
|
+
async provideCompletionItems(document, position, completionContext, token) {
|
|
23
24
|
if (document.languageId !== 'html')
|
|
24
25
|
return;
|
|
25
26
|
const [_, source] = context.documents.getVirtualFileByUri(document.uri);
|
|
@@ -30,7 +31,17 @@ exports.default = () => (context, modules) => {
|
|
|
30
31
|
if ((0, utils_js_1.isInComponentStartTag)(rootVirtualFile.htmlDocument, document.offsetAt(position))) {
|
|
31
32
|
return null;
|
|
32
33
|
}
|
|
33
|
-
|
|
34
|
+
const completions = await htmlPlugin.provideCompletionItems(document, position, completionContext, token);
|
|
35
|
+
if (!completions) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
// We don't want completions for file references, as they're mostly invalid for Astro
|
|
39
|
+
completions.items = completions.items.filter((completion) => completion.kind !== language_server_1.CompletionItemKind.File);
|
|
40
|
+
return completions;
|
|
41
|
+
},
|
|
42
|
+
// Document links provided by `vscode-html-languageservice` are invalid for Astro
|
|
43
|
+
provideDocumentLinks() {
|
|
44
|
+
return [];
|
|
34
45
|
},
|
|
35
46
|
};
|
|
36
47
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { CodeAction } from '@volar/language-server';
|
|
2
2
|
import type { TextDocument } from 'vscode-html-languageservice';
|
|
3
3
|
import type { AstroFile } from '../../core/index.js';
|
|
4
|
-
export declare function enhancedProvideCodeActions(codeActions: CodeAction[], file: AstroFile, document: TextDocument, newLine: string): CodeAction[];
|
|
4
|
+
export declare function enhancedProvideCodeActions(codeActions: CodeAction[], file: AstroFile, document: TextDocument, originalDocument: TextDocument, newLine: string): CodeAction[];
|
|
@@ -2,11 +2,16 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.enhancedProvideCodeActions = void 0;
|
|
4
4
|
const language_server_1 = require("@volar/language-server");
|
|
5
|
+
const vscode_uri_1 = require("vscode-uri");
|
|
5
6
|
const utils_js_1 = require("../../utils.js");
|
|
6
|
-
|
|
7
|
+
// Q: Why provideCodeActions instead of resolveCodeAction?
|
|
8
|
+
// A: TypeScript actions are already fully resolved in provideCodeActions, so editors won't call resolveCodeAction at all.
|
|
9
|
+
function enhancedProvideCodeActions(codeActions, file, document, originalDocument, newLine) {
|
|
7
10
|
codeActions = codeActions.map((codeAction) => {
|
|
8
11
|
if (!codeAction.edit)
|
|
9
12
|
return codeAction;
|
|
13
|
+
if (file.scriptFiles.includes(vscode_uri_1.URI.parse(originalDocument.uri).path))
|
|
14
|
+
return codeAction;
|
|
10
15
|
codeAction.edit.documentChanges = codeAction.edit.documentChanges?.map((change) => {
|
|
11
16
|
if (language_server_1.TextDocumentEdit.is(change)) {
|
|
12
17
|
change.edits = change.edits.map((edit) => {
|
|
@@ -31,8 +31,16 @@ function enhancedResolveCompletionItem(resolvedCompletion, originalItem, context
|
|
|
31
31
|
const file = source?.root;
|
|
32
32
|
if (!(file instanceof index_js_1.AstroFile) || !context.host)
|
|
33
33
|
return resolvedCompletion;
|
|
34
|
+
if (file.scriptFiles.includes(originalItem.data.fileName))
|
|
35
|
+
return resolvedCompletion;
|
|
34
36
|
const newLine = context.host.getNewLine ? context.host.getNewLine() : '\n';
|
|
35
37
|
resolvedCompletion.additionalTextEdits = resolvedCompletion.additionalTextEdits?.map((edit) => {
|
|
38
|
+
// HACK: There's a weird situation sometimes where some components (especially Svelte) will get imported as type imports
|
|
39
|
+
// for some unknown reason. This work around the problem by always ensuring a normal import for components
|
|
40
|
+
if (resolvedCompletion.data.isComponent && edit.newText.includes('import type')) {
|
|
41
|
+
edit.newText.replace('import type', 'import');
|
|
42
|
+
}
|
|
43
|
+
// Return a different edit depending on the state of the formatter
|
|
36
44
|
if (file.astroMeta.frontmatter.status === 'doesnt-exist') {
|
|
37
45
|
return (0, utils_js_1.getNewFrontmatterEdit)(edit, newLine);
|
|
38
46
|
}
|
|
@@ -68,7 +76,11 @@ const svelte2tsxTypes = new Set([
|
|
|
68
76
|
]);
|
|
69
77
|
function isValidCompletion(completion) {
|
|
70
78
|
const isSvelte2tsxCompletion = completion.label.startsWith('__sveltets_') || svelte2tsxTypes.has(completion.label);
|
|
71
|
-
|
|
79
|
+
// Filter out completions for the children prop, as it doesn't work in Astro
|
|
80
|
+
const isChildrenCompletion = completion.label === 'children?' &&
|
|
81
|
+
completion.kind === language_server_1.CompletionItemKind.Field &&
|
|
82
|
+
completion.filterText === 'children={$1}';
|
|
83
|
+
if (isSvelte2tsxCompletion || isChildrenCompletion)
|
|
72
84
|
return false;
|
|
73
85
|
return true;
|
|
74
86
|
}
|
|
@@ -11,7 +11,11 @@ const diagnostics_js_1 = require("./diagnostics.js");
|
|
|
11
11
|
exports.default = () => (context, modules) => {
|
|
12
12
|
const typeScriptPlugin = (0, volar_service_typescript_1.default)()(context, modules);
|
|
13
13
|
if (!context) {
|
|
14
|
-
return {
|
|
14
|
+
return {
|
|
15
|
+
triggerCharacters: typeScriptPlugin.triggerCharacters,
|
|
16
|
+
signatureHelpTriggerCharacters: typeScriptPlugin.signatureHelpTriggerCharacters,
|
|
17
|
+
signatureHelpRetriggerCharacters: typeScriptPlugin.signatureHelpRetriggerCharacters,
|
|
18
|
+
};
|
|
15
19
|
}
|
|
16
20
|
return {
|
|
17
21
|
...typeScriptPlugin,
|
|
@@ -36,7 +40,7 @@ exports.default = () => (context, modules) => {
|
|
|
36
40
|
if (!(file instanceof index_js_1.AstroFile) || !context.host)
|
|
37
41
|
return codeActions;
|
|
38
42
|
const newLine = context.host.getNewLine ? context.host.getNewLine() : '\n';
|
|
39
|
-
return (0, codeActions_js_1.enhancedProvideCodeActions)(codeActions, file, context.documents.getDocumentByFileName(file.snapshot, file.sourceFileName), newLine);
|
|
43
|
+
return (0, codeActions_js_1.enhancedProvideCodeActions)(codeActions, file, context.documents.getDocumentByFileName(file.snapshot, file.sourceFileName), document, newLine);
|
|
40
44
|
},
|
|
41
45
|
async provideSemanticDiagnostics(document, token) {
|
|
42
46
|
const [_, source] = context.documents.getVirtualFileByUri(document.uri);
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Point } from '@astrojs/compiler/types';
|
|
2
2
|
import { HTMLDocument, Node, Position, Range, TextEdit } from 'vscode-html-languageservice';
|
|
3
3
|
import type { FrontmatterStatus } from './core/parseAstro.js';
|
|
4
|
-
export declare function
|
|
4
|
+
export declare function isJSDocument(languageId: string): boolean;
|
|
5
5
|
/**
|
|
6
6
|
* Return true if a specific node could be a component.
|
|
7
7
|
* This is not a 100% sure test as it'll return false for any component that does not match the standard format for a component
|
|
@@ -24,7 +24,7 @@ export declare function isInsideFrontmatter(offset: number, frontmatter: Frontma
|
|
|
24
24
|
*/
|
|
25
25
|
export declare function PointToPosition(point: Point): Position;
|
|
26
26
|
/**
|
|
27
|
-
* Force a range to be at the start of the frontmatter
|
|
27
|
+
* Force a range to be at the start of the frontmatter if it is outside
|
|
28
28
|
*/
|
|
29
29
|
export declare function ensureRangeIsInFrontmatter(range: Range, frontmatter: FrontmatterStatus): Range;
|
|
30
30
|
export declare function getNewFrontmatterEdit(edit: TextEdit, newLine: string): TextEdit;
|
package/dist/utils.js
CHANGED
|
@@ -3,16 +3,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getWorkspacePnpPath = exports.getOpenFrontmatterEdit = exports.getNewFrontmatterEdit = exports.ensureRangeIsInFrontmatter = exports.PointToPosition = exports.isInsideFrontmatter = exports.isInsideExpression = exports.isInComponentStartTag = exports.isPossibleComponent = exports.
|
|
6
|
+
exports.getWorkspacePnpPath = exports.getOpenFrontmatterEdit = exports.getNewFrontmatterEdit = exports.ensureRangeIsInFrontmatter = exports.PointToPosition = exports.isInsideFrontmatter = exports.isInsideExpression = exports.isInComponentStartTag = exports.isPossibleComponent = exports.isJSDocument = void 0;
|
|
7
7
|
const node_path_1 = __importDefault(require("node:path"));
|
|
8
8
|
const vscode_html_languageservice_1 = require("vscode-html-languageservice");
|
|
9
|
-
function
|
|
9
|
+
function isJSDocument(languageId) {
|
|
10
10
|
return (languageId === 'javascript' ||
|
|
11
11
|
languageId === 'typescript' ||
|
|
12
12
|
languageId === 'javascriptreact' ||
|
|
13
13
|
languageId === 'typescriptreact');
|
|
14
14
|
}
|
|
15
|
-
exports.
|
|
15
|
+
exports.isJSDocument = isJSDocument;
|
|
16
16
|
/**
|
|
17
17
|
* Return true if a specific node could be a component.
|
|
18
18
|
* This is not a 100% sure test as it'll return false for any component that does not match the standard format for a component
|
|
@@ -55,17 +55,25 @@ exports.isInsideFrontmatter = isInsideFrontmatter;
|
|
|
55
55
|
* Transform a Point from the Astro compiler to an LSP Position
|
|
56
56
|
*/
|
|
57
57
|
function PointToPosition(point) {
|
|
58
|
-
|
|
58
|
+
// Columns are 0-based in LSP, but the compiler's Point are 1 based.
|
|
59
|
+
return vscode_html_languageservice_1.Position.create(point.line, point.column - 1);
|
|
59
60
|
}
|
|
60
61
|
exports.PointToPosition = PointToPosition;
|
|
61
62
|
/**
|
|
62
|
-
* Force a range to be at the start of the frontmatter
|
|
63
|
+
* Force a range to be at the start of the frontmatter if it is outside
|
|
63
64
|
*/
|
|
64
65
|
function ensureRangeIsInFrontmatter(range, frontmatter) {
|
|
65
66
|
if (frontmatter.status === 'open' || frontmatter.status === 'closed') {
|
|
66
|
-
const
|
|
67
|
-
position.
|
|
68
|
-
|
|
67
|
+
const frontmatterStartPosition = PointToPosition(frontmatter.position.start);
|
|
68
|
+
const frontmatterEndPosition = frontmatter.position.end
|
|
69
|
+
? PointToPosition(frontmatter.position.end)
|
|
70
|
+
: undefined;
|
|
71
|
+
// If the range start is outside the frontmatter, return a range at the start of the frontmatter
|
|
72
|
+
if (range.start.line < frontmatterStartPosition.line ||
|
|
73
|
+
(frontmatterEndPosition && range.start.line > frontmatterEndPosition.line)) {
|
|
74
|
+
return vscode_html_languageservice_1.Range.create(frontmatterStartPosition, frontmatterStartPosition);
|
|
75
|
+
}
|
|
76
|
+
return range;
|
|
69
77
|
}
|
|
70
78
|
return range;
|
|
71
79
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astrojs/language-server",
|
|
3
|
-
"version": "2.0.0-next.
|
|
3
|
+
"version": "2.0.0-next.9",
|
|
4
4
|
"author": "withastro",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@astrojs/compiler": "^1.4.2",
|
|
24
24
|
"@jridgewell/sourcemap-codec": "^1.4.15",
|
|
25
|
+
"@volar/kit": "^1.6.9",
|
|
25
26
|
"@volar/language-core": "^1.6.9",
|
|
26
27
|
"@volar/language-server": "^1.6.9",
|
|
27
28
|
"@volar/language-service": "^1.6.9",
|
|
@@ -29,7 +30,7 @@
|
|
|
29
30
|
"fast-glob": "^3.2.12",
|
|
30
31
|
"muggle-string": "^0.3.1",
|
|
31
32
|
"prettier": "^2.8.8",
|
|
32
|
-
"prettier-plugin-astro": "^0.9.
|
|
33
|
+
"prettier-plugin-astro": "^0.9.1",
|
|
33
34
|
"volar-service-css": "^0.0.4",
|
|
34
35
|
"volar-service-emmet": "^0.0.4",
|
|
35
36
|
"volar-service-html": "^0.0.4",
|
|
@@ -57,7 +58,7 @@
|
|
|
57
58
|
"scripts": {
|
|
58
59
|
"build": "tsc",
|
|
59
60
|
"dev": "tsc --watch",
|
|
60
|
-
"test": "mocha --require tsx --require test/takedown.ts test/misc/init.test.ts test/**/*.test.ts",
|
|
61
|
+
"test": "mocha --timeout 10000 --require tsx --require test/takedown.ts test/misc/init.test.ts test/**/*.test.ts",
|
|
61
62
|
"test:match": "pnpm run test -g"
|
|
62
63
|
}
|
|
63
64
|
}
|