@lvce-editor/shared-process 0.95.1 → 0.95.3

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.
@@ -11,7 +11,7 @@
11
11
  "editor.fontLigatures": true,
12
12
  "editor.links": true,
13
13
  "editor.tabSize": 2,
14
- "editor.hover": false,
14
+ "editor.hover": true,
15
15
 
16
16
  "editor.autoClosingBrackets": true,
17
17
  "editor.autoClosingQuotes": true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/shared-process",
3
- "version": "0.95.1",
3
+ "version": "0.95.3",
4
4
  "main": "index.js",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -19,7 +19,7 @@
19
19
  "dependencies": {
20
20
  "@lvce-editor/assert": "1.7.0",
21
21
  "@lvce-editor/auth-process": "1.12.0",
22
- "@lvce-editor/extension-host-helper-process": "0.95.1",
22
+ "@lvce-editor/extension-host-helper-process": "0.95.3",
23
23
  "@lvce-editor/ipc": "16.6.0",
24
24
  "@lvce-editor/json-rpc": "8.5.0",
25
25
  "@lvce-editor/jsonc-parser": "1.5.0",
@@ -3,6 +3,6 @@ import { fileURLToPath } from 'url'
3
3
 
4
4
  export const getBuiltinExtensionsPath = () => {
5
5
  const staticServerPath = fileURLToPath(import.meta.resolve('@lvce-editor/static-server'))
6
- const builtinExtensionsPath = join(staticServerPath, '..', '..', 'static', '2572a83', 'extensions')
6
+ const builtinExtensionsPath = join(staticServerPath, '..', '..', 'static', '6f688db', 'extensions')
7
7
  return builtinExtensionsPath
8
8
  }
@@ -13,6 +13,7 @@ import { normalizeLanguageServerDocumentUri } from '../NormalizeLanguageServerDo
13
13
 
14
14
 
15
15
 
16
+
16
17
 
17
18
 
18
19
 
@@ -20,6 +21,7 @@ import { normalizeLanguageServerDocumentUri } from '../NormalizeLanguageServerDo
20
21
 
21
22
 
22
23
 
24
+
23
25
 
24
26
 
25
27
 
@@ -61,23 +63,23 @@ const getConnection = (id, uri, argv, rootUri) => {
61
63
  return connection
62
64
  }
63
65
 
64
- export const complete = async ({ argv, id, offset, textDocument, uri } ) => {
66
+ export const complete = async ({ argv, id, offset, rootUri, textDocument, uri } ) => {
65
67
  const normalizedDocument = {
66
68
  ...textDocument,
67
69
  uri: normalizeLanguageServerDocumentUri(textDocument.uri),
68
70
  }
69
- const rootUri = getRootUri(normalizedDocument.uri)
70
- const connection = getConnection(`${id}:${rootUri}`, uri, argv, rootUri)
71
+ const normalizedRootUri = rootUri ? normalizeLanguageServerDocumentUri(rootUri) : getRootUri(normalizedDocument.uri)
72
+ const connection = getConnection(`${id}:${normalizedRootUri}`, uri, argv, normalizedRootUri)
71
73
  return connection.complete(normalizedDocument, offset)
72
74
  }
73
75
 
74
- export const diagnostic = async ({ argv, id, textDocument, uri } ) => {
76
+ export const diagnostic = async ({ argv, id, rootUri, textDocument, uri } ) => {
75
77
  const normalizedDocument = {
76
78
  ...textDocument,
77
79
  uri: normalizeLanguageServerDocumentUri(textDocument.uri),
78
80
  }
79
- const rootUri = getRootUri(normalizedDocument.uri)
80
- const connection = getConnection(`${id}:${rootUri}`, uri, argv, rootUri)
81
+ const normalizedRootUri = rootUri ? normalizeLanguageServerDocumentUri(rootUri) : getRootUri(normalizedDocument.uri)
82
+ const connection = getConnection(`${id}:${normalizedRootUri}`, uri, argv, normalizedRootUri)
81
83
  return connection.diagnostic(normalizedDocument)
82
84
  }
83
85
 
@@ -23,6 +23,22 @@ import {
23
23
 
24
24
 
25
25
 
26
+
27
+
28
+
29
+
30
+
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+
41
+
26
42
 
27
43
 
28
44
 
@@ -74,17 +90,40 @@ const getWorkspaceName = (rootUri) => {
74
90
  }
75
91
  }
76
92
 
93
+ const createDeferred = () => {
94
+ let resolve = () => {}
95
+ const promise = new Promise ((resolvePromise) => {
96
+ resolve = resolvePromise
97
+ })
98
+ return { promise, resolve }
99
+ }
100
+
101
+ const wait = (duration) => {
102
+ return new Promise((resolve) => {
103
+ setTimeout(resolve, duration)
104
+ })
105
+ }
106
+
107
+ const PublishDiagnosticsTimeout = 1_000
108
+
77
109
  export class LanguageServerConnection {
78
110
  child
111
+ configurationHandled = createDeferred()
112
+ diagnosticWaiters = new Map ()
79
113
  documents = new Map ()
114
+ initializationProgressEnded = createDeferred()
115
+ initializationProgressStarted = createDeferred()
80
116
  parser = new LanguageServerMessageParser()
81
117
  pendingRequests = new Map ()
118
+ publishedDiagnostics = new Map ()
82
119
  ready
83
120
  rootUri
121
+ initializationProgressWasStarted = false
84
122
  markdownConfigured = false
85
123
  nextRequestId = 1
86
124
  running = true
87
125
  stderr = ''
126
+ supportsPullDiagnostics = false
88
127
 
89
128
  constructor({ argv, rootUri, uri } ) {
90
129
  this.rootUri = rootUri
@@ -147,16 +186,29 @@ export class LanguageServerConnection {
147
186
  async diagnostic(textDocument) {
148
187
  await this.ready
149
188
  this.configureMarkdown(textDocument.languageId)
150
- this.syncDocument(textDocument)
151
- const result = await this.sendRequest('textDocument/diagnostic', {
152
- textDocument: {
153
- uri: textDocument.uri,
154
- },
155
- })
156
- if (result && typeof result === 'object' && Array.isArray((result).items)) {
157
- return (result).items
189
+ if (this.supportsPullDiagnostics) {
190
+ this.syncDocument(textDocument)
191
+ const result = await this.sendRequest('textDocument/diagnostic', {
192
+ textDocument: {
193
+ uri: textDocument.uri,
194
+ },
195
+ })
196
+ if (result && typeof result === 'object' && Array.isArray((result).items)) {
197
+ return (result).items
198
+ }
199
+ return []
158
200
  }
159
- return []
201
+ const previous = this.documents.get(textDocument.uri)
202
+ const documentChanged = !previous || previous.languageId !== textDocument.languageId || previous.text !== textDocument.text
203
+ const cached = this.publishedDiagnostics.get(textDocument.uri)
204
+ if (!documentChanged && cached) {
205
+ return cached
206
+ }
207
+ const diagnostics = this.waitForPublishedDiagnostics(textDocument.uri)
208
+ if (documentChanged) {
209
+ this.syncDocument(textDocument)
210
+ }
211
+ return diagnostics
160
212
  }
161
213
 
162
214
  configureMarkdown(languageId) {
@@ -206,7 +258,7 @@ export class LanguageServerConnection {
206
258
  }
207
259
 
208
260
  async initialize() {
209
- await this.sendRequest('initialize', {
261
+ const result = (await this.sendRequest('initialize', {
210
262
  capabilities: {
211
263
  textDocument: {
212
264
  completion: {
@@ -218,11 +270,17 @@ export class LanguageServerConnection {
218
270
  dynamicRegistration: false,
219
271
  relatedDocumentSupport: false,
220
272
  },
273
+ publishDiagnostics: {
274
+ relatedInformation: true,
275
+ },
221
276
  synchronization: {
222
277
  didSave: true,
223
278
  dynamicRegistration: false,
224
279
  },
225
280
  },
281
+ window: {
282
+ workDoneProgress: true,
283
+ },
226
284
  workspace: {
227
285
  configuration: true,
228
286
  workspaceFolders: true,
@@ -239,8 +297,15 @@ export class LanguageServerConnection {
239
297
  uri: this.rootUri,
240
298
  },
241
299
  ],
242
- })
300
+ }))
301
+ this.supportsPullDiagnostics = Boolean(result?.capabilities?.diagnosticProvider)
243
302
  this.sendNotification('initialized', {})
303
+ await Promise.race([this.initializationProgressStarted.promise, wait(100)])
304
+ if (this.initializationProgressWasStarted) {
305
+ await Promise.race([this.initializationProgressEnded.promise, wait(30_000)])
306
+ }
307
+ await Promise.race([this.configurationHandled.promise, wait(100)])
308
+ await wait(0)
244
309
  }
245
310
 
246
311
  syncDocument(textDocument) {
@@ -303,6 +368,14 @@ export class LanguageServerConnection {
303
368
  }
304
369
 
305
370
  handleMessage(message) {
371
+ if (message.method === 'textDocument/publishDiagnostics') {
372
+ this.handlePublishedDiagnostics(message.params)
373
+ return
374
+ }
375
+ if (message.method === '$/progress') {
376
+ this.handleProgress(message.params)
377
+ return
378
+ }
306
379
  if (message.method && message.id !== undefined && message.id !== null) {
307
380
  void this.handleServerRequest(message)
308
381
  return
@@ -322,12 +395,45 @@ export class LanguageServerConnection {
322
395
  pending.resolve(message.result)
323
396
  }
324
397
 
398
+ handlePublishedDiagnostics(params) {
399
+ if (!params || typeof params !== 'object') {
400
+ return
401
+ }
402
+ const { diagnostics, uri } = params
403
+ if (typeof uri !== 'string' || !Array.isArray(diagnostics)) {
404
+ return
405
+ }
406
+ this.publishedDiagnostics.set(uri, diagnostics)
407
+ const waiters = this.diagnosticWaiters.get(uri)
408
+ if (!waiters) {
409
+ return
410
+ }
411
+ this.diagnosticWaiters.delete(uri)
412
+ for (const waiter of waiters) {
413
+ waiter.resolve(diagnostics)
414
+ }
415
+ }
416
+
417
+ handleProgress(params) {
418
+ if (!params || typeof params !== 'object') {
419
+ return
420
+ }
421
+ const { value } = params
422
+ if (!value || typeof value !== 'object' || (value).kind !== 'end') {
423
+ return
424
+ }
425
+ this.initializationProgressEnded.resolve()
426
+ }
427
+
325
428
  async handleServerRequest(message) {
326
429
  try {
327
430
  let result = null
328
431
  if (message.method === 'workspace/configuration') {
329
432
  const itemCount = Array.isArray(message.params?.items) ? message.params.items.length : 0
330
433
  result = Array.from({ length: itemCount }).fill(null)
434
+ } else if (message.method === 'window/workDoneProgress/create') {
435
+ this.initializationProgressWasStarted = true
436
+ this.initializationProgressStarted.resolve()
331
437
  } else if (message.method === 'workspace/workspaceFolders') {
332
438
  result = [
333
439
  {
@@ -346,6 +452,9 @@ export class LanguageServerConnection {
346
452
  jsonrpc: '2.0',
347
453
  result,
348
454
  })
455
+ if (message.method === 'workspace/configuration') {
456
+ this.configurationHandled.resolve()
457
+ }
349
458
  } catch (error) {
350
459
  this.sendMessage({
351
460
  error: {
@@ -371,6 +480,12 @@ export class LanguageServerConnection {
371
480
  pending.reject(error)
372
481
  }
373
482
  this.pendingRequests.clear()
483
+ for (const waiters of this.diagnosticWaiters.values()) {
484
+ for (const waiter of waiters) {
485
+ waiter.reject(error)
486
+ }
487
+ }
488
+ this.diagnosticWaiters.clear()
374
489
  }
375
490
 
376
491
  sendNotification(method, params) {
@@ -398,6 +513,32 @@ export class LanguageServerConnection {
398
513
  return promise
399
514
  }
400
515
 
516
+ waitForPublishedDiagnostics(uri) {
517
+ return new Promise ((resolve, reject) => {
518
+ const waiters = this.diagnosticWaiters.get(uri) || new Set()
519
+ let timeout
520
+ const waiter = {
521
+ reject(error) {
522
+ clearTimeout(timeout)
523
+ reject(error)
524
+ },
525
+ resolve(value) {
526
+ clearTimeout(timeout)
527
+ resolve(value)
528
+ },
529
+ }
530
+ timeout = setTimeout(() => {
531
+ waiters.delete(waiter)
532
+ if (waiters.size === 0) {
533
+ this.diagnosticWaiters.delete(uri)
534
+ }
535
+ resolve(this.publishedDiagnostics.get(uri) || [])
536
+ }, PublishDiagnosticsTimeout)
537
+ waiters.add(waiter)
538
+ this.diagnosticWaiters.set(uri, waiters)
539
+ })
540
+ }
541
+
401
542
  sendMessage(message) {
402
543
  const content = JSON.stringify(message)
403
544
  const header = `Content-Length: ${Buffer.byteLength(content)}\r\n\r\n`
@@ -2,9 +2,22 @@ import { pathToFileURL } from 'node:url'
2
2
 
3
3
  const windowsFileUriRegex = /^file:\/\/\/([a-z])(?::|%3a)(?=\/|$)/i
4
4
 
5
+ const normalizeRemoteFileUrl = (uri) => {
6
+ try {
7
+ const url = new URL(uri)
8
+ if ((url.protocol === 'http:' || url.protocol === 'https:') && url.pathname.startsWith('/remote/')) {
9
+ return `file://${url.pathname.slice('/remote'.length)}`
10
+ }
11
+ } catch {
12
+ return undefined
13
+ }
14
+ return undefined
15
+ }
16
+
5
17
  export const normalizeLanguageServerDocumentUri = (uri) => {
6
18
  if (uri.startsWith('/')) {
7
19
  return pathToFileURL(uri).href
8
20
  }
9
- return uri.replace(windowsFileUriRegex, (_, driveLetter) => `file:///${driveLetter.toLowerCase()}%3A`)
21
+ const normalizedUri = normalizeRemoteFileUrl(uri) || uri
22
+ return normalizedUri.replace(windowsFileUriRegex, (_, driveLetter) => `file:///${driveLetter.toLowerCase()}%3A`)
10
23
  }
@@ -61,11 +61,11 @@ export const getSetupName = () => {
61
61
  return 'Lvce-Setup'
62
62
  }
63
63
 
64
- export const version = '0.95.1'
64
+ export const version = '0.95.3'
65
65
 
66
- export const commit = '2572a83'
66
+ export const commit = '6f688db'
67
67
 
68
- export const date = '2026-07-29T14:03:33.000Z'
68
+ export const date = '2026-07-29T19:12:57.000Z'
69
69
 
70
70
  export const getVersion = () => {
71
71
  return version
@@ -2,5 +2,5 @@ import { join } from 'node:path'
2
2
  import * as Root from '../Root/Root.js'
3
3
 
4
4
  export const getPreloadUrl = () => {
5
- return join(Root.root, 'static', '2572a83', 'packages', 'preload', 'dist', 'index.js')
5
+ return join(Root.root, 'static', '6f688db', 'packages', 'preload', 'dist', 'index.js')
6
6
  }