@codemirror/view 0.19.22 → 0.19.26
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 +36 -0
- package/dist/index.cjs +254 -285
- package/dist/index.d.ts +31 -16
- package/dist/index.js +254 -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();
|
|
@@ -1908,7 +1920,7 @@ class ViewUpdate {
|
|
|
1908
1920
|
Whether the document changed in this update.
|
|
1909
1921
|
*/
|
|
1910
1922
|
get docChanged() {
|
|
1911
|
-
return this.
|
|
1923
|
+
return !this.changes.empty;
|
|
1912
1924
|
}
|
|
1913
1925
|
/**
|
|
1914
1926
|
Whether the selection was explicitly set in this update.
|
|
@@ -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,71 +2057,9 @@ 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
|
-
|
|
2060
|
+
replaceRange(this, fromI, fromOff, toI, toOff, content, breakAtStart, openStart, openEnd);
|
|
2049
2061
|
}
|
|
2050
2062
|
}
|
|
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
|
-
}
|
|
2079
|
-
}
|
|
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
|
-
}
|
|
2113
2063
|
// Sync the DOM selection to this.state.selection
|
|
2114
2064
|
updateSelection(mustRead = false, fromPointer = false) {
|
|
2115
2065
|
if (mustRead)
|
|
@@ -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);
|
|
@@ -4569,10 +4524,11 @@ class ViewState {
|
|
|
4569
4524
|
if (scrollTarget && (scrollTarget.range.head < viewport.from || scrollTarget.range.head > viewport.to) ||
|
|
4570
4525
|
!this.viewportIsAppropriate(viewport))
|
|
4571
4526
|
viewport = this.getViewport(0, scrollTarget);
|
|
4572
|
-
|
|
4573
|
-
viewport.from != this.viewport.from || viewport.to != this.viewport.to
|
|
4574
|
-
this.updateViewportLines();
|
|
4527
|
+
let updateLines = !update.changes.empty || (update.flags & 2 /* Height */) ||
|
|
4528
|
+
viewport.from != this.viewport.from || viewport.to != this.viewport.to;
|
|
4575
4529
|
this.viewport = viewport;
|
|
4530
|
+
if (updateLines)
|
|
4531
|
+
this.updateViewportLines();
|
|
4576
4532
|
this.updateForViewport();
|
|
4577
4533
|
if (this.lineGaps.length || this.viewport.to - this.viewport.from > 4000 /* DoubleMargin */)
|
|
4578
4534
|
this.updateLineGaps(this.ensureLineGaps(this.mapLineGaps(this.lineGaps, update.changes)));
|
|
@@ -4787,7 +4743,7 @@ class ViewState {
|
|
|
4787
4743
|
return changed ? 4 /* Viewport */ : 0;
|
|
4788
4744
|
}
|
|
4789
4745
|
lineBlockAt(pos) {
|
|
4790
|
-
return (pos >= this.viewport.from && pos <= this.viewport.to && this.viewportLines.find(b => b.from <= pos && b.to
|
|
4746
|
+
return (pos >= this.viewport.from && pos <= this.viewport.to && this.viewportLines.find(b => b.from <= pos && b.to >= pos)) ||
|
|
4791
4747
|
scaleBlock(this.heightMap.lineAt(pos, QueryType.ByPos, this.state.doc, 0, 0), this.scaler);
|
|
4792
4748
|
}
|
|
4793
4749
|
lineBlockAtHeight(height) {
|
|
@@ -5058,7 +5014,7 @@ const baseTheme = /*@__PURE__*/buildTheme("." + baseThemeID, {
|
|
|
5058
5014
|
color: "inherit",
|
|
5059
5015
|
fontSize: "70%",
|
|
5060
5016
|
padding: ".2em 1em",
|
|
5061
|
-
borderRadius: "
|
|
5017
|
+
borderRadius: "1px"
|
|
5062
5018
|
},
|
|
5063
5019
|
"&light .cm-button": {
|
|
5064
5020
|
backgroundImage: "linear-gradient(#eff1f5, #d9d9df)",
|
|
@@ -5380,6 +5336,7 @@ class DOMObserver {
|
|
|
5380
5336
|
for (let dom of this.scrollTargets)
|
|
5381
5337
|
dom.removeEventListener("scroll", this.onScroll);
|
|
5382
5338
|
window.removeEventListener("scroll", this.onScroll);
|
|
5339
|
+
this.dom.ownerDocument.removeEventListener("selectionchange", this.onSelectionChange);
|
|
5383
5340
|
clearTimeout(this.parentCheck);
|
|
5384
5341
|
clearTimeout(this.resizeTimeout);
|
|
5385
5342
|
}
|
|
@@ -5676,6 +5633,7 @@ class EditorView {
|
|
|
5676
5633
|
*/
|
|
5677
5634
|
config = {}) {
|
|
5678
5635
|
this.plugins = [];
|
|
5636
|
+
this.pluginMap = new Map;
|
|
5679
5637
|
this.editorAttrs = {};
|
|
5680
5638
|
this.contentAttrs = {};
|
|
5681
5639
|
this.bidiCache = [];
|
|
@@ -5845,6 +5803,7 @@ class EditorView {
|
|
|
5845
5803
|
plugin.destroy(this);
|
|
5846
5804
|
this.viewState = new ViewState(newState);
|
|
5847
5805
|
this.plugins = newState.facet(viewPlugin).map(spec => new PluginInstance(spec).update(this));
|
|
5806
|
+
this.pluginMap.clear();
|
|
5848
5807
|
this.docView = new DocView(this);
|
|
5849
5808
|
this.inputState.ensureHandlers(this);
|
|
5850
5809
|
this.mountStyles();
|
|
@@ -5875,6 +5834,7 @@ class EditorView {
|
|
|
5875
5834
|
if (plugin.mustUpdate != update)
|
|
5876
5835
|
plugin.destroy(this);
|
|
5877
5836
|
this.plugins = newPlugins;
|
|
5837
|
+
this.pluginMap.clear();
|
|
5878
5838
|
this.inputState.ensureHandlers(this);
|
|
5879
5839
|
}
|
|
5880
5840
|
else {
|
|
@@ -5882,7 +5842,7 @@ class EditorView {
|
|
|
5882
5842
|
p.mustUpdate = update;
|
|
5883
5843
|
}
|
|
5884
5844
|
for (let i = 0; i < this.plugins.length; i++)
|
|
5885
|
-
this.plugins[i]
|
|
5845
|
+
this.plugins[i].update(this);
|
|
5886
5846
|
}
|
|
5887
5847
|
/**
|
|
5888
5848
|
@internal
|
|
@@ -5971,7 +5931,7 @@ class EditorView {
|
|
|
5971
5931
|
this.state.facet(theme);
|
|
5972
5932
|
}
|
|
5973
5933
|
updateAttrs() {
|
|
5974
|
-
let editorAttrs =
|
|
5934
|
+
let editorAttrs = attrsFromFacet(this, editorAttributes, {
|
|
5975
5935
|
class: "cm-editor" + (this.hasFocus ? " cm-focused " : " ") + this.themeClasses
|
|
5976
5936
|
});
|
|
5977
5937
|
let contentAttrs = {
|
|
@@ -5987,7 +5947,7 @@ class EditorView {
|
|
|
5987
5947
|
};
|
|
5988
5948
|
if (this.state.readOnly)
|
|
5989
5949
|
contentAttrs["aria-readonly"] = "true";
|
|
5990
|
-
|
|
5950
|
+
attrsFromFacet(this, contentAttributes, contentAttrs);
|
|
5991
5951
|
this.observer.ignore(() => {
|
|
5992
5952
|
updateAttrs(this.contentDOM, this.contentAttrs, contentAttrs);
|
|
5993
5953
|
updateAttrs(this.dom, this.editorAttrs, editorAttrs);
|
|
@@ -6056,19 +6016,26 @@ class EditorView {
|
|
|
6056
6016
|
the return value of this method.
|
|
6057
6017
|
*/
|
|
6058
6018
|
plugin(plugin) {
|
|
6059
|
-
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
return
|
|
6019
|
+
let known = this.pluginMap.get(plugin);
|
|
6020
|
+
if (known === undefined || known && known.spec != plugin)
|
|
6021
|
+
this.pluginMap.set(plugin, known = this.plugins.find(p => p.spec == plugin) || null);
|
|
6022
|
+
return known && known.update(this).value;
|
|
6063
6023
|
}
|
|
6064
6024
|
/**
|
|
6065
6025
|
The top position of the document, in screen coordinates. This
|
|
6066
|
-
may be negative when the editor is scrolled down.
|
|
6026
|
+
may be negative when the editor is scrolled down. Points
|
|
6027
|
+
directly to the top of the first line, not above the padding.
|
|
6067
6028
|
*/
|
|
6068
6029
|
get documentTop() {
|
|
6069
6030
|
return this.contentDOM.getBoundingClientRect().top + this.viewState.paddingTop;
|
|
6070
6031
|
}
|
|
6071
6032
|
/**
|
|
6033
|
+
Reports the padding above and below the document.
|
|
6034
|
+
*/
|
|
6035
|
+
get documentPadding() {
|
|
6036
|
+
return { top: this.viewState.paddingTop, bottom: this.viewState.paddingBottom };
|
|
6037
|
+
}
|
|
6038
|
+
/**
|
|
6072
6039
|
Find the line or block widget at the given vertical position.
|
|
6073
6040
|
|
|
6074
6041
|
By default, this position is interpreted as a screen position,
|
|
@@ -6539,6 +6506,14 @@ class CachedOrder {
|
|
|
6539
6506
|
return result;
|
|
6540
6507
|
}
|
|
6541
6508
|
}
|
|
6509
|
+
function attrsFromFacet(view, facet, base) {
|
|
6510
|
+
for (let sources = view.state.facet(facet), i = sources.length - 1; i >= 0; i--) {
|
|
6511
|
+
let source = sources[i], value = typeof source == "function" ? source(view) : source;
|
|
6512
|
+
if (value)
|
|
6513
|
+
combineAttrs(value, base);
|
|
6514
|
+
}
|
|
6515
|
+
return base;
|
|
6516
|
+
}
|
|
6542
6517
|
|
|
6543
6518
|
const currentPlatform = browser.mac ? "mac" : browser.windows ? "win" : browser.linux ? "linux" : "key";
|
|
6544
6519
|
function normalizeKeyName(name, platform) {
|
|
@@ -7191,35 +7166,29 @@ class TabWidget extends WidgetType {
|
|
|
7191
7166
|
}
|
|
7192
7167
|
|
|
7193
7168
|
const plugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
7194
|
-
constructor(
|
|
7195
|
-
this.height =
|
|
7196
|
-
this.
|
|
7197
|
-
read: view => Math.max(0, view.scrollDOM.clientHeight - view.defaultLineHeight),
|
|
7198
|
-
write: (value, view) => {
|
|
7199
|
-
if (Math.abs(value - this.height) > 1) {
|
|
7200
|
-
this.height = value;
|
|
7201
|
-
view.contentDOM.style.paddingBottom = value + "px";
|
|
7202
|
-
}
|
|
7203
|
-
}
|
|
7204
|
-
};
|
|
7205
|
-
view.requestMeasure(this.measure);
|
|
7169
|
+
constructor() {
|
|
7170
|
+
this.height = 1000;
|
|
7171
|
+
this.attrs = { style: "padding-bottom: 1000px" };
|
|
7206
7172
|
}
|
|
7207
7173
|
update(update) {
|
|
7208
|
-
|
|
7209
|
-
|
|
7174
|
+
let height = update.view.viewState.editorHeight - update.view.defaultLineHeight;
|
|
7175
|
+
if (height != this.height) {
|
|
7176
|
+
this.height = height;
|
|
7177
|
+
this.attrs = { style: `padding-bottom: ${height}px` };
|
|
7178
|
+
}
|
|
7210
7179
|
}
|
|
7211
7180
|
});
|
|
7212
7181
|
/**
|
|
7213
|
-
Returns
|
|
7214
|
-
equivalent to the height of the editor, minus one line
|
|
7215
|
-
that every line in the document can be scrolled to the
|
|
7216
|
-
editor.
|
|
7182
|
+
Returns an extension that makes sure the content has a bottom
|
|
7183
|
+
margin equivalent to the height of the editor, minus one line
|
|
7184
|
+
height, so that every line in the document can be scrolled to the
|
|
7185
|
+
top of the editor.
|
|
7217
7186
|
|
|
7218
7187
|
This is only meaningful when the editor is scrollable, and should
|
|
7219
7188
|
not be enabled in editors that take the size of their content.
|
|
7220
7189
|
*/
|
|
7221
7190
|
function scrollPastEnd() {
|
|
7222
|
-
return plugin;
|
|
7191
|
+
return [plugin, contentAttributes.of(view => { var _a; return ((_a = view.plugin(plugin)) === null || _a === void 0 ? void 0 : _a.attrs) || null; })];
|
|
7223
7192
|
}
|
|
7224
7193
|
|
|
7225
7194
|
/**
|