0
# Special Extensions
1
2
Specialized extensions for advanced functionality including collaborative editing, rulers, custom styling, and Python highlighting.
3
4
## Capabilities
5
6
### Y.js Collaborative Editing
7
8
Real-time collaborative editing integration using Y.js for shared document synchronization.
9
10
```typescript { .api }
11
/**
12
* Extension for CodeMirror 6 binding the Yjs text and editor state
13
* Enables real-time collaborative editing
14
*/
15
function ybinding(options: { ytext: Text; undoManager?: UndoManager }): Extension;
16
17
/**
18
* Y.js range class for relative positioning
19
*/
20
class YRange {
21
constructor(yanchor: RelativePosition, yhead: RelativePosition);
22
23
/**
24
* Convert the position to JSON
25
*/
26
toJSON(): Range;
27
28
/**
29
* Convert a JSON range to a YRange
30
*/
31
static fromJSON(json: Range): YRange;
32
}
33
34
/**
35
* Y.js binding configuration
36
*/
37
class YSyncConfig {
38
constructor(ytext: Text);
39
40
readonly ytext: Text;
41
42
/**
43
* Transform absolute index position to Yjs-based relative position
44
*/
45
toYPos(pos: number, assoc?: number): RelativePosition;
46
47
/**
48
* Transform relative position back to absolute position
49
*/
50
fromYPos(rpos: RelativePosition | Record<string, any>): number;
51
52
/**
53
* Convert selection range to Y range
54
*/
55
toYRange(range: SelectionRange): YRange;
56
57
/**
58
* Convert Y range to selection range
59
*/
60
fromYRange(yrange: YRange): SelectionRange;
61
}
62
63
/**
64
* Y.js undo manager integration
65
*/
66
class YUndoManagerConfig {
67
constructor(undoManager: UndoManager);
68
69
readonly undoManager: UndoManager;
70
}
71
72
// Facets and plugins
73
const ySyncFacet: Facet<YSyncConfig, YSyncConfig>;
74
const ySyncAnnotation: Annotation<YSyncConfig>;
75
const ySync: ViewPlugin;
76
const yUndoManagerFacet: Facet<YUndoManagerConfig, YUndoManagerConfig>;
77
const yUndoManager: ViewPlugin;
78
```
79
80
**Usage Examples:**
81
82
```typescript
83
import { ybinding } from "@jupyterlab/codemirror";
84
import { Text, UndoManager } from "yjs";
85
import { WebsocketProvider } from "y-websocket";
86
87
// Create Y.js document and text
88
const ydoc = new Y.Doc();
89
const ytext = ydoc.getText('codemirror');
90
const undoManager = new UndoManager(ytext);
91
92
// Create collaborative editor
93
const editor = new EditorView({
94
extensions: [
95
ybinding({ ytext, undoManager }),
96
// ... other extensions
97
],
98
parent: document.body
99
});
100
101
// Set up network provider for real-time sync
102
const provider = new WebsocketProvider('ws://localhost:1234', 'my-room', ydoc);
103
104
// Handle collaboration events
105
provider.on('status', (event) => {
106
console.log('Connection status:', event.status);
107
});
108
109
// Clean up
110
provider.destroy();
111
editor.destroy();
112
```
113
114
### Ruler Extensions
115
116
Visual ruler lines for code layout guidance and style enforcement.
117
118
```typescript { .api }
119
/**
120
* Extension for CodeMirror 6 displaying rulers
121
* Shows vertical lines at specified column positions
122
*/
123
function rulers(positions: number[]): Extension;
124
```
125
126
**Usage Examples:**
127
128
```typescript
129
import { rulers } from "@jupyterlab/codemirror";
130
131
// Add rulers at columns 80 and 120
132
const rulerExtension = rulers([80, 120]);
133
134
// Create editor with rulers
135
const editor = new EditorView({
136
extensions: [
137
rulerExtension,
138
// ... other extensions
139
]
140
});
141
142
// Dynamic ruler configuration
143
function createDynamicRulers(language: string): Extension {
144
switch (language) {
145
case 'python':
146
return rulers([79, 88]); // PEP 8 guidelines
147
case 'javascript':
148
case 'typescript':
149
return rulers([80, 100, 120]); // Common JS guidelines
150
case 'java':
151
return rulers([100, 120]); // Java conventions
152
default:
153
return rulers([80]); // Default ruler
154
}
155
}
156
157
// Update rulers based on language
158
editor.dispatch({
159
effects: StateEffect.reconfigure.of([
160
createDynamicRulers('python'),
161
// ... other extensions
162
])
163
});
164
```
165
166
### Custom Styling
167
168
Dynamic custom styling system for font family, size, and line height configuration.
169
170
```typescript { .api }
171
/**
172
* Get the extension to customize an editor theme
173
* Allows dynamic font and spacing configuration
174
*/
175
function customTheme(config: CustomTheme): Extension;
176
177
/**
178
* Editor customizable styles
179
*/
180
interface CustomTheme {
181
fontFamily: string | null;
182
fontSize: number | null;
183
lineHeight: number | null;
184
}
185
```
186
187
**Usage Examples:**
188
189
```typescript
190
import { customTheme, CustomTheme } from "@jupyterlab/codemirror";
191
192
// Create custom theme configuration
193
const themeConfig: CustomTheme = {
194
fontFamily: 'Monaco, "Courier New", monospace',
195
fontSize: 14,
196
lineHeight: 1.5
197
};
198
199
// Apply custom theme
200
const customThemeExtension = customTheme(themeConfig);
201
202
const editor = new EditorView({
203
extensions: [
204
customThemeExtension,
205
// ... other extensions
206
]
207
});
208
209
// Dynamic theme updates
210
function updateTheme(config: Partial<CustomTheme>) {
211
const currentConfig = getCurrentThemeConfig();
212
const newConfig = { ...currentConfig, ...config };
213
214
editor.dispatch({
215
effects: StateEffect.reconfigure.of([
216
customTheme(newConfig),
217
// ... other extensions
218
])
219
});
220
}
221
222
// Update font size
223
updateTheme({ fontSize: 16 });
224
225
// Update font family
226
updateTheme({ fontFamily: 'JetBrains Mono, monospace' });
227
228
// Responsive font sizing
229
function createResponsiveTheme(): CustomTheme {
230
const screenWidth = window.innerWidth;
231
232
if (screenWidth < 768) {
233
return { fontFamily: null, fontSize: 12, lineHeight: 1.4 }; // Mobile
234
} else if (screenWidth < 1024) {
235
return { fontFamily: null, fontSize: 13, lineHeight: 1.5 }; // Tablet
236
} else {
237
return { fontFamily: null, fontSize: 14, lineHeight: 1.6 }; // Desktop
238
}
239
}
240
```
241
242
### Python Built-in Highlighting
243
244
Enhanced syntax highlighting for Python built-in functions and keywords.
245
246
```typescript { .api }
247
/**
248
* Create a view plugin for highlighting Python built-in functions
249
* Provides enhanced highlighting for Python's 158 built-in functions
250
*/
251
function pythonBuiltin(langPython: Language): ViewPlugin;
252
253
/**
254
* View plugin class for highlighting Python built-in functions
255
*/
256
class PythonBuiltin {
257
constructor(view: EditorView, langPython: Language);
258
259
decorations: DecorationSet;
260
decoratedTo: number;
261
langPython: Language;
262
tree: Tree;
263
mark: Decoration;
264
265
update(update: ViewUpdate): void;
266
buildDeco(view: EditorView): DecorationSet;
267
}
268
269
/**
270
* List of Python built-in function names (158 functions)
271
*/
272
const builtins: string[];
273
```
274
275
**Usage Examples:**
276
277
```typescript
278
import { pythonBuiltin, builtins } from "@jupyterlab/codemirror";
279
import { python } from "@codemirror/lang-python";
280
281
// Create Python language support
282
const pythonLang = python();
283
284
// Add Python built-in highlighting
285
const pythonBuiltinExtension = pythonBuiltin(pythonLang.language);
286
287
const editor = new EditorView({
288
extensions: [
289
pythonLang,
290
pythonBuiltinExtension,
291
// ... other extensions
292
]
293
});
294
295
// Check if function is built-in
296
function isPythonBuiltin(functionName: string): boolean {
297
return builtins.includes(functionName);
298
}
299
300
// Get all Python built-ins
301
console.log(`Python has ${builtins.length} built-in functions`);
302
console.log('Built-ins include:', builtins.slice(0, 10).join(', '));
303
304
// Custom built-in highlighting
305
function createCustomPythonHighlighting(additionalBuiltins: string[]) {
306
const allBuiltins = [...builtins, ...additionalBuiltins];
307
308
return ViewPlugin.fromClass(class {
309
constructor(view: EditorView) {
310
// Custom highlighting logic for extended built-ins
311
}
312
313
update(update: ViewUpdate) {
314
// Update highlighting when document changes
315
}
316
});
317
}
318
```
319
320
### IPython Math Parsing
321
322
Mathematical expression parsing for IPython/Jupyter Markdown cells with LaTeX support.
323
324
```typescript { .api }
325
/**
326
* Define an IPython mathematical expression parser for Markdown
327
* Enables LaTeX math rendering in Markdown cells
328
*/
329
function parseMathIPython(latexParser?: Parser): MarkdownConfig;
330
```
331
332
**Usage Examples:**
333
334
```typescript
335
import { parseMathIPython } from "@jupyterlab/codemirror";
336
import { markdown } from "@codemirror/lang-markdown";
337
338
// Create IPython-compatible Markdown with math support
339
const ipythonMarkdown = markdown({
340
extensions: [parseMathIPython()]
341
});
342
343
const editor = new EditorView({
344
extensions: [
345
ipythonMarkdown,
346
// ... other extensions
347
]
348
});
349
350
// With custom LaTeX parser
351
import { LaTeX } from "@codemirror/lang-tex";
352
353
const customLatexParser = LaTeX.parser;
354
const ipythonMarkdownCustom = markdown({
355
extensions: [parseMathIPython(customLatexParser)]
356
});
357
358
// Example IPython math content
359
const mathContent = `
360
# Mathematical Expressions
361
362
Inline math: $E = mc^2$
363
364
Block math:
365
$$
366
\\int_{-\\infty}^{\\infty} e^{-x^2} dx = \\sqrt{\\pi}
367
$$
368
369
IPython display math:
370
$$\\begin{align}
371
x &= \\frac{-b \\pm \\sqrt{b^2 - 4ac}}{2a} \\\\
372
y &= mx + b
373
\\end{align}$$
374
`;
375
376
// Set content with math expressions
377
editor.dispatch({
378
changes: { from: 0, to: editor.state.doc.length, insert: mathContent }
379
});
380
```
381
382
### Advanced Extension Combinations
383
384
Complex scenarios combining multiple special extensions.
385
386
```typescript
387
// Collaborative Python development environment
388
async function createCollaborativePythonEditor(
389
roomId: string,
390
ytext: Text
391
): Promise<EditorView> {
392
const pythonLang = python();
393
const undoManager = new UndoManager(ytext);
394
395
return new EditorView({
396
extensions: [
397
// Language support
398
pythonLang,
399
pythonBuiltin(pythonLang.language),
400
401
// Collaboration
402
ybinding({ ytext, undoManager }),
403
404
// Visual aids
405
rulers([79, 88]), // PEP 8 guidelines
406
customTheme({
407
fontFamily: 'JetBrains Mono, Monaco, monospace',
408
fontSize: 13,
409
lineHeight: 1.6
410
}),
411
412
// ... other extensions
413
],
414
parent: document.body
415
});
416
}
417
418
// Multi-language notebook cell
419
function createNotebookCell(language: string): Extension[] {
420
const baseExtensions = [
421
customTheme({
422
fontFamily: 'var(--jp-code-font-family)',
423
fontSize: null, // Use CSS variable
424
lineHeight: null // Use CSS variable
425
})
426
];
427
428
switch (language) {
429
case 'python':
430
const pythonLang = python();
431
return [
432
...baseExtensions,
433
pythonLang,
434
pythonBuiltin(pythonLang.language),
435
rulers([79])
436
];
437
438
case 'markdown':
439
return [
440
...baseExtensions,
441
markdown({ extensions: [parseMathIPython()] }),
442
rulers([80])
443
];
444
445
case 'javascript':
446
return [
447
...baseExtensions,
448
javascript(),
449
rulers([80, 120])
450
];
451
452
default:
453
return baseExtensions;
454
}
455
}
456
457
// Dynamic extension reconfiguration
458
function reconfigureSpecialExtensions(
459
editor: EditorView,
460
options: {
461
collaboration?: { ytext: Text; undoManager?: UndoManager };
462
rulers?: number[];
463
customTheme?: CustomTheme;
464
pythonBuiltins?: boolean;
465
mathSupport?: boolean;
466
}
467
) {
468
const extensions: Extension[] = [];
469
470
if (options.collaboration) {
471
extensions.push(ybinding(options.collaboration));
472
}
473
474
if (options.rulers) {
475
extensions.push(rulers(options.rulers));
476
}
477
478
if (options.customTheme) {
479
extensions.push(customTheme(options.customTheme));
480
}
481
482
if (options.pythonBuiltins) {
483
const pythonLang = python();
484
extensions.push(pythonLang, pythonBuiltin(pythonLang.language));
485
}
486
487
if (options.mathSupport) {
488
extensions.push(markdown({ extensions: [parseMathIPython()] }));
489
}
490
491
editor.dispatch({
492
effects: StateEffect.reconfigure.of(extensions)
493
});
494
}
495
```
496
497
## Types
498
499
```typescript { .api }
500
// Y.js types
501
interface ID {
502
client: number;
503
clock: number;
504
}
505
506
interface Position {
507
type: ID | null;
508
tname: string | null;
509
item: ID | null;
510
assoc: number;
511
}
512
513
interface Range {
514
yanchor: Position;
515
yhead: Position;
516
}
517
518
// Custom theme types
519
interface CustomTheme {
520
fontFamily: string | null;
521
fontSize: number | null;
522
lineHeight: number | null;
523
}
524
525
// Y.js binding functions
526
function ybinding(options: { ytext: Text; undoManager?: UndoManager }): Extension;
527
528
// Ruler function
529
function rulers(positions: number[]): Extension;
530
531
// Custom theme function
532
function customTheme(config: CustomTheme): Extension;
533
534
// Python built-in highlighting
535
function pythonBuiltin(langPython: Language): ViewPlugin;
536
537
// IPython math parsing
538
function parseMathIPython(latexParser?: Parser): MarkdownConfig;
539
```