@astrojs/language-server 0.13.3 → 0.15.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.
- package/CHANGELOG.md +34 -0
- package/dist/core/documents/utils.d.ts +6 -0
- package/dist/core/documents/utils.js +17 -1
- package/dist/plugins/PluginHost.d.ts +1 -1
- package/dist/plugins/PluginHost.js +29 -4
- package/dist/plugins/astro/AstroPlugin.d.ts +1 -1
- package/dist/plugins/astro/AstroPlugin.js +1 -1
- package/dist/plugins/astro/features/CompletionsProvider.d.ts +2 -2
- package/dist/plugins/astro/features/CompletionsProvider.js +24 -9
- package/dist/plugins/css/CSSPlugin.js +9 -1
- package/dist/plugins/css/features/astro-selectors.js +1 -2
- package/dist/plugins/html/features/astro-attributes.js +56 -1
- package/dist/plugins/html/utils.d.ts +1 -1
- package/dist/plugins/html/utils.js +1 -1
- package/dist/plugins/interfaces.d.ts +2 -2
- package/dist/plugins/typescript/TypeScriptPlugin.d.ts +6 -4
- package/dist/plugins/typescript/TypeScriptPlugin.js +12 -4
- package/dist/plugins/typescript/astro2tsx.d.ts +1 -1
- package/dist/plugins/typescript/astro2tsx.js +11 -6
- package/dist/plugins/typescript/features/CompletionsProvider.d.ts +23 -6
- package/dist/plugins/typescript/features/CompletionsProvider.js +256 -51
- package/dist/plugins/typescript/features/DiagnosticsProvider.js +44 -58
- package/dist/plugins/typescript/features/DocumentSymbolsProvider.js +8 -5
- package/dist/plugins/typescript/features/FoldingRangesProvider.d.ts +9 -0
- package/dist/plugins/typescript/features/FoldingRangesProvider.js +64 -0
- package/dist/plugins/typescript/features/SemanticTokenProvider.js +4 -1
- package/dist/plugins/typescript/features/utils.d.ts +2 -0
- package/dist/plugins/typescript/features/utils.js +7 -1
- package/dist/plugins/typescript/language-service.d.ts +1 -1
- package/dist/plugins/typescript/language-service.js +44 -23
- package/dist/plugins/typescript/snapshots/SnapshotManager.js +2 -1
- package/dist/plugins/typescript/snapshots/utils.js +24 -3
- package/dist/plugins/typescript/utils.d.ts +3 -0
- package/dist/plugins/typescript/utils.js +17 -1
- package/dist/server.js +16 -0
- package/dist/utils.d.ts +16 -0
- package/dist/utils.js +57 -1
- package/package.json +4 -4
- package/types/astro-jsx.d.ts +112 -113
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { SnapshotFragment, DocumentSnapshot } from '../snapshots/DocumentSnapshot';
|
|
2
2
|
import type { LanguageServiceManager } from '../LanguageServiceManager';
|
|
3
|
+
import { Position } from 'vscode-languageserver';
|
|
4
|
+
export declare function isPartOfImportStatement(text: string, position: Position): boolean;
|
|
3
5
|
export declare class SnapshotFragmentMap {
|
|
4
6
|
private languageServiceManager;
|
|
5
7
|
private map;
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SnapshotFragmentMap = void 0;
|
|
3
|
+
exports.SnapshotFragmentMap = exports.isPartOfImportStatement = void 0;
|
|
4
|
+
const documents_1 = require("../../../core/documents");
|
|
5
|
+
function isPartOfImportStatement(text, position) {
|
|
6
|
+
const line = (0, documents_1.getLineAtPosition)(position, text);
|
|
7
|
+
return /\s*from\s+["'][^"']*/.test(line.slice(0, position.character));
|
|
8
|
+
}
|
|
9
|
+
exports.isPartOfImportStatement = isPartOfImportStatement;
|
|
4
10
|
class SnapshotFragmentMap {
|
|
5
11
|
constructor(languageServiceManager) {
|
|
6
12
|
this.languageServiceManager = languageServiceManager;
|
|
@@ -35,4 +35,4 @@ export declare function forAllLanguageServices(cb: (service: LanguageServiceCont
|
|
|
35
35
|
* @param tsconfigPath has to be absolute
|
|
36
36
|
* @param docContext
|
|
37
37
|
*/
|
|
38
|
-
export declare function getLanguageServiceForTsconfig(tsconfigPath: string, docContext: LanguageServiceDocumentContext): Promise<LanguageServiceContainer>;
|
|
38
|
+
export declare function getLanguageServiceForTsconfig(tsconfigPath: string, docContext: LanguageServiceDocumentContext, workspaceUris: string[]): Promise<LanguageServiceContainer>;
|
|
@@ -37,7 +37,7 @@ const DocumentSnapshotUtils = __importStar(require("./snapshots/utils"));
|
|
|
37
37
|
const services = new Map();
|
|
38
38
|
async function getLanguageService(path, workspaceUris, docContext) {
|
|
39
39
|
const tsconfigPath = (0, utils_2.findTsConfigPath)(path, workspaceUris);
|
|
40
|
-
return getLanguageServiceForTsconfig(tsconfigPath, docContext);
|
|
40
|
+
return getLanguageServiceForTsconfig(tsconfigPath, docContext, workspaceUris);
|
|
41
41
|
}
|
|
42
42
|
exports.getLanguageService = getLanguageService;
|
|
43
43
|
async function forAllLanguageServices(cb) {
|
|
@@ -50,34 +50,44 @@ exports.forAllLanguageServices = forAllLanguageServices;
|
|
|
50
50
|
* @param tsconfigPath has to be absolute
|
|
51
51
|
* @param docContext
|
|
52
52
|
*/
|
|
53
|
-
async function getLanguageServiceForTsconfig(tsconfigPath, docContext) {
|
|
53
|
+
async function getLanguageServiceForTsconfig(tsconfigPath, docContext, workspaceUris) {
|
|
54
54
|
let service;
|
|
55
55
|
if (services.has(tsconfigPath)) {
|
|
56
56
|
service = await services.get(tsconfigPath);
|
|
57
57
|
}
|
|
58
58
|
else {
|
|
59
|
-
const newService = createLanguageService(tsconfigPath, docContext);
|
|
59
|
+
const newService = createLanguageService(tsconfigPath, docContext, workspaceUris);
|
|
60
60
|
services.set(tsconfigPath, newService);
|
|
61
61
|
service = await newService;
|
|
62
62
|
}
|
|
63
63
|
return service;
|
|
64
64
|
}
|
|
65
65
|
exports.getLanguageServiceForTsconfig = getLanguageServiceForTsconfig;
|
|
66
|
-
async function createLanguageService(tsconfigPath, docContext) {
|
|
67
|
-
const
|
|
66
|
+
async function createLanguageService(tsconfigPath, docContext, workspaceUris) {
|
|
67
|
+
const tsconfigRoot = tsconfigPath ? (0, path_1.dirname)(tsconfigPath) : process.cwd();
|
|
68
|
+
const workspacePaths = workspaceUris.map((uri) => (0, utils_1.urlToPath)(uri));
|
|
69
|
+
const workspacePath = workspacePaths.find((uri) => tsconfigRoot.startsWith(uri)) || workspacePaths[0];
|
|
70
|
+
const astroVersion = (0, utils_1.getUserAstroVersion)(workspacePath);
|
|
68
71
|
// `raw` here represent the tsconfig merged with any extended config
|
|
69
72
|
const { compilerOptions, fileNames: files, raw: fullConfig } = getParsedTSConfig();
|
|
70
73
|
let projectVersion = 0;
|
|
71
|
-
const snapshotManager = new SnapshotManager_1.SnapshotManager(docContext.globalSnapshotManager, files, fullConfig,
|
|
74
|
+
const snapshotManager = new SnapshotManager_1.SnapshotManager(docContext.globalSnapshotManager, files, fullConfig, tsconfigRoot || process.cwd());
|
|
72
75
|
const astroModuleLoader = (0, module_loader_1.createAstroModuleLoader)(getScriptSnapshot, compilerOptions);
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
const scriptFileNames = [];
|
|
77
|
+
// Before Astro 1.0, JSX definitions were inside of the language-server instead of inside Astro
|
|
78
|
+
// TODO: Remove this and astro-jsx.d.ts in types when we consider having support for Astro < 1.0 unnecessary
|
|
79
|
+
if (astroVersion.major === 0 || astroVersion.full === '1.0.0-beta.0') {
|
|
80
|
+
let languageServerDirectory;
|
|
81
|
+
try {
|
|
82
|
+
languageServerDirectory = (0, path_1.dirname)(require.resolve('@astrojs/language-server'));
|
|
83
|
+
}
|
|
84
|
+
catch (e) {
|
|
85
|
+
languageServerDirectory = __dirname;
|
|
86
|
+
}
|
|
87
|
+
const astroTSXFile = typescript_1.default.sys.resolvePath((0, path_1.resolve)(languageServerDirectory, '../types/astro-jsx.d.ts'));
|
|
88
|
+
scriptFileNames.push(astroTSXFile);
|
|
89
|
+
console.warn("Version lower than 1.0 detected, using internal types instead of Astro's");
|
|
79
90
|
}
|
|
80
|
-
const astroTSXFile = typescript_1.default.sys.resolvePath((0, path_1.resolve)(languageServerDirectory, '../types/astro-jsx.d.ts'));
|
|
81
91
|
const host = {
|
|
82
92
|
getNewLine: () => typescript_1.default.sys.newLine,
|
|
83
93
|
useCaseSensitiveFileNames: () => typescript_1.default.sys.useCaseSensitiveFileNames,
|
|
@@ -87,10 +97,10 @@ async function createLanguageService(tsconfigPath, docContext) {
|
|
|
87
97
|
fileExists: astroModuleLoader.fileExists,
|
|
88
98
|
readDirectory: astroModuleLoader.readDirectory,
|
|
89
99
|
getCompilationSettings: () => compilerOptions,
|
|
90
|
-
getCurrentDirectory: () =>
|
|
100
|
+
getCurrentDirectory: () => tsconfigRoot,
|
|
91
101
|
getDefaultLibFileName: typescript_1.default.getDefaultLibFilePath,
|
|
92
102
|
getProjectVersion: () => projectVersion.toString(),
|
|
93
|
-
getScriptFileNames: () => Array.from(new Set([...snapshotManager.getProjectFileNames(), ...snapshotManager.getFileNames(),
|
|
103
|
+
getScriptFileNames: () => Array.from(new Set([...snapshotManager.getProjectFileNames(), ...snapshotManager.getFileNames(), ...scriptFileNames])),
|
|
94
104
|
getScriptSnapshot,
|
|
95
105
|
getScriptVersion: (fileName) => getScriptSnapshot(fileName).version.toString(),
|
|
96
106
|
};
|
|
@@ -176,17 +186,24 @@ async function createLanguageService(tsconfigPath, docContext) {
|
|
|
176
186
|
snapshotManager.updateNonAstroFile(fileName, changes);
|
|
177
187
|
}
|
|
178
188
|
function getParsedTSConfig() {
|
|
179
|
-
var _a, _b, _c;
|
|
189
|
+
var _a, _b, _c, _d;
|
|
180
190
|
let configJson = (tsconfigPath && typescript_1.default.readConfigFile(tsconfigPath, typescript_1.default.sys.readFile).config) || {};
|
|
181
191
|
// If our user has types in their config but it doesn't include the types needed for Astro, add them to the config
|
|
182
|
-
if ((
|
|
183
|
-
configJson.compilerOptions.types.
|
|
192
|
+
if ((_a = configJson.compilerOptions) === null || _a === void 0 ? void 0 : _a.types) {
|
|
193
|
+
if (!((_b = configJson.compilerOptions) === null || _b === void 0 ? void 0 : _b.types.includes('astro/env'))) {
|
|
194
|
+
configJson.compilerOptions.types.push('astro/env');
|
|
195
|
+
}
|
|
196
|
+
if (astroVersion.major >= 1 &&
|
|
197
|
+
astroVersion.full !== '1.0.0-beta.0' &&
|
|
198
|
+
!((_c = configJson.compilerOptions) === null || _c === void 0 ? void 0 : _c.types.includes('astro/astro-jsx'))) {
|
|
199
|
+
configJson.compilerOptions.types.push('astro/astro-jsx');
|
|
200
|
+
}
|
|
184
201
|
}
|
|
185
|
-
configJson.compilerOptions = Object.assign(getDefaultCompilerOptions(), configJson.compilerOptions);
|
|
202
|
+
configJson.compilerOptions = Object.assign(getDefaultCompilerOptions(astroVersion), configJson.compilerOptions);
|
|
186
203
|
// Delete include so that .astro files don't get mistakenly excluded by the user
|
|
187
204
|
delete configJson.include;
|
|
188
205
|
// If the user supplied exclude, let's use theirs otherwise, use ours
|
|
189
|
-
(
|
|
206
|
+
(_d = configJson.exclude) !== null && _d !== void 0 ? _d : (configJson.exclude = getDefaultExclude());
|
|
190
207
|
// Everything here will always, unconditionally, be in the resulting config
|
|
191
208
|
const forcedCompilerOptions = {
|
|
192
209
|
noEmit: true,
|
|
@@ -200,7 +217,7 @@ async function createLanguageService(tsconfigPath, docContext) {
|
|
|
200
217
|
target: typescript_1.default.ScriptTarget.ESNext,
|
|
201
218
|
moduleResolution: typescript_1.default.ModuleResolutionKind.NodeJs,
|
|
202
219
|
};
|
|
203
|
-
const project = typescript_1.default.parseJsonConfigFileContent(configJson, typescript_1.default.sys,
|
|
220
|
+
const project = typescript_1.default.parseJsonConfigFileContent(configJson, typescript_1.default.sys, tsconfigRoot, forcedCompilerOptions, tsconfigPath, undefined, [
|
|
204
221
|
{ extension: '.vue', isMixedContent: true, scriptKind: typescript_1.default.ScriptKind.Deferred },
|
|
205
222
|
{ extension: '.svelte', isMixedContent: true, scriptKind: typescript_1.default.ScriptKind.Deferred },
|
|
206
223
|
{ extension: '.astro', isMixedContent: true, scriptKind: typescript_1.default.ScriptKind.Deferred },
|
|
@@ -218,11 +235,15 @@ async function createLanguageService(tsconfigPath, docContext) {
|
|
|
218
235
|
/**
|
|
219
236
|
* Default configuration used as a base and when the user doesn't have any
|
|
220
237
|
*/
|
|
221
|
-
function getDefaultCompilerOptions() {
|
|
238
|
+
function getDefaultCompilerOptions(astroVersion) {
|
|
239
|
+
const types = ['astro/env'];
|
|
240
|
+
if (astroVersion.major >= 1 && astroVersion.full !== '1.0.0-beta.0') {
|
|
241
|
+
types.push('astro/astro-jsx');
|
|
242
|
+
}
|
|
222
243
|
return {
|
|
223
244
|
maxNodeModuleJsDepth: 2,
|
|
224
245
|
allowSyntheticDefaultImports: true,
|
|
225
|
-
types:
|
|
246
|
+
types: types,
|
|
226
247
|
};
|
|
227
248
|
}
|
|
228
249
|
function getDefaultExclude() {
|
|
@@ -185,7 +185,8 @@ class SnapshotManager {
|
|
|
185
185
|
if (date.getTime() - this.lastLogged.getTime() > 60000) {
|
|
186
186
|
this.lastLogged = date;
|
|
187
187
|
const projectFiles = this.getProjectFileNames();
|
|
188
|
-
|
|
188
|
+
let allFiles = Array.from(new Set([...projectFiles, ...this.getFileNames()]));
|
|
189
|
+
allFiles = allFiles.map((file) => (0, utils_2.ensureRealFilePath)(file));
|
|
189
190
|
console.log('SnapshotManager File Statistics:\n' +
|
|
190
191
|
`Project files: ${projectFiles.length}\n` +
|
|
191
192
|
`Astro files: ${allFiles.filter((name) => name.endsWith('.astro')).length}\n` +
|
|
@@ -6,12 +6,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.createFromFrameworkFilePath = exports.createFromAstroFilePath = exports.createFromTSFilePath = exports.createFromNonAstroFilePath = exports.createFromFilePath = exports.createFromDocument = void 0;
|
|
7
7
|
const typescript_1 = __importDefault(require("typescript"));
|
|
8
8
|
const astro2tsx_1 = __importDefault(require("../astro2tsx"));
|
|
9
|
+
const vscode_uri_1 = require("vscode-uri");
|
|
9
10
|
const utils_1 = require("../utils");
|
|
10
11
|
const DocumentSnapshot_1 = require("./DocumentSnapshot");
|
|
11
12
|
const svelte_language_integration_1 = require("@astrojs/svelte-language-integration");
|
|
13
|
+
const utils_2 = require("../../../utils");
|
|
12
14
|
// Utilities to create Snapshots from different contexts
|
|
13
15
|
function createFromDocument(document) {
|
|
14
|
-
const { code } = (0, astro2tsx_1.default)(document.getText());
|
|
16
|
+
const { code } = (0, astro2tsx_1.default)(document.getText(), classNameFromFilename(document.getURL()));
|
|
15
17
|
return new DocumentSnapshot_1.AstroSnapshot(document, code, typescript_1.default.ScriptKind.TSX);
|
|
16
18
|
}
|
|
17
19
|
exports.createFromDocument = createFromDocument;
|
|
@@ -71,14 +73,33 @@ function createFromAstroFilePath(filePath, createDocument) {
|
|
|
71
73
|
exports.createFromAstroFilePath = createFromAstroFilePath;
|
|
72
74
|
function createFromFrameworkFilePath(filePath, framework) {
|
|
73
75
|
var _a;
|
|
76
|
+
const className = classNameFromFilename(filePath);
|
|
74
77
|
const originalText = (_a = typescript_1.default.sys.readFile(filePath)) !== null && _a !== void 0 ? _a : '';
|
|
75
78
|
let code = '';
|
|
76
79
|
if (framework === 'svelte') {
|
|
77
|
-
code = (0, svelte_language_integration_1.toTSX)(originalText);
|
|
80
|
+
code = (0, svelte_language_integration_1.toTSX)(originalText, className);
|
|
78
81
|
}
|
|
79
82
|
else {
|
|
80
|
-
code =
|
|
83
|
+
code = `export default function ${className}__AstroComponent_(props: Record<string, any>): any {}`;
|
|
81
84
|
}
|
|
82
85
|
return new DocumentSnapshot_1.TypeScriptDocumentSnapshot(0, filePath, code, typescript_1.default.ScriptKind.TSX);
|
|
83
86
|
}
|
|
84
87
|
exports.createFromFrameworkFilePath = createFromFrameworkFilePath;
|
|
88
|
+
function classNameFromFilename(filename) {
|
|
89
|
+
const url = vscode_uri_1.URI.parse(filename);
|
|
90
|
+
const withoutExtensions = vscode_uri_1.Utils.basename(url).slice(0, -vscode_uri_1.Utils.extname(url).length);
|
|
91
|
+
const withoutInvalidCharacters = withoutExtensions
|
|
92
|
+
.split('')
|
|
93
|
+
// Although "-" is invalid, we leave it in, pascal-case-handling will throw it out later
|
|
94
|
+
.filter((char) => /[A-Za-z$_\d-]/.test(char))
|
|
95
|
+
.join('');
|
|
96
|
+
const firstValidCharIdx = withoutInvalidCharacters
|
|
97
|
+
.split('')
|
|
98
|
+
// Although _ and $ are valid first characters for classes, they are invalid first characters
|
|
99
|
+
// for tag names. For a better import autocompletion experience, we therefore throw them out.
|
|
100
|
+
.findIndex((char) => /[A-Za-z]/.test(char));
|
|
101
|
+
const withoutLeadingInvalidCharacters = withoutInvalidCharacters.substr(firstValidCharIdx);
|
|
102
|
+
const inPascalCase = (0, utils_2.toPascalCase)(withoutLeadingInvalidCharacters);
|
|
103
|
+
const finalName = firstValidCharIdx === -1 ? `A${inPascalCase}` : inPascalCase;
|
|
104
|
+
return finalName;
|
|
105
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
import { CompletionItemKind, DiagnosticSeverity, Position, Range, SymbolKind, SemanticTokensLegend } from 'vscode-languageserver';
|
|
3
|
+
import { AstroDocument } from '../../core/documents';
|
|
3
4
|
import { SnapshotFragment } from './snapshots/DocumentSnapshot';
|
|
4
5
|
export declare const enum TokenType {
|
|
5
6
|
class = 0,
|
|
@@ -39,6 +40,8 @@ export declare function convertRange(document: {
|
|
|
39
40
|
length?: number;
|
|
40
41
|
}): Range;
|
|
41
42
|
export declare function convertToLocationRange(defDoc: SnapshotFragment, textSpan: ts.TextSpan): Range;
|
|
43
|
+
export declare function ensureFrontmatterInsert(resultRange: Range, document: AstroDocument): Range;
|
|
44
|
+
export declare function removeAstroComponentSuffix(name: string): string;
|
|
42
45
|
export declare type FrameworkExt = 'astro' | 'vue' | 'jsx' | 'tsx' | 'svelte';
|
|
43
46
|
declare type FrameworkVirtualExt = 'ts' | 'tsx';
|
|
44
47
|
export declare function getFrameworkFromFilePath(filePath: string): FrameworkExt;
|
|
@@ -3,7 +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
|
-
exports.ensureRealFilePath = exports.ensureRealAstroFilePath = exports.toRealAstroFilePath = exports.toVirtualFilePath = exports.toVirtualAstroFilePath = exports.isVirtualFilePath = exports.isVirtualSvelteFilePath = exports.isVirtualVueFilePath = exports.isVirtualAstroFilePath = exports.isFrameworkFilePath = exports.isAstroFilePath = exports.isVirtualFrameworkFilePath = exports.getFrameworkFromFilePath = exports.convertToLocationRange = exports.convertRange = exports.mapSeverity = exports.getScriptKindFromFileName = exports.isSubPath = exports.findTsConfigPath = exports.getExtensionFromScriptKind = exports.getCommitCharactersForScriptElement = exports.scriptElementKindToCompletionItemKind = exports.symbolKindFromString = exports.getSemanticTokenLegend = void 0;
|
|
6
|
+
exports.ensureRealFilePath = exports.ensureRealAstroFilePath = exports.toRealAstroFilePath = exports.toVirtualFilePath = exports.toVirtualAstroFilePath = exports.isVirtualFilePath = exports.isVirtualSvelteFilePath = exports.isVirtualVueFilePath = exports.isVirtualAstroFilePath = exports.isFrameworkFilePath = exports.isAstroFilePath = exports.isVirtualFrameworkFilePath = exports.getFrameworkFromFilePath = exports.removeAstroComponentSuffix = exports.ensureFrontmatterInsert = exports.convertToLocationRange = exports.convertRange = exports.mapSeverity = exports.getScriptKindFromFileName = exports.isSubPath = exports.findTsConfigPath = exports.getExtensionFromScriptKind = exports.getCommitCharactersForScriptElement = exports.scriptElementKindToCompletionItemKind = exports.symbolKindFromString = exports.getSemanticTokenLegend = void 0;
|
|
7
7
|
const typescript_1 = __importDefault(require("typescript"));
|
|
8
8
|
const path_1 = require("path");
|
|
9
9
|
const utils_1 = require("../../utils");
|
|
@@ -239,6 +239,22 @@ function convertToLocationRange(defDoc, textSpan) {
|
|
|
239
239
|
return range;
|
|
240
240
|
}
|
|
241
241
|
exports.convertToLocationRange = convertToLocationRange;
|
|
242
|
+
// Some code actions will insert code at the start of the file instead of inside our frontmatter
|
|
243
|
+
// We'll redirect those to the proper starting place
|
|
244
|
+
function ensureFrontmatterInsert(resultRange, document) {
|
|
245
|
+
if (document.astroMeta.frontmatter.state === 'closed') {
|
|
246
|
+
const position = document.positionAt(document.astroMeta.frontmatter.startOffset);
|
|
247
|
+
position.line += 1;
|
|
248
|
+
position.character = resultRange.start.character;
|
|
249
|
+
return vscode_languageserver_1.Range.create(position, position);
|
|
250
|
+
}
|
|
251
|
+
return resultRange;
|
|
252
|
+
}
|
|
253
|
+
exports.ensureFrontmatterInsert = ensureFrontmatterInsert;
|
|
254
|
+
function removeAstroComponentSuffix(name) {
|
|
255
|
+
return name.replace(/(\w+)__AstroComponent_/, '$1');
|
|
256
|
+
}
|
|
257
|
+
exports.removeAstroComponentSuffix = removeAstroComponentSuffix;
|
|
242
258
|
const VirtualExtension = {
|
|
243
259
|
ts: 'ts',
|
|
244
260
|
tsx: 'tsx',
|
package/dist/server.js
CHANGED
|
@@ -46,6 +46,22 @@ function startLanguageServer(connection) {
|
|
|
46
46
|
connection.onInitialize((params) => {
|
|
47
47
|
var _a, _b, _c, _d, _e, _f;
|
|
48
48
|
const workspaceUris = (_b = (_a = params.workspaceFolders) === null || _a === void 0 ? void 0 : _a.map((folder) => folder.uri.toString())) !== null && _b !== void 0 ? _b : [(_c = params.rootUri) !== null && _c !== void 0 ? _c : ''];
|
|
49
|
+
workspaceUris.forEach((uri) => {
|
|
50
|
+
uri = (0, utils_1.urlToPath)(uri);
|
|
51
|
+
const astroVersion = (0, utils_1.getUserAstroVersion)(uri);
|
|
52
|
+
if (astroVersion.exist === false) {
|
|
53
|
+
connection.sendNotification(vscode_languageserver_1.ShowMessageNotification.type, {
|
|
54
|
+
message: `Couldn't find Astro in workspace "${uri}". Experience might be degraded. For the best experience, please make sure Astro is installed and then restart the language server`,
|
|
55
|
+
type: vscode_languageserver_1.MessageType.Warning,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
if (astroVersion.exist && astroVersion.major === 0 && astroVersion.minor < 24 && astroVersion.patch < 5) {
|
|
59
|
+
connection.sendNotification(vscode_languageserver_1.ShowMessageNotification.type, {
|
|
60
|
+
message: `The version of Astro you're using (${astroVersion.full}) is not supported by this version of the Astro language server. Please upgrade Astro to any version higher than 0.23.4 or if using the VS Code extension, downgrade the extension to 0.8.10`,
|
|
61
|
+
type: vscode_languageserver_1.MessageType.Error,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
});
|
|
49
65
|
pluginHost.initialize({
|
|
50
66
|
filterIncompleteCompletions: !((_d = params.initializationOptions) === null || _d === void 0 ? void 0 : _d.dontFilterIncompleteCompletions),
|
|
51
67
|
definitionLinkSupport: !!((_f = (_e = params.capabilities.textDocument) === null || _e === void 0 ? void 0 : _e.definition) === null || _f === void 0 ? void 0 : _f.linkSupport),
|
package/dist/utils.d.ts
CHANGED
|
@@ -16,6 +16,10 @@ export declare function pathToUrl(path: string): string;
|
|
|
16
16
|
* (bar or bar.astro in this example).
|
|
17
17
|
*/
|
|
18
18
|
export declare function getLastPartOfPath(path: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Transform a string into PascalCase
|
|
21
|
+
*/
|
|
22
|
+
export declare function toPascalCase(string: string): string;
|
|
19
23
|
/**
|
|
20
24
|
* Return true if a specific node could be a component.
|
|
21
25
|
* 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
|
|
@@ -28,6 +32,10 @@ export declare function clamp(num: number, min: number, max: number): number;
|
|
|
28
32
|
export declare function isNotNullOrUndefined<T>(val: T | undefined | null): val is T;
|
|
29
33
|
export declare function isInRange(range: Range, positionToTest: Position): boolean;
|
|
30
34
|
export declare function isBeforeOrEqualToPosition(position: Position, positionToTest: Position): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Get all matches of a regexp.
|
|
37
|
+
*/
|
|
38
|
+
export declare function getRegExpMatches(regex: RegExp, str: string): RegExpExecArray[];
|
|
31
39
|
/**
|
|
32
40
|
* Debounces a function but cancels previous invocation only if
|
|
33
41
|
* a second function determines it should.
|
|
@@ -46,3 +54,11 @@ export declare function debounceSameArg<T>(fn: (arg: T) => void, shouldCancelPre
|
|
|
46
54
|
* @param milliseconds Number of milliseconds to debounce/throttle
|
|
47
55
|
*/
|
|
48
56
|
export declare function debounceThrottle<T extends (...args: any) => void>(fn: T, milliseconds: number): T;
|
|
57
|
+
export interface AstroVersion {
|
|
58
|
+
full: string;
|
|
59
|
+
major: number;
|
|
60
|
+
minor: number;
|
|
61
|
+
patch: number;
|
|
62
|
+
exist: boolean;
|
|
63
|
+
}
|
|
64
|
+
export declare function getUserAstroVersion(basePath: string): AstroVersion;
|
package/dist/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.debounceThrottle = exports.debounceSameArg = exports.isBeforeOrEqualToPosition = exports.isInRange = exports.isNotNullOrUndefined = exports.clamp = exports.flatten = exports.isPossibleComponent = exports.getLastPartOfPath = exports.pathToUrl = exports.urlToPath = exports.normalizePath = exports.normalizeUri = void 0;
|
|
3
|
+
exports.getUserAstroVersion = exports.debounceThrottle = exports.debounceSameArg = exports.getRegExpMatches = exports.isBeforeOrEqualToPosition = exports.isInRange = exports.isNotNullOrUndefined = exports.clamp = exports.flatten = exports.isPossibleComponent = exports.toPascalCase = exports.getLastPartOfPath = exports.pathToUrl = exports.urlToPath = exports.normalizePath = exports.normalizeUri = void 0;
|
|
4
4
|
const vscode_uri_1 = require("vscode-uri");
|
|
5
5
|
/** Normalizes a document URI */
|
|
6
6
|
function normalizeUri(uri) {
|
|
@@ -37,6 +37,17 @@ function getLastPartOfPath(path) {
|
|
|
37
37
|
return path.replace(/\\/g, '/').split('/').pop() || '';
|
|
38
38
|
}
|
|
39
39
|
exports.getLastPartOfPath = getLastPartOfPath;
|
|
40
|
+
/**
|
|
41
|
+
* Transform a string into PascalCase
|
|
42
|
+
*/
|
|
43
|
+
function toPascalCase(string) {
|
|
44
|
+
return `${string}`
|
|
45
|
+
.replace(new RegExp(/[-_]+/, 'g'), ' ')
|
|
46
|
+
.replace(new RegExp(/[^\w\s]/, 'g'), '')
|
|
47
|
+
.replace(new RegExp(/\s+(.)(\w*)/, 'g'), ($1, $2, $3) => `${$2.toUpperCase() + $3.toLowerCase()}`)
|
|
48
|
+
.replace(new RegExp(/\w/), (s) => s.toUpperCase());
|
|
49
|
+
}
|
|
50
|
+
exports.toPascalCase = toPascalCase;
|
|
40
51
|
/**
|
|
41
52
|
* Return true if a specific node could be a component.
|
|
42
53
|
* 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
|
|
@@ -69,6 +80,18 @@ function isBeforeOrEqualToPosition(position, positionToTest) {
|
|
|
69
80
|
(positionToTest.line === position.line && positionToTest.character <= position.character));
|
|
70
81
|
}
|
|
71
82
|
exports.isBeforeOrEqualToPosition = isBeforeOrEqualToPosition;
|
|
83
|
+
/**
|
|
84
|
+
* Get all matches of a regexp.
|
|
85
|
+
*/
|
|
86
|
+
function getRegExpMatches(regex, str) {
|
|
87
|
+
const matches = [];
|
|
88
|
+
let match;
|
|
89
|
+
while ((match = regex.exec(str))) {
|
|
90
|
+
matches.push(match);
|
|
91
|
+
}
|
|
92
|
+
return matches;
|
|
93
|
+
}
|
|
94
|
+
exports.getRegExpMatches = getRegExpMatches;
|
|
72
95
|
/**
|
|
73
96
|
* Debounces a function but cancels previous invocation only if
|
|
74
97
|
* a second function determines it should.
|
|
@@ -117,3 +140,36 @@ function debounceThrottle(fn, milliseconds) {
|
|
|
117
140
|
return maybeCall;
|
|
118
141
|
}
|
|
119
142
|
exports.debounceThrottle = debounceThrottle;
|
|
143
|
+
function getUserAstroVersion(basePath) {
|
|
144
|
+
let version = '0.0.0';
|
|
145
|
+
let exist = true;
|
|
146
|
+
try {
|
|
147
|
+
const astroPackageJson = require.resolve('astro/package.json', { paths: [basePath] });
|
|
148
|
+
version = require(astroPackageJson).version;
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
// If we couldn't find it inside the workspace's node_modules, it might means we're in the monorepo
|
|
152
|
+
try {
|
|
153
|
+
const monorepoPackageJson = require.resolve('./packages/astro/package.json', { paths: [basePath] });
|
|
154
|
+
version = require(monorepoPackageJson).version;
|
|
155
|
+
}
|
|
156
|
+
catch (e) {
|
|
157
|
+
// If we still couldn't find it, it probably just doesn't exist
|
|
158
|
+
exist = false;
|
|
159
|
+
console.error(e);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
let [major, minor, patch] = version.split('.');
|
|
163
|
+
if (patch.includes('-')) {
|
|
164
|
+
const patchParts = patch.split('-');
|
|
165
|
+
patch = patchParts[0];
|
|
166
|
+
}
|
|
167
|
+
return {
|
|
168
|
+
full: version,
|
|
169
|
+
major: Number(major),
|
|
170
|
+
minor: Number(minor),
|
|
171
|
+
patch: Number(patch),
|
|
172
|
+
exist,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
exports.getUserAstroVersion = getUserAstroVersion;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@astrojs/language-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"author": "withastro",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "commonjs",
|
|
@@ -16,10 +16,10 @@
|
|
|
16
16
|
"scripts": {
|
|
17
17
|
"build": "tsc",
|
|
18
18
|
"dev": "astro-scripts dev \"src/**/*.ts\"",
|
|
19
|
-
"test": "cross-env TS_NODE_TRANSPILE_ONLY=true mocha --require ts-node/register \"test/**/*.ts\" --exclude \"test/**/*.d.ts\""
|
|
19
|
+
"test": "cross-env TS_NODE_TRANSPILE_ONLY=true mocha --timeout 20000 --require ts-node/register \"test/**/*.ts\" --exclude \"test/**/*.d.ts\""
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@astrojs/svelte-language-integration": "^0.1.
|
|
22
|
+
"@astrojs/svelte-language-integration": "^0.1.3",
|
|
23
23
|
"@vscode/emmet-helper": "^2.8.4",
|
|
24
24
|
"lodash": "^4.17.21",
|
|
25
25
|
"source-map": "^0.7.3",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"@types/lodash": "^4.14.179",
|
|
38
38
|
"@types/mocha": "^9.1.0",
|
|
39
39
|
"@types/sinon": "^10.0.11",
|
|
40
|
-
"astro": "^0.
|
|
40
|
+
"astro": "^1.0.0-beta.1",
|
|
41
41
|
"astro-scripts": "0.0.1",
|
|
42
42
|
"chai": "^4.3.6",
|
|
43
43
|
"cross-env": "^7.0.3",
|