@master/css-language-server 2.0.0-rc.35 → 2.0.0-rc.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/core.cjs CHANGED
@@ -8,53 +8,94 @@ var CSSLanguageService = require('@master/css-language-service');
8
8
  var exploreConfig = require('@master/css-explore-config');
9
9
  var extend = require('@techor/extend');
10
10
  var settings = require('./settings.cjs');
11
+ var interceptLogs = require('./utils/intercept-logs.cjs');
12
+ var glob = require('fast-glob');
11
13
 
12
14
  class CSSLanguageServer {
13
15
  customSettings;
14
16
  workspaceFolders;
15
- workspaceCSSLanguageService;
16
- workspaceSettings;
17
- workspaceConfigs;
17
+ workspaces;
18
18
  connection;
19
19
  documents;
20
+ initializing;
20
21
  disposables;
21
22
  constructor(customSettings){
22
23
  this.customSettings = customSettings;
23
24
  this.workspaceFolders = [];
24
- this.workspaceCSSLanguageService = {};
25
- this.workspaceSettings = {};
26
- this.workspaceConfigs = {};
25
+ this.workspaces = new Set();
27
26
  this.disposables = [];
28
27
  if (process.argv.includes('--stdio')) {
29
- console.log = (...args)=>{
30
- console.warn(...args);
31
- };
32
28
  this.connection = node.createConnection(process.stdin, process.stdout);
33
29
  } else {
34
- this.connection = node.createConnection(new node.IPCMessageReader(process), new node.IPCMessageWriter(process));
30
+ this.connection = node.createConnection();
35
31
  }
32
+ interceptLogs(console, this.connection);
36
33
  this.documents = new node.TextDocuments(vscodeLanguageserverTextdocument.TextDocument);
34
+ }
35
+ start() {
37
36
  this.disposables.push(this.documents.onDidSave(async (change)=>{
38
37
  // if the saved file is the master.css file, we need to refresh the css instance
39
38
  const name = path.parse(change.document.uri).name;
40
39
  if (name === 'master.css' || name.endsWith('.css')) {
41
- // const cssLanguageService = this.findWorkspaceCSSLanguageService(change.document.uri)
42
- // const workspaceFolder = this.findWorkspaceFolder(change.document.uri)
43
- // if (cssLanguageService)
44
- // cssLanguageService.css.refresh(this.updateWorkspaceConfig(workspaceFolder.uri))
45
40
  this.connection.sendRequest('masterCSS/restart', {
46
- title: 'Updating configuration...'
41
+ title: 'Updating Master CSS configuration'
47
42
  });
48
43
  }
49
- }), // Make the text document manager listen on the connection
50
- // for open, change and close text document events
51
- this.documents.listen(this.connection), this.connection.onDidChangeConfiguration(({ settings })=>{
44
+ }), this.documents.onDidOpen(async (params)=>{
45
+ await this.initializing;
46
+ const workspace = this.findClosestWorkspace(params.document.uri);
47
+ if (workspace.openedTextDocuments.has(params.document)) return;
48
+ if (!workspace.openedTextDocuments.size) {
49
+ this.initCSSLanguageService(workspace);
50
+ }
51
+ workspace.openedTextDocuments.add(params.document);
52
+ }), this.documents.onDidClose(async (params)=>{
53
+ await this.initializing;
54
+ const workspace = this.findClosestWorkspace(params.document.uri);
55
+ workspace.openedTextDocuments.delete(params.document);
56
+ if (!workspace.openedTextDocuments.size) {
57
+ this.destroyCSSLanguageService(workspace);
58
+ }
59
+ }), this.documents.listen(this.connection), this.connection.onDidChangeConfiguration(async ({ settings })=>{
60
+ await this.initializing;
52
61
  if (settings?.masterCSS) {
53
62
  this.connection.sendNotification('masterCSS/globalSettingsChanged', settings.masterCSS);
54
63
  this.customSettings = settings.masterCSS;
55
- this.reload();
64
+ this.connection.sendRequest('masterCSS/restart', {
65
+ title: 'Updating Master CSS settings'
66
+ });
67
+ }
68
+ }), this.connection.onHover(async (params)=>{
69
+ await this.initializing;
70
+ const workspace = this.findClosestWorkspace(params.textDocument.uri);
71
+ if (workspace?.cssLanguageService) {
72
+ const document = this.documents.get(params.textDocument.uri);
73
+ if (document) return workspace.cssLanguageService.inspectSyntax(document, params.position);
74
+ }
75
+ }), this.connection.onCompletion(async (params)=>{
76
+ await this.initializing;
77
+ const workspace = this.findClosestWorkspace(params.textDocument.uri);
78
+ if (workspace?.cssLanguageService) {
79
+ const document = this.documents.get(params.textDocument.uri);
80
+ if (document) return workspace.cssLanguageService.suggestSyntax(document, params.position, params.context);
56
81
  }
57
- }), this.connection.onInitialize((params)=>{
82
+ }), this.connection.onDocumentColor(async (params)=>{
83
+ await this.initializing;
84
+ const workspace = this.findClosestWorkspace(params.textDocument.uri);
85
+ if (workspace?.cssLanguageService) {
86
+ const document = this.documents.get(params.textDocument.uri);
87
+ if (document) return workspace.cssLanguageService.renderSyntaxColors(document);
88
+ }
89
+ }), this.connection.onColorPresentation(async (params)=>{
90
+ await this.initializing;
91
+ const workspace = this.findClosestWorkspace(params.textDocument.uri);
92
+ if (workspace?.cssLanguageService) {
93
+ const document = this.documents.get(params.textDocument.uri);
94
+ if (document) return workspace.cssLanguageService.editSyntaxColors(document, params.color, params.range);
95
+ }
96
+ }), // Make the text document manager listen on the connection
97
+ // for open, change and close text document events
98
+ this.connection.onInitialize((params)=>{
58
99
  if (params.workspaceFolders?.length) {
59
100
  this.workspaceFolders = params.workspaceFolders;
60
101
  } else {
@@ -69,108 +110,98 @@ class CSSLanguageServer {
69
110
  capabilities: CSSLanguageService.SERVER_CAPABILITIES
70
111
  };
71
112
  }), this.connection.onInitialized(async ()=>{
72
- await this.workspaceFolders.map(async (folder)=>{
73
- this.workspaceCSSLanguageService[folder.uri] = await this.createLanguageService(folder.uri);
74
- });
75
- this.connection.client.register(node.DidChangeConfigurationNotification.type, undefined);
76
- }), this.connection.onHover((params)=>{
77
- const cssLanguageService = this.findWorkspaceCSSLanguageService(params.textDocument.uri);
78
- if (cssLanguageService) {
79
- const document = this.documents.get(params.textDocument.uri);
80
- if (document) return cssLanguageService.inspectSyntax(document, params.position);
81
- }
82
- }), this.connection.onCompletion((params)=>{
83
- const cssLanguageService = this.findWorkspaceCSSLanguageService(params.textDocument.uri);
84
- if (cssLanguageService) {
85
- const document = this.documents.get(params.textDocument.uri);
86
- if (document) return cssLanguageService.suggestSyntax(document, params.position, params.context);
87
- }
88
- }), this.connection.onDocumentColor((params)=>{
89
- const cssLanguageService = this.findWorkspaceCSSLanguageService(params.textDocument.uri);
90
- if (cssLanguageService) {
91
- const document = this.documents.get(params.textDocument.uri);
92
- if (document) return cssLanguageService.renderSyntaxColors(document);
93
- }
94
- }), this.connection.onColorPresentation((params)=>{
95
- const cssLanguageService = this.findWorkspaceCSSLanguageService(params.textDocument.uri);
96
- if (cssLanguageService) {
97
- const document = this.documents.get(params.textDocument.uri);
98
- if (document) return cssLanguageService.editSyntaxColors(document, params.color, params.range);
99
- }
100
- }), this.connection.onShutdown(()=>{
101
- this.dispose();
113
+ this.initializing = Promise.all([
114
+ ...this.workspaceFolders.map((folder)=>this.initWorkspaceFolder(folder.uri)),
115
+ this.connection.client.register(node.DidChangeConfigurationNotification.type, undefined)
116
+ ]);
102
117
  }));
118
+ this.connection.listen();
103
119
  }
104
- async createLanguageService(workspaceURI) {
105
- const { config, ...workspaceCSSLanguageServiceSettings } = await this.updateWorkspaceSettings(workspaceURI);
106
- const workspaceConfig = this.workspaceConfigs[workspaceURI];
107
- return new CSSLanguageService({
108
- ...workspaceCSSLanguageServiceSettings,
109
- config: workspaceConfig
110
- });
111
- }
112
- async updateWorkspaceSettings(workspaceURI) {
113
- const customWorkspaceSettings = await this.connection.workspace.getConfiguration({
114
- scopeUri: workspaceURI,
120
+ async initWorkspaceFolder(workspaceFolderURI) {
121
+ const workspaceFolderCWD = this.fileURLToPath(workspaceFolderURI);
122
+ const customWorkspaceFolderSettings = await this.connection.workspace.getConfiguration({
123
+ scopeUri: workspaceFolderURI,
115
124
  section: 'masterCSS'
116
125
  });
117
- const resolvedSettings = extend(settings, this.customSettings, customWorkspaceSettings);
118
- this.workspaceSettings[workspaceURI] = resolvedSettings;
119
- this.updateWorkspaceConfig(workspaceURI);
120
- return resolvedSettings;
126
+ const { workspaces, ...languageServiceSettings } = extend(settings, this.customSettings, customWorkspaceFolderSettings);
127
+ const resolvedWorkspaceDirectories = new Set([
128
+ workspaceFolderCWD
129
+ ]);
130
+ console.info('Registered workspace folder');
131
+ console.log(workspaceFolderCWD);
132
+ if (workspaces === 'auto') {
133
+ (await glob('**/master.css.*', {
134
+ cwd: workspaceFolderCWD,
135
+ absolute: true,
136
+ onlyFiles: true,
137
+ ignore: [
138
+ '**/node_modules/**'
139
+ ]
140
+ })).forEach((workspaceFile)=>resolvedWorkspaceDirectories.add(path.dirname(workspaceFile)));
141
+ } else if (workspaces?.length) {
142
+ (await glob(workspaces, {
143
+ cwd: workspaceFolderCWD,
144
+ absolute: true,
145
+ onlyDirectories: true,
146
+ ignore: [
147
+ '**/node_modules/**'
148
+ ]
149
+ })).forEach((workspaceDir)=>resolvedWorkspaceDirectories.add(workspaceDir));
150
+ }
151
+ resolvedWorkspaceDirectories.forEach(async (workspaceDir)=>{
152
+ console.info('Added workspace');
153
+ console.log(workspaceDir);
154
+ this.workspaces.add({
155
+ path: workspaceDir,
156
+ uri: url.pathToFileURL(workspaceDir).href,
157
+ openedTextDocuments: new Set(),
158
+ languageServiceSettings
159
+ });
160
+ });
121
161
  }
122
- updateWorkspaceConfig(workspaceURI) {
123
- const workspaceSettings = this.workspaceSettings[workspaceURI];
124
- const workspaceCWD = url.fileURLToPath(workspaceURI.replace('%3A', ':'));
162
+ initCSSLanguageService(workspace) {
125
163
  let workspaceConfig;
126
- if (typeof workspaceSettings.config === 'string') {
127
- try {
128
- workspaceConfig = exploreConfig({
129
- name: workspaceSettings.config,
130
- cwd: workspaceCWD
131
- });
132
- } catch (e) {
133
- console.log('Config loading failed from', workspaceCWD);
134
- console.error(e);
135
- console.log('Fall back to default config');
136
- }
137
- } else {
138
- workspaceConfig = workspaceSettings.config;
164
+ try {
165
+ workspaceConfig = exploreConfig({
166
+ cwd: workspace.path,
167
+ found: undefined
168
+ });
169
+ } catch (e) {
170
+ console.info('Failed to load config from', workspace);
171
+ console.error(e);
139
172
  }
140
- return this.workspaceConfigs[workspaceURI] = workspaceConfig;
173
+ console.info('Initialized workspace', workspaceConfig ? '(with config file)' : '');
174
+ console.log(workspace.path);
175
+ workspace.cssLanguageService = new CSSLanguageService({
176
+ ...workspace.languageServiceSettings,
177
+ config: workspaceConfig
178
+ });
179
+ }
180
+ destroyCSSLanguageService(workspace) {
181
+ console.info('Destroyed workspace');
182
+ console.log(workspace.path);
183
+ delete workspace.cssLanguageService;
184
+ }
185
+ fileURLToPath(workspaceURI) {
186
+ return url.fileURLToPath(workspaceURI.replace('%3A', ':'));
141
187
  }
142
- // find the workspace language service for the given uri
143
- findWorkspaceCSSLanguageService(uri) {
144
- for(const workspaceURI in this.workspaceCSSLanguageService){
145
- if (uri.startsWith(workspaceURI)) {
146
- return this.workspaceCSSLanguageService[workspaceURI];
188
+ findClosestWorkspace(textDocumentURI) {
189
+ let foundWorkspace;
190
+ for (const workspace of this.workspaces){
191
+ if (textDocumentURI.startsWith(workspace.uri) && (!foundWorkspace || workspace.uri.length > foundWorkspace.uri.length)) {
192
+ foundWorkspace = workspace;
147
193
  }
148
194
  }
149
- }
150
- findWorkspaceFolder(uri) {
151
- const workspaceFolder = this.workspaceFolders.find((workspace)=>uri.startsWith(workspace.uri));
152
- if (!workspaceFolder) {
153
- throw new Error(`Workspace folder not found for ${uri}`);
195
+ if (!foundWorkspace) {
196
+ throw new Error(`No workspace found for ${textDocumentURI}`);
154
197
  }
155
- return workspaceFolder;
156
- }
157
- // revalidate workspace language services by all documents
158
- async revalidate(documents = this.documents.all()) {
159
- this.connection.sendNotification('masterCSS/revalidate');
160
- return await Promise.all(documents.map(async (textDocument)=>{
161
- const workspaceFolder = this.findWorkspaceFolder(textDocument.uri);
162
- return this.workspaceCSSLanguageService[workspaceFolder.uri] = await this.createLanguageService(workspaceFolder.uri);
163
- }));
164
- }
165
- async reload() {
166
- await Promise.all(Object.keys(this.workspaceCSSLanguageService).map(async (workspaceURI)=>{
167
- this.workspaceCSSLanguageService[workspaceURI] = await this.createLanguageService(workspaceURI);
168
- }));
198
+ return foundWorkspace;
169
199
  }
170
- dispose() {
200
+ stop() {
171
201
  this.connection.sendNotification('masterCSS/dispose');
172
202
  this.disposables.forEach((disposable)=>disposable.dispose());
173
203
  this.disposables.length = 0;
204
+ this.connection.dispose();
174
205
  }
175
206
  }
176
207
 
package/dist/core.d.ts CHANGED
@@ -1,24 +1,29 @@
1
- import { TextDocuments, WorkspaceFolder } from 'vscode-languageserver/node';
1
+ import { TextDocuments, WorkspaceFolder, Connection } from 'vscode-languageserver/node';
2
2
  import { TextDocument } from 'vscode-languageserver-textdocument';
3
- import CSSLanguageService from '@master/css-language-service';
3
+ import CSSLanguageService, { Settings as CSSLanguageServiceSettings } from '@master/css-language-service';
4
4
  import { Settings } from './settings';
5
- import { Config } from '@master/css';
5
+ declare type Workspace = {
6
+ path: string;
7
+ uri: string;
8
+ openedTextDocuments: Set<TextDocument>;
9
+ cssLanguageService?: CSSLanguageService;
10
+ languageServiceSettings: CSSLanguageServiceSettings;
11
+ };
6
12
  export default class CSSLanguageServer {
7
13
  customSettings?: Settings | undefined;
8
14
  workspaceFolders: WorkspaceFolder[];
9
- workspaceCSSLanguageService: Record<string, CSSLanguageService>;
10
- workspaceSettings: Record<string, Settings>;
11
- workspaceConfigs: Record<string, Config | undefined>;
12
- connection: import("vscode-languageserver/node").Connection;
15
+ workspaces: Set<Workspace>;
16
+ connection: Connection;
13
17
  documents: TextDocuments<TextDocument>;
18
+ initializing?: Promise<any[]>;
14
19
  private disposables;
15
20
  constructor(customSettings?: Settings | undefined);
16
- createLanguageService(workspaceURI: string): Promise<CSSLanguageService>;
17
- updateWorkspaceSettings(workspaceURI: string): Promise<Settings>;
18
- updateWorkspaceConfig(workspaceURI: string): Config | undefined;
19
- findWorkspaceCSSLanguageService(uri: string): CSSLanguageService | undefined;
20
- findWorkspaceFolder(uri: string): WorkspaceFolder;
21
- revalidate(documents?: TextDocument[]): Promise<CSSLanguageService[]>;
22
- reload(): Promise<void>;
23
- dispose(): void;
21
+ start(): void;
22
+ private initWorkspaceFolder;
23
+ initCSSLanguageService(workspace: Workspace): void;
24
+ destroyCSSLanguageService(workspace: Workspace): void;
25
+ fileURLToPath(workspaceURI: string): string;
26
+ findClosestWorkspace(textDocumentURI: string): Workspace;
27
+ stop(): void;
24
28
  }
29
+ export {};
package/dist/core.mjs CHANGED
@@ -1,58 +1,99 @@
1
- import { createConnection, IPCMessageReader, IPCMessageWriter, TextDocuments, DidChangeConfigurationNotification } from 'vscode-languageserver/node';
1
+ import { createConnection, TextDocuments, DidChangeConfigurationNotification } from 'vscode-languageserver/node';
2
2
  import { TextDocument } from 'vscode-languageserver-textdocument';
3
3
  import path from 'path';
4
- import { fileURLToPath } from 'url';
4
+ import { pathToFileURL, fileURLToPath } from 'url';
5
5
  import CSSLanguageService, { SERVER_CAPABILITIES } from '@master/css-language-service';
6
6
  import exploreConfig from '@master/css-explore-config';
7
7
  import extend from '@techor/extend';
8
8
  import settings from './settings.mjs';
9
+ import interceptLogs from './utils/intercept-logs.mjs';
10
+ import glob from 'fast-glob';
9
11
 
10
12
  class CSSLanguageServer {
11
13
  customSettings;
12
14
  workspaceFolders;
13
- workspaceCSSLanguageService;
14
- workspaceSettings;
15
- workspaceConfigs;
15
+ workspaces;
16
16
  connection;
17
17
  documents;
18
+ initializing;
18
19
  disposables;
19
20
  constructor(customSettings){
20
21
  this.customSettings = customSettings;
21
22
  this.workspaceFolders = [];
22
- this.workspaceCSSLanguageService = {};
23
- this.workspaceSettings = {};
24
- this.workspaceConfigs = {};
23
+ this.workspaces = new Set();
25
24
  this.disposables = [];
26
25
  if (process.argv.includes('--stdio')) {
27
- console.log = (...args)=>{
28
- console.warn(...args);
29
- };
30
26
  this.connection = createConnection(process.stdin, process.stdout);
31
27
  } else {
32
- this.connection = createConnection(new IPCMessageReader(process), new IPCMessageWriter(process));
28
+ this.connection = createConnection();
33
29
  }
30
+ interceptLogs(console, this.connection);
34
31
  this.documents = new TextDocuments(TextDocument);
32
+ }
33
+ start() {
35
34
  this.disposables.push(this.documents.onDidSave(async (change)=>{
36
35
  // if the saved file is the master.css file, we need to refresh the css instance
37
36
  const name = path.parse(change.document.uri).name;
38
37
  if (name === 'master.css' || name.endsWith('.css')) {
39
- // const cssLanguageService = this.findWorkspaceCSSLanguageService(change.document.uri)
40
- // const workspaceFolder = this.findWorkspaceFolder(change.document.uri)
41
- // if (cssLanguageService)
42
- // cssLanguageService.css.refresh(this.updateWorkspaceConfig(workspaceFolder.uri))
43
38
  this.connection.sendRequest('masterCSS/restart', {
44
- title: 'Updating configuration...'
39
+ title: 'Updating Master CSS configuration'
45
40
  });
46
41
  }
47
- }), // Make the text document manager listen on the connection
48
- // for open, change and close text document events
49
- this.documents.listen(this.connection), this.connection.onDidChangeConfiguration(({ settings })=>{
42
+ }), this.documents.onDidOpen(async (params)=>{
43
+ await this.initializing;
44
+ const workspace = this.findClosestWorkspace(params.document.uri);
45
+ if (workspace.openedTextDocuments.has(params.document)) return;
46
+ if (!workspace.openedTextDocuments.size) {
47
+ this.initCSSLanguageService(workspace);
48
+ }
49
+ workspace.openedTextDocuments.add(params.document);
50
+ }), this.documents.onDidClose(async (params)=>{
51
+ await this.initializing;
52
+ const workspace = this.findClosestWorkspace(params.document.uri);
53
+ workspace.openedTextDocuments.delete(params.document);
54
+ if (!workspace.openedTextDocuments.size) {
55
+ this.destroyCSSLanguageService(workspace);
56
+ }
57
+ }), this.documents.listen(this.connection), this.connection.onDidChangeConfiguration(async ({ settings })=>{
58
+ await this.initializing;
50
59
  if (settings?.masterCSS) {
51
60
  this.connection.sendNotification('masterCSS/globalSettingsChanged', settings.masterCSS);
52
61
  this.customSettings = settings.masterCSS;
53
- this.reload();
62
+ this.connection.sendRequest('masterCSS/restart', {
63
+ title: 'Updating Master CSS settings'
64
+ });
65
+ }
66
+ }), this.connection.onHover(async (params)=>{
67
+ await this.initializing;
68
+ const workspace = this.findClosestWorkspace(params.textDocument.uri);
69
+ if (workspace?.cssLanguageService) {
70
+ const document = this.documents.get(params.textDocument.uri);
71
+ if (document) return workspace.cssLanguageService.inspectSyntax(document, params.position);
72
+ }
73
+ }), this.connection.onCompletion(async (params)=>{
74
+ await this.initializing;
75
+ const workspace = this.findClosestWorkspace(params.textDocument.uri);
76
+ if (workspace?.cssLanguageService) {
77
+ const document = this.documents.get(params.textDocument.uri);
78
+ if (document) return workspace.cssLanguageService.suggestSyntax(document, params.position, params.context);
54
79
  }
55
- }), this.connection.onInitialize((params)=>{
80
+ }), this.connection.onDocumentColor(async (params)=>{
81
+ await this.initializing;
82
+ const workspace = this.findClosestWorkspace(params.textDocument.uri);
83
+ if (workspace?.cssLanguageService) {
84
+ const document = this.documents.get(params.textDocument.uri);
85
+ if (document) return workspace.cssLanguageService.renderSyntaxColors(document);
86
+ }
87
+ }), this.connection.onColorPresentation(async (params)=>{
88
+ await this.initializing;
89
+ const workspace = this.findClosestWorkspace(params.textDocument.uri);
90
+ if (workspace?.cssLanguageService) {
91
+ const document = this.documents.get(params.textDocument.uri);
92
+ if (document) return workspace.cssLanguageService.editSyntaxColors(document, params.color, params.range);
93
+ }
94
+ }), // Make the text document manager listen on the connection
95
+ // for open, change and close text document events
96
+ this.connection.onInitialize((params)=>{
56
97
  if (params.workspaceFolders?.length) {
57
98
  this.workspaceFolders = params.workspaceFolders;
58
99
  } else {
@@ -67,108 +108,98 @@ class CSSLanguageServer {
67
108
  capabilities: SERVER_CAPABILITIES
68
109
  };
69
110
  }), this.connection.onInitialized(async ()=>{
70
- await this.workspaceFolders.map(async (folder)=>{
71
- this.workspaceCSSLanguageService[folder.uri] = await this.createLanguageService(folder.uri);
72
- });
73
- this.connection.client.register(DidChangeConfigurationNotification.type, undefined);
74
- }), this.connection.onHover((params)=>{
75
- const cssLanguageService = this.findWorkspaceCSSLanguageService(params.textDocument.uri);
76
- if (cssLanguageService) {
77
- const document = this.documents.get(params.textDocument.uri);
78
- if (document) return cssLanguageService.inspectSyntax(document, params.position);
79
- }
80
- }), this.connection.onCompletion((params)=>{
81
- const cssLanguageService = this.findWorkspaceCSSLanguageService(params.textDocument.uri);
82
- if (cssLanguageService) {
83
- const document = this.documents.get(params.textDocument.uri);
84
- if (document) return cssLanguageService.suggestSyntax(document, params.position, params.context);
85
- }
86
- }), this.connection.onDocumentColor((params)=>{
87
- const cssLanguageService = this.findWorkspaceCSSLanguageService(params.textDocument.uri);
88
- if (cssLanguageService) {
89
- const document = this.documents.get(params.textDocument.uri);
90
- if (document) return cssLanguageService.renderSyntaxColors(document);
91
- }
92
- }), this.connection.onColorPresentation((params)=>{
93
- const cssLanguageService = this.findWorkspaceCSSLanguageService(params.textDocument.uri);
94
- if (cssLanguageService) {
95
- const document = this.documents.get(params.textDocument.uri);
96
- if (document) return cssLanguageService.editSyntaxColors(document, params.color, params.range);
97
- }
98
- }), this.connection.onShutdown(()=>{
99
- this.dispose();
111
+ this.initializing = Promise.all([
112
+ ...this.workspaceFolders.map((folder)=>this.initWorkspaceFolder(folder.uri)),
113
+ this.connection.client.register(DidChangeConfigurationNotification.type, undefined)
114
+ ]);
100
115
  }));
116
+ this.connection.listen();
101
117
  }
102
- async createLanguageService(workspaceURI) {
103
- const { config, ...workspaceCSSLanguageServiceSettings } = await this.updateWorkspaceSettings(workspaceURI);
104
- const workspaceConfig = this.workspaceConfigs[workspaceURI];
105
- return new CSSLanguageService({
106
- ...workspaceCSSLanguageServiceSettings,
107
- config: workspaceConfig
108
- });
109
- }
110
- async updateWorkspaceSettings(workspaceURI) {
111
- const customWorkspaceSettings = await this.connection.workspace.getConfiguration({
112
- scopeUri: workspaceURI,
118
+ async initWorkspaceFolder(workspaceFolderURI) {
119
+ const workspaceFolderCWD = this.fileURLToPath(workspaceFolderURI);
120
+ const customWorkspaceFolderSettings = await this.connection.workspace.getConfiguration({
121
+ scopeUri: workspaceFolderURI,
113
122
  section: 'masterCSS'
114
123
  });
115
- const resolvedSettings = extend(settings, this.customSettings, customWorkspaceSettings);
116
- this.workspaceSettings[workspaceURI] = resolvedSettings;
117
- this.updateWorkspaceConfig(workspaceURI);
118
- return resolvedSettings;
124
+ const { workspaces, ...languageServiceSettings } = extend(settings, this.customSettings, customWorkspaceFolderSettings);
125
+ const resolvedWorkspaceDirectories = new Set([
126
+ workspaceFolderCWD
127
+ ]);
128
+ console.info('Registered workspace folder');
129
+ console.log(workspaceFolderCWD);
130
+ if (workspaces === 'auto') {
131
+ (await glob('**/master.css.*', {
132
+ cwd: workspaceFolderCWD,
133
+ absolute: true,
134
+ onlyFiles: true,
135
+ ignore: [
136
+ '**/node_modules/**'
137
+ ]
138
+ })).forEach((workspaceFile)=>resolvedWorkspaceDirectories.add(path.dirname(workspaceFile)));
139
+ } else if (workspaces?.length) {
140
+ (await glob(workspaces, {
141
+ cwd: workspaceFolderCWD,
142
+ absolute: true,
143
+ onlyDirectories: true,
144
+ ignore: [
145
+ '**/node_modules/**'
146
+ ]
147
+ })).forEach((workspaceDir)=>resolvedWorkspaceDirectories.add(workspaceDir));
148
+ }
149
+ resolvedWorkspaceDirectories.forEach(async (workspaceDir)=>{
150
+ console.info('Added workspace');
151
+ console.log(workspaceDir);
152
+ this.workspaces.add({
153
+ path: workspaceDir,
154
+ uri: pathToFileURL(workspaceDir).href,
155
+ openedTextDocuments: new Set(),
156
+ languageServiceSettings
157
+ });
158
+ });
119
159
  }
120
- updateWorkspaceConfig(workspaceURI) {
121
- const workspaceSettings = this.workspaceSettings[workspaceURI];
122
- const workspaceCWD = fileURLToPath(workspaceURI.replace('%3A', ':'));
160
+ initCSSLanguageService(workspace) {
123
161
  let workspaceConfig;
124
- if (typeof workspaceSettings.config === 'string') {
125
- try {
126
- workspaceConfig = exploreConfig({
127
- name: workspaceSettings.config,
128
- cwd: workspaceCWD
129
- });
130
- } catch (e) {
131
- console.log('Config loading failed from', workspaceCWD);
132
- console.error(e);
133
- console.log('Fall back to default config');
134
- }
135
- } else {
136
- workspaceConfig = workspaceSettings.config;
162
+ try {
163
+ workspaceConfig = exploreConfig({
164
+ cwd: workspace.path,
165
+ found: undefined
166
+ });
167
+ } catch (e) {
168
+ console.info('Failed to load config from', workspace);
169
+ console.error(e);
137
170
  }
138
- return this.workspaceConfigs[workspaceURI] = workspaceConfig;
171
+ console.info('Initialized workspace', workspaceConfig ? '(with config file)' : '');
172
+ console.log(workspace.path);
173
+ workspace.cssLanguageService = new CSSLanguageService({
174
+ ...workspace.languageServiceSettings,
175
+ config: workspaceConfig
176
+ });
177
+ }
178
+ destroyCSSLanguageService(workspace) {
179
+ console.info('Destroyed workspace');
180
+ console.log(workspace.path);
181
+ delete workspace.cssLanguageService;
182
+ }
183
+ fileURLToPath(workspaceURI) {
184
+ return fileURLToPath(workspaceURI.replace('%3A', ':'));
139
185
  }
140
- // find the workspace language service for the given uri
141
- findWorkspaceCSSLanguageService(uri) {
142
- for(const workspaceURI in this.workspaceCSSLanguageService){
143
- if (uri.startsWith(workspaceURI)) {
144
- return this.workspaceCSSLanguageService[workspaceURI];
186
+ findClosestWorkspace(textDocumentURI) {
187
+ let foundWorkspace;
188
+ for (const workspace of this.workspaces){
189
+ if (textDocumentURI.startsWith(workspace.uri) && (!foundWorkspace || workspace.uri.length > foundWorkspace.uri.length)) {
190
+ foundWorkspace = workspace;
145
191
  }
146
192
  }
147
- }
148
- findWorkspaceFolder(uri) {
149
- const workspaceFolder = this.workspaceFolders.find((workspace)=>uri.startsWith(workspace.uri));
150
- if (!workspaceFolder) {
151
- throw new Error(`Workspace folder not found for ${uri}`);
193
+ if (!foundWorkspace) {
194
+ throw new Error(`No workspace found for ${textDocumentURI}`);
152
195
  }
153
- return workspaceFolder;
154
- }
155
- // revalidate workspace language services by all documents
156
- async revalidate(documents = this.documents.all()) {
157
- this.connection.sendNotification('masterCSS/revalidate');
158
- return await Promise.all(documents.map(async (textDocument)=>{
159
- const workspaceFolder = this.findWorkspaceFolder(textDocument.uri);
160
- return this.workspaceCSSLanguageService[workspaceFolder.uri] = await this.createLanguageService(workspaceFolder.uri);
161
- }));
162
- }
163
- async reload() {
164
- await Promise.all(Object.keys(this.workspaceCSSLanguageService).map(async (workspaceURI)=>{
165
- this.workspaceCSSLanguageService[workspaceURI] = await this.createLanguageService(workspaceURI);
166
- }));
196
+ return foundWorkspace;
167
197
  }
168
- dispose() {
198
+ stop() {
169
199
  this.connection.sendNotification('masterCSS/dispose');
170
200
  this.disposables.forEach((disposable)=>disposable.dispose());
171
201
  this.disposables.length = 0;
202
+ this.connection.dispose();
172
203
  }
173
204
  }
174
205
 
package/dist/settings.cjs CHANGED
@@ -4,7 +4,7 @@ var CSSLanguageService = require('@master/css-language-service');
4
4
 
5
5
  const settings = {
6
6
  ...CSSLanguageService.settings,
7
- config: 'master.css'
7
+ workspaces: 'auto'
8
8
  };
9
9
 
10
10
  module.exports = settings;
@@ -1,6 +1,6 @@
1
1
  import { type Settings as CSSLanguageServiceSettings } from '@master/css-language-service';
2
2
  declare const settings: Settings;
3
3
  export default settings;
4
- export declare type Settings = CSSLanguageServiceSettings | {
5
- config: string;
4
+ export declare type Settings = CSSLanguageServiceSettings & {
5
+ workspaces: string[] | 'auto';
6
6
  };
package/dist/settings.mjs CHANGED
@@ -2,7 +2,7 @@ import { settings as settings$1 } from '@master/css-language-service';
2
2
 
3
3
  const settings = {
4
4
  ...settings$1,
5
- config: 'master.css'
5
+ workspaces: 'auto'
6
6
  };
7
7
 
8
8
  export { settings as default };
@@ -0,0 +1,17 @@
1
+ 'use strict';
2
+
3
+ var node_util = require('node:util');
4
+
5
+ function formatMessages(params) {
6
+ return params.map((item)=>node_util.format(item)).join(' ');
7
+ }
8
+ function interceptLogs(console, connection) {
9
+ console.debug = (...params)=>connection.console.info(formatMessages(params));
10
+ console.error = (...params)=>connection.console.error(formatMessages(params));
11
+ console.warn = (...params)=>connection.console.warn(formatMessages(params));
12
+ console.info = (...params)=>connection.console.info(formatMessages(params));
13
+ console.log = (...params)=>connection.console.log(formatMessages(params));
14
+ return console;
15
+ }
16
+
17
+ module.exports = interceptLogs;
@@ -0,0 +1,2 @@
1
+ import type { Connection } from 'vscode-languageserver';
2
+ export default function interceptLogs(console: Console, connection: Connection): Console;
@@ -0,0 +1,15 @@
1
+ import { format } from 'node:util';
2
+
3
+ function formatMessages(params) {
4
+ return params.map((item)=>format(item)).join(' ');
5
+ }
6
+ function interceptLogs(console, connection) {
7
+ console.debug = (...params)=>connection.console.info(formatMessages(params));
8
+ console.error = (...params)=>connection.console.error(formatMessages(params));
9
+ console.warn = (...params)=>connection.console.warn(formatMessages(params));
10
+ console.info = (...params)=>connection.console.info(formatMessages(params));
11
+ console.log = (...params)=>connection.console.log(formatMessages(params));
12
+ return console;
13
+ }
14
+
15
+ export { interceptLogs as default };
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 src","test":"jest"},"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.35","@master/css-explore-config":"^2.0.0-rc.35","@master/css-language-service":"^2.0.0-rc.35","@techor/extend":"^3.0.22","js-beautify":"^1.15.1","vscode-languageserver":"^9.0.1","vscode-languageserver-textdocument":"^1.0.11"},"devDependencies":{"@master/css-shared":"^2.0.0-rc.35"},"sideEffects":false,"main":"./dist/index.cjs","module":"./dist/index.mjs","jsnext:main":"./dist/index.mjs","esnext":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"import":"./dist/index.mjs","require":"./dist/index.cjs","types":"./dist/index.d.ts"}},"files":["dist"],"publishConfig":{"access":"public","provenance":true},"version":"2.0.0-rc.35"}
1
+ {"name":"@master/css-language-server","type":"module","scripts":{"build":"techor build \"src/**/*.ts\"","dev":"pnpm build --watch","type-check":"tsc --noEmit","lint":"eslint src","test":"jest"},"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.37","@master/css-explore-config":"^2.0.0-rc.37","@master/css-language-service":"^2.0.0-rc.37","@techor/extend":"^3.0.22","fast-glob":"^3.3.2","js-beautify":"^1.15.1","vscode-languageserver":"^9.0.1","vscode-languageserver-textdocument":"^1.0.11"},"devDependencies":{"@master/css-shared":"^2.0.0-rc.37"},"sideEffects":false,"main":"./dist/index.cjs","module":"./dist/index.mjs","jsnext:main":"./dist/index.mjs","esnext":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"import":"./dist/index.mjs","require":"./dist/index.cjs","types":"./dist/index.d.ts"}},"files":["dist"],"publishConfig":{"access":"public","provenance":true},"version":"2.0.0-rc.37"}