codemirror-languageserver 1.20.0 → 1.22.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,115 @@
1
+ import {
2
+ EditorView,
3
+ highlightSpecialChars,
4
+ drawSelection,
5
+ highlightActiveLine,
6
+ keymap,
7
+ lineNumbers,
8
+ panels,
9
+ } from '@codemirror/view';
10
+ import { EditorState } from '@codemirror/state';
11
+ import {
12
+ indentOnInput,
13
+ bracketMatching,
14
+ foldGutter,
15
+ foldKeymap,
16
+ defaultHighlightStyle,
17
+ syntaxHighlighting,
18
+ } from '@codemirror/language';
19
+ import {
20
+ defaultKeymap,
21
+ indentWithTab,
22
+ history,
23
+ historyKeymap,
24
+ } from '@codemirror/commands';
25
+ import { highlightSelectionMatches, searchKeymap } from '@codemirror/search';
26
+ import {
27
+ completionKeymap,
28
+ closeBrackets,
29
+ closeBracketsKeymap,
30
+ } from '@codemirror/autocomplete';
31
+ import { lintKeymap } from '@codemirror/lint';
32
+ import { javascript } from '@codemirror/lang-javascript';
33
+ import {
34
+ languageServerWithTransport,
35
+ formatDocument,
36
+ renameSymbol,
37
+ } from '../src';
38
+ import { WorkerTransport } from './worker-transport';
39
+
40
+ const worker = new Worker('./dist/lsp-worker.js', { type: 'module' });
41
+ const transport = new WorkerTransport(worker);
42
+
43
+ const doc = `// Welcome to the CodeMirror Language Server demo!
44
+ // This editor is connected to a minimal LSP server
45
+ // running in a Web Worker. No backend needed.
46
+ //
47
+ // Try these features:
48
+ // - Type "console." to see completions
49
+ // - Hover over "Math", "document", "JSON", etc.
50
+ // - Place your cursor on a word to see highlights
51
+ // - Press Shift-Alt-F to format the document
52
+ // - Notice the "var" warning below
53
+
54
+ var message = "Hello, world!";
55
+ console.log(message);
56
+
57
+ function greet(name) {
58
+ const greeting = "Hello, " + name + "!";
59
+ console.log(greeting);
60
+ return greeting;
61
+ }
62
+
63
+ const numbers = [1, 2, 3, 4, 5];
64
+ const doubled = numbers.map(n => n * 2);
65
+ console.log(doubled);
66
+
67
+ const result = Math.floor(Math.random() * 100);
68
+ document.title = "Result: " + result;
69
+
70
+ fetch("https://example.com/api")
71
+ .then(response => response.json())
72
+ .then(data => console.log(data));
73
+ `;
74
+
75
+ const view = new EditorView({
76
+ doc,
77
+ parent: document.getElementById('editor'),
78
+ extensions: [
79
+ lineNumbers(),
80
+ highlightSpecialChars(),
81
+ history(),
82
+ foldGutter(),
83
+ drawSelection(),
84
+ EditorState.allowMultipleSelections.of(true),
85
+ indentOnInput(),
86
+ syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
87
+ bracketMatching(),
88
+ closeBrackets(),
89
+ highlightActiveLine(),
90
+ highlightSelectionMatches(),
91
+ panels(),
92
+ keymap.of([
93
+ ...closeBracketsKeymap,
94
+ ...defaultKeymap,
95
+ indentWithTab,
96
+ ...searchKeymap,
97
+ ...historyKeymap,
98
+ ...foldKeymap,
99
+ ...completionKeymap,
100
+ ...lintKeymap,
101
+ { key: 'Shift-Alt-f', run: formatDocument },
102
+ { key: 'F2', run: renameSymbol },
103
+ ]),
104
+ EditorState.tabSize.of(4),
105
+ javascript(),
106
+ languageServerWithTransport({
107
+ transport,
108
+ rootUri: 'file:///',
109
+ workspaceFolders: null,
110
+ documentUri: 'file:///demo.js',
111
+ languageId: 'javascript',
112
+ allowHTMLContent: true,
113
+ }),
114
+ ],
115
+ });
@@ -0,0 +1,459 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>codemirror-languageserver</title>
7
+ <style>
8
+ *,
9
+ *::before,
10
+ *::after {
11
+ box-sizing: border-box;
12
+ }
13
+ body {
14
+ font-family:
15
+ -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
16
+ Oxygen, Ubuntu, sans-serif;
17
+ margin: 0;
18
+ padding: 0;
19
+ background: #fff;
20
+ color: #24292f;
21
+ line-height: 1.6;
22
+ }
23
+
24
+ /* Header */
25
+ .hero {
26
+ background: linear-gradient(135deg, #0099e5 0%, #006daa 100%);
27
+ color: #fff;
28
+ padding: 48px 24px;
29
+ text-align: center;
30
+ }
31
+ .hero h1 {
32
+ font-size: 2em;
33
+ margin: 0 0 8px;
34
+ font-weight: 700;
35
+ }
36
+ .hero p {
37
+ margin: 0 0 20px;
38
+ font-size: 1.1em;
39
+ opacity: 0.9;
40
+ }
41
+ .hero-links {
42
+ display: flex;
43
+ gap: 12px;
44
+ justify-content: center;
45
+ flex-wrap: wrap;
46
+ }
47
+ .hero-links a {
48
+ display: inline-block;
49
+ padding: 8px 20px;
50
+ border-radius: 6px;
51
+ font-size: 0.9em;
52
+ font-weight: 600;
53
+ text-decoration: none;
54
+ transition: opacity 0.15s;
55
+ }
56
+ .hero-links a:hover {
57
+ opacity: 0.85;
58
+ }
59
+ .btn-primary {
60
+ background: #fff;
61
+ color: #0099e5;
62
+ }
63
+ .btn-secondary {
64
+ background: rgba(255, 255, 255, 0.15);
65
+ color: #fff;
66
+ border: 1px solid rgba(255, 255, 255, 0.3);
67
+ }
68
+
69
+ /* Main content */
70
+ .container {
71
+ max-width: 960px;
72
+ margin: 0 auto;
73
+ padding: 32px 24px;
74
+ }
75
+
76
+ /* Features grid */
77
+ .features-grid {
78
+ display: grid;
79
+ grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
80
+ gap: 16px;
81
+ margin: 0 0 40px;
82
+ }
83
+ .feature-card {
84
+ padding: 16px;
85
+ border-radius: 8px;
86
+ background: #f6f8fa;
87
+ text-align: center;
88
+ }
89
+ .feature-card .emoji {
90
+ display: block;
91
+ font-size: 1.6em;
92
+ text-align: center;
93
+ margin-bottom: 8px;
94
+ }
95
+ .feature-card strong {
96
+ display: block;
97
+ margin-bottom: 4px;
98
+ }
99
+ .feature-card p {
100
+ margin: 0;
101
+ font-size: 0.85em;
102
+ color: #57606a;
103
+ }
104
+
105
+ /* Demo section */
106
+ h2 {
107
+ font-size: 1.4em;
108
+ margin: 0 0 8px;
109
+ color: #24292f;
110
+ }
111
+ .demo-hint {
112
+ margin: 0 0 12px;
113
+ font-size: 0.9em;
114
+ color: #57606a;
115
+ }
116
+ #editor {
117
+ border: 1px solid #d0d7de;
118
+ border-radius: 8px;
119
+ overflow: hidden;
120
+ background: #fff;
121
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
122
+ }
123
+ .cm-editor {
124
+ height: 420px;
125
+ }
126
+ .cm-editor .cm-scroller {
127
+ overflow: auto;
128
+ }
129
+ .try-bar {
130
+ display: flex;
131
+ flex-wrap: wrap;
132
+ gap: 8px;
133
+ margin: 12px 0 0;
134
+ font-size: 0.8em;
135
+ }
136
+ .try-bar span {
137
+ display: inline-flex;
138
+ align-items: center;
139
+ gap: 4px;
140
+ padding: 4px 10px;
141
+ background: #f6f8fa;
142
+ border: 1px solid #d0d7de;
143
+ border-radius: 20px;
144
+ color: #57606a;
145
+ }
146
+ kbd {
147
+ display: inline-block;
148
+ padding: 1px 5px;
149
+ font-size: 0.85em;
150
+ font-family: inherit;
151
+ background: #fff;
152
+ border: 1px solid #d0d7de;
153
+ border-radius: 3px;
154
+ box-shadow: 0 1px 0 rgba(0, 0, 0, 0.06);
155
+ }
156
+
157
+ /* Quick start */
158
+ .quick-start {
159
+ margin: 48px 0 0;
160
+ }
161
+ .quick-start h2 {
162
+ margin: 0 0 16px;
163
+ }
164
+ .step {
165
+ margin: 0 0 24px;
166
+ }
167
+ .step h3 {
168
+ font-size: 1em;
169
+ margin: 0 0 8px;
170
+ color: #24292f;
171
+ }
172
+ .step p {
173
+ margin: 0 0 8px;
174
+ font-size: 0.9em;
175
+ color: #57606a;
176
+ }
177
+ pre {
178
+ margin: 0;
179
+ padding: 16px;
180
+ background: #f6f8fa;
181
+ border: 1px solid #d0d7de;
182
+ border-radius: 8px;
183
+ overflow-x: auto;
184
+ font-size: 0.85em;
185
+ line-height: 1.5;
186
+ }
187
+ code {
188
+ font-family: 'SFMono-Regular', Consolas, 'Liberation Mono',
189
+ Menlo, monospace;
190
+ font-size: 0.9em;
191
+ }
192
+ pre code {
193
+ font-size: inherit;
194
+ }
195
+ p code {
196
+ padding: 2px 6px;
197
+ background: #f6f8fa;
198
+ border-radius: 4px;
199
+ }
200
+
201
+ /* LSP Document Highlight */
202
+ .cm-lsp-highlight-text,
203
+ .cm-lsp-highlight-read {
204
+ background-color: rgba(103, 126, 234, 0.15);
205
+ border-radius: 2px;
206
+ }
207
+ .cm-lsp-highlight-write {
208
+ background-color: rgba(118, 75, 162, 0.2);
209
+ border-radius: 2px;
210
+ }
211
+ /* LSP Rename Panel */
212
+ .cm-lsp-rename-panel {
213
+ display: flex;
214
+ align-items: center;
215
+ gap: 8px;
216
+ padding: 6px 10px;
217
+ background: #f6f8fa;
218
+ border-bottom: 1px solid #d0d7de;
219
+ font-size: 0.85em;
220
+ }
221
+ .cm-lsp-rename-panel::before {
222
+ content: 'Rename:';
223
+ color: #57606a;
224
+ }
225
+ .cm-lsp-rename-input {
226
+ font-family: inherit;
227
+ font-size: inherit;
228
+ padding: 2px 6px;
229
+ border: 1px solid #d0d7de;
230
+ border-radius: 4px;
231
+ outline: none;
232
+ }
233
+ .cm-lsp-rename-input:focus {
234
+ border-color: #0099e5;
235
+ box-shadow: 0 0 0 2px rgba(103, 126, 234, 0.25);
236
+ }
237
+
238
+ /* Footer */
239
+ footer {
240
+ margin-top: 48px;
241
+ padding: 24px;
242
+ text-align: center;
243
+ font-size: 0.85em;
244
+ color: #8b949e;
245
+ border-top: 1px solid #d0d7de;
246
+ }
247
+ footer a {
248
+ color: #0099e5;
249
+ text-decoration: none;
250
+ }
251
+ footer a:hover {
252
+ text-decoration: underline;
253
+ }
254
+ </style>
255
+ </head>
256
+ <body>
257
+ <div class="hero">
258
+ <h1>codemirror-languageserver</h1>
259
+ <p>
260
+ Language Server Protocol support for CodeMirror 6 &mdash;
261
+ completions, hover, diagnostics, and more.
262
+ </p>
263
+ <div class="hero-links">
264
+ <a
265
+ class="btn-primary"
266
+ href="https://www.npmjs.com/package/codemirror-languageserver"
267
+ >npm install</a
268
+ >
269
+ <a
270
+ class="btn-secondary"
271
+ href="https://github.com/FurqanSoftware/codemirror-languageserver"
272
+ >GitHub</a
273
+ >
274
+ </div>
275
+ </div>
276
+
277
+ <div class="container">
278
+ <div class="features-grid">
279
+ <div class="feature-card">
280
+ <span class="emoji">⌨️</span>
281
+ <strong>Code Completion</strong>
282
+ <p>
283
+ Autocomplete with resolve support, triggered by typing
284
+ or trigger characters.
285
+ </p>
286
+ </div>
287
+ <div class="feature-card">
288
+ <span class="emoji">📚</span>
289
+ <strong>Hover Documentation</strong>
290
+ <p>
291
+ Rich hover tooltips with Markdown rendering for any
292
+ symbol.
293
+ </p>
294
+ </div>
295
+ <div class="feature-card">
296
+ <span class="emoji">🩺</span>
297
+ <strong>Diagnostics</strong>
298
+ <p>
299
+ Real-time errors and warnings from the language server,
300
+ shown inline.
301
+ </p>
302
+ </div>
303
+ <div class="feature-card">
304
+ <span class="emoji">🔍</span>
305
+ <strong>Go to Definition</strong>
306
+ <p>
307
+ Jump to definition, declaration, or type definition
308
+ with F12.
309
+ </p>
310
+ </div>
311
+ <div class="feature-card">
312
+ <span class="emoji">🔦</span>
313
+ <strong>Document Highlight</strong>
314
+ <p>
315
+ All occurrences of a symbol are highlighted when the
316
+ cursor is on it.
317
+ </p>
318
+ </div>
319
+ <div class="feature-card">
320
+ <span class="emoji">🎨</span>
321
+ <strong>Formatting</strong>
322
+ <p>
323
+ Format the entire document or a selection via the
324
+ language server.
325
+ </p>
326
+ </div>
327
+ <div class="feature-card">
328
+ <span class="emoji">✏️</span>
329
+ <strong>Rename Symbol</strong>
330
+ <p>
331
+ Rename a symbol across the document with an inline
332
+ prompt.
333
+ </p>
334
+ </div>
335
+ <div class="feature-card">
336
+ <span class="emoji">🔌</span>
337
+ <strong>Custom Transport</strong>
338
+ <p>
339
+ WebSocket out of the box, or bring your own transport
340
+ (Web Workers, MessagePort, etc.).
341
+ </p>
342
+ </div>
343
+ </div>
344
+
345
+ <h2>Live Demo</h2>
346
+ <p class="demo-hint">
347
+ This editor is connected to a minimal JavaScript LSP server
348
+ running entirely in a Web Worker &mdash; no backend needed.
349
+ </p>
350
+ <div id="editor"></div>
351
+ <div class="try-bar">
352
+ <span>Type <code>console.</code> for completions</span>
353
+ <span
354
+ >Hover over <code>Math</code>, <code>document</code>,
355
+ <code>JSON</code></span
356
+ >
357
+ <span>Click a word to see highlights</span>
358
+ <span
359
+ ><kbd>Shift</kbd>+<kbd>Alt</kbd>+<kbd>F</kbd> to
360
+ format</span
361
+ >
362
+ <span><kbd>F2</kbd> to rename</span>
363
+ </div>
364
+
365
+ <div class="quick-start">
366
+ <h2>Quick Start</h2>
367
+
368
+ <div class="step">
369
+ <h3>1. Install</h3>
370
+ <pre><code>npm i codemirror-languageserver</code></pre>
371
+ </div>
372
+
373
+ <div class="step">
374
+ <h3>2. Connect to a language server over WebSocket</h3>
375
+ <pre><code>import { EditorState } from '@codemirror/state';
376
+ import { EditorView } from '@codemirror/view';
377
+ import { languageServer } from 'codemirror-languageserver';
378
+
379
+ const ls = languageServer({
380
+ serverUri: 'ws://localhost:8080',
381
+ rootUri: 'file:///',
382
+ documentUri: 'file:///main.cpp',
383
+ languageId: 'cpp',
384
+ });
385
+
386
+ const view = new EditorView({
387
+ state: EditorState.create({
388
+ extensions: [/* other extensions, */ ls],
389
+ }),
390
+ });</code></pre>
391
+ </div>
392
+
393
+ <div class="step">
394
+ <h3>3. Or use a custom transport (like this demo does)</h3>
395
+ <pre><code>import { languageServerWithTransport } from 'codemirror-languageserver';
396
+
397
+ const worker = new Worker('./lsp-worker.js', { type: 'module' });
398
+
399
+ // WorkerTransport implements the Transport interface:
400
+ // send(), onMessage(), onClose(), onError(), close()
401
+ const transport = new WorkerTransport(worker);
402
+
403
+ const ls = languageServerWithTransport({
404
+ transport,
405
+ rootUri: 'file:///',
406
+ documentUri: 'file:///demo.js',
407
+ languageId: 'javascript',
408
+ });</code></pre>
409
+ </div>
410
+
411
+ <div class="step">
412
+ <h3>4. Add keybindings for formatting and rename</h3>
413
+ <pre><code>import { keymap } from '@codemirror/view';
414
+ import {
415
+ formatDocument,
416
+ formatSelection,
417
+ renameSymbol,
418
+ } from 'codemirror-languageserver';
419
+
420
+ keymap.of([
421
+ { key: 'Shift-Alt-f', run: formatDocument },
422
+ { key: 'Ctrl-k Ctrl-f', run: formatSelection },
423
+ { key: 'F2', run: renameSymbol },
424
+ ])</code></pre>
425
+ </div>
426
+
427
+ <div class="step">
428
+ <h3>5. React to server capabilities</h3>
429
+ <pre><code>languageServer({
430
+ serverUri: 'ws://localhost:8080',
431
+ rootUri: 'file:///',
432
+ documentUri: 'file:///main.cpp',
433
+ languageId: 'cpp',
434
+ onCapabilities(capabilities) {
435
+ // Update your UI based on what the server supports
436
+ // e.g. capabilities.documentFormattingProvider
437
+ },
438
+ onError(error) {
439
+ console.error('LSP error:', error);
440
+ },
441
+ onClose() {
442
+ console.log('LSP connection closed');
443
+ },
444
+ })</code></pre>
445
+ </div>
446
+ </div>
447
+ </div>
448
+
449
+ <footer>
450
+ <a
451
+ href="https://github.com/FurqanSoftware/codemirror-languageserver"
452
+ >codemirror-languageserver</a
453
+ >
454
+ &mdash; BSD-3-Clause &mdash; Built by
455
+ <a href="https://furqansoftware.com">Furqan Software</a>
456
+ </footer>
457
+ <script type="module" src="./dist/gh-pages.js"></script>
458
+ </body>
459
+ </html>