@jupyterlab/codemirror 4.0.0-rc.0 → 4.0.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/lib/editor.d.ts +0 -1
- package/lib/editor.js +20 -27
- package/lib/editor.js.map +1 -1
- package/lib/extension.js +1 -1
- package/lib/extension.js.map +1 -1
- package/lib/extensions/index.d.ts +1 -0
- package/lib/extensions/index.js +1 -0
- package/lib/extensions/index.js.map +1 -1
- package/lib/extensions/ipython-md.d.ts +9 -0
- package/lib/extensions/ipython-md.js +110 -0
- package/lib/extensions/ipython-md.js.map +1 -0
- package/lib/searchprovider.d.ts +56 -8
- package/lib/searchprovider.js +103 -43
- package/lib/searchprovider.js.map +1 -1
- package/package.json +9 -8
- package/src/editor.ts +20 -26
- package/src/extension.ts +1 -1
- package/src/extensions/index.ts +1 -0
- package/src/extensions/ipython-md.ts +158 -0
- package/src/searchprovider.ts +154 -46
- package/style/base.css +10 -6
- package/lib/codemirror-ipythongfm.d.ts +0 -9
- package/lib/codemirror-ipythongfm.js +0 -108
- package/lib/codemirror-ipythongfm.js.map +0 -1
- package/src/codemirror-ipythongfm.ts +0 -109
package/src/searchprovider.ts
CHANGED
|
@@ -32,7 +32,13 @@
|
|
|
32
32
|
|
|
33
33
|
import { ISearchMatch } from '@jupyterlab/documentsearch';
|
|
34
34
|
import { CodeMirrorEditor } from './editor';
|
|
35
|
-
import {
|
|
35
|
+
import {
|
|
36
|
+
EditorSelection,
|
|
37
|
+
Extension,
|
|
38
|
+
StateEffect,
|
|
39
|
+
StateEffectType,
|
|
40
|
+
StateField
|
|
41
|
+
} from '@codemirror/state';
|
|
36
42
|
import { Decoration, DecorationSet, EditorView } from '@codemirror/view';
|
|
37
43
|
import { CodeEditor } from '@jupyterlab/codeeditor';
|
|
38
44
|
import {
|
|
@@ -45,6 +51,43 @@ import {
|
|
|
45
51
|
import { ISignal, Signal } from '@lumino/signaling';
|
|
46
52
|
import { ISharedText, SourceChange } from '@jupyter/ydoc';
|
|
47
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Defines from which position the search should be executed.
|
|
56
|
+
* - `'selection'` - search from selection head/anchor (depending on search direction)
|
|
57
|
+
* - `'previous-match'` - search from previous match
|
|
58
|
+
* - `'auto'` - search from selection if editor is focused or previous match otherwise
|
|
59
|
+
* - `'selection-start'` - search from selection head/anchor whichever is smaller
|
|
60
|
+
* - `'start'` - from start of the editor
|
|
61
|
+
*/
|
|
62
|
+
type SearchStartAnchor =
|
|
63
|
+
| 'auto'
|
|
64
|
+
| 'selection'
|
|
65
|
+
| 'selection-start'
|
|
66
|
+
| 'previous-match'
|
|
67
|
+
| 'start';
|
|
68
|
+
|
|
69
|
+
interface IHighlightMatchOptions {
|
|
70
|
+
/**
|
|
71
|
+
* Whether the highlighted match should be scrolled into view.
|
|
72
|
+
* Defaults to `true`.
|
|
73
|
+
*/
|
|
74
|
+
scroll?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Whether the user cursor should be moved to select the match.
|
|
77
|
+
* `protectSelection` flag takes precedence over this option.
|
|
78
|
+
* Defaults to `true`.
|
|
79
|
+
*/
|
|
80
|
+
select?: boolean;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface IHighlightAdjacentMatchOptions extends IHighlightMatchOptions {
|
|
84
|
+
/**
|
|
85
|
+
* What should be used as an anchor when searching for adjacent match.
|
|
86
|
+
* Defaults to `'auto'`.
|
|
87
|
+
*/
|
|
88
|
+
from?: SearchStartAnchor;
|
|
89
|
+
}
|
|
90
|
+
|
|
48
91
|
/**
|
|
49
92
|
* Search provider for editors.
|
|
50
93
|
*/
|
|
@@ -167,7 +210,7 @@ export abstract class EditorSearchProvider<
|
|
|
167
210
|
}
|
|
168
211
|
|
|
169
212
|
/**
|
|
170
|
-
* Set whether search should be limitted to specified selection.
|
|
213
|
+
* Set whether search should be limitted to specified text selection.
|
|
171
214
|
*/
|
|
172
215
|
async setSearchSelection(selection: CodeEditor.IRange | null): Promise<void> {
|
|
173
216
|
if (this._inSelection === selection) {
|
|
@@ -178,6 +221,20 @@ export abstract class EditorSearchProvider<
|
|
|
178
221
|
this._stateChanged.emit();
|
|
179
222
|
}
|
|
180
223
|
|
|
224
|
+
/**
|
|
225
|
+
* Set whether user selection should be protected from modifications.
|
|
226
|
+
*
|
|
227
|
+
* If disabled, the selection will be updated on search and on editor focus
|
|
228
|
+
* to cover the current match. We need to protect selection from modifications
|
|
229
|
+
* for both: search in text and search in cells; since `setSearchSelection`
|
|
230
|
+
* is only telling us about search in text, we need to have an additional
|
|
231
|
+
* way to signal that either search in text or in cells is active, or for
|
|
232
|
+
* any other reason selection range should be protected.
|
|
233
|
+
*/
|
|
234
|
+
setProtectSelection(v: boolean) {
|
|
235
|
+
this.cmHandler.protectSelection = v;
|
|
236
|
+
}
|
|
237
|
+
|
|
181
238
|
/**
|
|
182
239
|
* Initialize the search using the provided options. Should update the UI
|
|
183
240
|
* to highlight all matches and "select" the first match.
|
|
@@ -211,13 +268,12 @@ export abstract class EditorSearchProvider<
|
|
|
211
268
|
*/
|
|
212
269
|
async highlightNext(
|
|
213
270
|
loop = true,
|
|
214
|
-
|
|
271
|
+
options?: IHighlightAdjacentMatchOptions
|
|
215
272
|
): Promise<ISearchMatch | undefined> {
|
|
216
273
|
if (this.matchesCount === 0 || !this.isActive) {
|
|
217
274
|
this.currentIndex = null;
|
|
218
275
|
} else {
|
|
219
|
-
|
|
220
|
-
let match = await this.cmHandler.highlightNext(fromCursor);
|
|
276
|
+
let match = await this.cmHandler.highlightNext(options);
|
|
221
277
|
if (match) {
|
|
222
278
|
this.currentIndex = this.cmHandler.currentIndex;
|
|
223
279
|
} else {
|
|
@@ -239,13 +295,12 @@ export abstract class EditorSearchProvider<
|
|
|
239
295
|
*/
|
|
240
296
|
async highlightPrevious(
|
|
241
297
|
loop = true,
|
|
242
|
-
|
|
298
|
+
options?: IHighlightAdjacentMatchOptions
|
|
243
299
|
): Promise<ISearchMatch | undefined> {
|
|
244
300
|
if (this.matchesCount === 0 || !this.isActive) {
|
|
245
301
|
this.currentIndex = null;
|
|
246
302
|
} else {
|
|
247
|
-
|
|
248
|
-
let match = await this.cmHandler.highlightPrevious(fromCursor);
|
|
303
|
+
let match = await this.cmHandler.highlightPrevious(options);
|
|
249
304
|
if (match) {
|
|
250
305
|
this.currentIndex = this.cmHandler.currentIndex;
|
|
251
306
|
} else {
|
|
@@ -405,7 +460,11 @@ export abstract class EditorSearchProvider<
|
|
|
405
460
|
this.cmHandler.currentIndex === null &&
|
|
406
461
|
this.cmHandler.matches.length > 0
|
|
407
462
|
) {
|
|
408
|
-
await this.cmHandler.highlightNext(
|
|
463
|
+
await this.cmHandler.highlightNext({
|
|
464
|
+
from: 'selection',
|
|
465
|
+
select: false,
|
|
466
|
+
scroll: false
|
|
467
|
+
});
|
|
409
468
|
}
|
|
410
469
|
this.currentIndex = this.cmHandler.currentIndex;
|
|
411
470
|
} else {
|
|
@@ -452,9 +511,9 @@ interface IEffectValue {
|
|
|
452
511
|
*
|
|
453
512
|
* **NOTES:**
|
|
454
513
|
* - to retain the selection visibility `drawSelection` extension is needed.
|
|
455
|
-
* - highlighting starts from the cursor (if editor is focused
|
|
456
|
-
* or `
|
|
457
|
-
* otherwise.
|
|
514
|
+
* - highlighting starts from the cursor (if editor is focused and `from` is set
|
|
515
|
+
* to `'auto'`, cursor moved, or `from` argument is set to `'selection'` or
|
|
516
|
+
* `'selection-start'`), or from last "current" match otherwise.
|
|
458
517
|
* - `currentIndex` is the (readonly) source of truth for the current match.
|
|
459
518
|
*/
|
|
460
519
|
export class CodeMirrorSearchHighlighter {
|
|
@@ -495,6 +554,8 @@ export class CodeMirrorSearchHighlighter {
|
|
|
495
554
|
if (ef.is(this._highlightEffect)) {
|
|
496
555
|
const e = ef as StateEffect<IEffectValue>;
|
|
497
556
|
if (e.value.matches.length) {
|
|
557
|
+
// Note: nesting will vary; sometimes `.cm-searching` will be
|
|
558
|
+
// inside `.jp-current-match`, sometime the other way round.
|
|
498
559
|
highlights = highlights.update({
|
|
499
560
|
add: e.value.matches.map(m =>
|
|
500
561
|
this._highlightMark.range(
|
|
@@ -525,6 +586,13 @@ export class CodeMirrorSearchHighlighter {
|
|
|
525
586
|
},
|
|
526
587
|
provide: f => EditorView.decorations.from(f)
|
|
527
588
|
});
|
|
589
|
+
|
|
590
|
+
this._domEventHandlers = EditorView.domEventHandlers({
|
|
591
|
+
focus: () => {
|
|
592
|
+
// Set cursor on active match when editor gets focused.
|
|
593
|
+
this._selectCurrentMatch();
|
|
594
|
+
}
|
|
595
|
+
});
|
|
528
596
|
}
|
|
529
597
|
|
|
530
598
|
/**
|
|
@@ -548,11 +616,22 @@ export class CodeMirrorSearchHighlighter {
|
|
|
548
616
|
) {
|
|
549
617
|
this._currentIndex = this._matches.length > 0 ? 0 : null;
|
|
550
618
|
}
|
|
551
|
-
this._highlightCurrentMatch(
|
|
619
|
+
this._highlightCurrentMatch({ select: false });
|
|
552
620
|
}
|
|
553
621
|
|
|
554
622
|
private _current: ISearchMatch | null = null;
|
|
555
623
|
|
|
624
|
+
/**
|
|
625
|
+
* Whether the cursor/selection should not be modified.
|
|
626
|
+
*/
|
|
627
|
+
get protectSelection(): boolean {
|
|
628
|
+
return this._protectSelection;
|
|
629
|
+
}
|
|
630
|
+
set protectSelection(v: boolean) {
|
|
631
|
+
this._protectSelection = v;
|
|
632
|
+
}
|
|
633
|
+
private _protectSelection: boolean;
|
|
634
|
+
|
|
556
635
|
/**
|
|
557
636
|
* Clear all highlighted matches
|
|
558
637
|
*/
|
|
@@ -583,11 +662,10 @@ export class CodeMirrorSearchHighlighter {
|
|
|
583
662
|
* @returns The next match if available
|
|
584
663
|
*/
|
|
585
664
|
highlightNext(
|
|
586
|
-
|
|
587
|
-
doNotModifySelection = false
|
|
665
|
+
options?: IHighlightAdjacentMatchOptions
|
|
588
666
|
): Promise<ISearchMatch | undefined> {
|
|
589
|
-
this._currentIndex = this._findNext(false,
|
|
590
|
-
this._highlightCurrentMatch(
|
|
667
|
+
this._currentIndex = this._findNext(false, options?.from ?? 'auto');
|
|
668
|
+
this._highlightCurrentMatch(options);
|
|
591
669
|
return Promise.resolve(
|
|
592
670
|
this._currentIndex !== null
|
|
593
671
|
? this._matches[this._currentIndex]
|
|
@@ -600,9 +678,11 @@ export class CodeMirrorSearchHighlighter {
|
|
|
600
678
|
*
|
|
601
679
|
* @returns The previous match if available
|
|
602
680
|
*/
|
|
603
|
-
highlightPrevious(
|
|
604
|
-
|
|
605
|
-
|
|
681
|
+
highlightPrevious(
|
|
682
|
+
options?: IHighlightAdjacentMatchOptions
|
|
683
|
+
): Promise<ISearchMatch | undefined> {
|
|
684
|
+
this._currentIndex = this._findNext(true, options?.from ?? 'auto');
|
|
685
|
+
this._highlightCurrentMatch(options);
|
|
606
686
|
return Promise.resolve(
|
|
607
687
|
this._currentIndex !== null
|
|
608
688
|
? this._matches[this._currentIndex]
|
|
@@ -623,11 +703,24 @@ export class CodeMirrorSearchHighlighter {
|
|
|
623
703
|
if (this._currentIndex !== null) {
|
|
624
704
|
this._highlightCurrentMatch();
|
|
625
705
|
}
|
|
706
|
+
this._cm.editor.dispatch({
|
|
707
|
+
effects: StateEffect.appendConfig.of(this._domEventHandlers)
|
|
708
|
+
});
|
|
626
709
|
this._refresh();
|
|
627
710
|
}
|
|
628
711
|
}
|
|
629
712
|
|
|
630
|
-
private _selectCurrentMatch(): void {
|
|
713
|
+
private _selectCurrentMatch(scroll = true): void {
|
|
714
|
+
// This method has two responsibilities:
|
|
715
|
+
// 1) Scroll the current match into the view - useful for long lines,
|
|
716
|
+
// and file editors with more lines that fit on the screen
|
|
717
|
+
// 2) When user has focus on the editor (not search box) and presses
|
|
718
|
+
// ctrl + g/ctrl + shift + g to jump to next match they want their
|
|
719
|
+
// cursor to jump too.
|
|
720
|
+
// We execute (1) and (2) together as CodeMirror has a special code path
|
|
721
|
+
// to handle both in a single dispatch.
|
|
722
|
+
// The (2) case is inapplicable to search in selection mode, as it would
|
|
723
|
+
// invalidate the query selection, so in that case we only execute (1).
|
|
631
724
|
const match = this._current;
|
|
632
725
|
if (!match) {
|
|
633
726
|
return;
|
|
@@ -635,24 +728,35 @@ export class CodeMirrorSearchHighlighter {
|
|
|
635
728
|
if (!this._cm) {
|
|
636
729
|
return;
|
|
637
730
|
}
|
|
638
|
-
const selection = this._cm.editor.state.selection.main;
|
|
639
|
-
if (
|
|
640
|
-
selection.from === match.position &&
|
|
641
|
-
selection.to === match.position + match.text.length
|
|
642
|
-
) {
|
|
643
|
-
return;
|
|
644
|
-
}
|
|
645
731
|
const cursor = {
|
|
646
732
|
anchor: match.position,
|
|
647
733
|
head: match.position + match.text.length
|
|
648
734
|
};
|
|
649
|
-
this._cm.editor.
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
735
|
+
const selection = this._cm.editor.state.selection.main;
|
|
736
|
+
if (
|
|
737
|
+
(selection.from === match.position &&
|
|
738
|
+
selection.to === match.position + match.text.length) ||
|
|
739
|
+
this._protectSelection
|
|
740
|
+
) {
|
|
741
|
+
// Correct selection is already set or search is restricted to selection:
|
|
742
|
+
// scroll without changing the selection.
|
|
743
|
+
if (scroll) {
|
|
744
|
+
this._cm.editor.dispatch({
|
|
745
|
+
effects: EditorView.scrollIntoView(
|
|
746
|
+
EditorSelection.range(cursor.anchor, cursor.head)
|
|
747
|
+
)
|
|
748
|
+
});
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
} else {
|
|
752
|
+
this._cm.editor.dispatch({
|
|
753
|
+
selection: cursor,
|
|
754
|
+
scrollIntoView: scroll
|
|
755
|
+
});
|
|
756
|
+
}
|
|
653
757
|
}
|
|
654
758
|
|
|
655
|
-
private _highlightCurrentMatch(
|
|
759
|
+
private _highlightCurrentMatch(options?: IHighlightMatchOptions): void {
|
|
656
760
|
if (!this._cm) {
|
|
657
761
|
// no-op
|
|
658
762
|
return;
|
|
@@ -662,12 +766,14 @@ export class CodeMirrorSearchHighlighter {
|
|
|
662
766
|
if (this._currentIndex !== null) {
|
|
663
767
|
const match = this.matches[this._currentIndex];
|
|
664
768
|
this._current = match;
|
|
665
|
-
//
|
|
666
|
-
|
|
769
|
+
// We do not change selection nor scroll if:
|
|
770
|
+
// - user is selecting text,
|
|
771
|
+
// - document was modified
|
|
772
|
+
if (options?.select ?? true) {
|
|
667
773
|
if (this._cm.hasFocus()) {
|
|
668
774
|
// If editor is focused we actually set the cursor on the match.
|
|
669
|
-
this._selectCurrentMatch();
|
|
670
|
-
} else {
|
|
775
|
+
this._selectCurrentMatch(options?.scroll ?? true);
|
|
776
|
+
} else if (options?.scroll ?? true) {
|
|
671
777
|
// otherwise we just scroll to preserve the selection.
|
|
672
778
|
this._cm.editor.dispatch({
|
|
673
779
|
effects: EditorView.scrollIntoView(match.position)
|
|
@@ -694,27 +800,28 @@ export class CodeMirrorSearchHighlighter {
|
|
|
694
800
|
|
|
695
801
|
if (!this._cm!.state.field(this._highlightField, false)) {
|
|
696
802
|
effects.push(StateEffect.appendConfig.of([this._highlightField]));
|
|
697
|
-
// set cursor on active match when editor gets focused
|
|
698
|
-
const focusExtension = EditorView.domEventHandlers({
|
|
699
|
-
focus: () => {
|
|
700
|
-
this._selectCurrentMatch();
|
|
701
|
-
}
|
|
702
|
-
});
|
|
703
|
-
effects.push(StateEffect.appendConfig.of([focusExtension]));
|
|
704
803
|
}
|
|
705
804
|
this._cm!.editor.dispatch({ effects });
|
|
706
805
|
}
|
|
707
806
|
|
|
708
|
-
private _findNext(
|
|
807
|
+
private _findNext(
|
|
808
|
+
reverse: boolean,
|
|
809
|
+
from: SearchStartAnchor = 'auto'
|
|
810
|
+
): number | null {
|
|
709
811
|
if (this._matches.length === 0) {
|
|
710
812
|
// No-op
|
|
711
813
|
return null;
|
|
712
814
|
}
|
|
713
815
|
|
|
714
816
|
let lastPosition = 0;
|
|
715
|
-
if (this._cm!.hasFocus() ||
|
|
817
|
+
if ((from === 'auto' && this._cm!.hasFocus()) || from === 'selection') {
|
|
716
818
|
const cursor = this._cm!.state.selection.main;
|
|
717
819
|
lastPosition = reverse ? cursor.anchor : cursor.head;
|
|
820
|
+
} else if (from === 'selection-start') {
|
|
821
|
+
const cursor = this._cm!.state.selection.main;
|
|
822
|
+
lastPosition = Math.min(cursor.anchor, cursor.head);
|
|
823
|
+
} else if (from === 'start') {
|
|
824
|
+
lastPosition = 0;
|
|
718
825
|
} else if (this._current) {
|
|
719
826
|
lastPosition = reverse
|
|
720
827
|
? this._current.position
|
|
@@ -757,6 +864,7 @@ export class CodeMirrorSearchHighlighter {
|
|
|
757
864
|
private _highlightMark: Decoration;
|
|
758
865
|
private _currentMark: Decoration;
|
|
759
866
|
private _highlightField: StateField<DecorationSet>;
|
|
867
|
+
private _domEventHandlers: Extension;
|
|
760
868
|
}
|
|
761
869
|
|
|
762
870
|
/**
|
package/style/base.css
CHANGED
|
@@ -59,24 +59,28 @@
|
|
|
59
59
|
|
|
60
60
|
.cm-searching,
|
|
61
61
|
.cm-searching span {
|
|
62
|
+
/* `.cm-searching span`: we need to override syntax highlighting */
|
|
62
63
|
background-color: var(--jp-search-unselected-match-background-color);
|
|
63
64
|
color: var(--jp-search-unselected-match-color);
|
|
64
65
|
}
|
|
65
66
|
|
|
66
|
-
.cm-
|
|
67
|
-
.cm-
|
|
67
|
+
.cm-searching::selection,
|
|
68
|
+
.cm-searching span::selection {
|
|
68
69
|
background-color: var(--jp-search-unselected-match-background-color);
|
|
69
70
|
color: var(--jp-search-unselected-match-color);
|
|
70
71
|
}
|
|
71
72
|
|
|
72
|
-
.jp-current-match .cm-searching,
|
|
73
|
-
.jp-current-match .cm-searching span
|
|
73
|
+
.jp-current-match > .cm-searching,
|
|
74
|
+
.jp-current-match > .cm-searching span,
|
|
75
|
+
.cm-searching > .jp-current-match,
|
|
76
|
+
.cm-searching > .jp-current-match span {
|
|
74
77
|
background-color: var(--jp-search-selected-match-background-color);
|
|
75
78
|
color: var(--jp-search-selected-match-color);
|
|
76
79
|
}
|
|
77
80
|
|
|
78
|
-
.
|
|
79
|
-
.cm-
|
|
81
|
+
.jp-current-match > .cm-searching::selection,
|
|
82
|
+
.cm-searching > .jp-current-match::selection,
|
|
83
|
+
.jp-current-match > .cm-searching span::selection {
|
|
80
84
|
background-color: var(--jp-search-selected-match-background-color);
|
|
81
85
|
color: var(--jp-search-selected-match-color);
|
|
82
86
|
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Define an IPython GFM (GitHub Flavored Markdown) mode.
|
|
3
|
-
*
|
|
4
|
-
* Is just a slightly altered GFM Mode with support for LaTeX.
|
|
5
|
-
* LaTeX support was supported by Codemirror GFM as of
|
|
6
|
-
* https://github.com/codemirror/CodeMirror/pull/567
|
|
7
|
-
* But was later removed in
|
|
8
|
-
* https://github.com/codemirror/CodeMirror/commit/d9c9f1b1ffe984aee41307f3e927f80d1f23590c
|
|
9
|
-
*/
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Jupyter Development Team.
|
|
2
|
-
// Distributed under the terms of the Modified BSD License.
|
|
3
|
-
// TODO: add support for LaTeX
|
|
4
|
-
// This should be coded as an extension for https://github.com/lezer-parser/markdown
|
|
5
|
-
// see https://github.com/lezer-parser/markdown/blob/main/src/extension.ts for examples
|
|
6
|
-
// Then this extension can be passed to the markdown function above:
|
|
7
|
-
//
|
|
8
|
-
// load: () => {
|
|
9
|
-
// return import('@codemirror/lang-markdown').then(m => m.markdown({extensions: latex}));
|
|
10
|
-
// }
|
|
11
|
-
/*import CodeMirror from 'codemirror';
|
|
12
|
-
import 'codemirror/addon/mode/multiplex';
|
|
13
|
-
import 'codemirror/mode/gfm/gfm';
|
|
14
|
-
import 'codemirror/mode/stex/stex';
|
|
15
|
-
*/
|
|
16
|
-
/**
|
|
17
|
-
* Define an IPython GFM (GitHub Flavored Markdown) mode.
|
|
18
|
-
*
|
|
19
|
-
* Is just a slightly altered GFM Mode with support for LaTeX.
|
|
20
|
-
* LaTeX support was supported by Codemirror GFM as of
|
|
21
|
-
* https://github.com/codemirror/CodeMirror/pull/567
|
|
22
|
-
* But was later removed in
|
|
23
|
-
* https://github.com/codemirror/CodeMirror/commit/d9c9f1b1ffe984aee41307f3e927f80d1f23590c
|
|
24
|
-
*/
|
|
25
|
-
/*CodeMirror.defineMode(
|
|
26
|
-
'ipythongfm',
|
|
27
|
-
(config: CodeMirror.EditorConfiguration, modeOptions?: any) => {
|
|
28
|
-
const gfmMode = CodeMirror.getMode(config, {
|
|
29
|
-
name: 'gfm',
|
|
30
|
-
// Override list3 with an under-used token, rather than `keyword`
|
|
31
|
-
tokenTypeOverrides: { list3: 'string-2' }
|
|
32
|
-
});
|
|
33
|
-
const texMode = CodeMirror.getMode(config, {
|
|
34
|
-
name: 'stex',
|
|
35
|
-
inMathMode: true
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
return CodeMirror.multiplexingMode(
|
|
39
|
-
gfmMode,
|
|
40
|
-
// force parsing inline code and code blocks with gfmMode to prevent
|
|
41
|
-
// parsing them as tex see:
|
|
42
|
-
// https://github.com/jupyterlab/jupyterlab/issues/6774
|
|
43
|
-
{
|
|
44
|
-
open: '<code>',
|
|
45
|
-
close: '</code>',
|
|
46
|
-
mode: gfmMode,
|
|
47
|
-
parseDelimiters: true
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
open: '<pre>',
|
|
51
|
-
close: '</pre>',
|
|
52
|
-
mode: gfmMode,
|
|
53
|
-
parseDelimiters: true
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
open: '```',
|
|
57
|
-
close: '```',
|
|
58
|
-
mode: gfmMode,
|
|
59
|
-
parseDelimiters: true
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
open: '`',
|
|
63
|
-
close: '`',
|
|
64
|
-
mode: gfmMode,
|
|
65
|
-
parseDelimiters: true
|
|
66
|
-
},
|
|
67
|
-
// only if we did not match a code element or block,
|
|
68
|
-
// then try do parse using the tex mode
|
|
69
|
-
{
|
|
70
|
-
open: '$$',
|
|
71
|
-
close: '$$',
|
|
72
|
-
mode: texMode,
|
|
73
|
-
delimStyle: 'delimit'
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
// `$math mode$` is only matched if both opening
|
|
77
|
-
// and closing $ are in the same line
|
|
78
|
-
open: /\$(?=.*\$)/,
|
|
79
|
-
close: '$',
|
|
80
|
-
mode: texMode,
|
|
81
|
-
delimStyle: 'delimit'
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
open: '\\(',
|
|
85
|
-
close: '\\)',
|
|
86
|
-
mode: texMode,
|
|
87
|
-
delimStyle: 'delimit'
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
open: '\\[',
|
|
91
|
-
close: '\\]',
|
|
92
|
-
mode: texMode,
|
|
93
|
-
delimStyle: 'delimit'
|
|
94
|
-
}
|
|
95
|
-
// .. more multiplexed styles can follow here
|
|
96
|
-
);
|
|
97
|
-
},
|
|
98
|
-
'gfm'
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
CodeMirror.defineMIME('text/x-ipythongfm', 'ipythongfm');
|
|
102
|
-
CodeMirror.modeInfo.push({
|
|
103
|
-
ext: [],
|
|
104
|
-
mime: 'text/x-ipythongfm',
|
|
105
|
-
mode: 'ipythongfm',
|
|
106
|
-
name: 'ipythongfm'
|
|
107
|
-
});*/
|
|
108
|
-
//# sourceMappingURL=codemirror-ipythongfm.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"codemirror-ipythongfm.js","sourceRoot":"","sources":["../src/codemirror-ipythongfm.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,2DAA2D;AAE3D,8BAA8B;AAC9B,oFAAoF;AACpF,uFAAuF;AACvF,oEAAoE;AACpE,EAAE;AACF,gBAAgB;AAChB,2FAA2F;AAC3F,IAAI;AAEJ;;;;EAIE;AACF;;;;;;;;GAQG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAkFK"}
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
// Copyright (c) Jupyter Development Team.
|
|
2
|
-
// Distributed under the terms of the Modified BSD License.
|
|
3
|
-
|
|
4
|
-
// TODO: add support for LaTeX
|
|
5
|
-
// This should be coded as an extension for https://github.com/lezer-parser/markdown
|
|
6
|
-
// see https://github.com/lezer-parser/markdown/blob/main/src/extension.ts for examples
|
|
7
|
-
// Then this extension can be passed to the markdown function above:
|
|
8
|
-
//
|
|
9
|
-
// load: () => {
|
|
10
|
-
// return import('@codemirror/lang-markdown').then(m => m.markdown({extensions: latex}));
|
|
11
|
-
// }
|
|
12
|
-
|
|
13
|
-
/*import CodeMirror from 'codemirror';
|
|
14
|
-
import 'codemirror/addon/mode/multiplex';
|
|
15
|
-
import 'codemirror/mode/gfm/gfm';
|
|
16
|
-
import 'codemirror/mode/stex/stex';
|
|
17
|
-
*/
|
|
18
|
-
/**
|
|
19
|
-
* Define an IPython GFM (GitHub Flavored Markdown) mode.
|
|
20
|
-
*
|
|
21
|
-
* Is just a slightly altered GFM Mode with support for LaTeX.
|
|
22
|
-
* LaTeX support was supported by Codemirror GFM as of
|
|
23
|
-
* https://github.com/codemirror/CodeMirror/pull/567
|
|
24
|
-
* But was later removed in
|
|
25
|
-
* https://github.com/codemirror/CodeMirror/commit/d9c9f1b1ffe984aee41307f3e927f80d1f23590c
|
|
26
|
-
*/
|
|
27
|
-
/*CodeMirror.defineMode(
|
|
28
|
-
'ipythongfm',
|
|
29
|
-
(config: CodeMirror.EditorConfiguration, modeOptions?: any) => {
|
|
30
|
-
const gfmMode = CodeMirror.getMode(config, {
|
|
31
|
-
name: 'gfm',
|
|
32
|
-
// Override list3 with an under-used token, rather than `keyword`
|
|
33
|
-
tokenTypeOverrides: { list3: 'string-2' }
|
|
34
|
-
});
|
|
35
|
-
const texMode = CodeMirror.getMode(config, {
|
|
36
|
-
name: 'stex',
|
|
37
|
-
inMathMode: true
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
return CodeMirror.multiplexingMode(
|
|
41
|
-
gfmMode,
|
|
42
|
-
// force parsing inline code and code blocks with gfmMode to prevent
|
|
43
|
-
// parsing them as tex see:
|
|
44
|
-
// https://github.com/jupyterlab/jupyterlab/issues/6774
|
|
45
|
-
{
|
|
46
|
-
open: '<code>',
|
|
47
|
-
close: '</code>',
|
|
48
|
-
mode: gfmMode,
|
|
49
|
-
parseDelimiters: true
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
open: '<pre>',
|
|
53
|
-
close: '</pre>',
|
|
54
|
-
mode: gfmMode,
|
|
55
|
-
parseDelimiters: true
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
open: '```',
|
|
59
|
-
close: '```',
|
|
60
|
-
mode: gfmMode,
|
|
61
|
-
parseDelimiters: true
|
|
62
|
-
},
|
|
63
|
-
{
|
|
64
|
-
open: '`',
|
|
65
|
-
close: '`',
|
|
66
|
-
mode: gfmMode,
|
|
67
|
-
parseDelimiters: true
|
|
68
|
-
},
|
|
69
|
-
// only if we did not match a code element or block,
|
|
70
|
-
// then try do parse using the tex mode
|
|
71
|
-
{
|
|
72
|
-
open: '$$',
|
|
73
|
-
close: '$$',
|
|
74
|
-
mode: texMode,
|
|
75
|
-
delimStyle: 'delimit'
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
// `$math mode$` is only matched if both opening
|
|
79
|
-
// and closing $ are in the same line
|
|
80
|
-
open: /\$(?=.*\$)/,
|
|
81
|
-
close: '$',
|
|
82
|
-
mode: texMode,
|
|
83
|
-
delimStyle: 'delimit'
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
open: '\\(',
|
|
87
|
-
close: '\\)',
|
|
88
|
-
mode: texMode,
|
|
89
|
-
delimStyle: 'delimit'
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
open: '\\[',
|
|
93
|
-
close: '\\]',
|
|
94
|
-
mode: texMode,
|
|
95
|
-
delimStyle: 'delimit'
|
|
96
|
-
}
|
|
97
|
-
// .. more multiplexed styles can follow here
|
|
98
|
-
);
|
|
99
|
-
},
|
|
100
|
-
'gfm'
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
CodeMirror.defineMIME('text/x-ipythongfm', 'ipythongfm');
|
|
104
|
-
CodeMirror.modeInfo.push({
|
|
105
|
-
ext: [],
|
|
106
|
-
mime: 'text/x-ipythongfm',
|
|
107
|
-
mode: 'ipythongfm',
|
|
108
|
-
name: 'ipythongfm'
|
|
109
|
-
});*/
|