@codemirror/view 0.19.23 → 0.19.27
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/CHANGELOG.md +34 -0
- package/dist/index.cjs +253 -288
- package/dist/index.d.ts +22 -15
- package/dist/index.js +252 -285
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -270,7 +270,7 @@ class DOMPos {
|
|
|
270
270
|
static before(dom, precise) { return new DOMPos(dom.parentNode, domIndex(dom), precise); }
|
|
271
271
|
static after(dom, precise) { return new DOMPos(dom.parentNode, domIndex(dom) + 1, precise); }
|
|
272
272
|
}
|
|
273
|
-
const
|
|
273
|
+
const noChildren = [];
|
|
274
274
|
class ContentView {
|
|
275
275
|
constructor() {
|
|
276
276
|
this.parent = null;
|
|
@@ -436,12 +436,12 @@ class ContentView {
|
|
|
436
436
|
v = parent;
|
|
437
437
|
}
|
|
438
438
|
}
|
|
439
|
-
replaceChildren(from, to, children =
|
|
439
|
+
replaceChildren(from, to, children = noChildren) {
|
|
440
440
|
this.markDirty();
|
|
441
441
|
for (let i = from; i < to; i++) {
|
|
442
442
|
let child = this.children[i];
|
|
443
443
|
if (child.parent == this)
|
|
444
|
-
child.
|
|
444
|
+
child.destroy();
|
|
445
445
|
}
|
|
446
446
|
this.children.splice(from, to - from, ...children);
|
|
447
447
|
for (let i = 0; i < children.length; i++)
|
|
@@ -463,6 +463,17 @@ class ContentView {
|
|
|
463
463
|
}
|
|
464
464
|
static get(node) { return node.cmView; }
|
|
465
465
|
get isEditable() { return true; }
|
|
466
|
+
merge(from, to, source, hasStart, openStart, openEnd) {
|
|
467
|
+
return false;
|
|
468
|
+
}
|
|
469
|
+
become(other) { return false; }
|
|
470
|
+
// When this is a zero-length view with a side, this should return a
|
|
471
|
+
// number <= 0 to indicate it is before its position, or a
|
|
472
|
+
// number > 0 when after its position.
|
|
473
|
+
getSide() { return 0; }
|
|
474
|
+
destroy() {
|
|
475
|
+
this.parent = null;
|
|
476
|
+
}
|
|
466
477
|
}
|
|
467
478
|
ContentView.prototype.breakAfter = 0;
|
|
468
479
|
// Remove a DOM node and return its next sibling.
|
|
@@ -490,6 +501,94 @@ class ChildCursor {
|
|
|
490
501
|
}
|
|
491
502
|
}
|
|
492
503
|
}
|
|
504
|
+
function replaceRange(parent, fromI, fromOff, toI, toOff, insert, breakAtStart, openStart, openEnd) {
|
|
505
|
+
let { children } = parent;
|
|
506
|
+
let before = children.length ? children[fromI] : null;
|
|
507
|
+
let last = insert.length ? insert[insert.length - 1] : null;
|
|
508
|
+
let breakAtEnd = last ? last.breakAfter : breakAtStart;
|
|
509
|
+
// Change within a single child
|
|
510
|
+
if (fromI == toI && before && !breakAtStart && !breakAtEnd && insert.length < 2 &&
|
|
511
|
+
before.merge(fromOff, toOff, insert.length ? last : null, fromOff == 0, openStart, openEnd))
|
|
512
|
+
return;
|
|
513
|
+
if (toI < children.length) {
|
|
514
|
+
let after = children[toI];
|
|
515
|
+
// Make sure the end of the child after the update is preserved in `after`
|
|
516
|
+
if (after && toOff < after.length) {
|
|
517
|
+
// If we're splitting a child, separate part of it to avoid that
|
|
518
|
+
// being mangled when updating the child before the update.
|
|
519
|
+
if (fromI == toI) {
|
|
520
|
+
after = after.split(toOff);
|
|
521
|
+
toOff = 0;
|
|
522
|
+
}
|
|
523
|
+
// If the element after the replacement should be merged with
|
|
524
|
+
// the last replacing element, update `content`
|
|
525
|
+
if (!breakAtEnd && last && after.merge(0, toOff, last, true, 0, openEnd)) {
|
|
526
|
+
insert[insert.length - 1] = after;
|
|
527
|
+
}
|
|
528
|
+
else {
|
|
529
|
+
// Remove the start of the after element, if necessary, and
|
|
530
|
+
// add it to `content`.
|
|
531
|
+
if (toOff)
|
|
532
|
+
after.merge(0, toOff, null, false, 0, openEnd);
|
|
533
|
+
insert.push(after);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
else if (after === null || after === void 0 ? void 0 : after.breakAfter) {
|
|
537
|
+
// The element at `toI` is entirely covered by this range.
|
|
538
|
+
// Preserve its line break, if any.
|
|
539
|
+
if (last)
|
|
540
|
+
last.breakAfter = 1;
|
|
541
|
+
else
|
|
542
|
+
breakAtStart = 1;
|
|
543
|
+
}
|
|
544
|
+
// Since we've handled the next element from the current elements
|
|
545
|
+
// now, make sure `toI` points after that.
|
|
546
|
+
toI++;
|
|
547
|
+
}
|
|
548
|
+
if (before) {
|
|
549
|
+
before.breakAfter = breakAtStart;
|
|
550
|
+
if (fromOff > 0) {
|
|
551
|
+
if (!breakAtStart && insert.length && before.merge(fromOff, before.length, insert[0], false, openStart, 0)) {
|
|
552
|
+
before.breakAfter = insert.shift().breakAfter;
|
|
553
|
+
}
|
|
554
|
+
else if (fromOff < before.length || before.children.length && before.children[before.children.length - 1].length == 0) {
|
|
555
|
+
before.merge(fromOff, before.length, null, false, openStart, 0);
|
|
556
|
+
}
|
|
557
|
+
fromI++;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
// Try to merge widgets on the boundaries of the replacement
|
|
561
|
+
while (fromI < toI && insert.length) {
|
|
562
|
+
if (children[toI - 1].become(insert[insert.length - 1])) {
|
|
563
|
+
toI--;
|
|
564
|
+
insert.pop();
|
|
565
|
+
openEnd = insert.length ? 0 : openStart;
|
|
566
|
+
}
|
|
567
|
+
else if (children[fromI].become(insert[0])) {
|
|
568
|
+
fromI++;
|
|
569
|
+
insert.shift();
|
|
570
|
+
openStart = insert.length ? 0 : openEnd;
|
|
571
|
+
}
|
|
572
|
+
else {
|
|
573
|
+
break;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
if (!insert.length && fromI && toI < children.length && !children[fromI - 1].breakAfter &&
|
|
577
|
+
children[toI].merge(0, 0, children[fromI - 1], false, openStart, openEnd))
|
|
578
|
+
fromI--;
|
|
579
|
+
if (fromI < toI || insert.length)
|
|
580
|
+
parent.replaceChildren(fromI, toI, insert);
|
|
581
|
+
}
|
|
582
|
+
function mergeChildrenInto(parent, from, to, insert, openStart, openEnd) {
|
|
583
|
+
let cur = parent.childCursor();
|
|
584
|
+
let { i: toI, off: toOff } = cur.findPos(to, 1);
|
|
585
|
+
let { i: fromI, off: fromOff } = cur.findPos(from, -1);
|
|
586
|
+
let dLen = from - to;
|
|
587
|
+
for (let view of insert)
|
|
588
|
+
dLen += view.length;
|
|
589
|
+
parent.length += dLen;
|
|
590
|
+
replaceRange(parent, fromI, fromOff, toI, toOff, insert, 0, openStart, openEnd);
|
|
591
|
+
}
|
|
493
592
|
|
|
494
593
|
let [nav, doc] = typeof navigator != "undefined"
|
|
495
594
|
? [navigator, document]
|
|
@@ -521,21 +620,8 @@ var browser = {
|
|
|
521
620
|
tabSize: doc.documentElement.style.tabSize != null ? "tab-size" : "-moz-tab-size"
|
|
522
621
|
};
|
|
523
622
|
|
|
524
|
-
const none$2 = [];
|
|
525
|
-
class InlineView extends ContentView {
|
|
526
|
-
/**
|
|
527
|
-
Return true when this view is equivalent to `other` and can take
|
|
528
|
-
on its role.
|
|
529
|
-
*/
|
|
530
|
-
become(_other) { return false; }
|
|
531
|
-
// When this is a zero-length view with a side, this should return a
|
|
532
|
-
// negative number to indicate it is before its position, or a
|
|
533
|
-
// positive number when after its position.
|
|
534
|
-
getSide() { return 0; }
|
|
535
|
-
}
|
|
536
|
-
InlineView.prototype.children = none$2;
|
|
537
623
|
const MaxJoinLen = 256;
|
|
538
|
-
class TextView extends
|
|
624
|
+
class TextView extends ContentView {
|
|
539
625
|
constructor(text) {
|
|
540
626
|
super();
|
|
541
627
|
this.text = text;
|
|
@@ -566,7 +652,7 @@ class TextView extends InlineView {
|
|
|
566
652
|
this.markDirty();
|
|
567
653
|
return true;
|
|
568
654
|
}
|
|
569
|
-
|
|
655
|
+
split(from) {
|
|
570
656
|
let result = new TextView(this.text.slice(from));
|
|
571
657
|
this.text = this.text.slice(0, from);
|
|
572
658
|
return result;
|
|
@@ -582,7 +668,7 @@ class TextView extends InlineView {
|
|
|
582
668
|
return textCoords(this.dom, pos, side);
|
|
583
669
|
}
|
|
584
670
|
}
|
|
585
|
-
class MarkView extends
|
|
671
|
+
class MarkView extends ContentView {
|
|
586
672
|
constructor(mark, children = [], length = 0) {
|
|
587
673
|
super();
|
|
588
674
|
this.mark = mark;
|
|
@@ -605,20 +691,20 @@ class MarkView extends InlineView {
|
|
|
605
691
|
this.createDOM();
|
|
606
692
|
super.sync(track);
|
|
607
693
|
}
|
|
608
|
-
merge(from, to, source, openStart, openEnd) {
|
|
694
|
+
merge(from, to, source, _hasStart, openStart, openEnd) {
|
|
609
695
|
if (source && (!(source instanceof MarkView && source.mark.eq(this.mark)) ||
|
|
610
696
|
(from && openStart <= 0) || (to < this.length && openEnd <= 0)))
|
|
611
697
|
return false;
|
|
612
|
-
|
|
698
|
+
mergeChildrenInto(this, from, to, source ? source.children : [], openStart - 1, openEnd - 1);
|
|
613
699
|
this.markDirty();
|
|
614
700
|
return true;
|
|
615
701
|
}
|
|
616
|
-
|
|
702
|
+
split(from) {
|
|
617
703
|
let result = [], off = 0, detachFrom = -1, i = 0;
|
|
618
704
|
for (let elt of this.children) {
|
|
619
705
|
let end = off + elt.length;
|
|
620
706
|
if (end > from)
|
|
621
|
-
result.push(off < from ? elt.
|
|
707
|
+
result.push(off < from ? elt.split(from - off) : elt);
|
|
622
708
|
if (detachFrom < 0 && off >= from)
|
|
623
709
|
detachFrom = i;
|
|
624
710
|
off = end;
|
|
@@ -626,8 +712,10 @@ class MarkView extends InlineView {
|
|
|
626
712
|
}
|
|
627
713
|
let length = this.length - from;
|
|
628
714
|
this.length = from;
|
|
629
|
-
if (detachFrom > -1)
|
|
630
|
-
this.
|
|
715
|
+
if (detachFrom > -1) {
|
|
716
|
+
this.children.length = detachFrom;
|
|
717
|
+
this.markDirty();
|
|
718
|
+
}
|
|
631
719
|
return new MarkView(this.mark, result, length);
|
|
632
720
|
}
|
|
633
721
|
domAtPos(pos) {
|
|
@@ -669,7 +757,7 @@ function textCoords(text, pos, side) {
|
|
|
669
757
|
return flatten ? flattenRect(rect, flatten < 0) : rect || null;
|
|
670
758
|
}
|
|
671
759
|
// Also used for collapsed ranges that don't have a placeholder widget!
|
|
672
|
-
class WidgetView extends
|
|
760
|
+
class WidgetView extends ContentView {
|
|
673
761
|
constructor(widget, length, side) {
|
|
674
762
|
super();
|
|
675
763
|
this.widget = widget;
|
|
@@ -679,7 +767,7 @@ class WidgetView extends InlineView {
|
|
|
679
767
|
static create(widget, length, side) {
|
|
680
768
|
return new (widget.customView || WidgetView)(widget, length, side);
|
|
681
769
|
}
|
|
682
|
-
|
|
770
|
+
split(from) {
|
|
683
771
|
let result = WidgetView.create(this.widget, this.length - from, this.side);
|
|
684
772
|
this.length -= from;
|
|
685
773
|
return result;
|
|
@@ -691,7 +779,7 @@ class WidgetView extends InlineView {
|
|
|
691
779
|
}
|
|
692
780
|
}
|
|
693
781
|
getSide() { return this.side; }
|
|
694
|
-
merge(from, to, source, openStart, openEnd) {
|
|
782
|
+
merge(from, to, source, hasStart, openStart, openEnd) {
|
|
695
783
|
if (source && (!(source instanceof WidgetView) || !this.widget.compare(source.widget) ||
|
|
696
784
|
from > 0 && openStart <= 0 || to < this.length && openEnd <= 0))
|
|
697
785
|
return false;
|
|
@@ -736,6 +824,11 @@ class WidgetView extends InlineView {
|
|
|
736
824
|
return (pos == 0 && side > 0 || pos == this.length && side <= 0) ? rect : flattenRect(rect, pos == 0);
|
|
737
825
|
}
|
|
738
826
|
get isEditable() { return false; }
|
|
827
|
+
destroy() {
|
|
828
|
+
super.destroy();
|
|
829
|
+
if (this.dom)
|
|
830
|
+
this.widget.destroy(this.dom);
|
|
831
|
+
}
|
|
739
832
|
}
|
|
740
833
|
class CompositionView extends WidgetView {
|
|
741
834
|
domAtPos(pos) { return new DOMPos(this.widget.text, pos); }
|
|
@@ -752,7 +845,7 @@ class CompositionView extends WidgetView {
|
|
|
752
845
|
// These are drawn around uneditable widgets to avoid a number of
|
|
753
846
|
// browser bugs that show up when the cursor is directly next to
|
|
754
847
|
// uneditable inline content.
|
|
755
|
-
class WidgetBufferView extends
|
|
848
|
+
class WidgetBufferView extends ContentView {
|
|
756
849
|
constructor(side) {
|
|
757
850
|
super();
|
|
758
851
|
this.side = side;
|
|
@@ -762,7 +855,7 @@ class WidgetBufferView extends InlineView {
|
|
|
762
855
|
become(other) {
|
|
763
856
|
return other instanceof WidgetBufferView && other.side == this.side;
|
|
764
857
|
}
|
|
765
|
-
|
|
858
|
+
split() { return new WidgetBufferView(this.side); }
|
|
766
859
|
sync() {
|
|
767
860
|
if (!this.dom)
|
|
768
861
|
this.setDOM(document.createTextNode("\u200b"));
|
|
@@ -780,90 +873,7 @@ class WidgetBufferView extends InlineView {
|
|
|
780
873
|
return Text.of([this.dom.nodeValue.replace(/\u200b/g, "")]);
|
|
781
874
|
}
|
|
782
875
|
}
|
|
783
|
-
|
|
784
|
-
let cur = parent.childCursor();
|
|
785
|
-
let { i: toI, off: toOff } = cur.findPos(to, 1);
|
|
786
|
-
let { i: fromI, off: fromOff } = cur.findPos(from, -1);
|
|
787
|
-
let dLen = from - to;
|
|
788
|
-
for (let view of elts)
|
|
789
|
-
dLen += view.length;
|
|
790
|
-
parent.length += dLen;
|
|
791
|
-
let { children } = parent;
|
|
792
|
-
// Both from and to point into the same child view
|
|
793
|
-
if (fromI == toI && fromOff) {
|
|
794
|
-
let start = children[fromI];
|
|
795
|
-
// Maybe just update that view and be done
|
|
796
|
-
if (elts.length == 1 && start.merge(fromOff, toOff, elts[0], openStart, openEnd))
|
|
797
|
-
return;
|
|
798
|
-
if (elts.length == 0) {
|
|
799
|
-
start.merge(fromOff, toOff, null, openStart, openEnd);
|
|
800
|
-
return;
|
|
801
|
-
}
|
|
802
|
-
// Otherwise split it, so that we don't have to worry about aliasing front/end afterwards
|
|
803
|
-
let after = start.slice(toOff);
|
|
804
|
-
if (after.merge(0, 0, elts[elts.length - 1], 0, openEnd))
|
|
805
|
-
elts[elts.length - 1] = after;
|
|
806
|
-
else
|
|
807
|
-
elts.push(after);
|
|
808
|
-
toI++;
|
|
809
|
-
openEnd = toOff = 0;
|
|
810
|
-
}
|
|
811
|
-
// Make sure start and end positions fall on node boundaries
|
|
812
|
-
// (fromOff/toOff are no longer used after this), and that if the
|
|
813
|
-
// start or end of the elts can be merged with adjacent nodes,
|
|
814
|
-
// this is done
|
|
815
|
-
if (toOff) {
|
|
816
|
-
let end = children[toI];
|
|
817
|
-
if (elts.length && end.merge(0, toOff, elts[elts.length - 1], 0, openEnd)) {
|
|
818
|
-
elts.pop();
|
|
819
|
-
openEnd = elts.length ? 0 : openStart;
|
|
820
|
-
}
|
|
821
|
-
else {
|
|
822
|
-
end.merge(0, toOff, null, 0, 0);
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
else if (toI < children.length && elts.length &&
|
|
826
|
-
children[toI].merge(0, 0, elts[elts.length - 1], 0, openEnd)) {
|
|
827
|
-
elts.pop();
|
|
828
|
-
openEnd = elts.length ? 0 : openStart;
|
|
829
|
-
}
|
|
830
|
-
if (fromOff) {
|
|
831
|
-
let start = children[fromI];
|
|
832
|
-
if (elts.length && start.merge(fromOff, start.length, elts[0], openStart, 0)) {
|
|
833
|
-
elts.shift();
|
|
834
|
-
openStart = elts.length ? 0 : openEnd;
|
|
835
|
-
}
|
|
836
|
-
else {
|
|
837
|
-
start.merge(fromOff, start.length, null, 0, 0);
|
|
838
|
-
}
|
|
839
|
-
fromI++;
|
|
840
|
-
}
|
|
841
|
-
else if (fromI && elts.length) {
|
|
842
|
-
let end = children[fromI - 1];
|
|
843
|
-
if (end.merge(end.length, end.length, elts[0], openStart, 0)) {
|
|
844
|
-
elts.shift();
|
|
845
|
-
openStart = elts.length ? 0 : openEnd;
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
// Then try to merge any mergeable nodes at the start and end of
|
|
849
|
-
// the changed range
|
|
850
|
-
while (fromI < toI && elts.length && children[toI - 1].become(elts[elts.length - 1])) {
|
|
851
|
-
elts.pop();
|
|
852
|
-
toI--;
|
|
853
|
-
openEnd = elts.length ? 0 : openStart;
|
|
854
|
-
}
|
|
855
|
-
while (fromI < toI && elts.length && children[fromI].become(elts[0])) {
|
|
856
|
-
elts.shift();
|
|
857
|
-
fromI++;
|
|
858
|
-
openStart = elts.length ? 0 : openEnd;
|
|
859
|
-
}
|
|
860
|
-
if (!elts.length && fromI && toI < children.length &&
|
|
861
|
-
children[toI].merge(0, 0, children[fromI - 1], openStart, openEnd))
|
|
862
|
-
fromI--;
|
|
863
|
-
// And if anything remains, splice the child array to insert the new elts
|
|
864
|
-
if (elts.length || fromI != toI)
|
|
865
|
-
parent.replaceChildren(fromI, toI, elts);
|
|
866
|
-
}
|
|
876
|
+
TextView.prototype.children = WidgetView.prototype.children = WidgetBufferView.prototype.children = noChildren;
|
|
867
877
|
function inlineDOMAtPos(dom, children, pos) {
|
|
868
878
|
let i = 0;
|
|
869
879
|
for (let off = 0; i < children.length; i++) {
|
|
@@ -1004,6 +1014,11 @@ class WidgetType {
|
|
|
1004
1014
|
@internal
|
|
1005
1015
|
*/
|
|
1006
1016
|
get customView() { return null; }
|
|
1017
|
+
/**
|
|
1018
|
+
This is called when the an instance of the widget is removed
|
|
1019
|
+
from the editor view.
|
|
1020
|
+
*/
|
|
1021
|
+
destroy(_dom) { }
|
|
1007
1022
|
}
|
|
1008
1023
|
/**
|
|
1009
1024
|
The different types of blocks that can occur in an editor view.
|
|
@@ -1082,8 +1097,9 @@ class Decoration extends RangeValue {
|
|
|
1082
1097
|
position.
|
|
1083
1098
|
*/
|
|
1084
1099
|
static widget(spec) {
|
|
1085
|
-
let side = spec.side || 0;
|
|
1086
|
-
|
|
1100
|
+
let side = spec.side || 0, block = !!spec.block;
|
|
1101
|
+
side += block ? (side > 0 ? 300000000 /* BlockAfter */ : -400000000 /* BlockBefore */) : (side > 0 ? 100000000 /* InlineAfter */ : -100000000 /* InlineBefore */);
|
|
1102
|
+
return new PointDecoration(spec, side, side, block, spec.widget || null, false);
|
|
1087
1103
|
}
|
|
1088
1104
|
/**
|
|
1089
1105
|
Create a replace decoration which replaces the given range with
|
|
@@ -1092,8 +1108,8 @@ class Decoration extends RangeValue {
|
|
|
1092
1108
|
static replace(spec) {
|
|
1093
1109
|
let block = !!spec.block;
|
|
1094
1110
|
let { start, end } = getInclusive(spec, block);
|
|
1095
|
-
let startSide =
|
|
1096
|
-
let endSide =
|
|
1111
|
+
let startSide = block ? (start ? -300000000 /* BlockIncStart */ : -1 /* InlineIncStart */) : 400000000 /* NonIncStart */;
|
|
1112
|
+
let endSide = block ? (end ? 200000000 /* BlockIncEnd */ : 1 /* InlineIncEnd */) : -500000000 /* NonIncEnd */;
|
|
1097
1113
|
return new PointDecoration(spec, startSide, endSide, block, spec.widget || null, true);
|
|
1098
1114
|
}
|
|
1099
1115
|
/**
|
|
@@ -1123,7 +1139,7 @@ Decoration.none = RangeSet.empty;
|
|
|
1123
1139
|
class MarkDecoration extends Decoration {
|
|
1124
1140
|
constructor(spec) {
|
|
1125
1141
|
let { start, end } = getInclusive(spec);
|
|
1126
|
-
super(
|
|
1142
|
+
super(start ? -1 /* InlineIncStart */ : 400000000 /* NonIncStart */, end ? 1 /* InlineIncEnd */ : -500000000 /* NonIncEnd */, null, spec);
|
|
1127
1143
|
this.tagName = spec.tagName || "span";
|
|
1128
1144
|
this.class = spec.class || "";
|
|
1129
1145
|
this.attrs = spec.attributes || null;
|
|
@@ -1144,7 +1160,7 @@ class MarkDecoration extends Decoration {
|
|
|
1144
1160
|
MarkDecoration.prototype.point = false;
|
|
1145
1161
|
class LineDecoration extends Decoration {
|
|
1146
1162
|
constructor(spec) {
|
|
1147
|
-
super(-
|
|
1163
|
+
super(-200000000 /* Line */, -200000000 /* Line */, null, spec);
|
|
1148
1164
|
}
|
|
1149
1165
|
eq(other) {
|
|
1150
1166
|
return other instanceof LineDecoration && attrsEq(this.spec.attributes, other.spec.attributes);
|
|
@@ -1162,12 +1178,12 @@ class PointDecoration extends Decoration {
|
|
|
1162
1178
|
super(startSide, endSide, widget, spec);
|
|
1163
1179
|
this.block = block;
|
|
1164
1180
|
this.isReplace = isReplace;
|
|
1165
|
-
this.mapMode = !block ? MapMode.TrackDel : startSide
|
|
1181
|
+
this.mapMode = !block ? MapMode.TrackDel : startSide <= 0 ? MapMode.TrackBefore : MapMode.TrackAfter;
|
|
1166
1182
|
}
|
|
1167
1183
|
// Only relevant when this.block == true
|
|
1168
1184
|
get type() {
|
|
1169
1185
|
return this.startSide < this.endSide ? BlockType.WidgetRange
|
|
1170
|
-
: this.startSide
|
|
1186
|
+
: this.startSide <= 0 ? BlockType.WidgetBefore : BlockType.WidgetAfter;
|
|
1171
1187
|
}
|
|
1172
1188
|
get heightRelevant() { return this.block || !!this.widget && this.widget.estimatedHeight >= 5; }
|
|
1173
1189
|
eq(other) {
|
|
@@ -1177,7 +1193,7 @@ class PointDecoration extends Decoration {
|
|
|
1177
1193
|
this.startSide == other.startSide && this.endSide == other.endSide;
|
|
1178
1194
|
}
|
|
1179
1195
|
range(from, to = from) {
|
|
1180
|
-
if (this.isReplace && (from > to || (from == to && this.startSide > 0 && this.endSide
|
|
1196
|
+
if (this.isReplace && (from > to || (from == to && this.startSide > 0 && this.endSide <= 0)))
|
|
1181
1197
|
throw new RangeError("Invalid range for replacement decoration");
|
|
1182
1198
|
if (!this.isReplace && to != from)
|
|
1183
1199
|
throw new RangeError("Widget decorations can only have zero-length ranges");
|
|
@@ -1214,16 +1230,16 @@ class LineView extends ContentView {
|
|
|
1214
1230
|
this.breakAfter = 0;
|
|
1215
1231
|
}
|
|
1216
1232
|
// Consumes source
|
|
1217
|
-
merge(from, to, source,
|
|
1233
|
+
merge(from, to, source, hasStart, openStart, openEnd) {
|
|
1218
1234
|
if (source) {
|
|
1219
1235
|
if (!(source instanceof LineView))
|
|
1220
1236
|
return false;
|
|
1221
1237
|
if (!this.dom)
|
|
1222
1238
|
source.transferDOM(this); // Reuse source.dom when appropriate
|
|
1223
1239
|
}
|
|
1224
|
-
if (
|
|
1240
|
+
if (hasStart)
|
|
1225
1241
|
this.setDeco(source ? source.attrs : null);
|
|
1226
|
-
|
|
1242
|
+
mergeChildrenInto(this, from, to, source ? source.children : [], openStart, openEnd);
|
|
1227
1243
|
return true;
|
|
1228
1244
|
}
|
|
1229
1245
|
split(at) {
|
|
@@ -1233,16 +1249,14 @@ class LineView extends ContentView {
|
|
|
1233
1249
|
return end;
|
|
1234
1250
|
let { i, off } = this.childPos(at);
|
|
1235
1251
|
if (off) {
|
|
1236
|
-
end.append(this.children[i].
|
|
1237
|
-
this.children[i].merge(off, this.children[i].length, null, 0, 0);
|
|
1252
|
+
end.append(this.children[i].split(off), 0);
|
|
1253
|
+
this.children[i].merge(off, this.children[i].length, null, false, 0, 0);
|
|
1238
1254
|
i++;
|
|
1239
1255
|
}
|
|
1240
1256
|
for (let j = i; j < this.children.length; j++)
|
|
1241
1257
|
end.append(this.children[j], 0);
|
|
1242
|
-
while (i > 0 && this.children[i - 1].length == 0)
|
|
1243
|
-
this.children[i
|
|
1244
|
-
i--;
|
|
1245
|
-
}
|
|
1258
|
+
while (i > 0 && this.children[i - 1].length == 0)
|
|
1259
|
+
this.children[--i].destroy();
|
|
1246
1260
|
this.children.length = i;
|
|
1247
1261
|
this.markDirty();
|
|
1248
1262
|
this.length = at;
|
|
@@ -1265,7 +1279,6 @@ class LineView extends ContentView {
|
|
|
1265
1279
|
this.attrs = attrs;
|
|
1266
1280
|
}
|
|
1267
1281
|
}
|
|
1268
|
-
// Only called when building a line view in ContentBuilder
|
|
1269
1282
|
append(child, openStart) {
|
|
1270
1283
|
joinInlineInto(this, child, openStart);
|
|
1271
1284
|
}
|
|
@@ -1322,7 +1335,7 @@ class LineView extends ContentView {
|
|
|
1322
1335
|
coordsAt(pos, side) {
|
|
1323
1336
|
return coordsInChildren(this, pos, side);
|
|
1324
1337
|
}
|
|
1325
|
-
|
|
1338
|
+
become(_other) { return false; }
|
|
1326
1339
|
get type() { return BlockType.Text; }
|
|
1327
1340
|
static find(docView, pos) {
|
|
1328
1341
|
for (let i = 0, off = 0;; i++) {
|
|
@@ -1337,7 +1350,6 @@ class LineView extends ContentView {
|
|
|
1337
1350
|
}
|
|
1338
1351
|
}
|
|
1339
1352
|
}
|
|
1340
|
-
const none$1 = [];
|
|
1341
1353
|
class BlockWidgetView extends ContentView {
|
|
1342
1354
|
constructor(widget, length, type) {
|
|
1343
1355
|
super();
|
|
@@ -1363,7 +1375,7 @@ class BlockWidgetView extends ContentView {
|
|
|
1363
1375
|
end.breakAfter = this.breakAfter;
|
|
1364
1376
|
return end;
|
|
1365
1377
|
}
|
|
1366
|
-
get children() { return
|
|
1378
|
+
get children() { return noChildren; }
|
|
1367
1379
|
sync() {
|
|
1368
1380
|
if (!this.dom || !this.widget.updateDOM(this.dom)) {
|
|
1369
1381
|
this.setDOM(this.widget.toDOM(this.editorView));
|
|
@@ -1374,7 +1386,7 @@ class BlockWidgetView extends ContentView {
|
|
|
1374
1386
|
return this.parent ? this.parent.view.state.doc.slice(this.posAtStart, this.posAtEnd) : Text$1.empty;
|
|
1375
1387
|
}
|
|
1376
1388
|
domBoundsAround() { return null; }
|
|
1377
|
-
|
|
1389
|
+
become(other) {
|
|
1378
1390
|
if (other instanceof BlockWidgetView && other.type == this.type &&
|
|
1379
1391
|
other.widget.constructor == this.widget.constructor) {
|
|
1380
1392
|
if (!other.widget.eq(this.widget))
|
|
@@ -1388,6 +1400,11 @@ class BlockWidgetView extends ContentView {
|
|
|
1388
1400
|
}
|
|
1389
1401
|
ignoreMutation() { return true; }
|
|
1390
1402
|
ignoreEvent(event) { return this.widget.ignoreEvent(event); }
|
|
1403
|
+
destroy() {
|
|
1404
|
+
super.destroy();
|
|
1405
|
+
if (this.dom)
|
|
1406
|
+
this.widget.destroy(this.dom);
|
|
1407
|
+
}
|
|
1391
1408
|
}
|
|
1392
1409
|
|
|
1393
1410
|
class ContentBuilder {
|
|
@@ -1723,36 +1740,39 @@ class PluginInstance {
|
|
|
1723
1740
|
this.value = null;
|
|
1724
1741
|
}
|
|
1725
1742
|
takeField(type, target) {
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1743
|
+
if (this.spec)
|
|
1744
|
+
for (let { field, get } of this.spec.fields)
|
|
1745
|
+
if (field == type)
|
|
1746
|
+
target.push(get(this.value));
|
|
1729
1747
|
}
|
|
1730
1748
|
update(view) {
|
|
1731
1749
|
if (!this.value) {
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1750
|
+
if (this.spec) {
|
|
1751
|
+
try {
|
|
1752
|
+
this.value = this.spec.create(view);
|
|
1753
|
+
}
|
|
1754
|
+
catch (e) {
|
|
1755
|
+
logException(view.state, e, "CodeMirror plugin crashed");
|
|
1756
|
+
this.deactivate();
|
|
1757
|
+
}
|
|
1738
1758
|
}
|
|
1739
1759
|
}
|
|
1740
1760
|
else if (this.mustUpdate) {
|
|
1741
1761
|
let update = this.mustUpdate;
|
|
1742
1762
|
this.mustUpdate = null;
|
|
1743
|
-
if (
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1763
|
+
if (this.value.update) {
|
|
1764
|
+
try {
|
|
1765
|
+
this.value.update(update);
|
|
1766
|
+
}
|
|
1767
|
+
catch (e) {
|
|
1768
|
+
logException(update.state, e, "CodeMirror plugin crashed");
|
|
1769
|
+
if (this.value.destroy)
|
|
1770
|
+
try {
|
|
1771
|
+
this.value.destroy();
|
|
1772
|
+
}
|
|
1773
|
+
catch (_) { }
|
|
1774
|
+
this.deactivate();
|
|
1775
|
+
}
|
|
1756
1776
|
}
|
|
1757
1777
|
}
|
|
1758
1778
|
return this;
|
|
@@ -1768,20 +1788,12 @@ class PluginInstance {
|
|
|
1768
1788
|
}
|
|
1769
1789
|
}
|
|
1770
1790
|
}
|
|
1791
|
+
deactivate() {
|
|
1792
|
+
this.spec = this.value = null;
|
|
1793
|
+
}
|
|
1771
1794
|
}
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
let result = {};
|
|
1775
|
-
for (let i = values.length - 1; i >= 0; i--)
|
|
1776
|
-
combineAttrs(values[i], result);
|
|
1777
|
-
return result;
|
|
1778
|
-
}
|
|
1779
|
-
const editorAttributes = /*@__PURE__*/Facet.define({
|
|
1780
|
-
combine: combineFacetAttrs
|
|
1781
|
-
});
|
|
1782
|
-
const contentAttributes = /*@__PURE__*/Facet.define({
|
|
1783
|
-
combine: combineFacetAttrs
|
|
1784
|
-
});
|
|
1795
|
+
const editorAttributes = /*@__PURE__*/Facet.define();
|
|
1796
|
+
const contentAttributes = /*@__PURE__*/Facet.define();
|
|
1785
1797
|
// Provide decorations
|
|
1786
1798
|
const decorations = /*@__PURE__*/Facet.define();
|
|
1787
1799
|
const styleModule = /*@__PURE__*/Facet.define();
|
|
@@ -1929,12 +1941,12 @@ class DocView extends ContentView {
|
|
|
1929
1941
|
this.compositionDeco = Decoration.none;
|
|
1930
1942
|
this.decorations = [];
|
|
1931
1943
|
// Track a minimum width for the editor. When measuring sizes in
|
|
1932
|
-
//
|
|
1933
|
-
// element and its extent in the document. When a change
|
|
1934
|
-
// that range, these are reset. That way, once we've seen
|
|
1935
|
-
// line/element of a given length, we keep the editor wide enough
|
|
1936
|
-
// fit at least that element, until it is changed, at which point
|
|
1937
|
-
// forget it again.
|
|
1944
|
+
// measureVisibleLineHeights, this is updated to point at the width
|
|
1945
|
+
// of a given element and its extent in the document. When a change
|
|
1946
|
+
// happens in that range, these are reset. That way, once we've seen
|
|
1947
|
+
// a line/element of a given length, we keep the editor wide enough
|
|
1948
|
+
// to fit at least that element, until it is changed, at which point
|
|
1949
|
+
// we forget it again.
|
|
1938
1950
|
this.minWidth = 0;
|
|
1939
1951
|
this.minWidthFrom = 0;
|
|
1940
1952
|
this.minWidthTo = 0;
|
|
@@ -2004,7 +2016,7 @@ class DocView extends ContentView {
|
|
|
2004
2016
|
this.updateSelection();
|
|
2005
2017
|
}
|
|
2006
2018
|
}
|
|
2007
|
-
// Used
|
|
2019
|
+
// Used by update and the constructor do perform the actual DOM
|
|
2008
2020
|
// update
|
|
2009
2021
|
updateInner(changes, deco, oldLength) {
|
|
2010
2022
|
this.view.viewState.mustMeasureContent = true;
|
|
@@ -2045,70 +2057,8 @@ class DocView extends ContentView {
|
|
|
2045
2057
|
let { content, breakAtStart, openStart, openEnd } = ContentBuilder.build(this.view.state.doc, fromB, toB, deco);
|
|
2046
2058
|
let { i: toI, off: toOff } = cursor.findPos(toA, 1);
|
|
2047
2059
|
let { i: fromI, off: fromOff } = cursor.findPos(fromA, -1);
|
|
2048
|
-
|
|
2049
|
-
}
|
|
2050
|
-
}
|
|
2051
|
-
replaceRange(fromI, fromOff, toI, toOff, content, breakAtStart, openStart, openEnd) {
|
|
2052
|
-
let before = this.children[fromI], last = content.length ? content[content.length - 1] : null;
|
|
2053
|
-
let breakAtEnd = last ? last.breakAfter : breakAtStart;
|
|
2054
|
-
// Change within a single line
|
|
2055
|
-
if (fromI == toI && !breakAtStart && !breakAtEnd && content.length < 2 &&
|
|
2056
|
-
before.merge(fromOff, toOff, content.length ? last : null, fromOff == 0, openStart, openEnd))
|
|
2057
|
-
return;
|
|
2058
|
-
let after = this.children[toI];
|
|
2059
|
-
// Make sure the end of the line after the update is preserved in `after`
|
|
2060
|
-
if (toOff < after.length) {
|
|
2061
|
-
// If we're splitting a line, separate part of the start line to
|
|
2062
|
-
// avoid that being mangled when updating the start line.
|
|
2063
|
-
if (fromI == toI) {
|
|
2064
|
-
after = after.split(toOff);
|
|
2065
|
-
toOff = 0;
|
|
2066
|
-
}
|
|
2067
|
-
// If the element after the replacement should be merged with
|
|
2068
|
-
// the last replacing element, update `content`
|
|
2069
|
-
if (!breakAtEnd && last && after.merge(0, toOff, last, true, 0, openEnd)) {
|
|
2070
|
-
content[content.length - 1] = after;
|
|
2071
|
-
}
|
|
2072
|
-
else {
|
|
2073
|
-
// Remove the start of the after element, if necessary, and
|
|
2074
|
-
// add it to `content`.
|
|
2075
|
-
if (toOff)
|
|
2076
|
-
after.merge(0, toOff, null, false, 0, openEnd);
|
|
2077
|
-
content.push(after);
|
|
2078
|
-
}
|
|
2060
|
+
replaceRange(this, fromI, fromOff, toI, toOff, content, breakAtStart, openStart, openEnd);
|
|
2079
2061
|
}
|
|
2080
|
-
else if (after.breakAfter) {
|
|
2081
|
-
// The element at `toI` is entirely covered by this range.
|
|
2082
|
-
// Preserve its line break, if any.
|
|
2083
|
-
if (last)
|
|
2084
|
-
last.breakAfter = 1;
|
|
2085
|
-
else
|
|
2086
|
-
breakAtStart = 1;
|
|
2087
|
-
}
|
|
2088
|
-
// Since we've handled the next element from the current elements
|
|
2089
|
-
// now, make sure `toI` points after that.
|
|
2090
|
-
toI++;
|
|
2091
|
-
before.breakAfter = breakAtStart;
|
|
2092
|
-
if (fromOff > 0) {
|
|
2093
|
-
if (!breakAtStart && content.length && before.merge(fromOff, before.length, content[0], false, openStart, 0)) {
|
|
2094
|
-
before.breakAfter = content.shift().breakAfter;
|
|
2095
|
-
}
|
|
2096
|
-
else if (fromOff < before.length || before.children.length && before.children[before.children.length - 1].length == 0) {
|
|
2097
|
-
before.merge(fromOff, before.length, null, false, openStart, 0);
|
|
2098
|
-
}
|
|
2099
|
-
fromI++;
|
|
2100
|
-
}
|
|
2101
|
-
// Try to merge widgets on the boundaries of the replacement
|
|
2102
|
-
while (fromI < toI && content.length) {
|
|
2103
|
-
if (this.children[toI - 1].match(content[content.length - 1]))
|
|
2104
|
-
toI--, content.pop();
|
|
2105
|
-
else if (this.children[fromI].match(content[0]))
|
|
2106
|
-
fromI++, content.shift();
|
|
2107
|
-
else
|
|
2108
|
-
break;
|
|
2109
|
-
}
|
|
2110
|
-
if (fromI < toI || content.length)
|
|
2111
|
-
this.replaceChildren(fromI, toI, content);
|
|
2112
2062
|
}
|
|
2113
2063
|
// Sync the DOM selection to this.state.selection
|
|
2114
2064
|
updateSelection(mustRead = false, fromPointer = false) {
|
|
@@ -2372,15 +2322,10 @@ function computeCompositionDeco(view, changes) {
|
|
|
2372
2322
|
if (!textNode)
|
|
2373
2323
|
return Decoration.none;
|
|
2374
2324
|
let cView = view.docView.nearest(textNode);
|
|
2325
|
+
if (!cView)
|
|
2326
|
+
return Decoration.none;
|
|
2375
2327
|
let from, to, topNode = textNode;
|
|
2376
|
-
if (cView instanceof
|
|
2377
|
-
while (cView.parent instanceof InlineView)
|
|
2378
|
-
cView = cView.parent;
|
|
2379
|
-
from = cView.posAtStart;
|
|
2380
|
-
to = from + cView.length;
|
|
2381
|
-
topNode = cView.dom;
|
|
2382
|
-
}
|
|
2383
|
-
else if (cView instanceof LineView) {
|
|
2328
|
+
if (cView instanceof LineView) {
|
|
2384
2329
|
while (topNode.parentNode != cView.dom)
|
|
2385
2330
|
topNode = topNode.parentNode;
|
|
2386
2331
|
let prev = topNode.previousSibling;
|
|
@@ -2389,7 +2334,17 @@ function computeCompositionDeco(view, changes) {
|
|
|
2389
2334
|
from = to = prev ? ContentView.get(prev).posAtEnd : cView.posAtStart;
|
|
2390
2335
|
}
|
|
2391
2336
|
else {
|
|
2392
|
-
|
|
2337
|
+
for (;;) {
|
|
2338
|
+
let { parent } = cView;
|
|
2339
|
+
if (!parent)
|
|
2340
|
+
return Decoration.none;
|
|
2341
|
+
if (parent instanceof LineView)
|
|
2342
|
+
break;
|
|
2343
|
+
cView = parent;
|
|
2344
|
+
}
|
|
2345
|
+
from = cView.posAtStart;
|
|
2346
|
+
to = from + cView.length;
|
|
2347
|
+
topNode = cView.dom;
|
|
2393
2348
|
}
|
|
2394
2349
|
let newFrom = changes.mapPos(from, 1), newTo = Math.max(newFrom, changes.mapPos(to, -1));
|
|
2395
2350
|
let text = textNode.nodeValue, { state } = view;
|
|
@@ -2926,7 +2881,7 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
|
2926
2881
|
y = docTop + yOffset;
|
|
2927
2882
|
let lineStart = block.from;
|
|
2928
2883
|
// Clip x to the viewport sides
|
|
2929
|
-
x = Math.max(content.left + 1, Math.min(content.right - 1, x));
|
|
2884
|
+
x = Math.max(content.left + 1, Math.min(Math.max(content.right, content.left + view.docView.minWidth) - 1, x));
|
|
2930
2885
|
// If this is outside of the rendered viewport, we can't determine a position
|
|
2931
2886
|
if (lineStart < view.viewport.from)
|
|
2932
2887
|
return view.viewport.from == 0 ? 0 : posAtCoordsImprecise(view, content, block, x, y);
|
|
@@ -4168,12 +4123,12 @@ class HeightMapBranch extends HeightMap {
|
|
|
4168
4123
|
get break() { return this.flags & 1 /* Break */; }
|
|
4169
4124
|
blockAt(height, doc, top, offset) {
|
|
4170
4125
|
let mid = top + this.left.height;
|
|
4171
|
-
return height < mid
|
|
4126
|
+
return height < mid ? this.left.blockAt(height, doc, top, offset)
|
|
4172
4127
|
: this.right.blockAt(height, doc, mid, offset + this.left.length + this.break);
|
|
4173
4128
|
}
|
|
4174
4129
|
lineAt(value, type, doc, top, offset) {
|
|
4175
4130
|
let rightTop = top + this.left.height, rightOffset = offset + this.left.length + this.break;
|
|
4176
|
-
let left = type == QueryType.ByHeight ? value < rightTop
|
|
4131
|
+
let left = type == QueryType.ByHeight ? value < rightTop : value < rightOffset;
|
|
4177
4132
|
let base = left ? this.left.lineAt(value, type, doc, top, offset)
|
|
4178
4133
|
: this.right.lineAt(value, type, doc, rightTop, rightOffset);
|
|
4179
4134
|
if (this.break || (left ? base.to < rightOffset : base.from > rightOffset))
|
|
@@ -4314,7 +4269,9 @@ class NodeBuilder {
|
|
|
4314
4269
|
}
|
|
4315
4270
|
point(from, to, deco) {
|
|
4316
4271
|
if (from < to || deco.heightRelevant) {
|
|
4317
|
-
let height = deco.widget ?
|
|
4272
|
+
let height = deco.widget ? deco.widget.estimatedHeight : 0;
|
|
4273
|
+
if (height < 0)
|
|
4274
|
+
height = this.oracle.lineHeight;
|
|
4318
4275
|
let len = to - from;
|
|
4319
4276
|
if (deco.block) {
|
|
4320
4277
|
this.addBlock(new HeightMapBlock(len, height, deco.type));
|
|
@@ -4788,7 +4745,7 @@ class ViewState {
|
|
|
4788
4745
|
return changed ? 4 /* Viewport */ : 0;
|
|
4789
4746
|
}
|
|
4790
4747
|
lineBlockAt(pos) {
|
|
4791
|
-
return (pos >= this.viewport.from && pos <= this.viewport.to && this.viewportLines.find(b => b.from <= pos && b.to
|
|
4748
|
+
return (pos >= this.viewport.from && pos <= this.viewport.to && this.viewportLines.find(b => b.from <= pos && b.to >= pos)) ||
|
|
4792
4749
|
scaleBlock(this.heightMap.lineAt(pos, QueryType.ByPos, this.state.doc, 0, 0), this.scaler);
|
|
4793
4750
|
}
|
|
4794
4751
|
lineBlockAtHeight(height) {
|
|
@@ -5059,7 +5016,7 @@ const baseTheme = /*@__PURE__*/buildTheme("." + baseThemeID, {
|
|
|
5059
5016
|
color: "inherit",
|
|
5060
5017
|
fontSize: "70%",
|
|
5061
5018
|
padding: ".2em 1em",
|
|
5062
|
-
borderRadius: "
|
|
5019
|
+
borderRadius: "1px"
|
|
5063
5020
|
},
|
|
5064
5021
|
"&light .cm-button": {
|
|
5065
5022
|
backgroundImage: "linear-gradient(#eff1f5, #d9d9df)",
|
|
@@ -5381,6 +5338,7 @@ class DOMObserver {
|
|
|
5381
5338
|
for (let dom of this.scrollTargets)
|
|
5382
5339
|
dom.removeEventListener("scroll", this.onScroll);
|
|
5383
5340
|
window.removeEventListener("scroll", this.onScroll);
|
|
5341
|
+
this.dom.ownerDocument.removeEventListener("selectionchange", this.onSelectionChange);
|
|
5384
5342
|
clearTimeout(this.parentCheck);
|
|
5385
5343
|
clearTimeout(this.resizeTimeout);
|
|
5386
5344
|
}
|
|
@@ -5677,6 +5635,7 @@ class EditorView {
|
|
|
5677
5635
|
*/
|
|
5678
5636
|
config = {}) {
|
|
5679
5637
|
this.plugins = [];
|
|
5638
|
+
this.pluginMap = new Map;
|
|
5680
5639
|
this.editorAttrs = {};
|
|
5681
5640
|
this.contentAttrs = {};
|
|
5682
5641
|
this.bidiCache = [];
|
|
@@ -5708,7 +5667,9 @@ class EditorView {
|
|
|
5708
5667
|
this.dispatch = this.dispatch.bind(this);
|
|
5709
5668
|
this.root = (config.root || getRoot(config.parent) || document);
|
|
5710
5669
|
this.viewState = new ViewState(config.state || EditorState.create());
|
|
5711
|
-
this.plugins = this.state.facet(viewPlugin).map(spec => new PluginInstance(spec)
|
|
5670
|
+
this.plugins = this.state.facet(viewPlugin).map(spec => new PluginInstance(spec));
|
|
5671
|
+
for (let plugin of this.plugins)
|
|
5672
|
+
plugin.update(this);
|
|
5712
5673
|
this.observer = new DOMObserver(this, (from, to, typeOver) => {
|
|
5713
5674
|
applyDOMChange(this, from, to, typeOver);
|
|
5714
5675
|
}, event => {
|
|
@@ -5845,7 +5806,10 @@ class EditorView {
|
|
|
5845
5806
|
for (let plugin of this.plugins)
|
|
5846
5807
|
plugin.destroy(this);
|
|
5847
5808
|
this.viewState = new ViewState(newState);
|
|
5848
|
-
this.plugins = newState.facet(viewPlugin).map(spec => new PluginInstance(spec)
|
|
5809
|
+
this.plugins = newState.facet(viewPlugin).map(spec => new PluginInstance(spec));
|
|
5810
|
+
this.pluginMap.clear();
|
|
5811
|
+
for (let plugin of this.plugins)
|
|
5812
|
+
plugin.update(this);
|
|
5849
5813
|
this.docView = new DocView(this);
|
|
5850
5814
|
this.inputState.ensureHandlers(this);
|
|
5851
5815
|
this.mountStyles();
|
|
@@ -5876,6 +5840,7 @@ class EditorView {
|
|
|
5876
5840
|
if (plugin.mustUpdate != update)
|
|
5877
5841
|
plugin.destroy(this);
|
|
5878
5842
|
this.plugins = newPlugins;
|
|
5843
|
+
this.pluginMap.clear();
|
|
5879
5844
|
this.inputState.ensureHandlers(this);
|
|
5880
5845
|
}
|
|
5881
5846
|
else {
|
|
@@ -5883,7 +5848,7 @@ class EditorView {
|
|
|
5883
5848
|
p.mustUpdate = update;
|
|
5884
5849
|
}
|
|
5885
5850
|
for (let i = 0; i < this.plugins.length; i++)
|
|
5886
|
-
this.plugins[i]
|
|
5851
|
+
this.plugins[i].update(this);
|
|
5887
5852
|
}
|
|
5888
5853
|
/**
|
|
5889
5854
|
@internal
|
|
@@ -5972,7 +5937,7 @@ class EditorView {
|
|
|
5972
5937
|
this.state.facet(theme);
|
|
5973
5938
|
}
|
|
5974
5939
|
updateAttrs() {
|
|
5975
|
-
let editorAttrs =
|
|
5940
|
+
let editorAttrs = attrsFromFacet(this, editorAttributes, {
|
|
5976
5941
|
class: "cm-editor" + (this.hasFocus ? " cm-focused " : " ") + this.themeClasses
|
|
5977
5942
|
});
|
|
5978
5943
|
let contentAttrs = {
|
|
@@ -5988,7 +5953,7 @@ class EditorView {
|
|
|
5988
5953
|
};
|
|
5989
5954
|
if (this.state.readOnly)
|
|
5990
5955
|
contentAttrs["aria-readonly"] = "true";
|
|
5991
|
-
|
|
5956
|
+
attrsFromFacet(this, contentAttributes, contentAttrs);
|
|
5992
5957
|
this.observer.ignore(() => {
|
|
5993
5958
|
updateAttrs(this.contentDOM, this.contentAttrs, contentAttrs);
|
|
5994
5959
|
updateAttrs(this.dom, this.editorAttrs, editorAttrs);
|
|
@@ -6057,10 +6022,10 @@ class EditorView {
|
|
|
6057
6022
|
the return value of this method.
|
|
6058
6023
|
*/
|
|
6059
6024
|
plugin(plugin) {
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
return
|
|
6025
|
+
let known = this.pluginMap.get(plugin);
|
|
6026
|
+
if (known === undefined || known && known.spec != plugin)
|
|
6027
|
+
this.pluginMap.set(plugin, known = this.plugins.find(p => p.spec == plugin) || null);
|
|
6028
|
+
return known && known.update(this).value;
|
|
6064
6029
|
}
|
|
6065
6030
|
/**
|
|
6066
6031
|
The top position of the document, in screen coordinates. This
|
|
@@ -6547,6 +6512,14 @@ class CachedOrder {
|
|
|
6547
6512
|
return result;
|
|
6548
6513
|
}
|
|
6549
6514
|
}
|
|
6515
|
+
function attrsFromFacet(view, facet, base) {
|
|
6516
|
+
for (let sources = view.state.facet(facet), i = sources.length - 1; i >= 0; i--) {
|
|
6517
|
+
let source = sources[i], value = typeof source == "function" ? source(view) : source;
|
|
6518
|
+
if (value)
|
|
6519
|
+
combineAttrs(value, base);
|
|
6520
|
+
}
|
|
6521
|
+
return base;
|
|
6522
|
+
}
|
|
6550
6523
|
|
|
6551
6524
|
const currentPlatform = browser.mac ? "mac" : browser.windows ? "win" : browser.linux ? "linux" : "key";
|
|
6552
6525
|
function normalizeKeyName(name, platform) {
|
|
@@ -7199,35 +7172,29 @@ class TabWidget extends WidgetType {
|
|
|
7199
7172
|
}
|
|
7200
7173
|
|
|
7201
7174
|
const plugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
7202
|
-
constructor(
|
|
7203
|
-
this.height =
|
|
7204
|
-
this.
|
|
7205
|
-
read: view => Math.max(0, view.scrollDOM.clientHeight - view.defaultLineHeight),
|
|
7206
|
-
write: (value, view) => {
|
|
7207
|
-
if (Math.abs(value - this.height) > 1) {
|
|
7208
|
-
this.height = value;
|
|
7209
|
-
view.contentDOM.style.paddingBottom = value + "px";
|
|
7210
|
-
}
|
|
7211
|
-
}
|
|
7212
|
-
};
|
|
7213
|
-
view.requestMeasure(this.measure);
|
|
7175
|
+
constructor() {
|
|
7176
|
+
this.height = 1000;
|
|
7177
|
+
this.attrs = { style: "padding-bottom: 1000px" };
|
|
7214
7178
|
}
|
|
7215
7179
|
update(update) {
|
|
7216
|
-
|
|
7217
|
-
|
|
7180
|
+
let height = update.view.viewState.editorHeight - update.view.defaultLineHeight;
|
|
7181
|
+
if (height != this.height) {
|
|
7182
|
+
this.height = height;
|
|
7183
|
+
this.attrs = { style: `padding-bottom: ${height}px` };
|
|
7184
|
+
}
|
|
7218
7185
|
}
|
|
7219
7186
|
});
|
|
7220
7187
|
/**
|
|
7221
|
-
Returns
|
|
7222
|
-
equivalent to the height of the editor, minus one line
|
|
7223
|
-
that every line in the document can be scrolled to the
|
|
7224
|
-
editor.
|
|
7188
|
+
Returns an extension that makes sure the content has a bottom
|
|
7189
|
+
margin equivalent to the height of the editor, minus one line
|
|
7190
|
+
height, so that every line in the document can be scrolled to the
|
|
7191
|
+
top of the editor.
|
|
7225
7192
|
|
|
7226
7193
|
This is only meaningful when the editor is scrollable, and should
|
|
7227
7194
|
not be enabled in editors that take the size of their content.
|
|
7228
7195
|
*/
|
|
7229
7196
|
function scrollPastEnd() {
|
|
7230
|
-
return plugin;
|
|
7197
|
+
return [plugin, contentAttributes.of(view => { var _a; return ((_a = view.plugin(plugin)) === null || _a === void 0 ? void 0 : _a.attrs) || null; })];
|
|
7231
7198
|
}
|
|
7232
7199
|
|
|
7233
7200
|
/**
|