@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.cjs
CHANGED
|
@@ -273,7 +273,7 @@ class DOMPos {
|
|
|
273
273
|
static before(dom, precise) { return new DOMPos(dom.parentNode, domIndex(dom), precise); }
|
|
274
274
|
static after(dom, precise) { return new DOMPos(dom.parentNode, domIndex(dom) + 1, precise); }
|
|
275
275
|
}
|
|
276
|
-
const
|
|
276
|
+
const noChildren = [];
|
|
277
277
|
class ContentView {
|
|
278
278
|
constructor() {
|
|
279
279
|
this.parent = null;
|
|
@@ -439,12 +439,12 @@ class ContentView {
|
|
|
439
439
|
v = parent;
|
|
440
440
|
}
|
|
441
441
|
}
|
|
442
|
-
replaceChildren(from, to, children =
|
|
442
|
+
replaceChildren(from, to, children = noChildren) {
|
|
443
443
|
this.markDirty();
|
|
444
444
|
for (let i = from; i < to; i++) {
|
|
445
445
|
let child = this.children[i];
|
|
446
446
|
if (child.parent == this)
|
|
447
|
-
child.
|
|
447
|
+
child.destroy();
|
|
448
448
|
}
|
|
449
449
|
this.children.splice(from, to - from, ...children);
|
|
450
450
|
for (let i = 0; i < children.length; i++)
|
|
@@ -466,6 +466,17 @@ class ContentView {
|
|
|
466
466
|
}
|
|
467
467
|
static get(node) { return node.cmView; }
|
|
468
468
|
get isEditable() { return true; }
|
|
469
|
+
merge(from, to, source, hasStart, openStart, openEnd) {
|
|
470
|
+
return false;
|
|
471
|
+
}
|
|
472
|
+
become(other) { return false; }
|
|
473
|
+
// When this is a zero-length view with a side, this should return a
|
|
474
|
+
// number <= 0 to indicate it is before its position, or a
|
|
475
|
+
// number > 0 when after its position.
|
|
476
|
+
getSide() { return 0; }
|
|
477
|
+
destroy() {
|
|
478
|
+
this.parent = null;
|
|
479
|
+
}
|
|
469
480
|
}
|
|
470
481
|
ContentView.prototype.breakAfter = 0;
|
|
471
482
|
// Remove a DOM node and return its next sibling.
|
|
@@ -493,6 +504,94 @@ class ChildCursor {
|
|
|
493
504
|
}
|
|
494
505
|
}
|
|
495
506
|
}
|
|
507
|
+
function replaceRange(parent, fromI, fromOff, toI, toOff, insert, breakAtStart, openStart, openEnd) {
|
|
508
|
+
let { children } = parent;
|
|
509
|
+
let before = children.length ? children[fromI] : null;
|
|
510
|
+
let last = insert.length ? insert[insert.length - 1] : null;
|
|
511
|
+
let breakAtEnd = last ? last.breakAfter : breakAtStart;
|
|
512
|
+
// Change within a single child
|
|
513
|
+
if (fromI == toI && before && !breakAtStart && !breakAtEnd && insert.length < 2 &&
|
|
514
|
+
before.merge(fromOff, toOff, insert.length ? last : null, fromOff == 0, openStart, openEnd))
|
|
515
|
+
return;
|
|
516
|
+
if (toI < children.length) {
|
|
517
|
+
let after = children[toI];
|
|
518
|
+
// Make sure the end of the child after the update is preserved in `after`
|
|
519
|
+
if (after && toOff < after.length) {
|
|
520
|
+
// If we're splitting a child, separate part of it to avoid that
|
|
521
|
+
// being mangled when updating the child before the update.
|
|
522
|
+
if (fromI == toI) {
|
|
523
|
+
after = after.split(toOff);
|
|
524
|
+
toOff = 0;
|
|
525
|
+
}
|
|
526
|
+
// If the element after the replacement should be merged with
|
|
527
|
+
// the last replacing element, update `content`
|
|
528
|
+
if (!breakAtEnd && last && after.merge(0, toOff, last, true, 0, openEnd)) {
|
|
529
|
+
insert[insert.length - 1] = after;
|
|
530
|
+
}
|
|
531
|
+
else {
|
|
532
|
+
// Remove the start of the after element, if necessary, and
|
|
533
|
+
// add it to `content`.
|
|
534
|
+
if (toOff)
|
|
535
|
+
after.merge(0, toOff, null, false, 0, openEnd);
|
|
536
|
+
insert.push(after);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
else if (after === null || after === void 0 ? void 0 : after.breakAfter) {
|
|
540
|
+
// The element at `toI` is entirely covered by this range.
|
|
541
|
+
// Preserve its line break, if any.
|
|
542
|
+
if (last)
|
|
543
|
+
last.breakAfter = 1;
|
|
544
|
+
else
|
|
545
|
+
breakAtStart = 1;
|
|
546
|
+
}
|
|
547
|
+
// Since we've handled the next element from the current elements
|
|
548
|
+
// now, make sure `toI` points after that.
|
|
549
|
+
toI++;
|
|
550
|
+
}
|
|
551
|
+
if (before) {
|
|
552
|
+
before.breakAfter = breakAtStart;
|
|
553
|
+
if (fromOff > 0) {
|
|
554
|
+
if (!breakAtStart && insert.length && before.merge(fromOff, before.length, insert[0], false, openStart, 0)) {
|
|
555
|
+
before.breakAfter = insert.shift().breakAfter;
|
|
556
|
+
}
|
|
557
|
+
else if (fromOff < before.length || before.children.length && before.children[before.children.length - 1].length == 0) {
|
|
558
|
+
before.merge(fromOff, before.length, null, false, openStart, 0);
|
|
559
|
+
}
|
|
560
|
+
fromI++;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
// Try to merge widgets on the boundaries of the replacement
|
|
564
|
+
while (fromI < toI && insert.length) {
|
|
565
|
+
if (children[toI - 1].become(insert[insert.length - 1])) {
|
|
566
|
+
toI--;
|
|
567
|
+
insert.pop();
|
|
568
|
+
openEnd = insert.length ? 0 : openStart;
|
|
569
|
+
}
|
|
570
|
+
else if (children[fromI].become(insert[0])) {
|
|
571
|
+
fromI++;
|
|
572
|
+
insert.shift();
|
|
573
|
+
openStart = insert.length ? 0 : openEnd;
|
|
574
|
+
}
|
|
575
|
+
else {
|
|
576
|
+
break;
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
if (!insert.length && fromI && toI < children.length && !children[fromI - 1].breakAfter &&
|
|
580
|
+
children[toI].merge(0, 0, children[fromI - 1], false, openStart, openEnd))
|
|
581
|
+
fromI--;
|
|
582
|
+
if (fromI < toI || insert.length)
|
|
583
|
+
parent.replaceChildren(fromI, toI, insert);
|
|
584
|
+
}
|
|
585
|
+
function mergeChildrenInto(parent, from, to, insert, openStart, openEnd) {
|
|
586
|
+
let cur = parent.childCursor();
|
|
587
|
+
let { i: toI, off: toOff } = cur.findPos(to, 1);
|
|
588
|
+
let { i: fromI, off: fromOff } = cur.findPos(from, -1);
|
|
589
|
+
let dLen = from - to;
|
|
590
|
+
for (let view of insert)
|
|
591
|
+
dLen += view.length;
|
|
592
|
+
parent.length += dLen;
|
|
593
|
+
replaceRange(parent, fromI, fromOff, toI, toOff, insert, 0, openStart, openEnd);
|
|
594
|
+
}
|
|
496
595
|
|
|
497
596
|
let [nav, doc] = typeof navigator != "undefined"
|
|
498
597
|
? [navigator, document]
|
|
@@ -524,21 +623,8 @@ var browser = {
|
|
|
524
623
|
tabSize: doc.documentElement.style.tabSize != null ? "tab-size" : "-moz-tab-size"
|
|
525
624
|
};
|
|
526
625
|
|
|
527
|
-
const none$2 = [];
|
|
528
|
-
class InlineView extends ContentView {
|
|
529
|
-
/**
|
|
530
|
-
Return true when this view is equivalent to `other` and can take
|
|
531
|
-
on its role.
|
|
532
|
-
*/
|
|
533
|
-
become(_other) { return false; }
|
|
534
|
-
// When this is a zero-length view with a side, this should return a
|
|
535
|
-
// negative number to indicate it is before its position, or a
|
|
536
|
-
// positive number when after its position.
|
|
537
|
-
getSide() { return 0; }
|
|
538
|
-
}
|
|
539
|
-
InlineView.prototype.children = none$2;
|
|
540
626
|
const MaxJoinLen = 256;
|
|
541
|
-
class TextView extends
|
|
627
|
+
class TextView extends ContentView {
|
|
542
628
|
constructor(text) {
|
|
543
629
|
super();
|
|
544
630
|
this.text = text;
|
|
@@ -569,7 +655,7 @@ class TextView extends InlineView {
|
|
|
569
655
|
this.markDirty();
|
|
570
656
|
return true;
|
|
571
657
|
}
|
|
572
|
-
|
|
658
|
+
split(from) {
|
|
573
659
|
let result = new TextView(this.text.slice(from));
|
|
574
660
|
this.text = this.text.slice(0, from);
|
|
575
661
|
return result;
|
|
@@ -585,7 +671,7 @@ class TextView extends InlineView {
|
|
|
585
671
|
return textCoords(this.dom, pos, side);
|
|
586
672
|
}
|
|
587
673
|
}
|
|
588
|
-
class MarkView extends
|
|
674
|
+
class MarkView extends ContentView {
|
|
589
675
|
constructor(mark, children = [], length = 0) {
|
|
590
676
|
super();
|
|
591
677
|
this.mark = mark;
|
|
@@ -608,20 +694,20 @@ class MarkView extends InlineView {
|
|
|
608
694
|
this.createDOM();
|
|
609
695
|
super.sync(track);
|
|
610
696
|
}
|
|
611
|
-
merge(from, to, source, openStart, openEnd) {
|
|
697
|
+
merge(from, to, source, _hasStart, openStart, openEnd) {
|
|
612
698
|
if (source && (!(source instanceof MarkView && source.mark.eq(this.mark)) ||
|
|
613
699
|
(from && openStart <= 0) || (to < this.length && openEnd <= 0)))
|
|
614
700
|
return false;
|
|
615
|
-
|
|
701
|
+
mergeChildrenInto(this, from, to, source ? source.children : [], openStart - 1, openEnd - 1);
|
|
616
702
|
this.markDirty();
|
|
617
703
|
return true;
|
|
618
704
|
}
|
|
619
|
-
|
|
705
|
+
split(from) {
|
|
620
706
|
let result = [], off = 0, detachFrom = -1, i = 0;
|
|
621
707
|
for (let elt of this.children) {
|
|
622
708
|
let end = off + elt.length;
|
|
623
709
|
if (end > from)
|
|
624
|
-
result.push(off < from ? elt.
|
|
710
|
+
result.push(off < from ? elt.split(from - off) : elt);
|
|
625
711
|
if (detachFrom < 0 && off >= from)
|
|
626
712
|
detachFrom = i;
|
|
627
713
|
off = end;
|
|
@@ -629,8 +715,10 @@ class MarkView extends InlineView {
|
|
|
629
715
|
}
|
|
630
716
|
let length = this.length - from;
|
|
631
717
|
this.length = from;
|
|
632
|
-
if (detachFrom > -1)
|
|
633
|
-
this.
|
|
718
|
+
if (detachFrom > -1) {
|
|
719
|
+
this.children.length = detachFrom;
|
|
720
|
+
this.markDirty();
|
|
721
|
+
}
|
|
634
722
|
return new MarkView(this.mark, result, length);
|
|
635
723
|
}
|
|
636
724
|
domAtPos(pos) {
|
|
@@ -672,7 +760,7 @@ function textCoords(text, pos, side) {
|
|
|
672
760
|
return flatten ? flattenRect(rect, flatten < 0) : rect || null;
|
|
673
761
|
}
|
|
674
762
|
// Also used for collapsed ranges that don't have a placeholder widget!
|
|
675
|
-
class WidgetView extends
|
|
763
|
+
class WidgetView extends ContentView {
|
|
676
764
|
constructor(widget, length, side) {
|
|
677
765
|
super();
|
|
678
766
|
this.widget = widget;
|
|
@@ -682,7 +770,7 @@ class WidgetView extends InlineView {
|
|
|
682
770
|
static create(widget, length, side) {
|
|
683
771
|
return new (widget.customView || WidgetView)(widget, length, side);
|
|
684
772
|
}
|
|
685
|
-
|
|
773
|
+
split(from) {
|
|
686
774
|
let result = WidgetView.create(this.widget, this.length - from, this.side);
|
|
687
775
|
this.length -= from;
|
|
688
776
|
return result;
|
|
@@ -694,7 +782,7 @@ class WidgetView extends InlineView {
|
|
|
694
782
|
}
|
|
695
783
|
}
|
|
696
784
|
getSide() { return this.side; }
|
|
697
|
-
merge(from, to, source, openStart, openEnd) {
|
|
785
|
+
merge(from, to, source, hasStart, openStart, openEnd) {
|
|
698
786
|
if (source && (!(source instanceof WidgetView) || !this.widget.compare(source.widget) ||
|
|
699
787
|
from > 0 && openStart <= 0 || to < this.length && openEnd <= 0))
|
|
700
788
|
return false;
|
|
@@ -739,6 +827,11 @@ class WidgetView extends InlineView {
|
|
|
739
827
|
return (pos == 0 && side > 0 || pos == this.length && side <= 0) ? rect : flattenRect(rect, pos == 0);
|
|
740
828
|
}
|
|
741
829
|
get isEditable() { return false; }
|
|
830
|
+
destroy() {
|
|
831
|
+
super.destroy();
|
|
832
|
+
if (this.dom)
|
|
833
|
+
this.widget.destroy(this.dom);
|
|
834
|
+
}
|
|
742
835
|
}
|
|
743
836
|
class CompositionView extends WidgetView {
|
|
744
837
|
domAtPos(pos) { return new DOMPos(this.widget.text, pos); }
|
|
@@ -755,7 +848,7 @@ class CompositionView extends WidgetView {
|
|
|
755
848
|
// These are drawn around uneditable widgets to avoid a number of
|
|
756
849
|
// browser bugs that show up when the cursor is directly next to
|
|
757
850
|
// uneditable inline content.
|
|
758
|
-
class WidgetBufferView extends
|
|
851
|
+
class WidgetBufferView extends ContentView {
|
|
759
852
|
constructor(side) {
|
|
760
853
|
super();
|
|
761
854
|
this.side = side;
|
|
@@ -765,7 +858,7 @@ class WidgetBufferView extends InlineView {
|
|
|
765
858
|
become(other) {
|
|
766
859
|
return other instanceof WidgetBufferView && other.side == this.side;
|
|
767
860
|
}
|
|
768
|
-
|
|
861
|
+
split() { return new WidgetBufferView(this.side); }
|
|
769
862
|
sync() {
|
|
770
863
|
if (!this.dom)
|
|
771
864
|
this.setDOM(document.createTextNode("\u200b"));
|
|
@@ -783,90 +876,7 @@ class WidgetBufferView extends InlineView {
|
|
|
783
876
|
return text.Text.of([this.dom.nodeValue.replace(/\u200b/g, "")]);
|
|
784
877
|
}
|
|
785
878
|
}
|
|
786
|
-
|
|
787
|
-
let cur = parent.childCursor();
|
|
788
|
-
let { i: toI, off: toOff } = cur.findPos(to, 1);
|
|
789
|
-
let { i: fromI, off: fromOff } = cur.findPos(from, -1);
|
|
790
|
-
let dLen = from - to;
|
|
791
|
-
for (let view of elts)
|
|
792
|
-
dLen += view.length;
|
|
793
|
-
parent.length += dLen;
|
|
794
|
-
let { children } = parent;
|
|
795
|
-
// Both from and to point into the same child view
|
|
796
|
-
if (fromI == toI && fromOff) {
|
|
797
|
-
let start = children[fromI];
|
|
798
|
-
// Maybe just update that view and be done
|
|
799
|
-
if (elts.length == 1 && start.merge(fromOff, toOff, elts[0], openStart, openEnd))
|
|
800
|
-
return;
|
|
801
|
-
if (elts.length == 0) {
|
|
802
|
-
start.merge(fromOff, toOff, null, openStart, openEnd);
|
|
803
|
-
return;
|
|
804
|
-
}
|
|
805
|
-
// Otherwise split it, so that we don't have to worry about aliasing front/end afterwards
|
|
806
|
-
let after = start.slice(toOff);
|
|
807
|
-
if (after.merge(0, 0, elts[elts.length - 1], 0, openEnd))
|
|
808
|
-
elts[elts.length - 1] = after;
|
|
809
|
-
else
|
|
810
|
-
elts.push(after);
|
|
811
|
-
toI++;
|
|
812
|
-
openEnd = toOff = 0;
|
|
813
|
-
}
|
|
814
|
-
// Make sure start and end positions fall on node boundaries
|
|
815
|
-
// (fromOff/toOff are no longer used after this), and that if the
|
|
816
|
-
// start or end of the elts can be merged with adjacent nodes,
|
|
817
|
-
// this is done
|
|
818
|
-
if (toOff) {
|
|
819
|
-
let end = children[toI];
|
|
820
|
-
if (elts.length && end.merge(0, toOff, elts[elts.length - 1], 0, openEnd)) {
|
|
821
|
-
elts.pop();
|
|
822
|
-
openEnd = elts.length ? 0 : openStart;
|
|
823
|
-
}
|
|
824
|
-
else {
|
|
825
|
-
end.merge(0, toOff, null, 0, 0);
|
|
826
|
-
}
|
|
827
|
-
}
|
|
828
|
-
else if (toI < children.length && elts.length &&
|
|
829
|
-
children[toI].merge(0, 0, elts[elts.length - 1], 0, openEnd)) {
|
|
830
|
-
elts.pop();
|
|
831
|
-
openEnd = elts.length ? 0 : openStart;
|
|
832
|
-
}
|
|
833
|
-
if (fromOff) {
|
|
834
|
-
let start = children[fromI];
|
|
835
|
-
if (elts.length && start.merge(fromOff, start.length, elts[0], openStart, 0)) {
|
|
836
|
-
elts.shift();
|
|
837
|
-
openStart = elts.length ? 0 : openEnd;
|
|
838
|
-
}
|
|
839
|
-
else {
|
|
840
|
-
start.merge(fromOff, start.length, null, 0, 0);
|
|
841
|
-
}
|
|
842
|
-
fromI++;
|
|
843
|
-
}
|
|
844
|
-
else if (fromI && elts.length) {
|
|
845
|
-
let end = children[fromI - 1];
|
|
846
|
-
if (end.merge(end.length, end.length, elts[0], openStart, 0)) {
|
|
847
|
-
elts.shift();
|
|
848
|
-
openStart = elts.length ? 0 : openEnd;
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
|
-
// Then try to merge any mergeable nodes at the start and end of
|
|
852
|
-
// the changed range
|
|
853
|
-
while (fromI < toI && elts.length && children[toI - 1].become(elts[elts.length - 1])) {
|
|
854
|
-
elts.pop();
|
|
855
|
-
toI--;
|
|
856
|
-
openEnd = elts.length ? 0 : openStart;
|
|
857
|
-
}
|
|
858
|
-
while (fromI < toI && elts.length && children[fromI].become(elts[0])) {
|
|
859
|
-
elts.shift();
|
|
860
|
-
fromI++;
|
|
861
|
-
openStart = elts.length ? 0 : openEnd;
|
|
862
|
-
}
|
|
863
|
-
if (!elts.length && fromI && toI < children.length &&
|
|
864
|
-
children[toI].merge(0, 0, children[fromI - 1], openStart, openEnd))
|
|
865
|
-
fromI--;
|
|
866
|
-
// And if anything remains, splice the child array to insert the new elts
|
|
867
|
-
if (elts.length || fromI != toI)
|
|
868
|
-
parent.replaceChildren(fromI, toI, elts);
|
|
869
|
-
}
|
|
879
|
+
TextView.prototype.children = WidgetView.prototype.children = WidgetBufferView.prototype.children = noChildren;
|
|
870
880
|
function inlineDOMAtPos(dom, children, pos) {
|
|
871
881
|
let i = 0;
|
|
872
882
|
for (let off = 0; i < children.length; i++) {
|
|
@@ -1007,6 +1017,11 @@ class WidgetType {
|
|
|
1007
1017
|
@internal
|
|
1008
1018
|
*/
|
|
1009
1019
|
get customView() { return null; }
|
|
1020
|
+
/**
|
|
1021
|
+
This is called when the an instance of the widget is removed
|
|
1022
|
+
from the editor view.
|
|
1023
|
+
*/
|
|
1024
|
+
destroy(_dom) { }
|
|
1010
1025
|
}
|
|
1011
1026
|
/**
|
|
1012
1027
|
The different types of blocks that can occur in an editor view.
|
|
@@ -1086,8 +1101,9 @@ class Decoration extends rangeset.RangeValue {
|
|
|
1086
1101
|
position.
|
|
1087
1102
|
*/
|
|
1088
1103
|
static widget(spec) {
|
|
1089
|
-
let side = spec.side || 0;
|
|
1090
|
-
|
|
1104
|
+
let side = spec.side || 0, block = !!spec.block;
|
|
1105
|
+
side += block ? (side > 0 ? 300000000 /* BlockAfter */ : -400000000 /* BlockBefore */) : (side > 0 ? 100000000 /* InlineAfter */ : -100000000 /* InlineBefore */);
|
|
1106
|
+
return new PointDecoration(spec, side, side, block, spec.widget || null, false);
|
|
1091
1107
|
}
|
|
1092
1108
|
/**
|
|
1093
1109
|
Create a replace decoration which replaces the given range with
|
|
@@ -1096,8 +1112,8 @@ class Decoration extends rangeset.RangeValue {
|
|
|
1096
1112
|
static replace(spec) {
|
|
1097
1113
|
let block = !!spec.block;
|
|
1098
1114
|
let { start, end } = getInclusive(spec, block);
|
|
1099
|
-
let startSide =
|
|
1100
|
-
let endSide =
|
|
1115
|
+
let startSide = block ? (start ? -300000000 /* BlockIncStart */ : -1 /* InlineIncStart */) : 400000000 /* NonIncStart */;
|
|
1116
|
+
let endSide = block ? (end ? 200000000 /* BlockIncEnd */ : 1 /* InlineIncEnd */) : -500000000 /* NonIncEnd */;
|
|
1101
1117
|
return new PointDecoration(spec, startSide, endSide, block, spec.widget || null, true);
|
|
1102
1118
|
}
|
|
1103
1119
|
/**
|
|
@@ -1127,7 +1143,7 @@ Decoration.none = rangeset.RangeSet.empty;
|
|
|
1127
1143
|
class MarkDecoration extends Decoration {
|
|
1128
1144
|
constructor(spec) {
|
|
1129
1145
|
let { start, end } = getInclusive(spec);
|
|
1130
|
-
super(
|
|
1146
|
+
super(start ? -1 /* InlineIncStart */ : 400000000 /* NonIncStart */, end ? 1 /* InlineIncEnd */ : -500000000 /* NonIncEnd */, null, spec);
|
|
1131
1147
|
this.tagName = spec.tagName || "span";
|
|
1132
1148
|
this.class = spec.class || "";
|
|
1133
1149
|
this.attrs = spec.attributes || null;
|
|
@@ -1148,7 +1164,7 @@ class MarkDecoration extends Decoration {
|
|
|
1148
1164
|
MarkDecoration.prototype.point = false;
|
|
1149
1165
|
class LineDecoration extends Decoration {
|
|
1150
1166
|
constructor(spec) {
|
|
1151
|
-
super(-
|
|
1167
|
+
super(-200000000 /* Line */, -200000000 /* Line */, null, spec);
|
|
1152
1168
|
}
|
|
1153
1169
|
eq(other) {
|
|
1154
1170
|
return other instanceof LineDecoration && attrsEq(this.spec.attributes, other.spec.attributes);
|
|
@@ -1166,12 +1182,12 @@ class PointDecoration extends Decoration {
|
|
|
1166
1182
|
super(startSide, endSide, widget, spec);
|
|
1167
1183
|
this.block = block;
|
|
1168
1184
|
this.isReplace = isReplace;
|
|
1169
|
-
this.mapMode = !block ? state.MapMode.TrackDel : startSide
|
|
1185
|
+
this.mapMode = !block ? state.MapMode.TrackDel : startSide <= 0 ? state.MapMode.TrackBefore : state.MapMode.TrackAfter;
|
|
1170
1186
|
}
|
|
1171
1187
|
// Only relevant when this.block == true
|
|
1172
1188
|
get type() {
|
|
1173
1189
|
return this.startSide < this.endSide ? exports.BlockType.WidgetRange
|
|
1174
|
-
: this.startSide
|
|
1190
|
+
: this.startSide <= 0 ? exports.BlockType.WidgetBefore : exports.BlockType.WidgetAfter;
|
|
1175
1191
|
}
|
|
1176
1192
|
get heightRelevant() { return this.block || !!this.widget && this.widget.estimatedHeight >= 5; }
|
|
1177
1193
|
eq(other) {
|
|
@@ -1181,7 +1197,7 @@ class PointDecoration extends Decoration {
|
|
|
1181
1197
|
this.startSide == other.startSide && this.endSide == other.endSide;
|
|
1182
1198
|
}
|
|
1183
1199
|
range(from, to = from) {
|
|
1184
|
-
if (this.isReplace && (from > to || (from == to && this.startSide > 0 && this.endSide
|
|
1200
|
+
if (this.isReplace && (from > to || (from == to && this.startSide > 0 && this.endSide <= 0)))
|
|
1185
1201
|
throw new RangeError("Invalid range for replacement decoration");
|
|
1186
1202
|
if (!this.isReplace && to != from)
|
|
1187
1203
|
throw new RangeError("Widget decorations can only have zero-length ranges");
|
|
@@ -1218,16 +1234,16 @@ class LineView extends ContentView {
|
|
|
1218
1234
|
this.breakAfter = 0;
|
|
1219
1235
|
}
|
|
1220
1236
|
// Consumes source
|
|
1221
|
-
merge(from, to, source,
|
|
1237
|
+
merge(from, to, source, hasStart, openStart, openEnd) {
|
|
1222
1238
|
if (source) {
|
|
1223
1239
|
if (!(source instanceof LineView))
|
|
1224
1240
|
return false;
|
|
1225
1241
|
if (!this.dom)
|
|
1226
1242
|
source.transferDOM(this); // Reuse source.dom when appropriate
|
|
1227
1243
|
}
|
|
1228
|
-
if (
|
|
1244
|
+
if (hasStart)
|
|
1229
1245
|
this.setDeco(source ? source.attrs : null);
|
|
1230
|
-
|
|
1246
|
+
mergeChildrenInto(this, from, to, source ? source.children : [], openStart, openEnd);
|
|
1231
1247
|
return true;
|
|
1232
1248
|
}
|
|
1233
1249
|
split(at) {
|
|
@@ -1237,16 +1253,14 @@ class LineView extends ContentView {
|
|
|
1237
1253
|
return end;
|
|
1238
1254
|
let { i, off } = this.childPos(at);
|
|
1239
1255
|
if (off) {
|
|
1240
|
-
end.append(this.children[i].
|
|
1241
|
-
this.children[i].merge(off, this.children[i].length, null, 0, 0);
|
|
1256
|
+
end.append(this.children[i].split(off), 0);
|
|
1257
|
+
this.children[i].merge(off, this.children[i].length, null, false, 0, 0);
|
|
1242
1258
|
i++;
|
|
1243
1259
|
}
|
|
1244
1260
|
for (let j = i; j < this.children.length; j++)
|
|
1245
1261
|
end.append(this.children[j], 0);
|
|
1246
|
-
while (i > 0 && this.children[i - 1].length == 0)
|
|
1247
|
-
this.children[i
|
|
1248
|
-
i--;
|
|
1249
|
-
}
|
|
1262
|
+
while (i > 0 && this.children[i - 1].length == 0)
|
|
1263
|
+
this.children[--i].destroy();
|
|
1250
1264
|
this.children.length = i;
|
|
1251
1265
|
this.markDirty();
|
|
1252
1266
|
this.length = at;
|
|
@@ -1269,7 +1283,6 @@ class LineView extends ContentView {
|
|
|
1269
1283
|
this.attrs = attrs;
|
|
1270
1284
|
}
|
|
1271
1285
|
}
|
|
1272
|
-
// Only called when building a line view in ContentBuilder
|
|
1273
1286
|
append(child, openStart) {
|
|
1274
1287
|
joinInlineInto(this, child, openStart);
|
|
1275
1288
|
}
|
|
@@ -1326,7 +1339,7 @@ class LineView extends ContentView {
|
|
|
1326
1339
|
coordsAt(pos, side) {
|
|
1327
1340
|
return coordsInChildren(this, pos, side);
|
|
1328
1341
|
}
|
|
1329
|
-
|
|
1342
|
+
become(_other) { return false; }
|
|
1330
1343
|
get type() { return exports.BlockType.Text; }
|
|
1331
1344
|
static find(docView, pos) {
|
|
1332
1345
|
for (let i = 0, off = 0;; i++) {
|
|
@@ -1341,7 +1354,6 @@ class LineView extends ContentView {
|
|
|
1341
1354
|
}
|
|
1342
1355
|
}
|
|
1343
1356
|
}
|
|
1344
|
-
const none$1 = [];
|
|
1345
1357
|
class BlockWidgetView extends ContentView {
|
|
1346
1358
|
constructor(widget, length, type) {
|
|
1347
1359
|
super();
|
|
@@ -1367,7 +1379,7 @@ class BlockWidgetView extends ContentView {
|
|
|
1367
1379
|
end.breakAfter = this.breakAfter;
|
|
1368
1380
|
return end;
|
|
1369
1381
|
}
|
|
1370
|
-
get children() { return
|
|
1382
|
+
get children() { return noChildren; }
|
|
1371
1383
|
sync() {
|
|
1372
1384
|
if (!this.dom || !this.widget.updateDOM(this.dom)) {
|
|
1373
1385
|
this.setDOM(this.widget.toDOM(this.editorView));
|
|
@@ -1378,7 +1390,7 @@ class BlockWidgetView extends ContentView {
|
|
|
1378
1390
|
return this.parent ? this.parent.view.state.doc.slice(this.posAtStart, this.posAtEnd) : state.Text.empty;
|
|
1379
1391
|
}
|
|
1380
1392
|
domBoundsAround() { return null; }
|
|
1381
|
-
|
|
1393
|
+
become(other) {
|
|
1382
1394
|
if (other instanceof BlockWidgetView && other.type == this.type &&
|
|
1383
1395
|
other.widget.constructor == this.widget.constructor) {
|
|
1384
1396
|
if (!other.widget.eq(this.widget))
|
|
@@ -1392,6 +1404,11 @@ class BlockWidgetView extends ContentView {
|
|
|
1392
1404
|
}
|
|
1393
1405
|
ignoreMutation() { return true; }
|
|
1394
1406
|
ignoreEvent(event) { return this.widget.ignoreEvent(event); }
|
|
1407
|
+
destroy() {
|
|
1408
|
+
super.destroy();
|
|
1409
|
+
if (this.dom)
|
|
1410
|
+
this.widget.destroy(this.dom);
|
|
1411
|
+
}
|
|
1395
1412
|
}
|
|
1396
1413
|
|
|
1397
1414
|
class ContentBuilder {
|
|
@@ -1727,36 +1744,39 @@ class PluginInstance {
|
|
|
1727
1744
|
this.value = null;
|
|
1728
1745
|
}
|
|
1729
1746
|
takeField(type, target) {
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1747
|
+
if (this.spec)
|
|
1748
|
+
for (let { field, get } of this.spec.fields)
|
|
1749
|
+
if (field == type)
|
|
1750
|
+
target.push(get(this.value));
|
|
1733
1751
|
}
|
|
1734
1752
|
update(view) {
|
|
1735
1753
|
if (!this.value) {
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1754
|
+
if (this.spec) {
|
|
1755
|
+
try {
|
|
1756
|
+
this.value = this.spec.create(view);
|
|
1757
|
+
}
|
|
1758
|
+
catch (e) {
|
|
1759
|
+
logException(view.state, e, "CodeMirror plugin crashed");
|
|
1760
|
+
this.deactivate();
|
|
1761
|
+
}
|
|
1742
1762
|
}
|
|
1743
1763
|
}
|
|
1744
1764
|
else if (this.mustUpdate) {
|
|
1745
1765
|
let update = this.mustUpdate;
|
|
1746
1766
|
this.mustUpdate = null;
|
|
1747
|
-
if (
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1767
|
+
if (this.value.update) {
|
|
1768
|
+
try {
|
|
1769
|
+
this.value.update(update);
|
|
1770
|
+
}
|
|
1771
|
+
catch (e) {
|
|
1772
|
+
logException(update.state, e, "CodeMirror plugin crashed");
|
|
1773
|
+
if (this.value.destroy)
|
|
1774
|
+
try {
|
|
1775
|
+
this.value.destroy();
|
|
1776
|
+
}
|
|
1777
|
+
catch (_) { }
|
|
1778
|
+
this.deactivate();
|
|
1779
|
+
}
|
|
1760
1780
|
}
|
|
1761
1781
|
}
|
|
1762
1782
|
return this;
|
|
@@ -1772,20 +1792,12 @@ class PluginInstance {
|
|
|
1772
1792
|
}
|
|
1773
1793
|
}
|
|
1774
1794
|
}
|
|
1795
|
+
deactivate() {
|
|
1796
|
+
this.spec = this.value = null;
|
|
1797
|
+
}
|
|
1775
1798
|
}
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
let result = {};
|
|
1779
|
-
for (let i = values.length - 1; i >= 0; i--)
|
|
1780
|
-
combineAttrs(values[i], result);
|
|
1781
|
-
return result;
|
|
1782
|
-
}
|
|
1783
|
-
const editorAttributes = state.Facet.define({
|
|
1784
|
-
combine: combineFacetAttrs
|
|
1785
|
-
});
|
|
1786
|
-
const contentAttributes = state.Facet.define({
|
|
1787
|
-
combine: combineFacetAttrs
|
|
1788
|
-
});
|
|
1799
|
+
const editorAttributes = state.Facet.define();
|
|
1800
|
+
const contentAttributes = state.Facet.define();
|
|
1789
1801
|
// Provide decorations
|
|
1790
1802
|
const decorations = state.Facet.define();
|
|
1791
1803
|
const styleModule = state.Facet.define();
|
|
@@ -1933,12 +1945,12 @@ class DocView extends ContentView {
|
|
|
1933
1945
|
this.compositionDeco = Decoration.none;
|
|
1934
1946
|
this.decorations = [];
|
|
1935
1947
|
// Track a minimum width for the editor. When measuring sizes in
|
|
1936
|
-
//
|
|
1937
|
-
// element and its extent in the document. When a change
|
|
1938
|
-
// that range, these are reset. That way, once we've seen
|
|
1939
|
-
// line/element of a given length, we keep the editor wide enough
|
|
1940
|
-
// fit at least that element, until it is changed, at which point
|
|
1941
|
-
// forget it again.
|
|
1948
|
+
// measureVisibleLineHeights, this is updated to point at the width
|
|
1949
|
+
// of a given element and its extent in the document. When a change
|
|
1950
|
+
// happens in that range, these are reset. That way, once we've seen
|
|
1951
|
+
// a line/element of a given length, we keep the editor wide enough
|
|
1952
|
+
// to fit at least that element, until it is changed, at which point
|
|
1953
|
+
// we forget it again.
|
|
1942
1954
|
this.minWidth = 0;
|
|
1943
1955
|
this.minWidthFrom = 0;
|
|
1944
1956
|
this.minWidthTo = 0;
|
|
@@ -2008,7 +2020,7 @@ class DocView extends ContentView {
|
|
|
2008
2020
|
this.updateSelection();
|
|
2009
2021
|
}
|
|
2010
2022
|
}
|
|
2011
|
-
// Used
|
|
2023
|
+
// Used by update and the constructor do perform the actual DOM
|
|
2012
2024
|
// update
|
|
2013
2025
|
updateInner(changes, deco, oldLength) {
|
|
2014
2026
|
this.view.viewState.mustMeasureContent = true;
|
|
@@ -2049,70 +2061,8 @@ class DocView extends ContentView {
|
|
|
2049
2061
|
let { content, breakAtStart, openStart, openEnd } = ContentBuilder.build(this.view.state.doc, fromB, toB, deco);
|
|
2050
2062
|
let { i: toI, off: toOff } = cursor.findPos(toA, 1);
|
|
2051
2063
|
let { i: fromI, off: fromOff } = cursor.findPos(fromA, -1);
|
|
2052
|
-
|
|
2053
|
-
}
|
|
2054
|
-
}
|
|
2055
|
-
replaceRange(fromI, fromOff, toI, toOff, content, breakAtStart, openStart, openEnd) {
|
|
2056
|
-
let before = this.children[fromI], last = content.length ? content[content.length - 1] : null;
|
|
2057
|
-
let breakAtEnd = last ? last.breakAfter : breakAtStart;
|
|
2058
|
-
// Change within a single line
|
|
2059
|
-
if (fromI == toI && !breakAtStart && !breakAtEnd && content.length < 2 &&
|
|
2060
|
-
before.merge(fromOff, toOff, content.length ? last : null, fromOff == 0, openStart, openEnd))
|
|
2061
|
-
return;
|
|
2062
|
-
let after = this.children[toI];
|
|
2063
|
-
// Make sure the end of the line after the update is preserved in `after`
|
|
2064
|
-
if (toOff < after.length) {
|
|
2065
|
-
// If we're splitting a line, separate part of the start line to
|
|
2066
|
-
// avoid that being mangled when updating the start line.
|
|
2067
|
-
if (fromI == toI) {
|
|
2068
|
-
after = after.split(toOff);
|
|
2069
|
-
toOff = 0;
|
|
2070
|
-
}
|
|
2071
|
-
// If the element after the replacement should be merged with
|
|
2072
|
-
// the last replacing element, update `content`
|
|
2073
|
-
if (!breakAtEnd && last && after.merge(0, toOff, last, true, 0, openEnd)) {
|
|
2074
|
-
content[content.length - 1] = after;
|
|
2075
|
-
}
|
|
2076
|
-
else {
|
|
2077
|
-
// Remove the start of the after element, if necessary, and
|
|
2078
|
-
// add it to `content`.
|
|
2079
|
-
if (toOff)
|
|
2080
|
-
after.merge(0, toOff, null, false, 0, openEnd);
|
|
2081
|
-
content.push(after);
|
|
2082
|
-
}
|
|
2064
|
+
replaceRange(this, fromI, fromOff, toI, toOff, content, breakAtStart, openStart, openEnd);
|
|
2083
2065
|
}
|
|
2084
|
-
else if (after.breakAfter) {
|
|
2085
|
-
// The element at `toI` is entirely covered by this range.
|
|
2086
|
-
// Preserve its line break, if any.
|
|
2087
|
-
if (last)
|
|
2088
|
-
last.breakAfter = 1;
|
|
2089
|
-
else
|
|
2090
|
-
breakAtStart = 1;
|
|
2091
|
-
}
|
|
2092
|
-
// Since we've handled the next element from the current elements
|
|
2093
|
-
// now, make sure `toI` points after that.
|
|
2094
|
-
toI++;
|
|
2095
|
-
before.breakAfter = breakAtStart;
|
|
2096
|
-
if (fromOff > 0) {
|
|
2097
|
-
if (!breakAtStart && content.length && before.merge(fromOff, before.length, content[0], false, openStart, 0)) {
|
|
2098
|
-
before.breakAfter = content.shift().breakAfter;
|
|
2099
|
-
}
|
|
2100
|
-
else if (fromOff < before.length || before.children.length && before.children[before.children.length - 1].length == 0) {
|
|
2101
|
-
before.merge(fromOff, before.length, null, false, openStart, 0);
|
|
2102
|
-
}
|
|
2103
|
-
fromI++;
|
|
2104
|
-
}
|
|
2105
|
-
// Try to merge widgets on the boundaries of the replacement
|
|
2106
|
-
while (fromI < toI && content.length) {
|
|
2107
|
-
if (this.children[toI - 1].match(content[content.length - 1]))
|
|
2108
|
-
toI--, content.pop();
|
|
2109
|
-
else if (this.children[fromI].match(content[0]))
|
|
2110
|
-
fromI++, content.shift();
|
|
2111
|
-
else
|
|
2112
|
-
break;
|
|
2113
|
-
}
|
|
2114
|
-
if (fromI < toI || content.length)
|
|
2115
|
-
this.replaceChildren(fromI, toI, content);
|
|
2116
2066
|
}
|
|
2117
2067
|
// Sync the DOM selection to this.state.selection
|
|
2118
2068
|
updateSelection(mustRead = false, fromPointer = false) {
|
|
@@ -2376,15 +2326,10 @@ function computeCompositionDeco(view, changes) {
|
|
|
2376
2326
|
if (!textNode)
|
|
2377
2327
|
return Decoration.none;
|
|
2378
2328
|
let cView = view.docView.nearest(textNode);
|
|
2329
|
+
if (!cView)
|
|
2330
|
+
return Decoration.none;
|
|
2379
2331
|
let from, to, topNode = textNode;
|
|
2380
|
-
if (cView instanceof
|
|
2381
|
-
while (cView.parent instanceof InlineView)
|
|
2382
|
-
cView = cView.parent;
|
|
2383
|
-
from = cView.posAtStart;
|
|
2384
|
-
to = from + cView.length;
|
|
2385
|
-
topNode = cView.dom;
|
|
2386
|
-
}
|
|
2387
|
-
else if (cView instanceof LineView) {
|
|
2332
|
+
if (cView instanceof LineView) {
|
|
2388
2333
|
while (topNode.parentNode != cView.dom)
|
|
2389
2334
|
topNode = topNode.parentNode;
|
|
2390
2335
|
let prev = topNode.previousSibling;
|
|
@@ -2393,7 +2338,17 @@ function computeCompositionDeco(view, changes) {
|
|
|
2393
2338
|
from = to = prev ? ContentView.get(prev).posAtEnd : cView.posAtStart;
|
|
2394
2339
|
}
|
|
2395
2340
|
else {
|
|
2396
|
-
|
|
2341
|
+
for (;;) {
|
|
2342
|
+
let { parent } = cView;
|
|
2343
|
+
if (!parent)
|
|
2344
|
+
return Decoration.none;
|
|
2345
|
+
if (parent instanceof LineView)
|
|
2346
|
+
break;
|
|
2347
|
+
cView = parent;
|
|
2348
|
+
}
|
|
2349
|
+
from = cView.posAtStart;
|
|
2350
|
+
to = from + cView.length;
|
|
2351
|
+
topNode = cView.dom;
|
|
2397
2352
|
}
|
|
2398
2353
|
let newFrom = changes.mapPos(from, 1), newTo = Math.max(newFrom, changes.mapPos(to, -1));
|
|
2399
2354
|
let text = textNode.nodeValue, { state } = view;
|
|
@@ -2931,7 +2886,7 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
|
2931
2886
|
y = docTop + yOffset;
|
|
2932
2887
|
let lineStart = block.from;
|
|
2933
2888
|
// Clip x to the viewport sides
|
|
2934
|
-
x = Math.max(content.left + 1, Math.min(content.right - 1, x));
|
|
2889
|
+
x = Math.max(content.left + 1, Math.min(Math.max(content.right, content.left + view.docView.minWidth) - 1, x));
|
|
2935
2890
|
// If this is outside of the rendered viewport, we can't determine a position
|
|
2936
2891
|
if (lineStart < view.viewport.from)
|
|
2937
2892
|
return view.viewport.from == 0 ? 0 : posAtCoordsImprecise(view, content, block, x, y);
|
|
@@ -4174,12 +4129,12 @@ class HeightMapBranch extends HeightMap {
|
|
|
4174
4129
|
get break() { return this.flags & 1 /* Break */; }
|
|
4175
4130
|
blockAt(height, doc, top, offset) {
|
|
4176
4131
|
let mid = top + this.left.height;
|
|
4177
|
-
return height < mid
|
|
4132
|
+
return height < mid ? this.left.blockAt(height, doc, top, offset)
|
|
4178
4133
|
: this.right.blockAt(height, doc, mid, offset + this.left.length + this.break);
|
|
4179
4134
|
}
|
|
4180
4135
|
lineAt(value, type, doc, top, offset) {
|
|
4181
4136
|
let rightTop = top + this.left.height, rightOffset = offset + this.left.length + this.break;
|
|
4182
|
-
let left = type == QueryType.ByHeight ? value < rightTop
|
|
4137
|
+
let left = type == QueryType.ByHeight ? value < rightTop : value < rightOffset;
|
|
4183
4138
|
let base = left ? this.left.lineAt(value, type, doc, top, offset)
|
|
4184
4139
|
: this.right.lineAt(value, type, doc, rightTop, rightOffset);
|
|
4185
4140
|
if (this.break || (left ? base.to < rightOffset : base.from > rightOffset))
|
|
@@ -4320,7 +4275,9 @@ class NodeBuilder {
|
|
|
4320
4275
|
}
|
|
4321
4276
|
point(from, to, deco) {
|
|
4322
4277
|
if (from < to || deco.heightRelevant) {
|
|
4323
|
-
let height = deco.widget ?
|
|
4278
|
+
let height = deco.widget ? deco.widget.estimatedHeight : 0;
|
|
4279
|
+
if (height < 0)
|
|
4280
|
+
height = this.oracle.lineHeight;
|
|
4324
4281
|
let len = to - from;
|
|
4325
4282
|
if (deco.block) {
|
|
4326
4283
|
this.addBlock(new HeightMapBlock(len, height, deco.type));
|
|
@@ -4794,7 +4751,7 @@ class ViewState {
|
|
|
4794
4751
|
return changed ? 4 /* Viewport */ : 0;
|
|
4795
4752
|
}
|
|
4796
4753
|
lineBlockAt(pos) {
|
|
4797
|
-
return (pos >= this.viewport.from && pos <= this.viewport.to && this.viewportLines.find(b => b.from <= pos && b.to
|
|
4754
|
+
return (pos >= this.viewport.from && pos <= this.viewport.to && this.viewportLines.find(b => b.from <= pos && b.to >= pos)) ||
|
|
4798
4755
|
scaleBlock(this.heightMap.lineAt(pos, QueryType.ByPos, this.state.doc, 0, 0), this.scaler);
|
|
4799
4756
|
}
|
|
4800
4757
|
lineBlockAtHeight(height) {
|
|
@@ -5065,7 +5022,7 @@ const baseTheme = buildTheme("." + baseThemeID, {
|
|
|
5065
5022
|
color: "inherit",
|
|
5066
5023
|
fontSize: "70%",
|
|
5067
5024
|
padding: ".2em 1em",
|
|
5068
|
-
borderRadius: "
|
|
5025
|
+
borderRadius: "1px"
|
|
5069
5026
|
},
|
|
5070
5027
|
"&light .cm-button": {
|
|
5071
5028
|
backgroundImage: "linear-gradient(#eff1f5, #d9d9df)",
|
|
@@ -5387,6 +5344,7 @@ class DOMObserver {
|
|
|
5387
5344
|
for (let dom of this.scrollTargets)
|
|
5388
5345
|
dom.removeEventListener("scroll", this.onScroll);
|
|
5389
5346
|
window.removeEventListener("scroll", this.onScroll);
|
|
5347
|
+
this.dom.ownerDocument.removeEventListener("selectionchange", this.onSelectionChange);
|
|
5390
5348
|
clearTimeout(this.parentCheck);
|
|
5391
5349
|
clearTimeout(this.resizeTimeout);
|
|
5392
5350
|
}
|
|
@@ -5683,6 +5641,7 @@ class EditorView {
|
|
|
5683
5641
|
*/
|
|
5684
5642
|
config = {}) {
|
|
5685
5643
|
this.plugins = [];
|
|
5644
|
+
this.pluginMap = new Map;
|
|
5686
5645
|
this.editorAttrs = {};
|
|
5687
5646
|
this.contentAttrs = {};
|
|
5688
5647
|
this.bidiCache = [];
|
|
@@ -5714,7 +5673,9 @@ class EditorView {
|
|
|
5714
5673
|
this.dispatch = this.dispatch.bind(this);
|
|
5715
5674
|
this.root = (config.root || getRoot(config.parent) || document);
|
|
5716
5675
|
this.viewState = new ViewState(config.state || state.EditorState.create());
|
|
5717
|
-
this.plugins = this.state.facet(viewPlugin).map(spec => new PluginInstance(spec)
|
|
5676
|
+
this.plugins = this.state.facet(viewPlugin).map(spec => new PluginInstance(spec));
|
|
5677
|
+
for (let plugin of this.plugins)
|
|
5678
|
+
plugin.update(this);
|
|
5718
5679
|
this.observer = new DOMObserver(this, (from, to, typeOver) => {
|
|
5719
5680
|
applyDOMChange(this, from, to, typeOver);
|
|
5720
5681
|
}, event => {
|
|
@@ -5851,7 +5812,10 @@ class EditorView {
|
|
|
5851
5812
|
for (let plugin of this.plugins)
|
|
5852
5813
|
plugin.destroy(this);
|
|
5853
5814
|
this.viewState = new ViewState(newState);
|
|
5854
|
-
this.plugins = newState.facet(viewPlugin).map(spec => new PluginInstance(spec)
|
|
5815
|
+
this.plugins = newState.facet(viewPlugin).map(spec => new PluginInstance(spec));
|
|
5816
|
+
this.pluginMap.clear();
|
|
5817
|
+
for (let plugin of this.plugins)
|
|
5818
|
+
plugin.update(this);
|
|
5855
5819
|
this.docView = new DocView(this);
|
|
5856
5820
|
this.inputState.ensureHandlers(this);
|
|
5857
5821
|
this.mountStyles();
|
|
@@ -5882,6 +5846,7 @@ class EditorView {
|
|
|
5882
5846
|
if (plugin.mustUpdate != update)
|
|
5883
5847
|
plugin.destroy(this);
|
|
5884
5848
|
this.plugins = newPlugins;
|
|
5849
|
+
this.pluginMap.clear();
|
|
5885
5850
|
this.inputState.ensureHandlers(this);
|
|
5886
5851
|
}
|
|
5887
5852
|
else {
|
|
@@ -5889,7 +5854,7 @@ class EditorView {
|
|
|
5889
5854
|
p.mustUpdate = update;
|
|
5890
5855
|
}
|
|
5891
5856
|
for (let i = 0; i < this.plugins.length; i++)
|
|
5892
|
-
this.plugins[i]
|
|
5857
|
+
this.plugins[i].update(this);
|
|
5893
5858
|
}
|
|
5894
5859
|
/**
|
|
5895
5860
|
@internal
|
|
@@ -5978,7 +5943,7 @@ class EditorView {
|
|
|
5978
5943
|
this.state.facet(theme);
|
|
5979
5944
|
}
|
|
5980
5945
|
updateAttrs() {
|
|
5981
|
-
let editorAttrs =
|
|
5946
|
+
let editorAttrs = attrsFromFacet(this, editorAttributes, {
|
|
5982
5947
|
class: "cm-editor" + (this.hasFocus ? " cm-focused " : " ") + this.themeClasses
|
|
5983
5948
|
});
|
|
5984
5949
|
let contentAttrs = {
|
|
@@ -5994,7 +5959,7 @@ class EditorView {
|
|
|
5994
5959
|
};
|
|
5995
5960
|
if (this.state.readOnly)
|
|
5996
5961
|
contentAttrs["aria-readonly"] = "true";
|
|
5997
|
-
|
|
5962
|
+
attrsFromFacet(this, contentAttributes, contentAttrs);
|
|
5998
5963
|
this.observer.ignore(() => {
|
|
5999
5964
|
updateAttrs(this.contentDOM, this.contentAttrs, contentAttrs);
|
|
6000
5965
|
updateAttrs(this.dom, this.editorAttrs, editorAttrs);
|
|
@@ -6063,10 +6028,10 @@ class EditorView {
|
|
|
6063
6028
|
the return value of this method.
|
|
6064
6029
|
*/
|
|
6065
6030
|
plugin(plugin) {
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
return
|
|
6031
|
+
let known = this.pluginMap.get(plugin);
|
|
6032
|
+
if (known === undefined || known && known.spec != plugin)
|
|
6033
|
+
this.pluginMap.set(plugin, known = this.plugins.find(p => p.spec == plugin) || null);
|
|
6034
|
+
return known && known.update(this).value;
|
|
6070
6035
|
}
|
|
6071
6036
|
/**
|
|
6072
6037
|
The top position of the document, in screen coordinates. This
|
|
@@ -6553,6 +6518,14 @@ class CachedOrder {
|
|
|
6553
6518
|
return result;
|
|
6554
6519
|
}
|
|
6555
6520
|
}
|
|
6521
|
+
function attrsFromFacet(view, facet, base) {
|
|
6522
|
+
for (let sources = view.state.facet(facet), i = sources.length - 1; i >= 0; i--) {
|
|
6523
|
+
let source = sources[i], value = typeof source == "function" ? source(view) : source;
|
|
6524
|
+
if (value)
|
|
6525
|
+
combineAttrs(value, base);
|
|
6526
|
+
}
|
|
6527
|
+
return base;
|
|
6528
|
+
}
|
|
6556
6529
|
|
|
6557
6530
|
const currentPlatform = browser.mac ? "mac" : browser.windows ? "win" : browser.linux ? "linux" : "key";
|
|
6558
6531
|
function normalizeKeyName(name, platform) {
|
|
@@ -7205,35 +7178,29 @@ class TabWidget extends WidgetType {
|
|
|
7205
7178
|
}
|
|
7206
7179
|
|
|
7207
7180
|
const plugin = ViewPlugin.fromClass(class {
|
|
7208
|
-
constructor(
|
|
7209
|
-
this.height =
|
|
7210
|
-
this.
|
|
7211
|
-
read: view => Math.max(0, view.scrollDOM.clientHeight - view.defaultLineHeight),
|
|
7212
|
-
write: (value, view) => {
|
|
7213
|
-
if (Math.abs(value - this.height) > 1) {
|
|
7214
|
-
this.height = value;
|
|
7215
|
-
view.contentDOM.style.paddingBottom = value + "px";
|
|
7216
|
-
}
|
|
7217
|
-
}
|
|
7218
|
-
};
|
|
7219
|
-
view.requestMeasure(this.measure);
|
|
7181
|
+
constructor() {
|
|
7182
|
+
this.height = 1000;
|
|
7183
|
+
this.attrs = { style: "padding-bottom: 1000px" };
|
|
7220
7184
|
}
|
|
7221
7185
|
update(update) {
|
|
7222
|
-
|
|
7223
|
-
|
|
7186
|
+
let height = update.view.viewState.editorHeight - update.view.defaultLineHeight;
|
|
7187
|
+
if (height != this.height) {
|
|
7188
|
+
this.height = height;
|
|
7189
|
+
this.attrs = { style: `padding-bottom: ${height}px` };
|
|
7190
|
+
}
|
|
7224
7191
|
}
|
|
7225
7192
|
});
|
|
7226
7193
|
/**
|
|
7227
|
-
Returns
|
|
7228
|
-
equivalent to the height of the editor, minus one line
|
|
7229
|
-
that every line in the document can be scrolled to the
|
|
7230
|
-
editor.
|
|
7194
|
+
Returns an extension that makes sure the content has a bottom
|
|
7195
|
+
margin equivalent to the height of the editor, minus one line
|
|
7196
|
+
height, so that every line in the document can be scrolled to the
|
|
7197
|
+
top of the editor.
|
|
7231
7198
|
|
|
7232
7199
|
This is only meaningful when the editor is scrollable, and should
|
|
7233
7200
|
not be enabled in editors that take the size of their content.
|
|
7234
7201
|
*/
|
|
7235
7202
|
function scrollPastEnd() {
|
|
7236
|
-
return plugin;
|
|
7203
|
+
return [plugin, contentAttributes.of(view => { var _a; return ((_a = view.plugin(plugin)) === null || _a === void 0 ? void 0 : _a.attrs) || null; })];
|
|
7237
7204
|
}
|
|
7238
7205
|
|
|
7239
7206
|
/**
|
|
@@ -7308,9 +7275,7 @@ const __test = { HeightMap, HeightOracle, MeasuredHeights, QueryType, ChangedRan
|
|
|
7308
7275
|
|
|
7309
7276
|
Object.defineProperty(exports, 'Range', {
|
|
7310
7277
|
enumerable: true,
|
|
7311
|
-
get: function () {
|
|
7312
|
-
return rangeset.Range;
|
|
7313
|
-
}
|
|
7278
|
+
get: function () { return rangeset.Range; }
|
|
7314
7279
|
});
|
|
7315
7280
|
exports.BidiSpan = BidiSpan;
|
|
7316
7281
|
exports.BlockInfo = BlockInfo;
|