@master/css-language-server 2.0.0-rc.69 → 2.0.0-rc.70
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/README.md +45 -6
- package/dist/core.d.ts +21 -10
- package/dist/core.mjs +300 -39
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/core.cjs +0 -227
- package/dist/index.cjs +0 -12
- package/dist/settings.cjs +0 -11
- package/dist/utils/create-document.cjs +0 -30
package/README.md
CHANGED
|
@@ -48,16 +48,55 @@
|
|
|
48
48
|
<img alt="Follow @mastercorg" src="https://img.shields.io/static/v1?label=%20&message=twitter&color=f6f7f8&logo=twitter&style=for-the-badge">
|
|
49
49
|
</picture>
|
|
50
50
|
</a>
|
|
51
|
-
<a aria-label="Github Actions" href="https://github.com/master-co/css/actions/workflows/release.yml">
|
|
51
|
+
<a aria-label="Github Actions" href="https://github.com/master-co/css/actions/workflows/ci-release.yml">
|
|
52
52
|
<picture>
|
|
53
|
-
<source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/github/actions/workflow/status/master-co/css/release.yml?branch=rc&label=%20&message=twitter&color=212022&logo=githubactions&style=for-the-badge">
|
|
54
|
-
<source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/github/actions/workflow/status/master-co/css/release.yml?branch=rc&label=%20&message=twitter&color=f6f7f8&logo=githubactions&style=for-the-badge&logoColor=%23000">
|
|
55
|
-
<img alt="Github release actions" src="https://img.shields.io/github/actions/workflow/status/master-co/css/release.yml?branch=rc&label=%20&message=twitter&color=f6f7f8&logo=githubactions&style=for-the-badge&logoColor=%23000">
|
|
53
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://img.shields.io/github/actions/workflow/status/master-co/css/ci-release.yml?branch=rc&label=%20&message=twitter&color=212022&logo=githubactions&style=for-the-badge">
|
|
54
|
+
<source media="(prefers-color-scheme: light)" srcset="https://img.shields.io/github/actions/workflow/status/master-co/css/ci-release.yml?branch=rc&label=%20&message=twitter&color=f6f7f8&logo=githubactions&style=for-the-badge&logoColor=%23000">
|
|
55
|
+
<img alt="Github release actions" src="https://img.shields.io/github/actions/workflow/status/master-co/css/ci-release.yml?branch=rc&label=%20&message=twitter&color=f6f7f8&logo=githubactions&style=for-the-badge&logoColor=%23000">
|
|
56
56
|
</picture>
|
|
57
57
|
</a>
|
|
58
58
|
</p>
|
|
59
59
|
|
|
60
60
|
</div>
|
|
61
61
|
|
|
62
|
-
##
|
|
63
|
-
|
|
62
|
+
## Installation
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
npm install @master/css-language-server
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Usage
|
|
69
|
+
|
|
70
|
+
```js
|
|
71
|
+
import CSSLanguageServer from '@master/css-language-server'
|
|
72
|
+
|
|
73
|
+
const languageServer = new CSSLanguageServer(connection, customSettings)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
`CSSLanguageServer` wraps `@master/css-language-service` with LSP workspace lifecycle, completion, hover, document color, color presentation, and semantic token handlers.
|
|
77
|
+
|
|
78
|
+
## Semantic tokens
|
|
79
|
+
|
|
80
|
+
The language server supports full-document and active-position semantic tokens.
|
|
81
|
+
|
|
82
|
+
| `embeddedSyntaxHighlighting` | Behavior |
|
|
83
|
+
| --- | --- |
|
|
84
|
+
| `always` | Advertises the standard LSP `semanticTokensProvider` and handles `textDocument/semanticTokens/full`. |
|
|
85
|
+
| `active` | Uses the VS Code extension request for active class-context highlighting. |
|
|
86
|
+
| `off` | Disables embedded utility highlighting. |
|
|
87
|
+
|
|
88
|
+
CSS directive syntax is highlighted by the shared TextMate grammar. Server semantic tokens cover Master CSS class-list spans and directive class-list spans such as `@compose` and `@safelist`.
|
|
89
|
+
|
|
90
|
+
## Settings
|
|
91
|
+
|
|
92
|
+
```js
|
|
93
|
+
import { settings } from '@master/css-language-server'
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
| Setting | Type | Default | Description |
|
|
97
|
+
| --- | --- | --- | --- |
|
|
98
|
+
| `workspaces` | `FastGlobPattern[] \| 'auto'` | `'auto'` | Workspace roots where independent language services are created. The root workspace is always included. |
|
|
99
|
+
| `verbose` | `boolean` | `false` | Print server logs. |
|
|
100
|
+
| `embeddedSyntaxHighlighting` | `'active' \| 'always' \| 'off'` | `'active'` | Inherited language-service semantic token mode. |
|
|
101
|
+
|
|
102
|
+
With `workspaces: 'auto'`, the server creates workspaces from CSS files containing `@master;` or `@import '@master/css'`, and from `package.json` files that declare Master CSS package dependencies.
|
package/dist/core.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TextDocuments, InitializeParams, WorkspaceFolder, Connection, ClientCapabilities, TextDocumentChangeEvent, DidChangeConfigurationParams, HoverParams, CompletionParams, DocumentColorParams, ColorPresentationParams, RemoteConsole } from 'vscode-languageserver/node';
|
|
1
|
+
import { TextDocuments, InitializeParams, InitializeResult, WorkspaceFolder, Connection, ClientCapabilities, TextDocumentChangeEvent, DidChangeConfigurationParams, HoverParams, CompletionParams, DocumentColorParams, ColorPresentationParams, RemoteConsole, SemanticTokensParams, TextDocumentPositionParams } from 'vscode-languageserver/node';
|
|
2
2
|
import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
3
3
|
import CSSLanguageService, { Settings as CSSLanguageServiceSettings } from '@master/css-language-service';
|
|
4
4
|
import { Settings } from './settings';
|
|
@@ -7,7 +7,10 @@ export declare interface Workspace {
|
|
|
7
7
|
openedTextDocuments: TextDocument[];
|
|
8
8
|
languageService?: CSSLanguageService;
|
|
9
9
|
languageServiceSettings: CSSLanguageServiceSettings;
|
|
10
|
+
planEntries?: string[];
|
|
10
11
|
}
|
|
12
|
+
export declare const ACTIVE_SEMANTIC_TOKENS_REQUEST = "masterCSS/renderActiveSemanticTokens";
|
|
13
|
+
export declare const DOCUMENT_SEMANTIC_TOKENS_REQUEST = "masterCSS/renderDocumentSemanticTokens";
|
|
11
14
|
export default class CSSLanguageServer {
|
|
12
15
|
connection: Connection;
|
|
13
16
|
customSettings?: Settings | undefined;
|
|
@@ -23,20 +26,28 @@ export default class CSSLanguageServer {
|
|
|
23
26
|
constructor(connection?: Connection, customSettings?: Settings | undefined);
|
|
24
27
|
start(): void;
|
|
25
28
|
init(): Promise<void>;
|
|
26
|
-
onInitialize(params: InitializeParams):
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
29
|
+
onInitialize(params: InitializeParams): InitializeResult;
|
|
30
|
+
onHover(params: HoverParams): Promise<import("vscode-languageserver-protocol").Hover | undefined>;
|
|
31
|
+
onCompletion(params: CompletionParams): Promise<import("vscode-languageserver-protocol").CompletionItem[] | undefined>;
|
|
32
|
+
onDocumentColor(params: DocumentColorParams): Promise<import("vscode-languageserver-protocol").ColorInformation[]>;
|
|
33
|
+
onColorPresentation(params: ColorPresentationParams): Promise<import("vscode-languageserver-protocol").ColorPresentation[]>;
|
|
34
|
+
onSemanticTokens(params: SemanticTokensParams): Promise<import("vscode-languageserver-protocol").SemanticTokens>;
|
|
35
|
+
onDocumentSemanticTokens(params: SemanticTokensParams): Promise<import("vscode-languageserver-protocol").SemanticTokens>;
|
|
36
|
+
onActiveSemanticTokens(params: TextDocumentPositionParams): Promise<import("vscode-languageserver-protocol").SemanticTokens>;
|
|
33
37
|
onDidOpen(params: TextDocumentChangeEvent<TextDocument>): Promise<void>;
|
|
38
|
+
onDidChangeContent(params: TextDocumentChangeEvent<TextDocument>): Promise<void>;
|
|
34
39
|
onDidClose(params: TextDocumentChangeEvent<TextDocument>): Promise<void>;
|
|
35
40
|
onDidSave(params: TextDocumentChangeEvent<TextDocument>): Promise<void>;
|
|
36
|
-
onDidChangeConfiguration({ settings }: DidChangeConfigurationParams): Promise<void>;
|
|
41
|
+
onDidChangeConfiguration({ settings: changedSettings }: DidChangeConfigurationParams): Promise<void>;
|
|
37
42
|
private initWorkspaceFolder;
|
|
38
|
-
initWorkspaceLanguageService(workspace: Workspace): void
|
|
43
|
+
initWorkspaceLanguageService(workspace: Workspace): Promise<void>;
|
|
44
|
+
private loadWorkspacePlan;
|
|
39
45
|
destroyLanguageService(workspace: Workspace): void;
|
|
40
46
|
findClosestWorkspace(textDocumentURI: string): Workspace;
|
|
47
|
+
private publishCSSDirectiveDiagnostics;
|
|
48
|
+
private createCSSDirectiveDiagnostic;
|
|
49
|
+
private createCSSDirectiveRelatedInformation;
|
|
50
|
+
private createCSSDirectiveRange;
|
|
51
|
+
private refreshSemanticTokens;
|
|
41
52
|
stop(): void;
|
|
42
53
|
}
|
package/dist/core.mjs
CHANGED
|
@@ -1,13 +1,120 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TextDocumentSyncKind, TextDocuments, createConnection, DiagnosticSeverity } from 'vscode-languageserver/node';
|
|
2
2
|
import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
3
3
|
import path from 'node:path';
|
|
4
|
-
import CSSLanguageService
|
|
5
|
-
import
|
|
4
|
+
import CSSLanguageService from '@master/css-language-service';
|
|
5
|
+
import { compileCSSManifest } from '@master/css-compiler';
|
|
6
|
+
import { findMasterCSSWorkspaceDirectories, findCSSManifestEntryFiles } from '@master/css-project/entries';
|
|
7
|
+
import { loadProjectManifest } from '@master/css-project/manifest';
|
|
6
8
|
import extend from '@techor/extend';
|
|
7
9
|
import settings from './settings.mjs';
|
|
10
|
+
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';
|
|
11
|
+
import { SEMANTIC_TOKENS_LEGEND } from '@master/css-language';
|
|
8
12
|
import glob from 'fast-glob';
|
|
9
13
|
import { URI } from 'vscode-uri';
|
|
14
|
+
import { CSSDirectiveError } from '@master/css-schema/css-directives';
|
|
10
15
|
|
|
16
|
+
const ACTIVE_SEMANTIC_TOKENS_REQUEST = 'masterCSS/renderActiveSemanticTokens';
|
|
17
|
+
const DOCUMENT_SEMANTIC_TOKENS_REQUEST = 'masterCSS/renderDocumentSemanticTokens';
|
|
18
|
+
const SERVER_CAPABILITIES = {
|
|
19
|
+
textDocumentSync: TextDocumentSyncKind.Incremental,
|
|
20
|
+
completionProvider: {
|
|
21
|
+
resolveProvider: false,
|
|
22
|
+
workDoneProgress: false,
|
|
23
|
+
triggerCharacters: [
|
|
24
|
+
...new Set([
|
|
25
|
+
...INVOKED_TRIGGER_CHARACTERS,
|
|
26
|
+
...VALUE_TRIGGER_CHARACTERS,
|
|
27
|
+
...SELECTOR_TRIGGER_CHARACTERS,
|
|
28
|
+
...QUERY_TRIGGER_CHARACTERS,
|
|
29
|
+
DECLARATION_SEPARATOR_TRIGGER_CHARACTER,
|
|
30
|
+
AT_TRIGGER_CHARACTER,
|
|
31
|
+
GROUP_TRIGGER_CHARACTER
|
|
32
|
+
])
|
|
33
|
+
]
|
|
34
|
+
},
|
|
35
|
+
colorProvider: true,
|
|
36
|
+
hoverProvider: true,
|
|
37
|
+
semanticTokensProvider: {
|
|
38
|
+
legend: SEMANTIC_TOKENS_LEGEND,
|
|
39
|
+
full: true
|
|
40
|
+
},
|
|
41
|
+
workspace: {
|
|
42
|
+
workspaceFolders: {
|
|
43
|
+
supported: true
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const CSS_DIAGNOSTIC_LANGUAGE_IDS = new Set([
|
|
48
|
+
'css',
|
|
49
|
+
'scss',
|
|
50
|
+
'less'
|
|
51
|
+
]);
|
|
52
|
+
const SFC_DIAGNOSTIC_LANGUAGE_IDS = new Set([
|
|
53
|
+
'vue',
|
|
54
|
+
'svelte',
|
|
55
|
+
'astro'
|
|
56
|
+
]);
|
|
57
|
+
const STYLE_BLOCK_RE = /<style\b([^>]*)>([\s\S]*?)<\/style>/gi;
|
|
58
|
+
function isCSSDiagnosticDocument(textDocument) {
|
|
59
|
+
return CSS_DIAGNOSTIC_LANGUAGE_IDS.has(textDocument.languageId) || SFC_DIAGNOSTIC_LANGUAGE_IDS.has(textDocument.languageId);
|
|
60
|
+
}
|
|
61
|
+
function getSFCStyleLanguage(attributes) {
|
|
62
|
+
const match = /\blang\s*=\s*(?:"([^"]+)"|'([^']+)'|([^\s>]+))/i.exec(attributes);
|
|
63
|
+
return (match?.[1] || match?.[2] || match?.[3] || 'css').toLowerCase();
|
|
64
|
+
}
|
|
65
|
+
function getCSSDiagnosticSources(textDocument) {
|
|
66
|
+
const text = textDocument.getText();
|
|
67
|
+
if (CSS_DIAGNOSTIC_LANGUAGE_IDS.has(textDocument.languageId)) {
|
|
68
|
+
return [
|
|
69
|
+
{
|
|
70
|
+
source: text,
|
|
71
|
+
offset: 0
|
|
72
|
+
}
|
|
73
|
+
];
|
|
74
|
+
}
|
|
75
|
+
if (!SFC_DIAGNOSTIC_LANGUAGE_IDS.has(textDocument.languageId)) return [];
|
|
76
|
+
const sources = [];
|
|
77
|
+
STYLE_BLOCK_RE.lastIndex = 0;
|
|
78
|
+
for (const match of text.matchAll(STYLE_BLOCK_RE)){
|
|
79
|
+
const styleLanguage = getSFCStyleLanguage(match[1]);
|
|
80
|
+
if (!CSS_DIAGNOSTIC_LANGUAGE_IDS.has(styleLanguage)) continue;
|
|
81
|
+
const source = match[2];
|
|
82
|
+
const offset = (match.index || 0) + match[0].indexOf(source);
|
|
83
|
+
sources.push({
|
|
84
|
+
source,
|
|
85
|
+
offset
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return sources;
|
|
89
|
+
}
|
|
90
|
+
function isCSSDirectiveError(error) {
|
|
91
|
+
return error instanceof CSSDirectiveError || !!error && typeof error === 'object' && error.name === 'CSSDirectiveError' && typeof error.code === 'string';
|
|
92
|
+
}
|
|
93
|
+
function getInitializationSettings(initializationOptions) {
|
|
94
|
+
if (!initializationOptions || typeof initializationOptions !== 'object') return;
|
|
95
|
+
const options = initializationOptions;
|
|
96
|
+
return options.masterCSS ?? options;
|
|
97
|
+
}
|
|
98
|
+
function isWindowsFilePath(fsPath) {
|
|
99
|
+
return /^[a-z]:[\\/]/i.test(fsPath) || fsPath.startsWith('\\\\') || fsPath.startsWith('//');
|
|
100
|
+
}
|
|
101
|
+
function getFilePathTools(...fsPaths) {
|
|
102
|
+
return fsPaths.some(isWindowsFilePath) ? path.win32 : path;
|
|
103
|
+
}
|
|
104
|
+
function toComparableFilePath(uri) {
|
|
105
|
+
const parsedURI = URI.parse(uri);
|
|
106
|
+
if (parsedURI.scheme !== 'file') return;
|
|
107
|
+
const fsPath = parsedURI.fsPath;
|
|
108
|
+
if (!fsPath) return;
|
|
109
|
+
const filePathTools = getFilePathTools(fsPath);
|
|
110
|
+
const resolvedPath = filePathTools.resolve(fsPath);
|
|
111
|
+
return isWindowsFilePath(resolvedPath) ? resolvedPath.toLowerCase() : resolvedPath;
|
|
112
|
+
}
|
|
113
|
+
function containsFilePath(parentPath, childPath) {
|
|
114
|
+
const filePathTools = getFilePathTools(parentPath, childPath);
|
|
115
|
+
const relativePath = filePathTools.relative(parentPath, childPath);
|
|
116
|
+
return relativePath === '' || !!relativePath && relativePath !== '..' && !relativePath.startsWith(`..${filePathTools.sep}`) && !filePathTools.isAbsolute(relativePath);
|
|
117
|
+
}
|
|
11
118
|
class CSSLanguageServer {
|
|
12
119
|
connection;
|
|
13
120
|
customSettings;
|
|
@@ -29,6 +136,7 @@ class CSSLanguageServer {
|
|
|
29
136
|
this.customSettings = customSettings;
|
|
30
137
|
this.documents = new TextDocuments(TextDocument);
|
|
31
138
|
this.settings = extend(settings, this.customSettings);
|
|
139
|
+
this.globalWorkspace.languageServiceSettings = this.settings;
|
|
32
140
|
this.console = new Proxy(this.connection.console, {
|
|
33
141
|
get: (target, prop)=>{
|
|
34
142
|
if (!this.settings?.verbose) return ()=>{};
|
|
@@ -37,7 +145,7 @@ class CSSLanguageServer {
|
|
|
37
145
|
});
|
|
38
146
|
}
|
|
39
147
|
start() {
|
|
40
|
-
this.disposables.push(this.documents.onDidSave(this.onDidSave.bind(this)), this.documents.onDidOpen(this.onDidOpen.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.onInitialize(this.onInitialize.bind(this)), this.connection.onInitialized(()=>this.init()));
|
|
148
|
+
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()));
|
|
41
149
|
this.connection.listen();
|
|
42
150
|
}
|
|
43
151
|
init() {
|
|
@@ -49,11 +157,23 @@ class CSSLanguageServer {
|
|
|
49
157
|
}
|
|
50
158
|
onInitialize(params) {
|
|
51
159
|
this.clientCapabilities = params.capabilities;
|
|
160
|
+
const initializationSettings = getInitializationSettings(params.initializationOptions);
|
|
161
|
+
if (initializationSettings) {
|
|
162
|
+
this.customSettings = extend(this.customSettings, initializationSettings);
|
|
163
|
+
this.settings = extend(settings, this.customSettings);
|
|
164
|
+
this.globalWorkspace.languageServiceSettings = this.settings;
|
|
165
|
+
}
|
|
52
166
|
if (params.workspaceFolders?.length) {
|
|
53
167
|
this.workspaceFolders = params.workspaceFolders;
|
|
54
168
|
}
|
|
169
|
+
const capabilities = {
|
|
170
|
+
...SERVER_CAPABILITIES
|
|
171
|
+
};
|
|
172
|
+
if (this.settings?.embeddedSyntaxHighlighting !== 'always') {
|
|
173
|
+
delete capabilities.semanticTokensProvider;
|
|
174
|
+
}
|
|
55
175
|
return {
|
|
56
|
-
capabilities
|
|
176
|
+
capabilities
|
|
57
177
|
};
|
|
58
178
|
}
|
|
59
179
|
async onHover(params) {
|
|
@@ -77,31 +197,77 @@ class CSSLanguageServer {
|
|
|
77
197
|
const workspace = this.findClosestWorkspace(params.textDocument.uri);
|
|
78
198
|
if (workspace?.languageService) {
|
|
79
199
|
const document = this.documents.get(params.textDocument.uri);
|
|
80
|
-
if (document) return workspace.languageService.renderSyntaxColors(document);
|
|
200
|
+
if (document) return await workspace.languageService.renderSyntaxColors(document) ?? [];
|
|
81
201
|
}
|
|
202
|
+
return [];
|
|
82
203
|
}
|
|
83
204
|
async onColorPresentation(params) {
|
|
84
205
|
await this.init();
|
|
85
206
|
const workspace = this.findClosestWorkspace(params.textDocument.uri);
|
|
86
207
|
if (workspace?.languageService) {
|
|
87
208
|
const document = this.documents.get(params.textDocument.uri);
|
|
88
|
-
if (document) return workspace.languageService.editSyntaxColors(document, params.color, params.range);
|
|
209
|
+
if (document) return workspace.languageService.editSyntaxColors(document, params.color, params.range) ?? [];
|
|
89
210
|
}
|
|
211
|
+
return [];
|
|
212
|
+
}
|
|
213
|
+
async onSemanticTokens(params) {
|
|
214
|
+
await this.init();
|
|
215
|
+
const workspace = this.findClosestWorkspace(params.textDocument.uri);
|
|
216
|
+
if (workspace?.languageService) {
|
|
217
|
+
const document = this.documents.get(params.textDocument.uri) ?? workspace.openedTextDocuments.find((document)=>document.uri === params.textDocument.uri);
|
|
218
|
+
if (document) return workspace.languageService.renderSemanticTokens(document) ?? {
|
|
219
|
+
data: []
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
data: []
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
async onDocumentSemanticTokens(params) {
|
|
227
|
+
return this.onSemanticTokens(params);
|
|
228
|
+
}
|
|
229
|
+
async onActiveSemanticTokens(params) {
|
|
230
|
+
await this.init();
|
|
231
|
+
const workspace = this.findClosestWorkspace(params.textDocument.uri);
|
|
232
|
+
if (workspace?.languageService) {
|
|
233
|
+
const document = this.documents.get(params.textDocument.uri) ?? workspace.openedTextDocuments.find((document)=>document.uri === params.textDocument.uri);
|
|
234
|
+
if (document) return workspace.languageService.renderSemanticTokensAtPosition(document, params.position) ?? {
|
|
235
|
+
data: []
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
return {
|
|
239
|
+
data: []
|
|
240
|
+
};
|
|
90
241
|
}
|
|
91
242
|
async onDidOpen(params) {
|
|
92
243
|
await this.init();
|
|
93
244
|
const workspace = this.findClosestWorkspace(params.document.uri);
|
|
94
|
-
if (!workspace
|
|
245
|
+
if (!workspace) return;
|
|
246
|
+
if (workspace.openedTextDocuments.includes(params.document)) {
|
|
247
|
+
this.publishCSSDirectiveDiagnostics(params.document, workspace);
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
95
250
|
if (!workspace.openedTextDocuments.length) {
|
|
96
|
-
this.initWorkspaceLanguageService(workspace);
|
|
251
|
+
await this.initWorkspaceLanguageService(workspace);
|
|
97
252
|
}
|
|
98
253
|
workspace.openedTextDocuments.push(params.document);
|
|
254
|
+
this.publishCSSDirectiveDiagnostics(params.document, workspace);
|
|
255
|
+
}
|
|
256
|
+
async onDidChangeContent(params) {
|
|
257
|
+
await this.init();
|
|
258
|
+
const workspace = this.findClosestWorkspace(params.document.uri);
|
|
259
|
+
if (!workspace) return;
|
|
260
|
+
this.publishCSSDirectiveDiagnostics(params.document, workspace);
|
|
99
261
|
}
|
|
100
262
|
async onDidClose(params) {
|
|
101
263
|
await this.init();
|
|
102
264
|
const workspace = this.findClosestWorkspace(params.document.uri);
|
|
103
265
|
if (!workspace) return;
|
|
104
266
|
workspace.openedTextDocuments.splice(workspace.openedTextDocuments.indexOf(params.document), 1);
|
|
267
|
+
this.connection.sendDiagnostics({
|
|
268
|
+
uri: params.document.uri,
|
|
269
|
+
diagnostics: []
|
|
270
|
+
});
|
|
105
271
|
if (!workspace.openedTextDocuments.length) {
|
|
106
272
|
this.destroyLanguageService(workspace);
|
|
107
273
|
}
|
|
@@ -110,21 +276,34 @@ class CSSLanguageServer {
|
|
|
110
276
|
await this.init();
|
|
111
277
|
const workspace = this.findClosestWorkspace(params.document.uri);
|
|
112
278
|
if (!workspace) return;
|
|
113
|
-
|
|
114
|
-
|
|
279
|
+
this.publishCSSDirectiveDiagnostics(params.document, workspace);
|
|
280
|
+
const name = path.basename(URI.parse(params.document.uri).fsPath);
|
|
281
|
+
if (name.endsWith('.css')) {
|
|
282
|
+
this.refreshSemanticTokens();
|
|
115
283
|
this.connection.sendRequest('masterCSS/restart', {
|
|
116
284
|
title: 'Updating Master CSS configuration'
|
|
117
285
|
});
|
|
118
286
|
}
|
|
119
287
|
}
|
|
120
|
-
async onDidChangeConfiguration({ settings }) {
|
|
288
|
+
async onDidChangeConfiguration({ settings: changedSettings }) {
|
|
121
289
|
await this.init();
|
|
122
|
-
if (
|
|
123
|
-
this.connection.sendNotification('masterCSS/globalSettingsChanged',
|
|
124
|
-
this.customSettings =
|
|
290
|
+
if (changedSettings?.masterCSS) {
|
|
291
|
+
this.connection.sendNotification('masterCSS/globalSettingsChanged', changedSettings.masterCSS);
|
|
292
|
+
this.customSettings = changedSettings.masterCSS;
|
|
293
|
+
this.settings = extend(settings, this.customSettings);
|
|
294
|
+
this.globalWorkspace.languageServiceSettings = this.settings;
|
|
295
|
+
this.refreshSemanticTokens();
|
|
125
296
|
this.connection.sendRequest('masterCSS/restart', {
|
|
126
297
|
title: 'Updating Master CSS settings'
|
|
127
298
|
});
|
|
299
|
+
for (const workspace of [
|
|
300
|
+
this.globalWorkspace,
|
|
301
|
+
...this.workspaces.values()
|
|
302
|
+
]){
|
|
303
|
+
for (const document of workspace.openedTextDocuments){
|
|
304
|
+
this.publishCSSDirectiveDiagnostics(document, workspace);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
128
307
|
}
|
|
129
308
|
}
|
|
130
309
|
async initWorkspaceFolder(workspaceFolderURI) {
|
|
@@ -146,14 +325,9 @@ class CSSLanguageServer {
|
|
|
146
325
|
this.console.info(`Registered global workspace folder`);
|
|
147
326
|
}
|
|
148
327
|
if (workspaces === 'auto') {
|
|
149
|
-
(await
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
onlyFiles: true,
|
|
153
|
-
ignore: [
|
|
154
|
-
'**/node_modules/**'
|
|
155
|
-
]
|
|
156
|
-
})).forEach((workspaceFile)=>resolvedWorkspaceDirectories.add(path.dirname(path.resolve(workspaceFile))));
|
|
328
|
+
for (const workspaceDir of (await findMasterCSSWorkspaceDirectories(workspaceFolderCWD))){
|
|
329
|
+
resolvedWorkspaceDirectories.add(workspaceDir);
|
|
330
|
+
}
|
|
157
331
|
} else if (workspaces?.length) {
|
|
158
332
|
(await glob(workspaces, {
|
|
159
333
|
cwd: workspaceFolderCWD,
|
|
@@ -164,55 +338,142 @@ class CSSLanguageServer {
|
|
|
164
338
|
]
|
|
165
339
|
})).forEach((workspaceDir)=>resolvedWorkspaceDirectories.add(path.resolve(workspaceDir)));
|
|
166
340
|
}
|
|
167
|
-
|
|
341
|
+
for (const workspaceDir of resolvedWorkspaceDirectories){
|
|
168
342
|
const workspaceURI = URI.file(workspaceDir).toString();
|
|
169
343
|
this.console.info(`Added workspace ${workspaceURI}`);
|
|
170
344
|
this.workspaces.set(workspaceURI, {
|
|
171
345
|
uri: workspaceURI,
|
|
172
346
|
openedTextDocuments: [],
|
|
173
|
-
languageServiceSettings
|
|
347
|
+
languageServiceSettings,
|
|
348
|
+
planEntries: await findCSSManifestEntryFiles(workspaceDir)
|
|
174
349
|
});
|
|
175
|
-
}
|
|
350
|
+
}
|
|
176
351
|
}
|
|
177
|
-
initWorkspaceLanguageService(workspace) {
|
|
178
|
-
let
|
|
352
|
+
async initWorkspaceLanguageService(workspace) {
|
|
353
|
+
let workspacePlan;
|
|
179
354
|
if (workspace !== this.globalWorkspace) {
|
|
180
355
|
try {
|
|
181
|
-
|
|
182
|
-
cwd: workspace.uri && URI.parse(workspace.uri).fsPath,
|
|
183
|
-
found: undefined
|
|
184
|
-
});
|
|
356
|
+
workspacePlan = await this.loadWorkspacePlan(workspace);
|
|
185
357
|
} catch (e) {
|
|
186
|
-
this.console.info(`Failed to load
|
|
187
|
-
this.console.error(e);
|
|
358
|
+
this.console.info(`Failed to load manifest from ${workspace.uri}`);
|
|
359
|
+
this.console.error(e instanceof Error ? e.stack : e.toString());
|
|
188
360
|
}
|
|
189
|
-
if (
|
|
190
|
-
this.console.info(`Initialized workspace ${
|
|
361
|
+
if (workspacePlan) {
|
|
362
|
+
this.console.info(`Initialized workspace ${workspace.planEntries?.length ? '(with manifest entry)' : '(with manifest)'} ${workspace.uri}`);
|
|
191
363
|
} else {
|
|
192
364
|
this.console.info(`Initialized workspace ${workspace.uri}`);
|
|
193
365
|
}
|
|
194
366
|
}
|
|
195
367
|
workspace.languageService = new CSSLanguageService({
|
|
196
368
|
...workspace.languageServiceSettings,
|
|
197
|
-
|
|
369
|
+
manifest: workspacePlan
|
|
198
370
|
});
|
|
199
371
|
}
|
|
372
|
+
async loadWorkspacePlan(workspace) {
|
|
373
|
+
const cwd = workspace.uri ? URI.parse(workspace.uri).fsPath : process.cwd();
|
|
374
|
+
const result = await loadProjectManifest(cwd);
|
|
375
|
+
return result.entries.length ? result.manifest : workspace.languageServiceSettings.manifest;
|
|
376
|
+
}
|
|
200
377
|
destroyLanguageService(workspace) {
|
|
201
378
|
this.console.info(`Destroyed workspace ${workspace.uri}`);
|
|
202
379
|
delete workspace.languageService;
|
|
203
380
|
}
|
|
204
381
|
findClosestWorkspace(textDocumentURI) {
|
|
382
|
+
const documentPath = toComparableFilePath(textDocumentURI);
|
|
383
|
+
if (!documentPath) {
|
|
384
|
+
this.console.info(`This is an external document ${textDocumentURI} with the global workspace`);
|
|
385
|
+
return this.globalWorkspace;
|
|
386
|
+
}
|
|
205
387
|
let foundWorkspace;
|
|
388
|
+
let foundWorkspacePath = '';
|
|
206
389
|
for (const [uri, workspace] of this.workspaces){
|
|
207
390
|
if (!uri) continue;
|
|
208
|
-
|
|
391
|
+
const workspacePath = toComparableFilePath(uri);
|
|
392
|
+
if (!workspacePath) continue;
|
|
393
|
+
if (containsFilePath(workspacePath, documentPath) && workspacePath.length > foundWorkspacePath.length) {
|
|
209
394
|
foundWorkspace = workspace;
|
|
395
|
+
foundWorkspacePath = workspacePath;
|
|
210
396
|
}
|
|
211
397
|
}
|
|
212
398
|
if (foundWorkspace) return foundWorkspace;
|
|
213
399
|
this.console.info(`This is an external document ${textDocumentURI} with the global workspace`);
|
|
214
400
|
return this.globalWorkspace;
|
|
215
401
|
}
|
|
402
|
+
publishCSSDirectiveDiagnostics(textDocument, workspace) {
|
|
403
|
+
if (!isCSSDiagnosticDocument(textDocument)) return;
|
|
404
|
+
const diagnostics = [];
|
|
405
|
+
const documentFile = path.resolve(URI.parse(textDocument.uri).fsPath);
|
|
406
|
+
for (const { source, offset } of getCSSDiagnosticSources(textDocument)){
|
|
407
|
+
try {
|
|
408
|
+
compileCSSManifest(source, {
|
|
409
|
+
from: documentFile
|
|
410
|
+
});
|
|
411
|
+
} catch (error) {
|
|
412
|
+
if (!isCSSDirectiveError(error)) continue;
|
|
413
|
+
const diagnostic = this.createCSSDirectiveDiagnostic(error, textDocument, documentFile, offset);
|
|
414
|
+
if (diagnostic) diagnostics.push(diagnostic);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
this.connection.sendDiagnostics({
|
|
418
|
+
uri: textDocument.uri,
|
|
419
|
+
diagnostics
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
createCSSDirectiveDiagnostic(error, textDocument, documentFile, sourceOffset) {
|
|
423
|
+
if (error.source?.file && path.resolve(error.source.file) !== documentFile) return;
|
|
424
|
+
return {
|
|
425
|
+
range: this.createCSSDirectiveRange(error.source, textDocument, documentFile, sourceOffset),
|
|
426
|
+
severity: DiagnosticSeverity.Error,
|
|
427
|
+
code: error.code,
|
|
428
|
+
source: 'Master CSS',
|
|
429
|
+
message: error.message,
|
|
430
|
+
relatedInformation: this.createCSSDirectiveRelatedInformation(error.related, textDocument, documentFile, sourceOffset)
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
createCSSDirectiveRelatedInformation(related, textDocument, documentFile, sourceOffset) {
|
|
434
|
+
if (!related?.length) return;
|
|
435
|
+
return related.map(({ message, source })=>({
|
|
436
|
+
message,
|
|
437
|
+
location: {
|
|
438
|
+
uri: source?.file ? URI.file(source.file).toString() : textDocument.uri,
|
|
439
|
+
range: this.createCSSDirectiveRange(source, textDocument, documentFile, sourceOffset)
|
|
440
|
+
}
|
|
441
|
+
}));
|
|
442
|
+
}
|
|
443
|
+
createCSSDirectiveRange(source, textDocument, documentFile, sourceOffset) {
|
|
444
|
+
if (source?.file && path.resolve(source.file) !== documentFile) {
|
|
445
|
+
return source.loc ? {
|
|
446
|
+
start: {
|
|
447
|
+
line: Math.max(0, source.loc.start.line - 1),
|
|
448
|
+
character: Math.max(0, source.loc.start.column - 1)
|
|
449
|
+
},
|
|
450
|
+
end: {
|
|
451
|
+
line: Math.max(0, source.loc.end.line - 1),
|
|
452
|
+
character: Math.max(0, source.loc.end.column - 1)
|
|
453
|
+
}
|
|
454
|
+
} : {
|
|
455
|
+
start: {
|
|
456
|
+
line: 0,
|
|
457
|
+
character: 0
|
|
458
|
+
},
|
|
459
|
+
end: {
|
|
460
|
+
line: 0,
|
|
461
|
+
character: 0
|
|
462
|
+
}
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
const start = Math.max(0, (source?.range.start || 0) + sourceOffset);
|
|
466
|
+
const end = Math.max(start, (source?.range.end || 0) + sourceOffset);
|
|
467
|
+
return {
|
|
468
|
+
start: textDocument.positionAt(start),
|
|
469
|
+
end: textDocument.positionAt(end)
|
|
470
|
+
};
|
|
471
|
+
}
|
|
472
|
+
refreshSemanticTokens() {
|
|
473
|
+
if (this.settings?.embeddedSyntaxHighlighting !== 'always') return;
|
|
474
|
+
if (!this.clientCapabilities.workspace?.semanticTokens?.refreshSupport) return;
|
|
475
|
+
this.connection.languages.semanticTokens.refresh();
|
|
476
|
+
}
|
|
216
477
|
stop() {
|
|
217
478
|
this.connection.sendNotification('masterCSS/dispose');
|
|
218
479
|
this.disposables.forEach((disposable)=>disposable.dispose());
|
|
@@ -222,4 +483,4 @@ class CSSLanguageServer {
|
|
|
222
483
|
}
|
|
223
484
|
}
|
|
224
485
|
|
|
225
|
-
export { CSSLanguageServer as default };
|
|
486
|
+
export { ACTIVE_SEMANTIC_TOKENS_REQUEST, DOCUMENT_SEMANTIC_TOKENS_REQUEST, CSSLanguageServer as default };
|
package/dist/index.d.ts
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { default as CSSLanguageServer, default } from './core.mjs';
|
|
1
|
+
export { ACTIVE_SEMANTIC_TOKENS_REQUEST, default as CSSLanguageServer, DOCUMENT_SEMANTIC_TOKENS_REQUEST, default } from './core.mjs';
|
|
2
2
|
export { default as settings } from './settings.mjs';
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@master/css-language-server","type":"module","scripts":{"build":"techor build \"src/**/*.ts\"","dev":"pnpm build --watch","type-check":"tsc --noEmit","lint":"eslint","test":"vitest"},"description":"Master CSS Language Server","author":"Aoyue Design LLC.","license":"MIT","repository":{"type":"git","url":"https://github.com/master-co/css.git","directory":"packages/language-server"},"dependencies":{"@master/css":"^2.0.0-rc.
|
|
1
|
+
{"name":"@master/css-language-server","type":"module","scripts":{"build":"techor build \"src/**/*.ts\" --formats esm","dev":"pnpm build --watch","type-check":"tsc --noEmit","lint":"eslint","test":"vitest"},"description":"Master CSS Language Server","author":"Aoyue Design LLC.","license":"MIT","repository":{"type":"git","url":"https://github.com/master-co/css.git","directory":"packages/language-server"},"dependencies":{"@master/css":"^2.0.0-rc.70","@master/css-compiler":"^2.0.0-rc.70","@master/css-language":"^2.0.0-rc.70","@master/css-language-service":"^2.0.0-rc.70","@master/css-project":"^2.0.0-rc.70","@techor/extend":"^3.2.5","fast-glob":"^3.3.3","js-beautify":"^1.15.4","nanoid":"^5.1.15","vscode-languageserver":"^10.0.0","vscode-languageserver-textdocument":"^1.0.12","vscode-uri":"^3.1.0","@master/css-schema":"^2.0.0-rc.70"},"sideEffects":false,"main":"./dist/index.mjs","module":"./dist/index.mjs","jsnext:main":"./dist/index.mjs","esnext":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","default":"./dist/index.mjs"}},"files":["dist"],"publishConfig":{"access":"public","provenance":true},"version":"2.0.0-rc.70"}
|
package/dist/core.cjs
DELETED
|
@@ -1,227 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var node = require('vscode-languageserver/node');
|
|
4
|
-
var vscodeLanguageserverTextdocument = require('vscode-languageserver-textdocument');
|
|
5
|
-
var path = require('node:path');
|
|
6
|
-
var CSSLanguageService = require('@master/css-language-service');
|
|
7
|
-
var exploreConfig = require('@master/css-explore-config');
|
|
8
|
-
var extend = require('@techor/extend');
|
|
9
|
-
var settings = require('./settings.cjs');
|
|
10
|
-
var glob = require('fast-glob');
|
|
11
|
-
var vscodeUri = require('vscode-uri');
|
|
12
|
-
|
|
13
|
-
class CSSLanguageServer {
|
|
14
|
-
connection;
|
|
15
|
-
customSettings;
|
|
16
|
-
workspaceFolders = [];
|
|
17
|
-
workspaces = new Map();
|
|
18
|
-
globalWorkspace = {
|
|
19
|
-
uri: '',
|
|
20
|
-
openedTextDocuments: [],
|
|
21
|
-
languageServiceSettings: this.settings
|
|
22
|
-
};
|
|
23
|
-
documents;
|
|
24
|
-
initializing;
|
|
25
|
-
clientCapabilities = {};
|
|
26
|
-
settings;
|
|
27
|
-
console;
|
|
28
|
-
disposables = [];
|
|
29
|
-
constructor(connection = process.argv.includes('--stdio') ? node.createConnection(process.stdin, process.stdout) : node.createConnection(), customSettings){
|
|
30
|
-
this.connection = connection;
|
|
31
|
-
this.customSettings = customSettings;
|
|
32
|
-
this.documents = new node.TextDocuments(vscodeLanguageserverTextdocument.TextDocument);
|
|
33
|
-
this.settings = extend(settings, this.customSettings);
|
|
34
|
-
this.console = new Proxy(this.connection.console, {
|
|
35
|
-
get: (target, prop)=>{
|
|
36
|
-
if (!this.settings?.verbose) return ()=>{};
|
|
37
|
-
return this.connection.console[prop];
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
start() {
|
|
42
|
-
this.disposables.push(this.documents.onDidSave(this.onDidSave.bind(this)), this.documents.onDidOpen(this.onDidOpen.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.onInitialize(this.onInitialize.bind(this)), this.connection.onInitialized(()=>this.init()));
|
|
43
|
-
this.connection.listen();
|
|
44
|
-
}
|
|
45
|
-
init() {
|
|
46
|
-
if (this.initializing) return this.initializing;
|
|
47
|
-
return this.initializing = new Promise(async (resolve)=>{
|
|
48
|
-
await Promise.all(this.workspaceFolders.map((folder)=>this.initWorkspaceFolder(folder.uri)));
|
|
49
|
-
resolve();
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
onInitialize(params) {
|
|
53
|
-
this.clientCapabilities = params.capabilities;
|
|
54
|
-
if (params.workspaceFolders?.length) {
|
|
55
|
-
this.workspaceFolders = params.workspaceFolders;
|
|
56
|
-
}
|
|
57
|
-
return {
|
|
58
|
-
capabilities: CSSLanguageService.SERVER_CAPABILITIES
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
async onHover(params) {
|
|
62
|
-
await this.init();
|
|
63
|
-
const workspace = this.findClosestWorkspace(params.textDocument.uri);
|
|
64
|
-
if (workspace?.languageService) {
|
|
65
|
-
const document = this.documents.get(params.textDocument.uri);
|
|
66
|
-
if (document) return workspace.languageService.inspectSyntax(document, params.position);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
async onCompletion(params) {
|
|
70
|
-
await this.init();
|
|
71
|
-
const workspace = this.findClosestWorkspace(params.textDocument.uri);
|
|
72
|
-
if (workspace?.languageService) {
|
|
73
|
-
const document = this.documents.get(params.textDocument.uri);
|
|
74
|
-
if (document) return workspace.languageService.suggestSyntax(document, params.position, params.context);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
async onDocumentColor(params) {
|
|
78
|
-
await this.init();
|
|
79
|
-
const workspace = this.findClosestWorkspace(params.textDocument.uri);
|
|
80
|
-
if (workspace?.languageService) {
|
|
81
|
-
const document = this.documents.get(params.textDocument.uri);
|
|
82
|
-
if (document) return workspace.languageService.renderSyntaxColors(document);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
async onColorPresentation(params) {
|
|
86
|
-
await this.init();
|
|
87
|
-
const workspace = this.findClosestWorkspace(params.textDocument.uri);
|
|
88
|
-
if (workspace?.languageService) {
|
|
89
|
-
const document = this.documents.get(params.textDocument.uri);
|
|
90
|
-
if (document) return workspace.languageService.editSyntaxColors(document, params.color, params.range);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
async onDidOpen(params) {
|
|
94
|
-
await this.init();
|
|
95
|
-
const workspace = this.findClosestWorkspace(params.document.uri);
|
|
96
|
-
if (!workspace || workspace.openedTextDocuments.includes(params.document)) return;
|
|
97
|
-
if (!workspace.openedTextDocuments.length) {
|
|
98
|
-
this.initWorkspaceLanguageService(workspace);
|
|
99
|
-
}
|
|
100
|
-
workspace.openedTextDocuments.push(params.document);
|
|
101
|
-
}
|
|
102
|
-
async onDidClose(params) {
|
|
103
|
-
await this.init();
|
|
104
|
-
const workspace = this.findClosestWorkspace(params.document.uri);
|
|
105
|
-
if (!workspace) return;
|
|
106
|
-
workspace.openedTextDocuments.splice(workspace.openedTextDocuments.indexOf(params.document), 1);
|
|
107
|
-
if (!workspace.openedTextDocuments.length) {
|
|
108
|
-
this.destroyLanguageService(workspace);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
async onDidSave(params) {
|
|
112
|
-
await this.init();
|
|
113
|
-
const workspace = this.findClosestWorkspace(params.document.uri);
|
|
114
|
-
if (!workspace) return;
|
|
115
|
-
const name = path.parse(params.document.uri).name;
|
|
116
|
-
if (name === 'master.css' || name.endsWith('.css')) {
|
|
117
|
-
this.connection.sendRequest('masterCSS/restart', {
|
|
118
|
-
title: 'Updating Master CSS configuration'
|
|
119
|
-
});
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
async onDidChangeConfiguration({ settings }) {
|
|
123
|
-
await this.init();
|
|
124
|
-
if (settings?.masterCSS) {
|
|
125
|
-
this.connection.sendNotification('masterCSS/globalSettingsChanged', settings.masterCSS);
|
|
126
|
-
this.customSettings = settings.masterCSS;
|
|
127
|
-
this.connection.sendRequest('masterCSS/restart', {
|
|
128
|
-
title: 'Updating Master CSS settings'
|
|
129
|
-
});
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
async initWorkspaceFolder(workspaceFolderURI) {
|
|
133
|
-
const workspaceFolderCWD = vscodeUri.URI.parse(workspaceFolderURI).fsPath;
|
|
134
|
-
let customWorkspaceFolderSettings;
|
|
135
|
-
if (this.clientCapabilities.workspace?.configuration) {
|
|
136
|
-
customWorkspaceFolderSettings = await this.connection.workspace.getConfiguration({
|
|
137
|
-
scopeUri: workspaceFolderURI,
|
|
138
|
-
section: 'masterCSS'
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
const { workspaces, ...languageServiceSettings } = extend(settings, this.customSettings, customWorkspaceFolderSettings);
|
|
142
|
-
const resolvedWorkspaceDirectories = new Set([
|
|
143
|
-
workspaceFolderCWD
|
|
144
|
-
]);
|
|
145
|
-
if (workspaceFolderCWD) {
|
|
146
|
-
this.console.info(`Registered workspace folder ${workspaceFolderURI}`);
|
|
147
|
-
} else {
|
|
148
|
-
this.console.info(`Registered global workspace folder`);
|
|
149
|
-
}
|
|
150
|
-
if (workspaces === 'auto') {
|
|
151
|
-
(await glob('**/master.css.*', {
|
|
152
|
-
cwd: workspaceFolderCWD,
|
|
153
|
-
absolute: true,
|
|
154
|
-
onlyFiles: true,
|
|
155
|
-
ignore: [
|
|
156
|
-
'**/node_modules/**'
|
|
157
|
-
]
|
|
158
|
-
})).forEach((workspaceFile)=>resolvedWorkspaceDirectories.add(path.dirname(path.resolve(workspaceFile))));
|
|
159
|
-
} else if (workspaces?.length) {
|
|
160
|
-
(await glob(workspaces, {
|
|
161
|
-
cwd: workspaceFolderCWD,
|
|
162
|
-
absolute: true,
|
|
163
|
-
onlyDirectories: true,
|
|
164
|
-
ignore: [
|
|
165
|
-
'**/node_modules/**'
|
|
166
|
-
]
|
|
167
|
-
})).forEach((workspaceDir)=>resolvedWorkspaceDirectories.add(path.resolve(workspaceDir)));
|
|
168
|
-
}
|
|
169
|
-
resolvedWorkspaceDirectories.forEach(async (workspaceDir)=>{
|
|
170
|
-
const workspaceURI = vscodeUri.URI.file(workspaceDir).toString();
|
|
171
|
-
this.console.info(`Added workspace ${workspaceURI}`);
|
|
172
|
-
this.workspaces.set(workspaceURI, {
|
|
173
|
-
uri: workspaceURI,
|
|
174
|
-
openedTextDocuments: [],
|
|
175
|
-
languageServiceSettings
|
|
176
|
-
});
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
initWorkspaceLanguageService(workspace) {
|
|
180
|
-
let workspaceConfig;
|
|
181
|
-
if (workspace !== this.globalWorkspace) {
|
|
182
|
-
try {
|
|
183
|
-
workspaceConfig = exploreConfig({
|
|
184
|
-
cwd: workspace.uri && vscodeUri.URI.parse(workspace.uri).fsPath,
|
|
185
|
-
found: undefined
|
|
186
|
-
});
|
|
187
|
-
} catch (e) {
|
|
188
|
-
this.console.info(`Failed to load config from ${workspace}`);
|
|
189
|
-
this.console.error(e);
|
|
190
|
-
}
|
|
191
|
-
if (workspaceConfig) {
|
|
192
|
-
this.console.info(`Initialized workspace ${workspaceConfig ? '(with config file)' : ''} ${workspace.uri}`);
|
|
193
|
-
} else {
|
|
194
|
-
this.console.info(`Initialized workspace ${workspace.uri}`);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
workspace.languageService = new CSSLanguageService({
|
|
198
|
-
...workspace.languageServiceSettings,
|
|
199
|
-
config: workspaceConfig
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
destroyLanguageService(workspace) {
|
|
203
|
-
this.console.info(`Destroyed workspace ${workspace.uri}`);
|
|
204
|
-
delete workspace.languageService;
|
|
205
|
-
}
|
|
206
|
-
findClosestWorkspace(textDocumentURI) {
|
|
207
|
-
let foundWorkspace;
|
|
208
|
-
for (const [uri, workspace] of this.workspaces){
|
|
209
|
-
if (!uri) continue;
|
|
210
|
-
if (textDocumentURI.startsWith(uri) && (!foundWorkspace || uri.length > (foundWorkspace.uri || '').length)) {
|
|
211
|
-
foundWorkspace = workspace;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
if (foundWorkspace) return foundWorkspace;
|
|
215
|
-
this.console.info(`This is an external document ${textDocumentURI} with the global workspace`);
|
|
216
|
-
return this.globalWorkspace;
|
|
217
|
-
}
|
|
218
|
-
stop() {
|
|
219
|
-
this.connection.sendNotification('masterCSS/dispose');
|
|
220
|
-
this.disposables.forEach((disposable)=>disposable.dispose());
|
|
221
|
-
this.disposables.length = 0;
|
|
222
|
-
this.connection.dispose();
|
|
223
|
-
this.initializing = undefined;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
module.exports = CSSLanguageServer;
|
package/dist/index.cjs
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
|
-
var core = require('./core.cjs');
|
|
6
|
-
var settings = require('./settings.cjs');
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
exports.CSSLanguageServer = core;
|
|
11
|
-
exports.default = core;
|
|
12
|
-
exports.settings = settings;
|
package/dist/settings.cjs
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var vscodeLanguageserverTextdocument = require('vscode-languageserver-textdocument');
|
|
4
|
-
var nanoid = require('nanoid');
|
|
5
|
-
var path = require('path');
|
|
6
|
-
var vscodeUri = require('vscode-uri');
|
|
7
|
-
|
|
8
|
-
const extOfLang = {
|
|
9
|
-
typescript: 'ts',
|
|
10
|
-
typescriptreact: 'tsx',
|
|
11
|
-
javascript: 'js',
|
|
12
|
-
javascriptreact: 'jsx',
|
|
13
|
-
css: 'css',
|
|
14
|
-
scss: 'scss',
|
|
15
|
-
less: 'less',
|
|
16
|
-
html: 'html',
|
|
17
|
-
json: 'json',
|
|
18
|
-
vue: 'vue',
|
|
19
|
-
svelte: 'svelte',
|
|
20
|
-
astro: 'astro'
|
|
21
|
-
};
|
|
22
|
-
function createDocument(text, options) {
|
|
23
|
-
const lang = options?.lang || 'html';
|
|
24
|
-
const dir = options?.dir || './';
|
|
25
|
-
const filePath = path.join(dir, `${nanoid.nanoid()}.${extOfLang[lang]}`);
|
|
26
|
-
const fileURI = vscodeUri.URI.file(filePath).toString();
|
|
27
|
-
return vscodeLanguageserverTextdocument.TextDocument.create(fileURI, lang, 0, text);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
module.exports = createDocument;
|