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.
@@ -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 "@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";
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
- "textDocument/publishDiagnostics": LSP.PublishDiagnosticsParams;
9
+ 'textDocument/publishDiagnostics': LSP.PublishDiagnosticsParams;
10
10
  }
11
11
  type Notification = {
12
12
  [key in keyof LSPEventMap]: {
13
- jsonrpc: "2.0";
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/lib/marked.esm.js';
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({ combine: useLast });
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("message", (message) => {
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: "2.0",
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("initialize", {
48
+ const { capabilities } = await this.request('initialize', {
47
49
  capabilities: {
48
50
  textDocument: {
49
51
  hover: {
50
52
  dynamicRegistration: true,
51
- contentFormat: ["plaintext", "markdown"],
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: ["plaintext", "markdown"],
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: ["plaintext", "markdown"],
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("initialized", {});
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("textDocument/didOpen", params);
115
+ return this.notify('textDocument/didOpen', params);
114
116
  }
115
117
  textDocumentDidChange(params) {
116
- return this.notify("textDocument/didChange", params);
118
+ return this.notify('textDocument/didChange', params);
117
119
  }
118
120
  async textDocumentHover(params) {
119
- return await this.request("textDocument/hover", params, timeout);
121
+ return await this.request('textDocument/hover', params, timeout);
120
122
  }
121
123
  async textDocumentCompletion(params) {
122
- return await this.request("textDocument/completion", params, timeout);
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("div");
235
- dom.classList.add("documentation");
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 || !this.client.capabilities.completionProvider) {
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 = "items" in result ? result.items : result;
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) < posToOffset(view.state.doc, b)) {
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) > posToOffset(view.state.doc, b)) {
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 = formatContents(documentation);
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 "textDocument/publishDiagnostics":
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]: "error",
364
- [DiagnosticSeverity.Warning]: "warning",
365
- [DiagnosticSeverity.Information]: "info",
366
- [DiagnosticSeverity.Hint]: "info",
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 && to !== null && from !== undefined && to !== undefined)
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 || new LanguageServerClient({ ...options, autoClose: true })),
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 === "markdown") {
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) + "\n\n").join("");
477
+ return contents.map((c) => formatContents(c) + '\n\n').join('');
458
478
  }
459
- else if (typeof contents === "string") {
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 += "\\w";
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("^" + source), new RegExp(source)];
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
- "name": "codemirror-languageserver",
3
- "version": "1.13.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
- "@rollup/plugin-babel": "^6.0.4",
28
- "@rollup/plugin-typescript": "^12.1.4",
29
- "prettier": "^3.6.2",
30
- "rollup": "^4.46.2",
31
- "tslib": "^2.8.1",
32
- "tslint": "^6.1.3",
33
- "typescript": "^5.9.2"
34
- },
35
- "dependencies": {
36
- "@codemirror/autocomplete": "^6.18.6",
37
- "@codemirror/lint": "^6.8.5",
38
- "@codemirror/state": "^6.5.2",
39
- "@codemirror/view": "^6.38.1",
40
- "@open-rpc/client-js": "^1.8.1",
41
- "marked": "^16.1.2",
42
- "vscode-languageserver-protocol": "^3.17.5"
43
- },
44
- "prettier": {
45
- "tabWidth": 4,
46
- "singleQuote": true
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
+ };