codemirror-languageserver 1.10.0 → 1.12.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/README.md +1 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.js +67 -45
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -51,9 +51,7 @@ Contributions are welcome.
|
|
|
51
51
|
|
|
52
52
|
https://user-images.githubusercontent.com/348107/120141150-c6bb9180-c1fd-11eb-8ada-9b7b7a1e4ade.mp4
|
|
53
53
|
|
|
54
|
-
|
|
55
|
-
| --- | --- |
|
|
56
|
-
| [Toph](https://toph.co) | Competitive programming platform |
|
|
54
|
+
- [Toph](https://toph.co): Competitive programming platform. Toph uses Language Server Plugin for CodeMirror 6 with its integrated code editor.
|
|
57
55
|
|
|
58
56
|
## License
|
|
59
57
|
|
package/dist/index.d.ts
CHANGED
|
@@ -40,12 +40,13 @@ declare class LanguageServerClient {
|
|
|
40
40
|
}
|
|
41
41
|
declare class LanguageServerPlugin implements PluginValue {
|
|
42
42
|
private view;
|
|
43
|
+
private allowHTMLContent;
|
|
43
44
|
client: LanguageServerClient;
|
|
44
45
|
private documentUri;
|
|
45
46
|
private languageId;
|
|
46
47
|
private documentVersion;
|
|
47
48
|
private changesTimeout;
|
|
48
|
-
constructor(view: EditorView);
|
|
49
|
+
constructor(view: EditorView, allowHTMLContent: boolean);
|
|
49
50
|
update({ docChanged }: ViewUpdate): void;
|
|
50
51
|
destroy(): void;
|
|
51
52
|
initialize({ documentText }: {
|
|
@@ -81,10 +82,15 @@ interface LanguageServerClientOptions extends LanguageServerBaseOptions {
|
|
|
81
82
|
}
|
|
82
83
|
interface LanguageServerOptions extends LanguageServerClientOptions {
|
|
83
84
|
client?: LanguageServerClient;
|
|
85
|
+
allowHTMLContent?: boolean;
|
|
84
86
|
}
|
|
85
87
|
interface LanguageServerWebsocketOptions extends LanguageServerBaseOptions {
|
|
86
88
|
serverUri: `ws://${string}` | `wss://${string}`;
|
|
87
89
|
}
|
|
88
|
-
declare function languageServer(options: LanguageServerWebsocketOptions):
|
|
89
|
-
|
|
90
|
+
declare function languageServer(options: LanguageServerWebsocketOptions): ({
|
|
91
|
+
extension: import("@codemirror/state").Extension;
|
|
92
|
+
} | readonly import("@codemirror/state").Extension[])[];
|
|
93
|
+
declare function languageServerWithTransport(options: LanguageServerOptions): ({
|
|
94
|
+
extension: import("@codemirror/state").Extension;
|
|
95
|
+
} | readonly import("@codemirror/state").Extension[])[];
|
|
90
96
|
export { LanguageServerClient, languageServer, languageServerWithTransport };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { autocompletion } from '@codemirror/autocomplete';
|
|
1
|
+
import { autocompletion, insertCompletionText } from '@codemirror/autocomplete';
|
|
2
2
|
import { setDiagnostics } from '@codemirror/lint';
|
|
3
3
|
import { Facet } from '@codemirror/state';
|
|
4
|
-
import {
|
|
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
7
|
|
|
@@ -143,8 +143,9 @@ class LanguageServerClient {
|
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
145
|
class LanguageServerPlugin {
|
|
146
|
-
constructor(view) {
|
|
146
|
+
constructor(view, allowHTMLContent) {
|
|
147
147
|
this.view = view;
|
|
148
|
+
this.allowHTMLContent = allowHTMLContent;
|
|
148
149
|
this.client = this.view.state.facet(client);
|
|
149
150
|
this.documentUri = this.view.state.facet(documentUri);
|
|
150
151
|
this.languageId = this.view.state.facet(languageId);
|
|
@@ -222,7 +223,10 @@ class LanguageServerPlugin {
|
|
|
222
223
|
return null;
|
|
223
224
|
const dom = document.createElement('div');
|
|
224
225
|
dom.classList.add('documentation');
|
|
225
|
-
|
|
226
|
+
if (this.allowHTMLContent)
|
|
227
|
+
dom.innerHTML = formatContents(contents);
|
|
228
|
+
else
|
|
229
|
+
dom.textContent = formatContents(contents);
|
|
226
230
|
return { pos, end, create: (view) => ({ dom }), above: true };
|
|
227
231
|
}
|
|
228
232
|
async requestCompletion(context, { line, character }, { triggerKind, triggerCharacter, }) {
|
|
@@ -241,47 +245,77 @@ class LanguageServerPlugin {
|
|
|
241
245
|
});
|
|
242
246
|
if (!result)
|
|
243
247
|
return null;
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
var _a;
|
|
247
|
-
const completion = {
|
|
248
|
-
label,
|
|
249
|
-
detail,
|
|
250
|
-
apply: (_a = textEdit === null || textEdit === void 0 ? void 0 : textEdit.newText) !== null && _a !== void 0 ? _a : label,
|
|
251
|
-
type: kind && CompletionItemKindMap[kind].toLowerCase(),
|
|
252
|
-
sortText: sortText !== null && sortText !== void 0 ? sortText : label,
|
|
253
|
-
filterText: filterText !== null && filterText !== void 0 ? filterText : label,
|
|
254
|
-
};
|
|
255
|
-
if (documentation) {
|
|
256
|
-
completion.info = formatContents(documentation);
|
|
257
|
-
}
|
|
258
|
-
return completion;
|
|
259
|
-
});
|
|
260
|
-
const [span, match] = prefixMatch(options);
|
|
248
|
+
let items = 'items' in result ? result.items : result;
|
|
249
|
+
const [span, match] = prefixMatch(items);
|
|
261
250
|
const token = context.matchBefore(match);
|
|
262
251
|
let { pos } = context;
|
|
263
252
|
if (token) {
|
|
264
253
|
pos = token.from;
|
|
265
254
|
const word = token.text.toLowerCase();
|
|
266
255
|
if (/^\w+$/.test(word)) {
|
|
267
|
-
|
|
268
|
-
.filter(({ filterText }) =>
|
|
269
|
-
|
|
256
|
+
items = items
|
|
257
|
+
.filter(({ label, filterText }) => {
|
|
258
|
+
const text = filterText !== null && filterText !== void 0 ? filterText : label;
|
|
259
|
+
return text.toLowerCase().startsWith(word);
|
|
260
|
+
})
|
|
261
|
+
.sort((a, b) => {
|
|
262
|
+
var _a, _b;
|
|
263
|
+
const aText = (_a = a.sortText) !== null && _a !== void 0 ? _a : a.label;
|
|
264
|
+
const bText = (_b = b.sortText) !== null && _b !== void 0 ? _b : b.label;
|
|
270
265
|
switch (true) {
|
|
271
|
-
case
|
|
272
|
-
!
|
|
266
|
+
case aText.startsWith(token.text) &&
|
|
267
|
+
!bText.startsWith(token.text):
|
|
273
268
|
return -1;
|
|
274
|
-
case !
|
|
275
|
-
|
|
269
|
+
case !aText.startsWith(token.text) &&
|
|
270
|
+
bText.startsWith(token.text):
|
|
276
271
|
return 1;
|
|
277
272
|
}
|
|
278
273
|
return 0;
|
|
279
274
|
});
|
|
280
275
|
}
|
|
281
276
|
}
|
|
277
|
+
const options = items.map(({ detail, label, kind, textEdit, documentation, additionalTextEdits, }) => {
|
|
278
|
+
const completion = {
|
|
279
|
+
label,
|
|
280
|
+
detail,
|
|
281
|
+
apply: function (view, completion, from, to) {
|
|
282
|
+
var _a;
|
|
283
|
+
const text = (_a = textEdit === null || textEdit === void 0 ? void 0 : textEdit.newText) !== null && _a !== void 0 ? _a : label;
|
|
284
|
+
view.dispatch(insertCompletionText(view.state, text, from, to));
|
|
285
|
+
if (!additionalTextEdits) {
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
additionalTextEdits
|
|
289
|
+
.sort(({ range: { end: a } }, { range: { end: b } }) => {
|
|
290
|
+
if (posToOffset(view.state.doc, a) < posToOffset(view.state.doc, b)) {
|
|
291
|
+
return 1;
|
|
292
|
+
}
|
|
293
|
+
else if (posToOffset(view.state.doc, a) > posToOffset(view.state.doc, b)) {
|
|
294
|
+
return -1;
|
|
295
|
+
}
|
|
296
|
+
return 0;
|
|
297
|
+
})
|
|
298
|
+
.forEach((textEdit) => {
|
|
299
|
+
view.dispatch(view.state.update({
|
|
300
|
+
changes: {
|
|
301
|
+
from: posToOffset(view.state.doc, textEdit.range.start),
|
|
302
|
+
to: posToOffset(view.state.doc, textEdit.range.end),
|
|
303
|
+
insert: textEdit.newText
|
|
304
|
+
}
|
|
305
|
+
}));
|
|
306
|
+
});
|
|
307
|
+
},
|
|
308
|
+
type: kind && CompletionItemKindMap[kind].toLowerCase()
|
|
309
|
+
};
|
|
310
|
+
if (documentation) {
|
|
311
|
+
completion.info = formatContents(documentation);
|
|
312
|
+
}
|
|
313
|
+
return completion;
|
|
314
|
+
});
|
|
282
315
|
return {
|
|
283
316
|
from: pos,
|
|
284
317
|
options,
|
|
318
|
+
filter: false
|
|
285
319
|
};
|
|
286
320
|
}
|
|
287
321
|
processNotification(notification) {
|
|
@@ -337,7 +371,7 @@ function languageServerWithTransport(options) {
|
|
|
337
371
|
client.of(options.client || new LanguageServerClient({ ...options, autoClose: true })),
|
|
338
372
|
documentUri.of(options.documentUri),
|
|
339
373
|
languageId.of(options.languageId),
|
|
340
|
-
ViewPlugin.define((view) => (plugin = new LanguageServerPlugin(view))),
|
|
374
|
+
ViewPlugin.define((view) => (plugin = new LanguageServerPlugin(view, options.allowHTMLContent))),
|
|
341
375
|
hoverTooltip((view, pos) => {
|
|
342
376
|
var _a;
|
|
343
377
|
return (_a = plugin === null || plugin === void 0 ? void 0 : plugin.requestHoverTooltip(view, offsetToPos(view.state.doc, pos))) !== null && _a !== void 0 ? _a : null;
|
|
@@ -368,7 +402,6 @@ function languageServerWithTransport(options) {
|
|
|
368
402
|
},
|
|
369
403
|
],
|
|
370
404
|
}),
|
|
371
|
-
baseTheme,
|
|
372
405
|
];
|
|
373
406
|
}
|
|
374
407
|
function posToOffset(doc, pos) {
|
|
@@ -407,11 +440,12 @@ function toSet(chars) {
|
|
|
407
440
|
}
|
|
408
441
|
return `[${preamble}${flat.replace(/[^\w\s]/g, '\\$&')}]`;
|
|
409
442
|
}
|
|
410
|
-
function prefixMatch(
|
|
443
|
+
function prefixMatch(items) {
|
|
444
|
+
var _a;
|
|
411
445
|
const first = new Set();
|
|
412
446
|
const rest = new Set();
|
|
413
|
-
for (const
|
|
414
|
-
const [initial, ...restStr] =
|
|
447
|
+
for (const item of items) {
|
|
448
|
+
const [initial, ...restStr] = ((_a = item.textEdit) === null || _a === void 0 ? void 0 : _a.newText) || item.label;
|
|
415
449
|
first.add(initial);
|
|
416
450
|
for (const char of restStr) {
|
|
417
451
|
rest.add(char);
|
|
@@ -420,17 +454,5 @@ function prefixMatch(options) {
|
|
|
420
454
|
const source = toSet(first) + toSet(rest) + '*$';
|
|
421
455
|
return [new RegExp('^' + source), new RegExp(source)];
|
|
422
456
|
}
|
|
423
|
-
const baseTheme = EditorView.baseTheme({
|
|
424
|
-
'.cm-tooltip.documentation': {
|
|
425
|
-
display: 'block',
|
|
426
|
-
marginLeft: '0',
|
|
427
|
-
padding: '3px 6px 3px 8px',
|
|
428
|
-
borderLeft: '5px solid #999',
|
|
429
|
-
whiteSpace: 'pre',
|
|
430
|
-
},
|
|
431
|
-
'.cm-tooltip.lint': {
|
|
432
|
-
whiteSpace: 'pre',
|
|
433
|
-
},
|
|
434
|
-
});
|
|
435
457
|
|
|
436
458
|
export { LanguageServerClient, languageServer, languageServerWithTransport };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codemirror-languageserver",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.12.0",
|
|
4
4
|
"description": "Language Server Plugin for CodeMirror 6",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -30,12 +30,12 @@
|
|
|
30
30
|
"typescript": "^4.7.4"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@codemirror/autocomplete": "^6.
|
|
34
|
-
"@codemirror/lint": "^6.
|
|
35
|
-
"@codemirror/state": "^6.1
|
|
36
|
-
"@codemirror/view": "^6.
|
|
37
|
-
"@open-rpc/client-js": "^1.
|
|
38
|
-
"vscode-languageserver-protocol": "^3.
|
|
33
|
+
"@codemirror/autocomplete": "^6.18.4",
|
|
34
|
+
"@codemirror/lint": "^6.8.4",
|
|
35
|
+
"@codemirror/state": "^6.5.1",
|
|
36
|
+
"@codemirror/view": "^6.36.2",
|
|
37
|
+
"@open-rpc/client-js": "^1.8.1",
|
|
38
|
+
"vscode-languageserver-protocol": "^3.17.5"
|
|
39
39
|
},
|
|
40
40
|
"prettier": {
|
|
41
41
|
"tabWidth": 4,
|