@master/css-language-server 2.0.0-rc.73 → 2.0.0-rc.74
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/LICENSE +21 -0
- package/dist/core.d.ts +64 -58
- package/dist/core.js +480 -0
- package/dist/index.d.ts +3 -4
- package/dist/index.js +3 -0
- package/dist/server.d.ts +1 -1
- package/dist/server.js +8 -0
- package/dist/settings.d.ts +9 -6
- package/dist/settings.js +9 -0
- package/dist/utils/create-document.d.ts +8 -4
- package/dist/utils/create-document.js +28 -0
- package/package.json +60 -1
- package/dist/core.mjs +0 -559
- package/dist/index.mjs +0 -2
- package/dist/server.mjs +0 -9
- package/dist/settings.mjs +0 -9
- package/dist/utils/create-document.mjs +0 -28
package/dist/core.mjs
DELETED
|
@@ -1,559 +0,0 @@
|
|
|
1
|
-
import { TextDocumentSyncKind, TextDocuments, createConnection, DiagnosticSeverity } from 'vscode-languageserver/node';
|
|
2
|
-
import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
3
|
-
import path from 'node:path';
|
|
4
|
-
import { readFile } from 'node:fs/promises';
|
|
5
|
-
import { pathToFileURL } from 'node:url';
|
|
6
|
-
import CSSLanguageService from '@master/css-language-service';
|
|
7
|
-
import { compileCSSManifest } from '@master/css-compiler';
|
|
8
|
-
import { findMasterCSSWorkspaceDirectories, findCSSManifestEntryFiles } from '@master/css-project/entries';
|
|
9
|
-
import { loadProjectManifest } from '@master/css-project/manifest';
|
|
10
|
-
import { resolveMasterCSSWorkspacePackages } from '@master/css-project/workspace';
|
|
11
|
-
import extend from '@techor/extend';
|
|
12
|
-
import settings from './settings.mjs';
|
|
13
|
-
import { INVOKED_TRIGGER_CHARACTERS, VALUE_TRIGGER_CHARACTERS, SELECTOR_TRIGGER_CHARACTERS, QUERY_TRIGGER_CHARACTERS, DECLARATION_SEPARATOR_TRIGGER_CHARACTER, AT_TRIGGER_CHARACTER, GROUP_TRIGGER_CHARACTER } from '@master/css-language-service/common';
|
|
14
|
-
import { defaultCSSLanguageRuntime, SEMANTIC_TOKENS_LEGEND, matchesLanguageServiceNativeDeclaration } from '@master/css-language';
|
|
15
|
-
import glob from 'fast-glob';
|
|
16
|
-
import { URI } from 'vscode-uri';
|
|
17
|
-
import { CSSDirectiveError } from '@master/css-schema/css-directives';
|
|
18
|
-
|
|
19
|
-
const ACTIVE_SEMANTIC_TOKENS_REQUEST = 'masterCSS/renderActiveSemanticTokens';
|
|
20
|
-
const DOCUMENT_SEMANTIC_TOKENS_REQUEST = 'masterCSS/renderDocumentSemanticTokens';
|
|
21
|
-
const SERVER_CAPABILITIES = {
|
|
22
|
-
textDocumentSync: TextDocumentSyncKind.Incremental,
|
|
23
|
-
completionProvider: {
|
|
24
|
-
resolveProvider: false,
|
|
25
|
-
workDoneProgress: false,
|
|
26
|
-
triggerCharacters: [
|
|
27
|
-
...new Set([
|
|
28
|
-
...INVOKED_TRIGGER_CHARACTERS,
|
|
29
|
-
...VALUE_TRIGGER_CHARACTERS,
|
|
30
|
-
...SELECTOR_TRIGGER_CHARACTERS,
|
|
31
|
-
...QUERY_TRIGGER_CHARACTERS,
|
|
32
|
-
DECLARATION_SEPARATOR_TRIGGER_CHARACTER,
|
|
33
|
-
AT_TRIGGER_CHARACTER,
|
|
34
|
-
GROUP_TRIGGER_CHARACTER
|
|
35
|
-
])
|
|
36
|
-
]
|
|
37
|
-
},
|
|
38
|
-
colorProvider: true,
|
|
39
|
-
hoverProvider: true,
|
|
40
|
-
semanticTokensProvider: {
|
|
41
|
-
legend: SEMANTIC_TOKENS_LEGEND,
|
|
42
|
-
full: true
|
|
43
|
-
},
|
|
44
|
-
workspace: {
|
|
45
|
-
workspaceFolders: {
|
|
46
|
-
supported: true
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
const CSS_DIAGNOSTIC_LANGUAGE_IDS = new Set([
|
|
51
|
-
'css',
|
|
52
|
-
'scss',
|
|
53
|
-
'less'
|
|
54
|
-
]);
|
|
55
|
-
const SFC_DIAGNOSTIC_LANGUAGE_IDS = new Set([
|
|
56
|
-
'vue',
|
|
57
|
-
'svelte',
|
|
58
|
-
'astro'
|
|
59
|
-
]);
|
|
60
|
-
const STYLE_BLOCK_RE = /<style\b([^>]*)>([\s\S]*?)<\/style>/gi;
|
|
61
|
-
function isCSSDiagnosticDocument(textDocument) {
|
|
62
|
-
return CSS_DIAGNOSTIC_LANGUAGE_IDS.has(textDocument.languageId) || SFC_DIAGNOSTIC_LANGUAGE_IDS.has(textDocument.languageId);
|
|
63
|
-
}
|
|
64
|
-
function getSFCStyleLanguage(attributes) {
|
|
65
|
-
const match = /\blang\s*=\s*(?:"([^"]+)"|'([^']+)'|([^\s>]+))/i.exec(attributes);
|
|
66
|
-
return (match?.[1] || match?.[2] || match?.[3] || 'css').toLowerCase();
|
|
67
|
-
}
|
|
68
|
-
function getCSSDiagnosticSources(textDocument) {
|
|
69
|
-
const text = textDocument.getText();
|
|
70
|
-
if (CSS_DIAGNOSTIC_LANGUAGE_IDS.has(textDocument.languageId)) {
|
|
71
|
-
return [
|
|
72
|
-
{
|
|
73
|
-
source: text,
|
|
74
|
-
offset: 0
|
|
75
|
-
}
|
|
76
|
-
];
|
|
77
|
-
}
|
|
78
|
-
if (!SFC_DIAGNOSTIC_LANGUAGE_IDS.has(textDocument.languageId)) return [];
|
|
79
|
-
const sources = [];
|
|
80
|
-
STYLE_BLOCK_RE.lastIndex = 0;
|
|
81
|
-
for (const match of text.matchAll(STYLE_BLOCK_RE)){
|
|
82
|
-
const styleLanguage = getSFCStyleLanguage(match[1]);
|
|
83
|
-
if (!CSS_DIAGNOSTIC_LANGUAGE_IDS.has(styleLanguage)) continue;
|
|
84
|
-
const source = match[2];
|
|
85
|
-
const offset = (match.index || 0) + match[0].indexOf(source);
|
|
86
|
-
sources.push({
|
|
87
|
-
source,
|
|
88
|
-
offset
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
return sources;
|
|
92
|
-
}
|
|
93
|
-
function isCSSDirectiveError(error) {
|
|
94
|
-
return error instanceof CSSDirectiveError || !!error && typeof error === 'object' && error.name === 'CSSDirectiveError' && typeof error.code === 'string';
|
|
95
|
-
}
|
|
96
|
-
function getInitializationSettings(initializationOptions) {
|
|
97
|
-
if (!initializationOptions || typeof initializationOptions !== 'object') return;
|
|
98
|
-
const options = initializationOptions;
|
|
99
|
-
return options.masterCSS ?? options;
|
|
100
|
-
}
|
|
101
|
-
function isWindowsFilePath(fsPath) {
|
|
102
|
-
return /^[a-z]:[\\/]/i.test(fsPath) || fsPath.startsWith('\\\\') || fsPath.startsWith('//');
|
|
103
|
-
}
|
|
104
|
-
function getFilePathTools(...fsPaths) {
|
|
105
|
-
return fsPaths.some(isWindowsFilePath) ? path.win32 : path;
|
|
106
|
-
}
|
|
107
|
-
function toComparableFilePath(uri) {
|
|
108
|
-
const parsedURI = URI.parse(uri);
|
|
109
|
-
if (parsedURI.scheme !== 'file') return;
|
|
110
|
-
const fsPath = parsedURI.fsPath;
|
|
111
|
-
if (!fsPath) return;
|
|
112
|
-
const filePathTools = getFilePathTools(fsPath);
|
|
113
|
-
const resolvedPath = filePathTools.resolve(fsPath);
|
|
114
|
-
return isWindowsFilePath(resolvedPath) ? resolvedPath.toLowerCase() : resolvedPath;
|
|
115
|
-
}
|
|
116
|
-
function containsFilePath(parentPath, childPath) {
|
|
117
|
-
const filePathTools = getFilePathTools(parentPath, childPath);
|
|
118
|
-
const relativePath = filePathTools.relative(parentPath, childPath);
|
|
119
|
-
return relativePath === '' || !!relativePath && relativePath !== '..' && !relativePath.startsWith(`..${filePathTools.sep}`) && !filePathTools.isAbsolute(relativePath);
|
|
120
|
-
}
|
|
121
|
-
class CSSLanguageServer {
|
|
122
|
-
connection;
|
|
123
|
-
customSettings;
|
|
124
|
-
workspaceFolders = [];
|
|
125
|
-
workspaces = new Map();
|
|
126
|
-
globalWorkspace = {
|
|
127
|
-
uri: '',
|
|
128
|
-
openedTextDocuments: [],
|
|
129
|
-
languageServiceSettings: this.settings,
|
|
130
|
-
languageRuntime: defaultCSSLanguageRuntime,
|
|
131
|
-
languageRuntimeSource: 'bundled'
|
|
132
|
-
};
|
|
133
|
-
documents;
|
|
134
|
-
initializing;
|
|
135
|
-
clientCapabilities = {};
|
|
136
|
-
settings;
|
|
137
|
-
console;
|
|
138
|
-
disposables = [];
|
|
139
|
-
constructor(connection = process.argv.includes('--stdio') ? createConnection(process.stdin, process.stdout) : createConnection(), customSettings){
|
|
140
|
-
this.connection = connection;
|
|
141
|
-
this.customSettings = customSettings;
|
|
142
|
-
this.documents = new TextDocuments(TextDocument);
|
|
143
|
-
this.settings = extend(settings, this.customSettings);
|
|
144
|
-
this.globalWorkspace.languageServiceSettings = this.settings;
|
|
145
|
-
this.console = new Proxy(this.connection.console, {
|
|
146
|
-
get: (target, prop)=>{
|
|
147
|
-
if (!this.settings?.verbose) return ()=>{};
|
|
148
|
-
return this.connection.console[prop];
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
start() {
|
|
153
|
-
this.disposables.push(this.documents.onDidSave(this.onDidSave.bind(this)), this.documents.onDidOpen(this.onDidOpen.bind(this)), this.documents.onDidChangeContent(this.onDidChangeContent.bind(this)), this.documents.onDidClose(this.onDidClose.bind(this)), this.documents.listen(this.connection), this.connection.onDidChangeConfiguration(this.onDidChangeConfiguration.bind(this)), this.connection.onHover(this.onHover.bind(this)), this.connection.onCompletion(this.onCompletion.bind(this)), this.connection.onDocumentColor(this.onDocumentColor.bind(this)), this.connection.onColorPresentation(this.onColorPresentation.bind(this)), this.connection.languages.semanticTokens.on(this.onSemanticTokens.bind(this)), this.connection.onRequest(DOCUMENT_SEMANTIC_TOKENS_REQUEST, this.onDocumentSemanticTokens.bind(this)), this.connection.onRequest(ACTIVE_SEMANTIC_TOKENS_REQUEST, this.onActiveSemanticTokens.bind(this)), this.connection.onInitialize(this.onInitialize.bind(this)), this.connection.onInitialized(()=>this.init()));
|
|
154
|
-
this.connection.listen();
|
|
155
|
-
}
|
|
156
|
-
init() {
|
|
157
|
-
if (this.initializing) return this.initializing;
|
|
158
|
-
return this.initializing = new Promise(async (resolve)=>{
|
|
159
|
-
await Promise.all(this.workspaceFolders.map((folder)=>this.initWorkspaceFolder(folder.uri)));
|
|
160
|
-
resolve();
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
onInitialize(params) {
|
|
164
|
-
this.clientCapabilities = params.capabilities;
|
|
165
|
-
const initializationSettings = getInitializationSettings(params.initializationOptions);
|
|
166
|
-
if (initializationSettings) {
|
|
167
|
-
this.customSettings = extend(this.customSettings, initializationSettings);
|
|
168
|
-
this.settings = extend(settings, this.customSettings);
|
|
169
|
-
this.globalWorkspace.languageServiceSettings = this.settings;
|
|
170
|
-
}
|
|
171
|
-
if (params.workspaceFolders?.length) {
|
|
172
|
-
this.workspaceFolders = params.workspaceFolders;
|
|
173
|
-
}
|
|
174
|
-
const capabilities = {
|
|
175
|
-
...SERVER_CAPABILITIES
|
|
176
|
-
};
|
|
177
|
-
if (this.settings?.embeddedSyntaxHighlighting !== 'always') {
|
|
178
|
-
delete capabilities.semanticTokensProvider;
|
|
179
|
-
}
|
|
180
|
-
return {
|
|
181
|
-
capabilities
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
async onHover(params) {
|
|
185
|
-
await this.init();
|
|
186
|
-
const workspace = this.findClosestWorkspace(params.textDocument.uri);
|
|
187
|
-
if (workspace?.languageService) {
|
|
188
|
-
const document = this.documents.get(params.textDocument.uri);
|
|
189
|
-
if (document) return workspace.languageService.inspectSyntax(document, params.position);
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
async onCompletion(params) {
|
|
193
|
-
await this.init();
|
|
194
|
-
const workspace = this.findClosestWorkspace(params.textDocument.uri);
|
|
195
|
-
if (workspace?.languageService) {
|
|
196
|
-
const document = this.documents.get(params.textDocument.uri);
|
|
197
|
-
if (document) return workspace.languageService.suggestSyntax(document, params.position, params.context);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
async onDocumentColor(params) {
|
|
201
|
-
await this.init();
|
|
202
|
-
const workspace = this.findClosestWorkspace(params.textDocument.uri);
|
|
203
|
-
if (workspace?.languageService) {
|
|
204
|
-
const document = this.documents.get(params.textDocument.uri);
|
|
205
|
-
if (document) return await workspace.languageService.renderSyntaxColors(document) ?? [];
|
|
206
|
-
}
|
|
207
|
-
return [];
|
|
208
|
-
}
|
|
209
|
-
async onColorPresentation(params) {
|
|
210
|
-
await this.init();
|
|
211
|
-
const workspace = this.findClosestWorkspace(params.textDocument.uri);
|
|
212
|
-
if (workspace?.languageService) {
|
|
213
|
-
const document = this.documents.get(params.textDocument.uri);
|
|
214
|
-
if (document) return workspace.languageService.editSyntaxColors(document, params.color, params.range) ?? [];
|
|
215
|
-
}
|
|
216
|
-
return [];
|
|
217
|
-
}
|
|
218
|
-
async onSemanticTokens(params) {
|
|
219
|
-
await this.init();
|
|
220
|
-
const workspace = this.findClosestWorkspace(params.textDocument.uri);
|
|
221
|
-
if (workspace?.languageService) {
|
|
222
|
-
const document = this.documents.get(params.textDocument.uri) ?? workspace.openedTextDocuments.find((document)=>document.uri === params.textDocument.uri);
|
|
223
|
-
if (document) return workspace.languageService.renderSemanticTokens(document) ?? {
|
|
224
|
-
data: []
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
return {
|
|
228
|
-
data: []
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
async onDocumentSemanticTokens(params) {
|
|
232
|
-
return this.onSemanticTokens(params);
|
|
233
|
-
}
|
|
234
|
-
async onActiveSemanticTokens(params) {
|
|
235
|
-
await this.init();
|
|
236
|
-
const workspace = this.findClosestWorkspace(params.textDocument.uri);
|
|
237
|
-
if (workspace?.languageService) {
|
|
238
|
-
const document = this.documents.get(params.textDocument.uri) ?? workspace.openedTextDocuments.find((document)=>document.uri === params.textDocument.uri);
|
|
239
|
-
if (document) return workspace.languageService.renderSemanticTokensAtPosition(document, params.position) ?? {
|
|
240
|
-
data: []
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
return {
|
|
244
|
-
data: []
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
async onDidOpen(params) {
|
|
248
|
-
await this.init();
|
|
249
|
-
const workspace = this.findClosestWorkspace(params.document.uri);
|
|
250
|
-
if (!workspace) return;
|
|
251
|
-
if (workspace.openedTextDocuments.includes(params.document)) {
|
|
252
|
-
this.publishCSSDirectiveDiagnostics(params.document, workspace);
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
if (!workspace.openedTextDocuments.length) {
|
|
256
|
-
await this.initWorkspaceLanguageService(workspace);
|
|
257
|
-
}
|
|
258
|
-
workspace.openedTextDocuments.push(params.document);
|
|
259
|
-
this.publishCSSDirectiveDiagnostics(params.document, workspace);
|
|
260
|
-
}
|
|
261
|
-
async onDidChangeContent(params) {
|
|
262
|
-
await this.init();
|
|
263
|
-
const workspace = this.findClosestWorkspace(params.document.uri);
|
|
264
|
-
if (!workspace) return;
|
|
265
|
-
this.publishCSSDirectiveDiagnostics(params.document, workspace);
|
|
266
|
-
}
|
|
267
|
-
async onDidClose(params) {
|
|
268
|
-
await this.init();
|
|
269
|
-
const workspace = this.findClosestWorkspace(params.document.uri);
|
|
270
|
-
if (!workspace) return;
|
|
271
|
-
workspace.openedTextDocuments.splice(workspace.openedTextDocuments.indexOf(params.document), 1);
|
|
272
|
-
this.connection.sendDiagnostics({
|
|
273
|
-
uri: params.document.uri,
|
|
274
|
-
diagnostics: []
|
|
275
|
-
});
|
|
276
|
-
if (!workspace.openedTextDocuments.length) {
|
|
277
|
-
this.destroyLanguageService(workspace);
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
async onDidSave(params) {
|
|
281
|
-
await this.init();
|
|
282
|
-
const workspace = this.findClosestWorkspace(params.document.uri);
|
|
283
|
-
if (!workspace) return;
|
|
284
|
-
this.publishCSSDirectiveDiagnostics(params.document, workspace);
|
|
285
|
-
const name = path.basename(URI.parse(params.document.uri).fsPath);
|
|
286
|
-
if (name.endsWith('.css')) {
|
|
287
|
-
this.refreshSemanticTokens();
|
|
288
|
-
this.connection.sendRequest('masterCSS/restart', {
|
|
289
|
-
title: 'Updating Master CSS configuration'
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
async onDidChangeConfiguration({ settings: changedSettings }) {
|
|
294
|
-
await this.init();
|
|
295
|
-
if (changedSettings?.masterCSS) {
|
|
296
|
-
this.connection.sendNotification('masterCSS/globalSettingsChanged', changedSettings.masterCSS);
|
|
297
|
-
this.customSettings = changedSettings.masterCSS;
|
|
298
|
-
this.settings = extend(settings, this.customSettings);
|
|
299
|
-
this.globalWorkspace.languageServiceSettings = this.settings;
|
|
300
|
-
this.refreshSemanticTokens();
|
|
301
|
-
this.connection.sendRequest('masterCSS/restart', {
|
|
302
|
-
title: 'Updating Master CSS settings'
|
|
303
|
-
});
|
|
304
|
-
for (const workspace of [
|
|
305
|
-
this.globalWorkspace,
|
|
306
|
-
...this.workspaces.values()
|
|
307
|
-
]){
|
|
308
|
-
for (const document of workspace.openedTextDocuments){
|
|
309
|
-
this.publishCSSDirectiveDiagnostics(document, workspace);
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
async initWorkspaceFolder(workspaceFolderURI) {
|
|
315
|
-
const workspaceFolderCWD = URI.parse(workspaceFolderURI).fsPath;
|
|
316
|
-
let customWorkspaceFolderSettings;
|
|
317
|
-
if (this.clientCapabilities.workspace?.configuration) {
|
|
318
|
-
customWorkspaceFolderSettings = await this.connection.workspace.getConfiguration({
|
|
319
|
-
scopeUri: workspaceFolderURI,
|
|
320
|
-
section: 'masterCSS'
|
|
321
|
-
});
|
|
322
|
-
}
|
|
323
|
-
const { workspaces, ...languageServiceSettings } = extend(settings, this.customSettings, customWorkspaceFolderSettings);
|
|
324
|
-
const resolvedWorkspaceDirectories = new Set([
|
|
325
|
-
workspaceFolderCWD
|
|
326
|
-
]);
|
|
327
|
-
if (workspaceFolderCWD) {
|
|
328
|
-
this.console.info(`Registered workspace folder ${workspaceFolderURI}`);
|
|
329
|
-
} else {
|
|
330
|
-
this.console.info(`Registered global workspace folder`);
|
|
331
|
-
}
|
|
332
|
-
if (workspaces === 'auto') {
|
|
333
|
-
for (const workspaceDir of (await findMasterCSSWorkspaceDirectories(workspaceFolderCWD))){
|
|
334
|
-
resolvedWorkspaceDirectories.add(workspaceDir);
|
|
335
|
-
}
|
|
336
|
-
} else if (workspaces?.length) {
|
|
337
|
-
(await glob(workspaces, {
|
|
338
|
-
cwd: workspaceFolderCWD,
|
|
339
|
-
absolute: true,
|
|
340
|
-
onlyDirectories: true,
|
|
341
|
-
ignore: [
|
|
342
|
-
'**/node_modules/**'
|
|
343
|
-
]
|
|
344
|
-
})).forEach((workspaceDir)=>resolvedWorkspaceDirectories.add(path.resolve(workspaceDir)));
|
|
345
|
-
}
|
|
346
|
-
for (const workspaceDir of resolvedWorkspaceDirectories){
|
|
347
|
-
const workspaceURI = URI.file(workspaceDir).toString();
|
|
348
|
-
this.console.info(`Added workspace ${workspaceURI}`);
|
|
349
|
-
this.workspaces.set(workspaceURI, {
|
|
350
|
-
uri: workspaceURI,
|
|
351
|
-
openedTextDocuments: [],
|
|
352
|
-
languageServiceSettings,
|
|
353
|
-
planEntries: await findCSSManifestEntryFiles(workspaceDir)
|
|
354
|
-
});
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
async initWorkspaceLanguageService(workspace) {
|
|
358
|
-
workspace.languageRuntime = await this.loadWorkspaceLanguageRuntime(workspace);
|
|
359
|
-
let workspacePlan;
|
|
360
|
-
if (workspace !== this.globalWorkspace) {
|
|
361
|
-
try {
|
|
362
|
-
workspacePlan = await this.loadWorkspacePlan(workspace);
|
|
363
|
-
} catch (e) {
|
|
364
|
-
this.console.info(`Failed to load manifest from ${workspace.uri}`);
|
|
365
|
-
this.console.error(e instanceof Error ? e.stack : e.toString());
|
|
366
|
-
}
|
|
367
|
-
if (workspacePlan) {
|
|
368
|
-
this.console.info(`Initialized workspace ${workspace.planEntries?.length ? '(with manifest entry)' : '(with manifest)'} ${workspace.uri}`);
|
|
369
|
-
} else {
|
|
370
|
-
this.console.info(`Initialized workspace ${workspace.uri}`);
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
workspace.languageService = new CSSLanguageService({
|
|
374
|
-
...workspace.languageServiceSettings,
|
|
375
|
-
manifest: workspacePlan
|
|
376
|
-
}, {
|
|
377
|
-
runtime: workspace.languageRuntime
|
|
378
|
-
});
|
|
379
|
-
}
|
|
380
|
-
async loadWorkspacePlan(workspace) {
|
|
381
|
-
const cwd = workspace.uri ? URI.parse(workspace.uri).fsPath : process.cwd();
|
|
382
|
-
const result = await loadProjectManifest(cwd, {
|
|
383
|
-
baseManifest: (workspace.languageRuntime ?? defaultCSSLanguageRuntime).defaultManifest
|
|
384
|
-
});
|
|
385
|
-
return result.entries.length ? result.manifest : workspace.languageServiceSettings.manifest;
|
|
386
|
-
}
|
|
387
|
-
async loadWorkspaceLanguageRuntime(workspace) {
|
|
388
|
-
if (workspace === this.globalWorkspace || !workspace.uri) {
|
|
389
|
-
workspace.languageRuntimeSource = 'bundled';
|
|
390
|
-
return defaultCSSLanguageRuntime;
|
|
391
|
-
}
|
|
392
|
-
const cwd = URI.parse(workspace.uri).fsPath;
|
|
393
|
-
let resolution;
|
|
394
|
-
try {
|
|
395
|
-
resolution = resolveMasterCSSWorkspacePackages(cwd);
|
|
396
|
-
workspace.languageRuntimeResolution = resolution;
|
|
397
|
-
const missingPackages = [
|
|
398
|
-
!resolution.css && '@master/css',
|
|
399
|
-
!resolution.engine && '@master/css-engine',
|
|
400
|
-
!resolution.presetManifest && '@master/css-preset/default-manifest.json'
|
|
401
|
-
].filter(Boolean);
|
|
402
|
-
if (missingPackages.length) {
|
|
403
|
-
throw new Error(`Missing workspace package(s): ${missingPackages.join(', ')}`);
|
|
404
|
-
}
|
|
405
|
-
const cssPackage = resolution.css;
|
|
406
|
-
const enginePackage = resolution.engine;
|
|
407
|
-
const presetManifestPackage = resolution.presetManifest;
|
|
408
|
-
if (!cssPackage || !enginePackage || !presetManifestPackage) {
|
|
409
|
-
throw new Error('Missing required workspace Master CSS runtime packages.');
|
|
410
|
-
}
|
|
411
|
-
const [cssModule, engineModule, utilityTypeModule] = await Promise.all([
|
|
412
|
-
this.importWorkspaceModule(cssPackage.entry),
|
|
413
|
-
this.importWorkspaceModule(enginePackage.entry),
|
|
414
|
-
resolution.utilityType ? this.importWorkspaceModule(resolution.utilityType.entry) : undefined
|
|
415
|
-
]);
|
|
416
|
-
const MasterCSS = cssModule.MasterCSS || cssModule.default;
|
|
417
|
-
const builtinKeyAliases = engineModule.builtinKeyAliases;
|
|
418
|
-
const builtinNativeValueNamespaces = engineModule.builtinNativeValueNamespaces;
|
|
419
|
-
if (!MasterCSS) throw new Error(`Missing MasterCSS export from ${cssPackage.entry}`);
|
|
420
|
-
if (!builtinKeyAliases) throw new Error(`Missing builtinKeyAliases export from ${enginePackage.entry}`);
|
|
421
|
-
if (!builtinNativeValueNamespaces) throw new Error(`Missing builtinNativeValueNamespaces export from ${enginePackage.entry}`);
|
|
422
|
-
const manifest = JSON.parse(await readFile(presetManifestPackage.entry, 'utf8'));
|
|
423
|
-
workspace.languageRuntimeSource = 'workspace';
|
|
424
|
-
this.console.info(`Using workspace Master CSS runtime ${cssPackage.version ?? '(unknown version)'} from ${cssPackage.directory}`);
|
|
425
|
-
if (resolution.errors.length) {
|
|
426
|
-
this.console.info(`Workspace Master CSS runtime optional resolution warnings: ${resolution.errors.map(({ name, message })=>`${name}: ${message}`).join('; ')}`);
|
|
427
|
-
}
|
|
428
|
-
return {
|
|
429
|
-
MasterCSS,
|
|
430
|
-
UtilityType: utilityTypeModule?.UtilityType || utilityTypeModule?.default || defaultCSSLanguageRuntime.UtilityType,
|
|
431
|
-
defaultManifest: manifest,
|
|
432
|
-
builtinKeyAliases,
|
|
433
|
-
builtinNativeValueNamespaces,
|
|
434
|
-
nativeDeclarationMatcher: matchesLanguageServiceNativeDeclaration
|
|
435
|
-
};
|
|
436
|
-
} catch (error) {
|
|
437
|
-
workspace.languageRuntimeSource = 'bundled';
|
|
438
|
-
this.console.info(`Using bundled Master CSS runtime for ${workspace.uri}`);
|
|
439
|
-
if (resolution?.errors.length) {
|
|
440
|
-
this.console.info(`Workspace Master CSS package resolution errors: ${resolution.errors.map(({ name, message })=>`${name}: ${message}`).join('; ')}`);
|
|
441
|
-
}
|
|
442
|
-
this.console.error(error instanceof Error ? error.stack || error.message : String(error));
|
|
443
|
-
return defaultCSSLanguageRuntime;
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
|
-
async importWorkspaceModule(path) {
|
|
447
|
-
return await import(pathToFileURL(path).href);
|
|
448
|
-
}
|
|
449
|
-
destroyLanguageService(workspace) {
|
|
450
|
-
this.console.info(`Destroyed workspace ${workspace.uri}`);
|
|
451
|
-
delete workspace.languageService;
|
|
452
|
-
}
|
|
453
|
-
findClosestWorkspace(textDocumentURI) {
|
|
454
|
-
const documentPath = toComparableFilePath(textDocumentURI);
|
|
455
|
-
if (!documentPath) {
|
|
456
|
-
this.console.info(`This is an external document ${textDocumentURI} with the global workspace`);
|
|
457
|
-
return this.globalWorkspace;
|
|
458
|
-
}
|
|
459
|
-
let foundWorkspace;
|
|
460
|
-
let foundWorkspacePath = '';
|
|
461
|
-
for (const [uri, workspace] of this.workspaces){
|
|
462
|
-
if (!uri) continue;
|
|
463
|
-
const workspacePath = toComparableFilePath(uri);
|
|
464
|
-
if (!workspacePath) continue;
|
|
465
|
-
if (containsFilePath(workspacePath, documentPath) && workspacePath.length > foundWorkspacePath.length) {
|
|
466
|
-
foundWorkspace = workspace;
|
|
467
|
-
foundWorkspacePath = workspacePath;
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
if (foundWorkspace) return foundWorkspace;
|
|
471
|
-
this.console.info(`This is an external document ${textDocumentURI} with the global workspace`);
|
|
472
|
-
return this.globalWorkspace;
|
|
473
|
-
}
|
|
474
|
-
publishCSSDirectiveDiagnostics(textDocument, workspace) {
|
|
475
|
-
if (!isCSSDiagnosticDocument(textDocument)) return;
|
|
476
|
-
const diagnostics = [];
|
|
477
|
-
const documentFile = path.resolve(URI.parse(textDocument.uri).fsPath);
|
|
478
|
-
for (const { source, offset } of getCSSDiagnosticSources(textDocument)){
|
|
479
|
-
try {
|
|
480
|
-
compileCSSManifest(source, {
|
|
481
|
-
from: documentFile,
|
|
482
|
-
baseManifest: (workspace.languageRuntime ?? defaultCSSLanguageRuntime).defaultManifest
|
|
483
|
-
});
|
|
484
|
-
} catch (error) {
|
|
485
|
-
if (!isCSSDirectiveError(error)) continue;
|
|
486
|
-
const diagnostic = this.createCSSDirectiveDiagnostic(error, textDocument, documentFile, offset);
|
|
487
|
-
if (diagnostic) diagnostics.push(diagnostic);
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
this.connection.sendDiagnostics({
|
|
491
|
-
uri: textDocument.uri,
|
|
492
|
-
diagnostics
|
|
493
|
-
});
|
|
494
|
-
}
|
|
495
|
-
createCSSDirectiveDiagnostic(error, textDocument, documentFile, sourceOffset) {
|
|
496
|
-
if (error.source?.file && path.resolve(error.source.file) !== documentFile) return;
|
|
497
|
-
return {
|
|
498
|
-
range: this.createCSSDirectiveRange(error.source, textDocument, documentFile, sourceOffset),
|
|
499
|
-
severity: DiagnosticSeverity.Error,
|
|
500
|
-
code: error.code,
|
|
501
|
-
source: 'Master CSS',
|
|
502
|
-
message: error.message,
|
|
503
|
-
relatedInformation: this.createCSSDirectiveRelatedInformation(error.related, textDocument, documentFile, sourceOffset)
|
|
504
|
-
};
|
|
505
|
-
}
|
|
506
|
-
createCSSDirectiveRelatedInformation(related, textDocument, documentFile, sourceOffset) {
|
|
507
|
-
if (!related?.length) return;
|
|
508
|
-
return related.map(({ message, source })=>({
|
|
509
|
-
message,
|
|
510
|
-
location: {
|
|
511
|
-
uri: source?.file ? URI.file(source.file).toString() : textDocument.uri,
|
|
512
|
-
range: this.createCSSDirectiveRange(source, textDocument, documentFile, sourceOffset)
|
|
513
|
-
}
|
|
514
|
-
}));
|
|
515
|
-
}
|
|
516
|
-
createCSSDirectiveRange(source, textDocument, documentFile, sourceOffset) {
|
|
517
|
-
if (source?.file && path.resolve(source.file) !== documentFile) {
|
|
518
|
-
return source.loc ? {
|
|
519
|
-
start: {
|
|
520
|
-
line: Math.max(0, source.loc.start.line - 1),
|
|
521
|
-
character: Math.max(0, source.loc.start.column - 1)
|
|
522
|
-
},
|
|
523
|
-
end: {
|
|
524
|
-
line: Math.max(0, source.loc.end.line - 1),
|
|
525
|
-
character: Math.max(0, source.loc.end.column - 1)
|
|
526
|
-
}
|
|
527
|
-
} : {
|
|
528
|
-
start: {
|
|
529
|
-
line: 0,
|
|
530
|
-
character: 0
|
|
531
|
-
},
|
|
532
|
-
end: {
|
|
533
|
-
line: 0,
|
|
534
|
-
character: 0
|
|
535
|
-
}
|
|
536
|
-
};
|
|
537
|
-
}
|
|
538
|
-
const start = Math.max(0, (source?.range.start || 0) + sourceOffset);
|
|
539
|
-
const end = Math.max(start, (source?.range.end || 0) + sourceOffset);
|
|
540
|
-
return {
|
|
541
|
-
start: textDocument.positionAt(start),
|
|
542
|
-
end: textDocument.positionAt(end)
|
|
543
|
-
};
|
|
544
|
-
}
|
|
545
|
-
refreshSemanticTokens() {
|
|
546
|
-
if (this.settings?.embeddedSyntaxHighlighting !== 'always') return;
|
|
547
|
-
if (!this.clientCapabilities.workspace?.semanticTokens?.refreshSupport) return;
|
|
548
|
-
this.connection.languages.semanticTokens.refresh();
|
|
549
|
-
}
|
|
550
|
-
stop() {
|
|
551
|
-
this.connection.sendNotification('masterCSS/dispose');
|
|
552
|
-
this.disposables.forEach((disposable)=>disposable.dispose());
|
|
553
|
-
this.disposables.length = 0;
|
|
554
|
-
this.connection.dispose();
|
|
555
|
-
this.initializing = undefined;
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
export { ACTIVE_SEMANTIC_TOKENS_REQUEST, DOCUMENT_SEMANTIC_TOKENS_REQUEST, CSSLanguageServer as default };
|
package/dist/index.mjs
DELETED
package/dist/server.mjs
DELETED
package/dist/settings.mjs
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
2
|
-
import { nanoid } from 'nanoid';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import { URI } from 'vscode-uri';
|
|
5
|
-
|
|
6
|
-
const extOfLang = {
|
|
7
|
-
typescript: 'ts',
|
|
8
|
-
typescriptreact: 'tsx',
|
|
9
|
-
javascript: 'js',
|
|
10
|
-
javascriptreact: 'jsx',
|
|
11
|
-
css: 'css',
|
|
12
|
-
scss: 'scss',
|
|
13
|
-
less: 'less',
|
|
14
|
-
html: 'html',
|
|
15
|
-
json: 'json',
|
|
16
|
-
vue: 'vue',
|
|
17
|
-
svelte: 'svelte',
|
|
18
|
-
astro: 'astro'
|
|
19
|
-
};
|
|
20
|
-
function createDocument(text, options) {
|
|
21
|
-
const lang = options?.lang || 'html';
|
|
22
|
-
const dir = options?.dir || './';
|
|
23
|
-
const filePath = path.join(dir, `${nanoid()}.${extOfLang[lang]}`);
|
|
24
|
-
const fileURI = URI.file(filePath).toString();
|
|
25
|
-
return TextDocument.create(fileURI, lang, 0, text);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export { createDocument as default };
|