codemirror-languageserver 1.13.0 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/demo/demo.js +84 -0
- package/demo/dist/demo.js +40349 -0
- package/demo/index.html +17 -0
- package/dist/index.d.ts +9 -9
- package/dist/index.js +62 -42
- package/package.json +53 -46
- package/rollup.config.demo.js +30 -0
package/demo/index.html
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>CodeMirror Language Server Demo</title>
|
|
5
|
+
<link
|
|
6
|
+
type="text/css"
|
|
7
|
+
rel="stylesheet"
|
|
8
|
+
href="https://cdn.jsdelivr.net/gh/FurqanSoftware/sleek@v1.52.4/dist/sleek.css"
|
|
9
|
+
/>
|
|
10
|
+
</head>
|
|
11
|
+
<body class="p-1">
|
|
12
|
+
<div class="form__field br-1-4">
|
|
13
|
+
<div id="editor"></div>
|
|
14
|
+
</div>
|
|
15
|
+
<script type="module" src="./dist/demo.js"></script>
|
|
16
|
+
</body>
|
|
17
|
+
</html>
|
package/dist/index.d.ts
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { EditorView, Tooltip } from
|
|
2
|
-
import { CompletionTriggerKind } from
|
|
3
|
-
import type { CompletionContext, CompletionResult } from
|
|
4
|
-
import type { PluginValue, ViewUpdate } from
|
|
5
|
-
import { Transport } from
|
|
6
|
-
import type { PublishDiagnosticsParams } from
|
|
7
|
-
import type * as LSP from
|
|
1
|
+
import { EditorView, Tooltip } from '@codemirror/view';
|
|
2
|
+
import { CompletionTriggerKind } from 'vscode-languageserver-protocol';
|
|
3
|
+
import type { CompletionContext, CompletionResult } from '@codemirror/autocomplete';
|
|
4
|
+
import type { PluginValue, ViewUpdate } from '@codemirror/view';
|
|
5
|
+
import { Transport } from '@open-rpc/client-js/build/transports/Transport';
|
|
6
|
+
import type { PublishDiagnosticsParams } from 'vscode-languageserver-protocol';
|
|
7
|
+
import type * as LSP from 'vscode-languageserver-protocol';
|
|
8
8
|
interface LSPEventMap {
|
|
9
|
-
|
|
9
|
+
'textDocument/publishDiagnostics': LSP.PublishDiagnosticsParams;
|
|
10
10
|
}
|
|
11
11
|
type Notification = {
|
|
12
12
|
[key in keyof LSPEventMap]: {
|
|
13
|
-
jsonrpc:
|
|
13
|
+
jsonrpc: '2.0';
|
|
14
14
|
id?: null | undefined;
|
|
15
15
|
method: key;
|
|
16
16
|
params: LSPEventMap[key];
|
package/dist/index.js
CHANGED
|
@@ -4,13 +4,15 @@ import { Facet } from '@codemirror/state';
|
|
|
4
4
|
import { ViewPlugin, hoverTooltip } from '@codemirror/view';
|
|
5
5
|
import { RequestManager, Client, WebSocketTransport } from '@open-rpc/client-js';
|
|
6
6
|
import { CompletionItemKind, CompletionTriggerKind, DiagnosticSeverity } from 'vscode-languageserver-protocol';
|
|
7
|
-
import { marked } from 'marked
|
|
7
|
+
import { marked } from 'marked';
|
|
8
8
|
|
|
9
9
|
const timeout = 10000;
|
|
10
10
|
const changesDelay = 500;
|
|
11
11
|
const CompletionItemKindMap = Object.fromEntries(Object.entries(CompletionItemKind).map(([key, value]) => [value, key]));
|
|
12
|
-
const useLast = (values) => values.reduce((_, v) => v,
|
|
13
|
-
const client = Facet.define({
|
|
12
|
+
const useLast = (values) => values.reduce((_, v) => v, '');
|
|
13
|
+
const client = Facet.define({
|
|
14
|
+
combine: useLast,
|
|
15
|
+
});
|
|
14
16
|
const documentUri = Facet.define({ combine: useLast });
|
|
15
17
|
const languageId = Facet.define({ combine: useLast });
|
|
16
18
|
class LanguageServerClient {
|
|
@@ -29,11 +31,11 @@ class LanguageServerClient {
|
|
|
29
31
|
if (webSocketTransport && webSocketTransport.connection) {
|
|
30
32
|
// XXX(hjr265): Need a better way to do this. Relevant issue:
|
|
31
33
|
// https://github.com/FurqanSoftware/codemirror-languageserver/issues/9
|
|
32
|
-
webSocketTransport.connection.addEventListener(
|
|
34
|
+
webSocketTransport.connection.addEventListener('message', (message) => {
|
|
33
35
|
const data = JSON.parse(message.data);
|
|
34
36
|
if (data.method && data.id) {
|
|
35
37
|
webSocketTransport.connection.send(JSON.stringify({
|
|
36
|
-
jsonrpc:
|
|
38
|
+
jsonrpc: '2.0',
|
|
37
39
|
id: data.id,
|
|
38
40
|
result: null,
|
|
39
41
|
}));
|
|
@@ -43,12 +45,12 @@ class LanguageServerClient {
|
|
|
43
45
|
this.initializePromise = this.initialize();
|
|
44
46
|
}
|
|
45
47
|
async initialize() {
|
|
46
|
-
const { capabilities } = await this.request(
|
|
48
|
+
const { capabilities } = await this.request('initialize', {
|
|
47
49
|
capabilities: {
|
|
48
50
|
textDocument: {
|
|
49
51
|
hover: {
|
|
50
52
|
dynamicRegistration: true,
|
|
51
|
-
contentFormat: [
|
|
53
|
+
contentFormat: ['plaintext', 'markdown'],
|
|
52
54
|
},
|
|
53
55
|
moniker: {},
|
|
54
56
|
synchronization: {
|
|
@@ -62,7 +64,7 @@ class LanguageServerClient {
|
|
|
62
64
|
completionItem: {
|
|
63
65
|
snippetSupport: false,
|
|
64
66
|
commitCharactersSupport: true,
|
|
65
|
-
documentationFormat: [
|
|
67
|
+
documentationFormat: ['plaintext', 'markdown'],
|
|
66
68
|
deprecatedSupport: false,
|
|
67
69
|
preselectSupport: false,
|
|
68
70
|
},
|
|
@@ -71,7 +73,7 @@ class LanguageServerClient {
|
|
|
71
73
|
signatureHelp: {
|
|
72
74
|
dynamicRegistration: true,
|
|
73
75
|
signatureInformation: {
|
|
74
|
-
documentationFormat: [
|
|
76
|
+
documentationFormat: ['plaintext', 'markdown'],
|
|
75
77
|
},
|
|
76
78
|
},
|
|
77
79
|
declaration: {
|
|
@@ -103,23 +105,23 @@ class LanguageServerClient {
|
|
|
103
105
|
workspaceFolders: this.workspaceFolders,
|
|
104
106
|
}, timeout * 3);
|
|
105
107
|
this.capabilities = capabilities;
|
|
106
|
-
this.notify(
|
|
108
|
+
this.notify('initialized', {});
|
|
107
109
|
this.ready = true;
|
|
108
110
|
}
|
|
109
111
|
close() {
|
|
110
112
|
this.client.close();
|
|
111
113
|
}
|
|
112
114
|
textDocumentDidOpen(params) {
|
|
113
|
-
return this.notify(
|
|
115
|
+
return this.notify('textDocument/didOpen', params);
|
|
114
116
|
}
|
|
115
117
|
textDocumentDidChange(params) {
|
|
116
|
-
return this.notify(
|
|
118
|
+
return this.notify('textDocument/didChange', params);
|
|
117
119
|
}
|
|
118
120
|
async textDocumentHover(params) {
|
|
119
|
-
return await this.request(
|
|
121
|
+
return await this.request('textDocument/hover', params, timeout);
|
|
120
122
|
}
|
|
121
123
|
async textDocumentCompletion(params) {
|
|
122
|
-
return await this.request(
|
|
124
|
+
return await this.request('textDocument/completion', params, timeout);
|
|
123
125
|
}
|
|
124
126
|
attachPlugin(plugin) {
|
|
125
127
|
this.plugins.push(plugin);
|
|
@@ -231,13 +233,13 @@ class LanguageServerPlugin {
|
|
|
231
233
|
if (pos === null) {
|
|
232
234
|
return null;
|
|
233
235
|
}
|
|
234
|
-
const dom = document.createElement(
|
|
235
|
-
dom.classList.add(
|
|
236
|
+
const dom = document.createElement('div');
|
|
237
|
+
dom.classList.add('documentation');
|
|
236
238
|
if (this.allowHTMLContent) {
|
|
237
|
-
dom.innerHTML = formatContents(contents);
|
|
239
|
+
dom.innerHTML = await formatContents(contents);
|
|
238
240
|
}
|
|
239
241
|
else {
|
|
240
|
-
dom.textContent = formatContents(contents);
|
|
242
|
+
dom.textContent = await formatContents(contents);
|
|
241
243
|
}
|
|
242
244
|
return {
|
|
243
245
|
pos,
|
|
@@ -247,7 +249,8 @@ class LanguageServerPlugin {
|
|
|
247
249
|
};
|
|
248
250
|
}
|
|
249
251
|
async requestCompletion(context, { line, character }, { triggerKind, triggerCharacter, }) {
|
|
250
|
-
if (!this.client.ready ||
|
|
252
|
+
if (!this.client.ready ||
|
|
253
|
+
!this.client.capabilities.completionProvider) {
|
|
251
254
|
return null;
|
|
252
255
|
}
|
|
253
256
|
this.sendChange({
|
|
@@ -264,7 +267,7 @@ class LanguageServerPlugin {
|
|
|
264
267
|
if (!result) {
|
|
265
268
|
return null;
|
|
266
269
|
}
|
|
267
|
-
let items =
|
|
270
|
+
let items = 'items' in result ? result.items : result;
|
|
268
271
|
const [span, match] = prefixMatch(items);
|
|
269
272
|
const token = context.matchBefore(match);
|
|
270
273
|
let { pos } = context;
|
|
@@ -309,10 +312,12 @@ class LanguageServerPlugin {
|
|
|
309
312
|
}
|
|
310
313
|
additionalTextEdits
|
|
311
314
|
.sort(({ range: { end: a } }, { range: { end: b } }) => {
|
|
312
|
-
if (posToOffset(view.state.doc, a) <
|
|
315
|
+
if (posToOffset(view.state.doc, a) <
|
|
316
|
+
posToOffset(view.state.doc, b)) {
|
|
313
317
|
return 1;
|
|
314
318
|
}
|
|
315
|
-
else if (posToOffset(view.state.doc, a) >
|
|
319
|
+
else if (posToOffset(view.state.doc, a) >
|
|
320
|
+
posToOffset(view.state.doc, b)) {
|
|
316
321
|
return -1;
|
|
317
322
|
}
|
|
318
323
|
return 0;
|
|
@@ -330,7 +335,18 @@ class LanguageServerPlugin {
|
|
|
330
335
|
type: kind && CompletionItemKindMap[kind].toLowerCase(),
|
|
331
336
|
};
|
|
332
337
|
if (documentation) {
|
|
333
|
-
completion.info =
|
|
338
|
+
completion.info = async () => {
|
|
339
|
+
const dom = document.createElement('div');
|
|
340
|
+
dom.classList.add('documentation');
|
|
341
|
+
if (this.allowHTMLContent) {
|
|
342
|
+
dom.innerHTML = await formatContents(documentation);
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
dom.textContent =
|
|
346
|
+
await formatContents(documentation);
|
|
347
|
+
}
|
|
348
|
+
return dom;
|
|
349
|
+
};
|
|
334
350
|
}
|
|
335
351
|
return completion;
|
|
336
352
|
});
|
|
@@ -343,7 +359,7 @@ class LanguageServerPlugin {
|
|
|
343
359
|
processNotification(notification) {
|
|
344
360
|
try {
|
|
345
361
|
switch (notification.method) {
|
|
346
|
-
case
|
|
362
|
+
case 'textDocument/publishDiagnostics':
|
|
347
363
|
this.processDiagnostics(notification.params);
|
|
348
364
|
}
|
|
349
365
|
}
|
|
@@ -360,14 +376,17 @@ class LanguageServerPlugin {
|
|
|
360
376
|
from: posToOffset(this.view.state.doc, range.start),
|
|
361
377
|
to: posToOffset(this.view.state.doc, range.end),
|
|
362
378
|
severity: {
|
|
363
|
-
[DiagnosticSeverity.Error]:
|
|
364
|
-
[DiagnosticSeverity.Warning]:
|
|
365
|
-
[DiagnosticSeverity.Information]:
|
|
366
|
-
[DiagnosticSeverity.Hint]:
|
|
379
|
+
[DiagnosticSeverity.Error]: 'error',
|
|
380
|
+
[DiagnosticSeverity.Warning]: 'warning',
|
|
381
|
+
[DiagnosticSeverity.Information]: 'info',
|
|
382
|
+
[DiagnosticSeverity.Hint]: 'info',
|
|
367
383
|
}[severity],
|
|
368
384
|
message,
|
|
369
385
|
}))
|
|
370
|
-
.filter(({ from, to }) => from !== null &&
|
|
386
|
+
.filter(({ from, to }) => from !== null &&
|
|
387
|
+
to !== null &&
|
|
388
|
+
from !== undefined &&
|
|
389
|
+
to !== undefined)
|
|
371
390
|
.sort((a, b) => {
|
|
372
391
|
switch (true) {
|
|
373
392
|
case a.from < b.from:
|
|
@@ -391,7 +410,8 @@ function languageServer(options) {
|
|
|
391
410
|
function languageServerWithTransport(options) {
|
|
392
411
|
let plugin = null;
|
|
393
412
|
return [
|
|
394
|
-
client.of(options.client ||
|
|
413
|
+
client.of(options.client ||
|
|
414
|
+
new LanguageServerClient({ ...options, autoClose: true })),
|
|
395
415
|
documentUri.of(options.documentUri),
|
|
396
416
|
languageId.of(options.languageId),
|
|
397
417
|
ViewPlugin.define((view) => (plugin = new LanguageServerPlugin(view, options.allowHTMLContent))),
|
|
@@ -445,30 +465,30 @@ function offsetToPos(doc, offset) {
|
|
|
445
465
|
line: line.number - 1,
|
|
446
466
|
};
|
|
447
467
|
}
|
|
448
|
-
function formatContents(contents) {
|
|
468
|
+
async function formatContents(contents) {
|
|
449
469
|
if (isLSPMarkupContent(contents)) {
|
|
450
470
|
let value = contents.value;
|
|
451
|
-
if (contents.kind ===
|
|
452
|
-
value = marked.parse(value);
|
|
471
|
+
if (contents.kind === 'markdown') {
|
|
472
|
+
value = await marked.parse(value);
|
|
453
473
|
}
|
|
454
474
|
return value;
|
|
455
475
|
}
|
|
456
476
|
else if (Array.isArray(contents)) {
|
|
457
|
-
return contents.map((c) => formatContents(c) +
|
|
477
|
+
return contents.map((c) => formatContents(c) + '\n\n').join('');
|
|
458
478
|
}
|
|
459
|
-
else if (typeof contents ===
|
|
479
|
+
else if (typeof contents === 'string') {
|
|
460
480
|
return contents;
|
|
461
481
|
}
|
|
462
482
|
}
|
|
463
483
|
function toSet(chars) {
|
|
464
|
-
let preamble =
|
|
465
|
-
let flat = Array.from(chars).join(
|
|
484
|
+
let preamble = '';
|
|
485
|
+
let flat = Array.from(chars).join('');
|
|
466
486
|
const words = /\w/.test(flat);
|
|
467
487
|
if (words) {
|
|
468
|
-
preamble +=
|
|
469
|
-
flat = flat.replace(/\w/g,
|
|
488
|
+
preamble += '\\w';
|
|
489
|
+
flat = flat.replace(/\w/g, '');
|
|
470
490
|
}
|
|
471
|
-
return `[${preamble}${flat.replace(/[^\w\s]/g,
|
|
491
|
+
return `[${preamble}${flat.replace(/[^\w\s]/g, '\\$&')}]`;
|
|
472
492
|
}
|
|
473
493
|
function prefixMatch(items) {
|
|
474
494
|
var _a;
|
|
@@ -481,8 +501,8 @@ function prefixMatch(items) {
|
|
|
481
501
|
rest.add(char);
|
|
482
502
|
}
|
|
483
503
|
}
|
|
484
|
-
const source = toSet(first) + toSet(rest) +
|
|
485
|
-
return [new RegExp(
|
|
504
|
+
const source = toSet(first) + toSet(rest) + '*$';
|
|
505
|
+
return [new RegExp('^' + source), new RegExp(source)];
|
|
486
506
|
}
|
|
487
507
|
function isLSPTextEdit(textEdit) {
|
|
488
508
|
return (textEdit === null || textEdit === void 0 ? void 0 : textEdit.range) !== undefined;
|
package/package.json
CHANGED
|
@@ -1,48 +1,55 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
2
|
+
"name": "codemirror-languageserver",
|
|
3
|
+
"version": "1.14.0",
|
|
4
|
+
"description": "Language Server Plugin for CodeMirror 6",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"prepare": "rollup -c rollup.config.js"
|
|
9
|
+
},
|
|
10
|
+
"author": {
|
|
11
|
+
"name": "Mahmud Ridwan",
|
|
12
|
+
"email": "m@hjr265.me",
|
|
13
|
+
"url": "https://hjr265.me"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/FurqanSoftware/codemirror-languageserver",
|
|
16
|
+
"bugs": {
|
|
17
|
+
"url": "https://github.com/FurqanSoftware/codemirror-languageserver/issues"
|
|
18
|
+
},
|
|
19
|
+
"repository": {
|
|
20
|
+
"type": "git",
|
|
21
|
+
"url": "https://github.com/FurqanSoftware/codemirror-languageserver.git"
|
|
22
|
+
},
|
|
23
|
+
"license": "BSD-3-Clause",
|
|
24
|
+
"devDependencies": {
|
|
25
|
+
"@babel/core": "^7.28.0",
|
|
26
|
+
"@babel/preset-env": "^7.28.0",
|
|
27
|
+
"@codemirror/commands": "^6.8.1",
|
|
28
|
+
"@codemirror/lang-cpp": "^6.0.3",
|
|
29
|
+
"@codemirror/search": "^6.5.11",
|
|
30
|
+
"@rollup/plugin-babel": "^6.0.4",
|
|
31
|
+
"@rollup/plugin-commonjs": "^28.0.6",
|
|
32
|
+
"@rollup/plugin-node-resolve": "^16.0.1",
|
|
33
|
+
"@rollup/plugin-typescript": "^12.1.4",
|
|
34
|
+
"prettier": "^3.6.2",
|
|
35
|
+
"rollup": "^4.46.2",
|
|
36
|
+
"rollup-plugin-node-polyfills": "^0.2.1",
|
|
37
|
+
"rollup-plugin-serve": "^3.0.0",
|
|
38
|
+
"tslib": "^2.8.1",
|
|
39
|
+
"tslint": "^6.1.3",
|
|
40
|
+
"typescript": "^5.9.2"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"@codemirror/autocomplete": "^6.18.6",
|
|
44
|
+
"@codemirror/lint": "^6.8.5",
|
|
45
|
+
"@codemirror/state": "^6.5.2",
|
|
46
|
+
"@codemirror/view": "^6.38.1",
|
|
47
|
+
"@open-rpc/client-js": "^1.8.1",
|
|
48
|
+
"marked": "^16.1.2",
|
|
49
|
+
"vscode-languageserver-protocol": "^3.17.5"
|
|
50
|
+
},
|
|
51
|
+
"prettier": {
|
|
52
|
+
"tabWidth": 4,
|
|
53
|
+
"singleQuote": true
|
|
54
|
+
}
|
|
48
55
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import babel from '@rollup/plugin-babel';
|
|
2
|
+
import typescript from '@rollup/plugin-typescript';
|
|
3
|
+
import serve from 'rollup-plugin-serve';
|
|
4
|
+
import { nodeResolve } from '@rollup/plugin-node-resolve';
|
|
5
|
+
import commonjs from '@rollup/plugin-commonjs';
|
|
6
|
+
import nodePolyfills from 'rollup-plugin-node-polyfills';
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
input: 'demo/demo.js',
|
|
10
|
+
output: {
|
|
11
|
+
dir: 'demo/dist',
|
|
12
|
+
format: 'es',
|
|
13
|
+
intro: 'const global = window;',
|
|
14
|
+
},
|
|
15
|
+
plugins: [
|
|
16
|
+
typescript({
|
|
17
|
+
declaration: false,
|
|
18
|
+
}),
|
|
19
|
+
babel({
|
|
20
|
+
babelHelpers: 'bundled',
|
|
21
|
+
}),
|
|
22
|
+
nodeResolve({
|
|
23
|
+
browser: true,
|
|
24
|
+
preferBuiltins: true,
|
|
25
|
+
}),
|
|
26
|
+
commonjs(),
|
|
27
|
+
nodePolyfills(),
|
|
28
|
+
serve('./demo'),
|
|
29
|
+
],
|
|
30
|
+
};
|