@codemirror/view 0.19.24 → 0.19.28
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 +38 -0
- package/dist/index.cjs +854 -861
- package/dist/index.d.ts +22 -15
- package/dist/index.js +854 -859
- 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); }
|
|
@@ -752,10 +845,13 @@ class CompositionView extends WidgetView {
|
|
|
752
845
|
coordsAt(pos, side) { return textCoords(this.widget.text, pos, side); }
|
|
753
846
|
get isEditable() { return true; }
|
|
754
847
|
}
|
|
848
|
+
// Use two characters on Android, to prevent Chrome from closing the
|
|
849
|
+
// virtual keyboard when backspacing after a widget (#602).
|
|
850
|
+
const ZeroWidthSpace = browser.android ? "\u200b\u200b" : "\u200b";
|
|
755
851
|
// These are drawn around uneditable widgets to avoid a number of
|
|
756
852
|
// browser bugs that show up when the cursor is directly next to
|
|
757
853
|
// uneditable inline content.
|
|
758
|
-
class WidgetBufferView extends
|
|
854
|
+
class WidgetBufferView extends ContentView {
|
|
759
855
|
constructor(side) {
|
|
760
856
|
super();
|
|
761
857
|
this.side = side;
|
|
@@ -765,15 +861,16 @@ class WidgetBufferView extends InlineView {
|
|
|
765
861
|
become(other) {
|
|
766
862
|
return other instanceof WidgetBufferView && other.side == this.side;
|
|
767
863
|
}
|
|
768
|
-
|
|
864
|
+
split() { return new WidgetBufferView(this.side); }
|
|
769
865
|
sync() {
|
|
770
866
|
if (!this.dom)
|
|
771
|
-
this.setDOM(document.createTextNode(
|
|
772
|
-
else if (this.dirty && this.dom.nodeValue !=
|
|
773
|
-
this.dom.nodeValue =
|
|
867
|
+
this.setDOM(document.createTextNode(ZeroWidthSpace));
|
|
868
|
+
else if (this.dirty && this.dom.nodeValue != ZeroWidthSpace)
|
|
869
|
+
this.dom.nodeValue = ZeroWidthSpace;
|
|
774
870
|
}
|
|
775
871
|
getSide() { return this.side; }
|
|
776
872
|
domAtPos(pos) { return DOMPos.before(this.dom); }
|
|
873
|
+
localPosFromDOM() { return 0; }
|
|
777
874
|
domBoundsAround() { return null; }
|
|
778
875
|
coordsAt(pos) {
|
|
779
876
|
let rects = clientRectsFor(this.dom);
|
|
@@ -783,90 +880,7 @@ class WidgetBufferView extends InlineView {
|
|
|
783
880
|
return text.Text.of([this.dom.nodeValue.replace(/\u200b/g, "")]);
|
|
784
881
|
}
|
|
785
882
|
}
|
|
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
|
-
}
|
|
883
|
+
TextView.prototype.children = WidgetView.prototype.children = WidgetBufferView.prototype.children = noChildren;
|
|
870
884
|
function inlineDOMAtPos(dom, children, pos) {
|
|
871
885
|
let i = 0;
|
|
872
886
|
for (let off = 0; i < children.length; i++) {
|
|
@@ -1007,6 +1021,11 @@ class WidgetType {
|
|
|
1007
1021
|
@internal
|
|
1008
1022
|
*/
|
|
1009
1023
|
get customView() { return null; }
|
|
1024
|
+
/**
|
|
1025
|
+
This is called when the an instance of the widget is removed
|
|
1026
|
+
from the editor view.
|
|
1027
|
+
*/
|
|
1028
|
+
destroy(_dom) { }
|
|
1010
1029
|
}
|
|
1011
1030
|
/**
|
|
1012
1031
|
The different types of blocks that can occur in an editor view.
|
|
@@ -1086,8 +1105,9 @@ class Decoration extends rangeset.RangeValue {
|
|
|
1086
1105
|
position.
|
|
1087
1106
|
*/
|
|
1088
1107
|
static widget(spec) {
|
|
1089
|
-
let side = spec.side || 0;
|
|
1090
|
-
|
|
1108
|
+
let side = spec.side || 0, block = !!spec.block;
|
|
1109
|
+
side += block ? (side > 0 ? 300000000 /* BlockAfter */ : -400000000 /* BlockBefore */) : (side > 0 ? 100000000 /* InlineAfter */ : -100000000 /* InlineBefore */);
|
|
1110
|
+
return new PointDecoration(spec, side, side, block, spec.widget || null, false);
|
|
1091
1111
|
}
|
|
1092
1112
|
/**
|
|
1093
1113
|
Create a replace decoration which replaces the given range with
|
|
@@ -1096,8 +1116,8 @@ class Decoration extends rangeset.RangeValue {
|
|
|
1096
1116
|
static replace(spec) {
|
|
1097
1117
|
let block = !!spec.block;
|
|
1098
1118
|
let { start, end } = getInclusive(spec, block);
|
|
1099
|
-
let startSide =
|
|
1100
|
-
let endSide =
|
|
1119
|
+
let startSide = block ? (start ? -300000000 /* BlockIncStart */ : -1 /* InlineIncStart */) : 400000000 /* NonIncStart */;
|
|
1120
|
+
let endSide = block ? (end ? 200000000 /* BlockIncEnd */ : 1 /* InlineIncEnd */) : -500000000 /* NonIncEnd */;
|
|
1101
1121
|
return new PointDecoration(spec, startSide, endSide, block, spec.widget || null, true);
|
|
1102
1122
|
}
|
|
1103
1123
|
/**
|
|
@@ -1127,7 +1147,7 @@ Decoration.none = rangeset.RangeSet.empty;
|
|
|
1127
1147
|
class MarkDecoration extends Decoration {
|
|
1128
1148
|
constructor(spec) {
|
|
1129
1149
|
let { start, end } = getInclusive(spec);
|
|
1130
|
-
super(
|
|
1150
|
+
super(start ? -1 /* InlineIncStart */ : 400000000 /* NonIncStart */, end ? 1 /* InlineIncEnd */ : -500000000 /* NonIncEnd */, null, spec);
|
|
1131
1151
|
this.tagName = spec.tagName || "span";
|
|
1132
1152
|
this.class = spec.class || "";
|
|
1133
1153
|
this.attrs = spec.attributes || null;
|
|
@@ -1148,7 +1168,7 @@ class MarkDecoration extends Decoration {
|
|
|
1148
1168
|
MarkDecoration.prototype.point = false;
|
|
1149
1169
|
class LineDecoration extends Decoration {
|
|
1150
1170
|
constructor(spec) {
|
|
1151
|
-
super(-
|
|
1171
|
+
super(-200000000 /* Line */, -200000000 /* Line */, null, spec);
|
|
1152
1172
|
}
|
|
1153
1173
|
eq(other) {
|
|
1154
1174
|
return other instanceof LineDecoration && attrsEq(this.spec.attributes, other.spec.attributes);
|
|
@@ -1166,12 +1186,12 @@ class PointDecoration extends Decoration {
|
|
|
1166
1186
|
super(startSide, endSide, widget, spec);
|
|
1167
1187
|
this.block = block;
|
|
1168
1188
|
this.isReplace = isReplace;
|
|
1169
|
-
this.mapMode = !block ? state.MapMode.TrackDel : startSide
|
|
1189
|
+
this.mapMode = !block ? state.MapMode.TrackDel : startSide <= 0 ? state.MapMode.TrackBefore : state.MapMode.TrackAfter;
|
|
1170
1190
|
}
|
|
1171
1191
|
// Only relevant when this.block == true
|
|
1172
1192
|
get type() {
|
|
1173
1193
|
return this.startSide < this.endSide ? exports.BlockType.WidgetRange
|
|
1174
|
-
: this.startSide
|
|
1194
|
+
: this.startSide <= 0 ? exports.BlockType.WidgetBefore : exports.BlockType.WidgetAfter;
|
|
1175
1195
|
}
|
|
1176
1196
|
get heightRelevant() { return this.block || !!this.widget && this.widget.estimatedHeight >= 5; }
|
|
1177
1197
|
eq(other) {
|
|
@@ -1181,7 +1201,7 @@ class PointDecoration extends Decoration {
|
|
|
1181
1201
|
this.startSide == other.startSide && this.endSide == other.endSide;
|
|
1182
1202
|
}
|
|
1183
1203
|
range(from, to = from) {
|
|
1184
|
-
if (this.isReplace && (from > to || (from == to && this.startSide > 0 && this.endSide
|
|
1204
|
+
if (this.isReplace && (from > to || (from == to && this.startSide > 0 && this.endSide <= 0)))
|
|
1185
1205
|
throw new RangeError("Invalid range for replacement decoration");
|
|
1186
1206
|
if (!this.isReplace && to != from)
|
|
1187
1207
|
throw new RangeError("Widget decorations can only have zero-length ranges");
|
|
@@ -1218,16 +1238,16 @@ class LineView extends ContentView {
|
|
|
1218
1238
|
this.breakAfter = 0;
|
|
1219
1239
|
}
|
|
1220
1240
|
// Consumes source
|
|
1221
|
-
merge(from, to, source,
|
|
1241
|
+
merge(from, to, source, hasStart, openStart, openEnd) {
|
|
1222
1242
|
if (source) {
|
|
1223
1243
|
if (!(source instanceof LineView))
|
|
1224
1244
|
return false;
|
|
1225
1245
|
if (!this.dom)
|
|
1226
1246
|
source.transferDOM(this); // Reuse source.dom when appropriate
|
|
1227
1247
|
}
|
|
1228
|
-
if (
|
|
1248
|
+
if (hasStart)
|
|
1229
1249
|
this.setDeco(source ? source.attrs : null);
|
|
1230
|
-
|
|
1250
|
+
mergeChildrenInto(this, from, to, source ? source.children : [], openStart, openEnd);
|
|
1231
1251
|
return true;
|
|
1232
1252
|
}
|
|
1233
1253
|
split(at) {
|
|
@@ -1237,16 +1257,14 @@ class LineView extends ContentView {
|
|
|
1237
1257
|
return end;
|
|
1238
1258
|
let { i, off } = this.childPos(at);
|
|
1239
1259
|
if (off) {
|
|
1240
|
-
end.append(this.children[i].
|
|
1241
|
-
this.children[i].merge(off, this.children[i].length, null, 0, 0);
|
|
1260
|
+
end.append(this.children[i].split(off), 0);
|
|
1261
|
+
this.children[i].merge(off, this.children[i].length, null, false, 0, 0);
|
|
1242
1262
|
i++;
|
|
1243
1263
|
}
|
|
1244
1264
|
for (let j = i; j < this.children.length; j++)
|
|
1245
1265
|
end.append(this.children[j], 0);
|
|
1246
|
-
while (i > 0 && this.children[i - 1].length == 0)
|
|
1247
|
-
this.children[i
|
|
1248
|
-
i--;
|
|
1249
|
-
}
|
|
1266
|
+
while (i > 0 && this.children[i - 1].length == 0)
|
|
1267
|
+
this.children[--i].destroy();
|
|
1250
1268
|
this.children.length = i;
|
|
1251
1269
|
this.markDirty();
|
|
1252
1270
|
this.length = at;
|
|
@@ -1269,7 +1287,6 @@ class LineView extends ContentView {
|
|
|
1269
1287
|
this.attrs = attrs;
|
|
1270
1288
|
}
|
|
1271
1289
|
}
|
|
1272
|
-
// Only called when building a line view in ContentBuilder
|
|
1273
1290
|
append(child, openStart) {
|
|
1274
1291
|
joinInlineInto(this, child, openStart);
|
|
1275
1292
|
}
|
|
@@ -1326,7 +1343,7 @@ class LineView extends ContentView {
|
|
|
1326
1343
|
coordsAt(pos, side) {
|
|
1327
1344
|
return coordsInChildren(this, pos, side);
|
|
1328
1345
|
}
|
|
1329
|
-
|
|
1346
|
+
become(_other) { return false; }
|
|
1330
1347
|
get type() { return exports.BlockType.Text; }
|
|
1331
1348
|
static find(docView, pos) {
|
|
1332
1349
|
for (let i = 0, off = 0;; i++) {
|
|
@@ -1341,7 +1358,6 @@ class LineView extends ContentView {
|
|
|
1341
1358
|
}
|
|
1342
1359
|
}
|
|
1343
1360
|
}
|
|
1344
|
-
const none$1 = [];
|
|
1345
1361
|
class BlockWidgetView extends ContentView {
|
|
1346
1362
|
constructor(widget, length, type) {
|
|
1347
1363
|
super();
|
|
@@ -1367,7 +1383,7 @@ class BlockWidgetView extends ContentView {
|
|
|
1367
1383
|
end.breakAfter = this.breakAfter;
|
|
1368
1384
|
return end;
|
|
1369
1385
|
}
|
|
1370
|
-
get children() { return
|
|
1386
|
+
get children() { return noChildren; }
|
|
1371
1387
|
sync() {
|
|
1372
1388
|
if (!this.dom || !this.widget.updateDOM(this.dom)) {
|
|
1373
1389
|
this.setDOM(this.widget.toDOM(this.editorView));
|
|
@@ -1378,7 +1394,7 @@ class BlockWidgetView extends ContentView {
|
|
|
1378
1394
|
return this.parent ? this.parent.view.state.doc.slice(this.posAtStart, this.posAtEnd) : state.Text.empty;
|
|
1379
1395
|
}
|
|
1380
1396
|
domBoundsAround() { return null; }
|
|
1381
|
-
|
|
1397
|
+
become(other) {
|
|
1382
1398
|
if (other instanceof BlockWidgetView && other.type == this.type &&
|
|
1383
1399
|
other.widget.constructor == this.widget.constructor) {
|
|
1384
1400
|
if (!other.widget.eq(this.widget))
|
|
@@ -1392,6 +1408,11 @@ class BlockWidgetView extends ContentView {
|
|
|
1392
1408
|
}
|
|
1393
1409
|
ignoreMutation() { return true; }
|
|
1394
1410
|
ignoreEvent(event) { return this.widget.ignoreEvent(event); }
|
|
1411
|
+
destroy() {
|
|
1412
|
+
super.destroy();
|
|
1413
|
+
if (this.dom)
|
|
1414
|
+
this.widget.destroy(this.dom);
|
|
1415
|
+
}
|
|
1395
1416
|
}
|
|
1396
1417
|
|
|
1397
1418
|
class ContentBuilder {
|
|
@@ -1727,36 +1748,39 @@ class PluginInstance {
|
|
|
1727
1748
|
this.value = null;
|
|
1728
1749
|
}
|
|
1729
1750
|
takeField(type, target) {
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1751
|
+
if (this.spec)
|
|
1752
|
+
for (let { field, get } of this.spec.fields)
|
|
1753
|
+
if (field == type)
|
|
1754
|
+
target.push(get(this.value));
|
|
1733
1755
|
}
|
|
1734
1756
|
update(view) {
|
|
1735
1757
|
if (!this.value) {
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1758
|
+
if (this.spec) {
|
|
1759
|
+
try {
|
|
1760
|
+
this.value = this.spec.create(view);
|
|
1761
|
+
}
|
|
1762
|
+
catch (e) {
|
|
1763
|
+
logException(view.state, e, "CodeMirror plugin crashed");
|
|
1764
|
+
this.deactivate();
|
|
1765
|
+
}
|
|
1742
1766
|
}
|
|
1743
1767
|
}
|
|
1744
1768
|
else if (this.mustUpdate) {
|
|
1745
1769
|
let update = this.mustUpdate;
|
|
1746
1770
|
this.mustUpdate = null;
|
|
1747
|
-
if (
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1771
|
+
if (this.value.update) {
|
|
1772
|
+
try {
|
|
1773
|
+
this.value.update(update);
|
|
1774
|
+
}
|
|
1775
|
+
catch (e) {
|
|
1776
|
+
logException(update.state, e, "CodeMirror plugin crashed");
|
|
1777
|
+
if (this.value.destroy)
|
|
1778
|
+
try {
|
|
1779
|
+
this.value.destroy();
|
|
1780
|
+
}
|
|
1781
|
+
catch (_) { }
|
|
1782
|
+
this.deactivate();
|
|
1783
|
+
}
|
|
1760
1784
|
}
|
|
1761
1785
|
}
|
|
1762
1786
|
return this;
|
|
@@ -1772,20 +1796,12 @@ class PluginInstance {
|
|
|
1772
1796
|
}
|
|
1773
1797
|
}
|
|
1774
1798
|
}
|
|
1799
|
+
deactivate() {
|
|
1800
|
+
this.spec = this.value = null;
|
|
1801
|
+
}
|
|
1775
1802
|
}
|
|
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
|
-
});
|
|
1803
|
+
const editorAttributes = state.Facet.define();
|
|
1804
|
+
const contentAttributes = state.Facet.define();
|
|
1789
1805
|
// Provide decorations
|
|
1790
1806
|
const decorations = state.Facet.define();
|
|
1791
1807
|
const styleModule = state.Facet.define();
|
|
@@ -1926,196 +1942,446 @@ class ViewUpdate {
|
|
|
1926
1942
|
get empty() { return this.flags == 0 && this.transactions.length == 0; }
|
|
1927
1943
|
}
|
|
1928
1944
|
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1945
|
+
/**
|
|
1946
|
+
Used to indicate [text direction](https://codemirror.net/6/docs/ref/#view.EditorView.textDirection).
|
|
1947
|
+
*/
|
|
1948
|
+
exports.Direction = void 0;
|
|
1949
|
+
(function (Direction) {
|
|
1950
|
+
// (These are chosen to match the base levels, in bidi algorithm
|
|
1951
|
+
// terms, of spans in that direction.)
|
|
1952
|
+
/**
|
|
1953
|
+
Left-to-right.
|
|
1954
|
+
*/
|
|
1955
|
+
Direction[Direction["LTR"] = 0] = "LTR";
|
|
1956
|
+
/**
|
|
1957
|
+
Right-to-left.
|
|
1958
|
+
*/
|
|
1959
|
+
Direction[Direction["RTL"] = 1] = "RTL";
|
|
1960
|
+
})(exports.Direction || (exports.Direction = {}));
|
|
1961
|
+
const LTR = exports.Direction.LTR, RTL = exports.Direction.RTL;
|
|
1962
|
+
// Decode a string with each type encoded as log2(type)
|
|
1963
|
+
function dec(str) {
|
|
1964
|
+
let result = [];
|
|
1965
|
+
for (let i = 0; i < str.length; i++)
|
|
1966
|
+
result.push(1 << +str[i]);
|
|
1967
|
+
return result;
|
|
1968
|
+
}
|
|
1969
|
+
// Character types for codepoints 0 to 0xf8
|
|
1970
|
+
const LowTypes = dec("88888888888888888888888888888888888666888888787833333333337888888000000000000000000000000008888880000000000000000000000000088888888888888888888888888888888888887866668888088888663380888308888800000000000000000000000800000000000000000000000000000008");
|
|
1971
|
+
// Character types for codepoints 0x600 to 0x6f9
|
|
1972
|
+
const ArabicTypes = dec("4444448826627288999999999992222222222222222222222222222222222222222222222229999999999999999999994444444444644222822222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222999999949999999229989999223333333333");
|
|
1973
|
+
const Brackets = Object.create(null), BracketStack = [];
|
|
1974
|
+
// There's a lot more in
|
|
1975
|
+
// https://www.unicode.org/Public/UCD/latest/ucd/BidiBrackets.txt,
|
|
1976
|
+
// which are left out to keep code size down.
|
|
1977
|
+
for (let p of ["()", "[]", "{}"]) {
|
|
1978
|
+
let l = p.charCodeAt(0), r = p.charCodeAt(1);
|
|
1979
|
+
Brackets[l] = r;
|
|
1980
|
+
Brackets[r] = -l;
|
|
1981
|
+
}
|
|
1982
|
+
function charType(ch) {
|
|
1983
|
+
return ch <= 0xf7 ? LowTypes[ch] :
|
|
1984
|
+
0x590 <= ch && ch <= 0x5f4 ? 2 /* R */ :
|
|
1985
|
+
0x600 <= ch && ch <= 0x6f9 ? ArabicTypes[ch - 0x600] :
|
|
1986
|
+
0x6ee <= ch && ch <= 0x8ac ? 4 /* AL */ :
|
|
1987
|
+
0x2000 <= ch && ch <= 0x200b ? 256 /* NI */ :
|
|
1988
|
+
ch == 0x200c ? 256 /* NI */ : 1 /* L */;
|
|
1989
|
+
}
|
|
1990
|
+
const BidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
|
|
1991
|
+
/**
|
|
1992
|
+
Represents a contiguous range of text that has a single direction
|
|
1993
|
+
(as in left-to-right or right-to-left).
|
|
1994
|
+
*/
|
|
1995
|
+
class BidiSpan {
|
|
1996
|
+
/**
|
|
1997
|
+
@internal
|
|
1998
|
+
*/
|
|
1999
|
+
constructor(
|
|
2000
|
+
/**
|
|
2001
|
+
The start of the span (relative to the start of the line).
|
|
2002
|
+
*/
|
|
2003
|
+
from,
|
|
2004
|
+
/**
|
|
2005
|
+
The end of the span.
|
|
2006
|
+
*/
|
|
2007
|
+
to,
|
|
2008
|
+
/**
|
|
2009
|
+
The ["bidi
|
|
2010
|
+
level"](https://unicode.org/reports/tr9/#Basic_Display_Algorithm)
|
|
2011
|
+
of the span (in this context, 0 means
|
|
2012
|
+
left-to-right, 1 means right-to-left, 2 means left-to-right
|
|
2013
|
+
number inside right-to-left text).
|
|
2014
|
+
*/
|
|
2015
|
+
level) {
|
|
2016
|
+
this.from = from;
|
|
2017
|
+
this.to = to;
|
|
2018
|
+
this.level = level;
|
|
1957
2019
|
}
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
// getSelection than the one that it actually shows to the user.
|
|
1983
|
-
// This forces a selection update when lines are joined to work
|
|
1984
|
-
// around that. Issue #54
|
|
1985
|
-
if ((browser.ie || browser.chrome) && !this.compositionDeco.size && update &&
|
|
1986
|
-
update.state.doc.lines != update.startState.doc.lines)
|
|
1987
|
-
this.forceSelection = true;
|
|
1988
|
-
let prevDeco = this.decorations, deco = this.updateDeco();
|
|
1989
|
-
let decoDiff = findChangedDeco(prevDeco, deco, update.changes);
|
|
1990
|
-
changedRanges = ChangedRange.extendWithRanges(changedRanges, decoDiff);
|
|
1991
|
-
if (this.dirty == 0 /* Not */ && changedRanges.length == 0) {
|
|
1992
|
-
return false;
|
|
1993
|
-
}
|
|
1994
|
-
else {
|
|
1995
|
-
this.updateInner(changedRanges, deco, update.startState.doc.length);
|
|
1996
|
-
if (update.transactions.length)
|
|
1997
|
-
this.lastUpdate = Date.now();
|
|
1998
|
-
return true;
|
|
2020
|
+
/**
|
|
2021
|
+
The direction of this span.
|
|
2022
|
+
*/
|
|
2023
|
+
get dir() { return this.level % 2 ? RTL : LTR; }
|
|
2024
|
+
/**
|
|
2025
|
+
@internal
|
|
2026
|
+
*/
|
|
2027
|
+
side(end, dir) { return (this.dir == dir) == end ? this.to : this.from; }
|
|
2028
|
+
/**
|
|
2029
|
+
@internal
|
|
2030
|
+
*/
|
|
2031
|
+
static find(order, index, level, assoc) {
|
|
2032
|
+
let maybe = -1;
|
|
2033
|
+
for (let i = 0; i < order.length; i++) {
|
|
2034
|
+
let span = order[i];
|
|
2035
|
+
if (span.from <= index && span.to >= index) {
|
|
2036
|
+
if (span.level == level)
|
|
2037
|
+
return i;
|
|
2038
|
+
// When multiple spans match, if assoc != 0, take the one that
|
|
2039
|
+
// covers that side, otherwise take the one with the minimum
|
|
2040
|
+
// level.
|
|
2041
|
+
if (maybe < 0 || (assoc != 0 ? (assoc < 0 ? span.from < index : span.to > index) : order[maybe].level > span.level))
|
|
2042
|
+
maybe = i;
|
|
2043
|
+
}
|
|
1999
2044
|
}
|
|
2045
|
+
if (maybe < 0)
|
|
2046
|
+
throw new RangeError("Index out of range");
|
|
2047
|
+
return maybe;
|
|
2000
2048
|
}
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2049
|
+
}
|
|
2050
|
+
// Reused array of character types
|
|
2051
|
+
const types = [];
|
|
2052
|
+
function computeOrder(line, direction) {
|
|
2053
|
+
let len = line.length, outerType = direction == LTR ? 1 /* L */ : 2 /* R */, oppositeType = direction == LTR ? 2 /* R */ : 1 /* L */;
|
|
2054
|
+
if (!line || outerType == 1 /* L */ && !BidiRE.test(line))
|
|
2055
|
+
return trivialOrder(len);
|
|
2056
|
+
// W1. Examine each non-spacing mark (NSM) in the level run, and
|
|
2057
|
+
// change the type of the NSM to the type of the previous
|
|
2058
|
+
// character. If the NSM is at the start of the level run, it will
|
|
2059
|
+
// get the type of sor.
|
|
2060
|
+
// W2. Search backwards from each instance of a European number
|
|
2061
|
+
// until the first strong type (R, L, AL, or sor) is found. If an
|
|
2062
|
+
// AL is found, change the type of the European number to Arabic
|
|
2063
|
+
// number.
|
|
2064
|
+
// W3. Change all ALs to R.
|
|
2065
|
+
// (Left after this: L, R, EN, AN, ET, CS, NI)
|
|
2066
|
+
for (let i = 0, prev = outerType, prevStrong = outerType; i < len; i++) {
|
|
2067
|
+
let type = charType(line.charCodeAt(i));
|
|
2068
|
+
if (type == 512 /* NSM */)
|
|
2069
|
+
type = prev;
|
|
2070
|
+
else if (type == 8 /* EN */ && prevStrong == 4 /* AL */)
|
|
2071
|
+
type = 16 /* AN */;
|
|
2072
|
+
types[i] = type == 4 /* AL */ ? 2 /* R */ : type;
|
|
2073
|
+
if (type & 7 /* Strong */)
|
|
2074
|
+
prevStrong = type;
|
|
2075
|
+
prev = type;
|
|
2076
|
+
}
|
|
2077
|
+
// W5. A sequence of European terminators adjacent to European
|
|
2078
|
+
// numbers changes to all European numbers.
|
|
2079
|
+
// W6. Otherwise, separators and terminators change to Other
|
|
2080
|
+
// Neutral.
|
|
2081
|
+
// W7. Search backwards from each instance of a European number
|
|
2082
|
+
// until the first strong type (R, L, or sor) is found. If an L is
|
|
2083
|
+
// found, then change the type of the European number to L.
|
|
2084
|
+
// (Left after this: L, R, EN+AN, NI)
|
|
2085
|
+
for (let i = 0, prev = outerType, prevStrong = outerType; i < len; i++) {
|
|
2086
|
+
let type = types[i];
|
|
2087
|
+
if (type == 128 /* CS */) {
|
|
2088
|
+
if (i < len - 1 && prev == types[i + 1] && (prev & 24 /* Num */))
|
|
2089
|
+
type = types[i] = prev;
|
|
2090
|
+
else
|
|
2091
|
+
types[i] = 256 /* NI */;
|
|
2006
2092
|
}
|
|
2007
|
-
else {
|
|
2008
|
-
|
|
2093
|
+
else if (type == 64 /* ET */) {
|
|
2094
|
+
let end = i + 1;
|
|
2095
|
+
while (end < len && types[end] == 64 /* ET */)
|
|
2096
|
+
end++;
|
|
2097
|
+
let replace = (i && prev == 8 /* EN */) || (end < len && types[end] == 8 /* EN */) ? (prevStrong == 1 /* L */ ? 1 /* L */ : 8 /* EN */) : 256 /* NI */;
|
|
2098
|
+
for (let j = i; j < end; j++)
|
|
2099
|
+
types[j] = replace;
|
|
2100
|
+
i = end - 1;
|
|
2009
2101
|
}
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
// update
|
|
2013
|
-
updateInner(changes, deco, oldLength) {
|
|
2014
|
-
this.view.viewState.mustMeasureContent = true;
|
|
2015
|
-
this.updateChildren(changes, deco, oldLength);
|
|
2016
|
-
let { observer } = this.view;
|
|
2017
|
-
observer.ignore(() => {
|
|
2018
|
-
// Lock the height during redrawing, since Chrome sometimes
|
|
2019
|
-
// messes with the scroll position during DOM mutation (though
|
|
2020
|
-
// no relayout is triggered and I cannot imagine how it can
|
|
2021
|
-
// recompute the scroll position without a layout)
|
|
2022
|
-
this.dom.style.height = this.view.viewState.contentHeight + "px";
|
|
2023
|
-
this.dom.style.minWidth = this.minWidth ? this.minWidth + "px" : "";
|
|
2024
|
-
// Chrome will sometimes, when DOM mutations occur directly
|
|
2025
|
-
// around the selection, get confused and report a different
|
|
2026
|
-
// selection from the one it displays (issue #218). This tries
|
|
2027
|
-
// to detect that situation.
|
|
2028
|
-
let track = browser.chrome || browser.ios ? { node: observer.selectionRange.focusNode, written: false } : undefined;
|
|
2029
|
-
this.sync(track);
|
|
2030
|
-
this.dirty = 0 /* Not */;
|
|
2031
|
-
if (track && (track.written || observer.selectionRange.focusNode != track.node))
|
|
2032
|
-
this.forceSelection = true;
|
|
2033
|
-
this.dom.style.height = "";
|
|
2034
|
-
});
|
|
2035
|
-
let gaps = [];
|
|
2036
|
-
if (this.view.viewport.from || this.view.viewport.to < this.view.state.doc.length)
|
|
2037
|
-
for (let child of this.children)
|
|
2038
|
-
if (child instanceof BlockWidgetView && child.widget instanceof BlockGapWidget)
|
|
2039
|
-
gaps.push(child.dom);
|
|
2040
|
-
observer.updateGaps(gaps);
|
|
2041
|
-
}
|
|
2042
|
-
updateChildren(changes, deco, oldLength) {
|
|
2043
|
-
let cursor = this.childCursor(oldLength);
|
|
2044
|
-
for (let i = changes.length - 1;; i--) {
|
|
2045
|
-
let next = i >= 0 ? changes[i] : null;
|
|
2046
|
-
if (!next)
|
|
2047
|
-
break;
|
|
2048
|
-
let { fromA, toA, fromB, toB } = next;
|
|
2049
|
-
let { content, breakAtStart, openStart, openEnd } = ContentBuilder.build(this.view.state.doc, fromB, toB, deco);
|
|
2050
|
-
let { i: toI, off: toOff } = cursor.findPos(toA, 1);
|
|
2051
|
-
let { i: fromI, off: fromOff } = cursor.findPos(fromA, -1);
|
|
2052
|
-
this.replaceRange(fromI, fromOff, toI, toOff, content, breakAtStart, openStart, openEnd);
|
|
2102
|
+
else if (type == 8 /* EN */ && prevStrong == 1 /* L */) {
|
|
2103
|
+
types[i] = 1 /* L */;
|
|
2053
2104
|
}
|
|
2105
|
+
prev = type;
|
|
2106
|
+
if (type & 7 /* Strong */)
|
|
2107
|
+
prevStrong = type;
|
|
2054
2108
|
}
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2109
|
+
// N0. Process bracket pairs in an isolating run sequence
|
|
2110
|
+
// sequentially in the logical order of the text positions of the
|
|
2111
|
+
// opening paired brackets using the logic given below. Within this
|
|
2112
|
+
// scope, bidirectional types EN and AN are treated as R.
|
|
2113
|
+
for (let i = 0, sI = 0, context = 0, ch, br, type; i < len; i++) {
|
|
2114
|
+
// Keeps [startIndex, type, strongSeen] triples for each open
|
|
2115
|
+
// bracket on BracketStack.
|
|
2116
|
+
if (br = Brackets[ch = line.charCodeAt(i)]) {
|
|
2117
|
+
if (br < 0) { // Closing bracket
|
|
2118
|
+
for (let sJ = sI - 3; sJ >= 0; sJ -= 3) {
|
|
2119
|
+
if (BracketStack[sJ + 1] == -br) {
|
|
2120
|
+
let flags = BracketStack[sJ + 2];
|
|
2121
|
+
let type = (flags & 2 /* EmbedInside */) ? outerType :
|
|
2122
|
+
!(flags & 4 /* OppositeInside */) ? 0 :
|
|
2123
|
+
(flags & 1 /* OppositeBefore */) ? oppositeType : outerType;
|
|
2124
|
+
if (type)
|
|
2125
|
+
types[i] = types[BracketStack[sJ]] = type;
|
|
2126
|
+
sI = sJ;
|
|
2127
|
+
break;
|
|
2128
|
+
}
|
|
2129
|
+
}
|
|
2070
2130
|
}
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
if (!breakAtEnd && last && after.merge(0, toOff, last, true, 0, openEnd)) {
|
|
2074
|
-
content[content.length - 1] = after;
|
|
2131
|
+
else if (BracketStack.length == 189 /* MaxDepth */) {
|
|
2132
|
+
break;
|
|
2075
2133
|
}
|
|
2076
2134
|
else {
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
after.merge(0, toOff, null, false, 0, openEnd);
|
|
2081
|
-
content.push(after);
|
|
2135
|
+
BracketStack[sI++] = i;
|
|
2136
|
+
BracketStack[sI++] = ch;
|
|
2137
|
+
BracketStack[sI++] = context;
|
|
2082
2138
|
}
|
|
2083
2139
|
}
|
|
2084
|
-
else if (
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2140
|
+
else if ((type = types[i]) == 2 /* R */ || type == 1 /* L */) {
|
|
2141
|
+
let embed = type == outerType;
|
|
2142
|
+
context = embed ? 0 : 1 /* OppositeBefore */;
|
|
2143
|
+
for (let sJ = sI - 3; sJ >= 0; sJ -= 3) {
|
|
2144
|
+
let cur = BracketStack[sJ + 2];
|
|
2145
|
+
if (cur & 2 /* EmbedInside */)
|
|
2146
|
+
break;
|
|
2147
|
+
if (embed) {
|
|
2148
|
+
BracketStack[sJ + 2] |= 2 /* EmbedInside */;
|
|
2149
|
+
}
|
|
2150
|
+
else {
|
|
2151
|
+
if (cur & 4 /* OppositeInside */)
|
|
2152
|
+
break;
|
|
2153
|
+
BracketStack[sJ + 2] |= 4 /* OppositeInside */;
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2091
2156
|
}
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2157
|
+
}
|
|
2158
|
+
// N1. A sequence of neutrals takes the direction of the
|
|
2159
|
+
// surrounding strong text if the text on both sides has the same
|
|
2160
|
+
// direction. European and Arabic numbers act as if they were R in
|
|
2161
|
+
// terms of their influence on neutrals. Start-of-level-run (sor)
|
|
2162
|
+
// and end-of-level-run (eor) are used at level run boundaries.
|
|
2163
|
+
// N2. Any remaining neutrals take the embedding direction.
|
|
2164
|
+
// (Left after this: L, R, EN+AN)
|
|
2165
|
+
for (let i = 0; i < len; i++) {
|
|
2166
|
+
if (types[i] == 256 /* NI */) {
|
|
2167
|
+
let end = i + 1;
|
|
2168
|
+
while (end < len && types[end] == 256 /* NI */)
|
|
2169
|
+
end++;
|
|
2170
|
+
let beforeL = (i ? types[i - 1] : outerType) == 1 /* L */;
|
|
2171
|
+
let afterL = (end < len ? types[end] : outerType) == 1 /* L */;
|
|
2172
|
+
let replace = beforeL == afterL ? (beforeL ? 1 /* L */ : 2 /* R */) : outerType;
|
|
2173
|
+
for (let j = i; j < end; j++)
|
|
2174
|
+
types[j] = replace;
|
|
2175
|
+
i = end - 1;
|
|
2176
|
+
}
|
|
2177
|
+
}
|
|
2178
|
+
// Here we depart from the documented algorithm, in order to avoid
|
|
2179
|
+
// building up an actual levels array. Since there are only three
|
|
2180
|
+
// levels (0, 1, 2) in an implementation that doesn't take
|
|
2181
|
+
// explicit embedding into account, we can build up the order on
|
|
2182
|
+
// the fly, without following the level-based algorithm.
|
|
2183
|
+
let order = [];
|
|
2184
|
+
if (outerType == 1 /* L */) {
|
|
2185
|
+
for (let i = 0; i < len;) {
|
|
2186
|
+
let start = i, rtl = types[i++] != 1 /* L */;
|
|
2187
|
+
while (i < len && rtl == (types[i] != 1 /* L */))
|
|
2188
|
+
i++;
|
|
2189
|
+
if (rtl) {
|
|
2190
|
+
for (let j = i; j > start;) {
|
|
2191
|
+
let end = j, l = types[--j] != 2 /* R */;
|
|
2192
|
+
while (j > start && l == (types[j - 1] != 2 /* R */))
|
|
2193
|
+
j--;
|
|
2194
|
+
order.push(new BidiSpan(j, end, l ? 2 : 1));
|
|
2195
|
+
}
|
|
2099
2196
|
}
|
|
2100
|
-
else
|
|
2101
|
-
|
|
2197
|
+
else {
|
|
2198
|
+
order.push(new BidiSpan(start, i, 0));
|
|
2102
2199
|
}
|
|
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
2200
|
}
|
|
2114
|
-
if (fromI < toI || content.length)
|
|
2115
|
-
this.replaceChildren(fromI, toI, content);
|
|
2116
2201
|
}
|
|
2117
|
-
|
|
2118
|
-
|
|
2202
|
+
else {
|
|
2203
|
+
for (let i = 0; i < len;) {
|
|
2204
|
+
let start = i, rtl = types[i++] == 2 /* R */;
|
|
2205
|
+
while (i < len && rtl == (types[i] == 2 /* R */))
|
|
2206
|
+
i++;
|
|
2207
|
+
order.push(new BidiSpan(start, i, rtl ? 1 : 2));
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
return order;
|
|
2211
|
+
}
|
|
2212
|
+
function trivialOrder(length) {
|
|
2213
|
+
return [new BidiSpan(0, length, 0)];
|
|
2214
|
+
}
|
|
2215
|
+
let movedOver = "";
|
|
2216
|
+
function moveVisually(line, order, dir, start, forward) {
|
|
2217
|
+
var _a;
|
|
2218
|
+
let startIndex = start.head - line.from, spanI = -1;
|
|
2219
|
+
if (startIndex == 0) {
|
|
2220
|
+
if (!forward || !line.length)
|
|
2221
|
+
return null;
|
|
2222
|
+
if (order[0].level != dir) {
|
|
2223
|
+
startIndex = order[0].side(false, dir);
|
|
2224
|
+
spanI = 0;
|
|
2225
|
+
}
|
|
2226
|
+
}
|
|
2227
|
+
else if (startIndex == line.length) {
|
|
2228
|
+
if (forward)
|
|
2229
|
+
return null;
|
|
2230
|
+
let last = order[order.length - 1];
|
|
2231
|
+
if (last.level != dir) {
|
|
2232
|
+
startIndex = last.side(true, dir);
|
|
2233
|
+
spanI = order.length - 1;
|
|
2234
|
+
}
|
|
2235
|
+
}
|
|
2236
|
+
if (spanI < 0)
|
|
2237
|
+
spanI = BidiSpan.find(order, startIndex, (_a = start.bidiLevel) !== null && _a !== void 0 ? _a : -1, start.assoc);
|
|
2238
|
+
let span = order[spanI];
|
|
2239
|
+
// End of span. (But not end of line--that was checked for above.)
|
|
2240
|
+
if (startIndex == span.side(forward, dir)) {
|
|
2241
|
+
span = order[spanI += forward ? 1 : -1];
|
|
2242
|
+
startIndex = span.side(!forward, dir);
|
|
2243
|
+
}
|
|
2244
|
+
let indexForward = forward == (span.dir == dir);
|
|
2245
|
+
let nextIndex = text.findClusterBreak(line.text, startIndex, indexForward);
|
|
2246
|
+
movedOver = line.text.slice(Math.min(startIndex, nextIndex), Math.max(startIndex, nextIndex));
|
|
2247
|
+
if (nextIndex != span.side(forward, dir))
|
|
2248
|
+
return state.EditorSelection.cursor(nextIndex + line.from, indexForward ? -1 : 1, span.level);
|
|
2249
|
+
let nextSpan = spanI == (forward ? order.length - 1 : 0) ? null : order[spanI + (forward ? 1 : -1)];
|
|
2250
|
+
if (!nextSpan && span.level != dir)
|
|
2251
|
+
return state.EditorSelection.cursor(forward ? line.to : line.from, forward ? -1 : 1, dir);
|
|
2252
|
+
if (nextSpan && nextSpan.level < span.level)
|
|
2253
|
+
return state.EditorSelection.cursor(nextSpan.side(!forward, dir) + line.from, forward ? 1 : -1, nextSpan.level);
|
|
2254
|
+
return state.EditorSelection.cursor(nextIndex + line.from, forward ? -1 : 1, span.level);
|
|
2255
|
+
}
|
|
2256
|
+
|
|
2257
|
+
class DocView extends ContentView {
|
|
2258
|
+
constructor(view) {
|
|
2259
|
+
super();
|
|
2260
|
+
this.view = view;
|
|
2261
|
+
this.compositionDeco = Decoration.none;
|
|
2262
|
+
this.decorations = [];
|
|
2263
|
+
// Track a minimum width for the editor. When measuring sizes in
|
|
2264
|
+
// measureVisibleLineHeights, this is updated to point at the width
|
|
2265
|
+
// of a given element and its extent in the document. When a change
|
|
2266
|
+
// happens in that range, these are reset. That way, once we've seen
|
|
2267
|
+
// a line/element of a given length, we keep the editor wide enough
|
|
2268
|
+
// to fit at least that element, until it is changed, at which point
|
|
2269
|
+
// we forget it again.
|
|
2270
|
+
this.minWidth = 0;
|
|
2271
|
+
this.minWidthFrom = 0;
|
|
2272
|
+
this.minWidthTo = 0;
|
|
2273
|
+
// Track whether the DOM selection was set in a lossy way, so that
|
|
2274
|
+
// we don't mess it up when reading it back it
|
|
2275
|
+
this.impreciseAnchor = null;
|
|
2276
|
+
this.impreciseHead = null;
|
|
2277
|
+
this.forceSelection = false;
|
|
2278
|
+
// Used by the resize observer to ignore resizes that we caused
|
|
2279
|
+
// ourselves
|
|
2280
|
+
this.lastUpdate = Date.now();
|
|
2281
|
+
this.setDOM(view.contentDOM);
|
|
2282
|
+
this.children = [new LineView];
|
|
2283
|
+
this.children[0].setParent(this);
|
|
2284
|
+
this.updateInner([new ChangedRange(0, 0, 0, view.state.doc.length)], this.updateDeco(), 0);
|
|
2285
|
+
}
|
|
2286
|
+
get root() { return this.view.root; }
|
|
2287
|
+
get editorView() { return this.view; }
|
|
2288
|
+
get length() { return this.view.state.doc.length; }
|
|
2289
|
+
// Update the document view to a given state. scrollIntoView can be
|
|
2290
|
+
// used as a hint to compute a new viewport that includes that
|
|
2291
|
+
// position, if we know the editor is going to scroll that position
|
|
2292
|
+
// into view.
|
|
2293
|
+
update(update) {
|
|
2294
|
+
let changedRanges = update.changedRanges;
|
|
2295
|
+
if (this.minWidth > 0 && changedRanges.length) {
|
|
2296
|
+
if (!changedRanges.every(({ fromA, toA }) => toA < this.minWidthFrom || fromA > this.minWidthTo)) {
|
|
2297
|
+
this.minWidth = this.minWidthFrom = this.minWidthTo = 0;
|
|
2298
|
+
}
|
|
2299
|
+
else {
|
|
2300
|
+
this.minWidthFrom = update.changes.mapPos(this.minWidthFrom, 1);
|
|
2301
|
+
this.minWidthTo = update.changes.mapPos(this.minWidthTo, 1);
|
|
2302
|
+
}
|
|
2303
|
+
}
|
|
2304
|
+
if (this.view.inputState.composing < 0)
|
|
2305
|
+
this.compositionDeco = Decoration.none;
|
|
2306
|
+
else if (update.transactions.length)
|
|
2307
|
+
this.compositionDeco = computeCompositionDeco(this.view, update.changes);
|
|
2308
|
+
// When the DOM nodes around the selection are moved to another
|
|
2309
|
+
// parent, Chrome sometimes reports a different selection through
|
|
2310
|
+
// getSelection than the one that it actually shows to the user.
|
|
2311
|
+
// This forces a selection update when lines are joined to work
|
|
2312
|
+
// around that. Issue #54
|
|
2313
|
+
if ((browser.ie || browser.chrome) && !this.compositionDeco.size && update &&
|
|
2314
|
+
update.state.doc.lines != update.startState.doc.lines)
|
|
2315
|
+
this.forceSelection = true;
|
|
2316
|
+
let prevDeco = this.decorations, deco = this.updateDeco();
|
|
2317
|
+
let decoDiff = findChangedDeco(prevDeco, deco, update.changes);
|
|
2318
|
+
changedRanges = ChangedRange.extendWithRanges(changedRanges, decoDiff);
|
|
2319
|
+
if (this.dirty == 0 /* Not */ && changedRanges.length == 0) {
|
|
2320
|
+
return false;
|
|
2321
|
+
}
|
|
2322
|
+
else {
|
|
2323
|
+
this.updateInner(changedRanges, deco, update.startState.doc.length);
|
|
2324
|
+
if (update.transactions.length)
|
|
2325
|
+
this.lastUpdate = Date.now();
|
|
2326
|
+
return true;
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
reset(sel) {
|
|
2330
|
+
if (this.dirty) {
|
|
2331
|
+
this.view.observer.ignore(() => this.view.docView.sync());
|
|
2332
|
+
this.dirty = 0 /* Not */;
|
|
2333
|
+
this.updateSelection(true);
|
|
2334
|
+
}
|
|
2335
|
+
else {
|
|
2336
|
+
this.updateSelection();
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
// Used by update and the constructor do perform the actual DOM
|
|
2340
|
+
// update
|
|
2341
|
+
updateInner(changes, deco, oldLength) {
|
|
2342
|
+
this.view.viewState.mustMeasureContent = true;
|
|
2343
|
+
this.updateChildren(changes, deco, oldLength);
|
|
2344
|
+
let { observer } = this.view;
|
|
2345
|
+
observer.ignore(() => {
|
|
2346
|
+
// Lock the height during redrawing, since Chrome sometimes
|
|
2347
|
+
// messes with the scroll position during DOM mutation (though
|
|
2348
|
+
// no relayout is triggered and I cannot imagine how it can
|
|
2349
|
+
// recompute the scroll position without a layout)
|
|
2350
|
+
this.dom.style.height = this.view.viewState.contentHeight + "px";
|
|
2351
|
+
this.dom.style.minWidth = this.minWidth ? this.minWidth + "px" : "";
|
|
2352
|
+
// Chrome will sometimes, when DOM mutations occur directly
|
|
2353
|
+
// around the selection, get confused and report a different
|
|
2354
|
+
// selection from the one it displays (issue #218). This tries
|
|
2355
|
+
// to detect that situation.
|
|
2356
|
+
let track = browser.chrome || browser.ios ? { node: observer.selectionRange.focusNode, written: false } : undefined;
|
|
2357
|
+
this.sync(track);
|
|
2358
|
+
this.dirty = 0 /* Not */;
|
|
2359
|
+
if (track && (track.written || observer.selectionRange.focusNode != track.node))
|
|
2360
|
+
this.forceSelection = true;
|
|
2361
|
+
this.dom.style.height = "";
|
|
2362
|
+
});
|
|
2363
|
+
let gaps = [];
|
|
2364
|
+
if (this.view.viewport.from || this.view.viewport.to < this.view.state.doc.length)
|
|
2365
|
+
for (let child of this.children)
|
|
2366
|
+
if (child instanceof BlockWidgetView && child.widget instanceof BlockGapWidget)
|
|
2367
|
+
gaps.push(child.dom);
|
|
2368
|
+
observer.updateGaps(gaps);
|
|
2369
|
+
}
|
|
2370
|
+
updateChildren(changes, deco, oldLength) {
|
|
2371
|
+
let cursor = this.childCursor(oldLength);
|
|
2372
|
+
for (let i = changes.length - 1;; i--) {
|
|
2373
|
+
let next = i >= 0 ? changes[i] : null;
|
|
2374
|
+
if (!next)
|
|
2375
|
+
break;
|
|
2376
|
+
let { fromA, toA, fromB, toB } = next;
|
|
2377
|
+
let { content, breakAtStart, openStart, openEnd } = ContentBuilder.build(this.view.state.doc, fromB, toB, deco);
|
|
2378
|
+
let { i: toI, off: toOff } = cursor.findPos(toA, 1);
|
|
2379
|
+
let { i: fromI, off: fromOff } = cursor.findPos(fromA, -1);
|
|
2380
|
+
replaceRange(this, fromI, fromOff, toI, toOff, content, breakAtStart, openStart, openEnd);
|
|
2381
|
+
}
|
|
2382
|
+
}
|
|
2383
|
+
// Sync the DOM selection to this.state.selection
|
|
2384
|
+
updateSelection(mustRead = false, fromPointer = false) {
|
|
2119
2385
|
if (mustRead)
|
|
2120
2386
|
this.view.observer.readSelectionRange();
|
|
2121
2387
|
if (!(fromPointer || this.mayControlSelection()) ||
|
|
@@ -2250,18 +2516,30 @@ class DocView extends ContentView {
|
|
|
2250
2516
|
}
|
|
2251
2517
|
measureVisibleLineHeights() {
|
|
2252
2518
|
let result = [], { from, to } = this.view.viewState.viewport;
|
|
2253
|
-
let
|
|
2519
|
+
let contentWidth = this.view.contentDOM.clientWidth;
|
|
2520
|
+
let isWider = contentWidth > Math.max(this.view.scrollDOM.clientWidth, this.minWidth) + 1;
|
|
2521
|
+
let widest = -1;
|
|
2254
2522
|
for (let pos = 0, i = 0; i < this.children.length; i++) {
|
|
2255
2523
|
let child = this.children[i], end = pos + child.length;
|
|
2256
2524
|
if (end > to)
|
|
2257
2525
|
break;
|
|
2258
2526
|
if (pos >= from) {
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
if (
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2527
|
+
let childRect = child.dom.getBoundingClientRect();
|
|
2528
|
+
result.push(childRect.height);
|
|
2529
|
+
if (isWider) {
|
|
2530
|
+
let last = child.dom.lastChild;
|
|
2531
|
+
let rects = last ? clientRectsFor(last) : [];
|
|
2532
|
+
if (rects.length) {
|
|
2533
|
+
let rect = rects[rects.length - 1];
|
|
2534
|
+
let width = this.view.textDirection == exports.Direction.LTR ? rect.right - childRect.left
|
|
2535
|
+
: childRect.right - rect.left;
|
|
2536
|
+
if (width > widest) {
|
|
2537
|
+
widest = width;
|
|
2538
|
+
this.minWidth = contentWidth;
|
|
2539
|
+
this.minWidthFrom = pos;
|
|
2540
|
+
this.minWidthTo = end;
|
|
2541
|
+
}
|
|
2542
|
+
}
|
|
2265
2543
|
}
|
|
2266
2544
|
}
|
|
2267
2545
|
pos = end + child.breakAfter;
|
|
@@ -2292,489 +2570,182 @@ class DocView extends ContentView {
|
|
|
2292
2570
|
childCursor(pos = this.length) {
|
|
2293
2571
|
// Move back to start of last element when possible, so that
|
|
2294
2572
|
// `ChildCursor.findPos` doesn't have to deal with the edge case
|
|
2295
|
-
// of being after the last element.
|
|
2296
|
-
let i = this.children.length;
|
|
2297
|
-
if (i)
|
|
2298
|
-
pos -= this.children[--i].length;
|
|
2299
|
-
return new ChildCursor(this.children, pos, i);
|
|
2300
|
-
}
|
|
2301
|
-
computeBlockGapDeco() {
|
|
2302
|
-
let deco = [], vs = this.view.viewState;
|
|
2303
|
-
for (let pos = 0, i = 0;; i++) {
|
|
2304
|
-
let next = i == vs.viewports.length ? null : vs.viewports[i];
|
|
2305
|
-
let end = next ? next.from - 1 : this.length;
|
|
2306
|
-
if (end > pos) {
|
|
2307
|
-
let height = vs.lineBlockAt(end).bottom - vs.lineBlockAt(pos).top;
|
|
2308
|
-
deco.push(Decoration.replace({ widget: new BlockGapWidget(height), block: true, inclusive: true }).range(pos, end));
|
|
2309
|
-
}
|
|
2310
|
-
if (!next)
|
|
2311
|
-
break;
|
|
2312
|
-
pos = next.to + 1;
|
|
2313
|
-
}
|
|
2314
|
-
return Decoration.set(deco);
|
|
2315
|
-
}
|
|
2316
|
-
updateDeco() {
|
|
2317
|
-
return this.decorations = [
|
|
2318
|
-
...this.view.pluginField(PluginField.decorations),
|
|
2319
|
-
...this.view.state.facet(decorations),
|
|
2320
|
-
this.compositionDeco,
|
|
2321
|
-
this.computeBlockGapDeco(),
|
|
2322
|
-
this.view.viewState.lineGapDeco
|
|
2323
|
-
];
|
|
2324
|
-
}
|
|
2325
|
-
scrollIntoView({ range, center }) {
|
|
2326
|
-
let rect = this.coordsAt(range.head, range.empty ? range.assoc : range.head > range.anchor ? -1 : 1), other;
|
|
2327
|
-
if (!rect)
|
|
2328
|
-
return;
|
|
2329
|
-
if (!range.empty && (other = this.coordsAt(range.anchor, range.anchor > range.head ? -1 : 1)))
|
|
2330
|
-
rect = { left: Math.min(rect.left, other.left), top: Math.min(rect.top, other.top),
|
|
2331
|
-
right: Math.max(rect.right, other.right), bottom: Math.max(rect.bottom, other.bottom) };
|
|
2332
|
-
let mLeft = 0, mRight = 0, mTop = 0, mBottom = 0;
|
|
2333
|
-
for (let margins of this.view.pluginField(PluginField.scrollMargins))
|
|
2334
|
-
if (margins) {
|
|
2335
|
-
let { left, right, top, bottom } = margins;
|
|
2336
|
-
if (left != null)
|
|
2337
|
-
mLeft = Math.max(mLeft, left);
|
|
2338
|
-
if (right != null)
|
|
2339
|
-
mRight = Math.max(mRight, right);
|
|
2340
|
-
if (top != null)
|
|
2341
|
-
mTop = Math.max(mTop, top);
|
|
2342
|
-
if (bottom != null)
|
|
2343
|
-
mBottom = Math.max(mBottom, bottom);
|
|
2344
|
-
}
|
|
2345
|
-
scrollRectIntoView(this.view.scrollDOM, {
|
|
2346
|
-
left: rect.left - mLeft, top: rect.top - mTop,
|
|
2347
|
-
right: rect.right + mRight, bottom: rect.bottom + mBottom
|
|
2348
|
-
}, range.head < range.anchor ? -1 : 1, center);
|
|
2349
|
-
}
|
|
2350
|
-
}
|
|
2351
|
-
function betweenUneditable(pos) {
|
|
2352
|
-
return pos.node.nodeType == 1 && pos.node.firstChild &&
|
|
2353
|
-
(pos.offset == 0 || pos.node.childNodes[pos.offset - 1].contentEditable == "false") &&
|
|
2354
|
-
(pos.offset == pos.node.childNodes.length || pos.node.childNodes[pos.offset].contentEditable == "false");
|
|
2355
|
-
}
|
|
2356
|
-
class BlockGapWidget extends WidgetType {
|
|
2357
|
-
constructor(height) {
|
|
2358
|
-
super();
|
|
2359
|
-
this.height = height;
|
|
2360
|
-
}
|
|
2361
|
-
toDOM() {
|
|
2362
|
-
let elt = document.createElement("div");
|
|
2363
|
-
this.updateDOM(elt);
|
|
2364
|
-
return elt;
|
|
2365
|
-
}
|
|
2366
|
-
eq(other) { return other.height == this.height; }
|
|
2367
|
-
updateDOM(elt) {
|
|
2368
|
-
elt.style.height = this.height + "px";
|
|
2369
|
-
return true;
|
|
2370
|
-
}
|
|
2371
|
-
get estimatedHeight() { return this.height; }
|
|
2372
|
-
}
|
|
2373
|
-
function computeCompositionDeco(view, changes) {
|
|
2374
|
-
let sel = view.observer.selectionRange;
|
|
2375
|
-
let textNode = sel.focusNode && nearbyTextNode(sel.focusNode, sel.focusOffset, 0);
|
|
2376
|
-
if (!textNode)
|
|
2377
|
-
return Decoration.none;
|
|
2378
|
-
let cView = view.docView.nearest(textNode);
|
|
2379
|
-
let from, to, topNode = textNode;
|
|
2380
|
-
if (cView instanceof InlineView) {
|
|
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) {
|
|
2388
|
-
while (topNode.parentNode != cView.dom)
|
|
2389
|
-
topNode = topNode.parentNode;
|
|
2390
|
-
let prev = topNode.previousSibling;
|
|
2391
|
-
while (prev && !ContentView.get(prev))
|
|
2392
|
-
prev = prev.previousSibling;
|
|
2393
|
-
from = to = prev ? ContentView.get(prev).posAtEnd : cView.posAtStart;
|
|
2394
|
-
}
|
|
2395
|
-
else {
|
|
2396
|
-
return Decoration.none;
|
|
2397
|
-
}
|
|
2398
|
-
let newFrom = changes.mapPos(from, 1), newTo = Math.max(newFrom, changes.mapPos(to, -1));
|
|
2399
|
-
let text = textNode.nodeValue, { state } = view;
|
|
2400
|
-
if (newTo - newFrom < text.length) {
|
|
2401
|
-
if (state.sliceDoc(newFrom, Math.min(state.doc.length, newFrom + text.length)) == text)
|
|
2402
|
-
newTo = newFrom + text.length;
|
|
2403
|
-
else if (state.sliceDoc(Math.max(0, newTo - text.length), newTo) == text)
|
|
2404
|
-
newFrom = newTo - text.length;
|
|
2405
|
-
else
|
|
2406
|
-
return Decoration.none;
|
|
2407
|
-
}
|
|
2408
|
-
else if (state.sliceDoc(newFrom, newTo) != text) {
|
|
2409
|
-
return Decoration.none;
|
|
2410
|
-
}
|
|
2411
|
-
return Decoration.set(Decoration.replace({ widget: new CompositionWidget(topNode, textNode) }).range(newFrom, newTo));
|
|
2412
|
-
}
|
|
2413
|
-
class CompositionWidget extends WidgetType {
|
|
2414
|
-
constructor(top, text) {
|
|
2415
|
-
super();
|
|
2416
|
-
this.top = top;
|
|
2417
|
-
this.text = text;
|
|
2418
|
-
}
|
|
2419
|
-
eq(other) { return this.top == other.top && this.text == other.text; }
|
|
2420
|
-
toDOM() { return this.top; }
|
|
2421
|
-
ignoreEvent() { return false; }
|
|
2422
|
-
get customView() { return CompositionView; }
|
|
2423
|
-
}
|
|
2424
|
-
function nearbyTextNode(node, offset, side) {
|
|
2425
|
-
for (;;) {
|
|
2426
|
-
if (node.nodeType == 3)
|
|
2427
|
-
return node;
|
|
2428
|
-
if (node.nodeType == 1 && offset > 0 && side <= 0) {
|
|
2429
|
-
node = node.childNodes[offset - 1];
|
|
2430
|
-
offset = maxOffset(node);
|
|
2431
|
-
}
|
|
2432
|
-
else if (node.nodeType == 1 && offset < node.childNodes.length && side >= 0) {
|
|
2433
|
-
node = node.childNodes[offset];
|
|
2434
|
-
offset = 0;
|
|
2435
|
-
}
|
|
2436
|
-
else {
|
|
2437
|
-
return null;
|
|
2438
|
-
}
|
|
2439
|
-
}
|
|
2440
|
-
}
|
|
2441
|
-
function nextToUneditable(node, offset) {
|
|
2442
|
-
if (node.nodeType != 1)
|
|
2443
|
-
return 0;
|
|
2444
|
-
return (offset && node.childNodes[offset - 1].contentEditable == "false" ? 1 /* Before */ : 0) |
|
|
2445
|
-
(offset < node.childNodes.length && node.childNodes[offset].contentEditable == "false" ? 2 /* After */ : 0);
|
|
2446
|
-
}
|
|
2447
|
-
class DecorationComparator$1 {
|
|
2448
|
-
constructor() {
|
|
2449
|
-
this.changes = [];
|
|
2450
|
-
}
|
|
2451
|
-
compareRange(from, to) { addRange(from, to, this.changes); }
|
|
2452
|
-
comparePoint(from, to) { addRange(from, to, this.changes); }
|
|
2453
|
-
}
|
|
2454
|
-
function findChangedDeco(a, b, diff) {
|
|
2455
|
-
let comp = new DecorationComparator$1;
|
|
2456
|
-
rangeset.RangeSet.compare(a, b, diff, comp);
|
|
2457
|
-
return comp.changes;
|
|
2458
|
-
}
|
|
2459
|
-
function inUneditable(node, inside) {
|
|
2460
|
-
for (let cur = node; cur && cur != inside; cur = cur.assignedSlot || cur.parentNode) {
|
|
2461
|
-
if (cur.nodeType == 1 && cur.contentEditable == 'false') {
|
|
2462
|
-
return true;
|
|
2463
|
-
}
|
|
2464
|
-
}
|
|
2465
|
-
return false;
|
|
2466
|
-
}
|
|
2467
|
-
|
|
2468
|
-
/**
|
|
2469
|
-
Used to indicate [text direction](https://codemirror.net/6/docs/ref/#view.EditorView.textDirection).
|
|
2470
|
-
*/
|
|
2471
|
-
exports.Direction = void 0;
|
|
2472
|
-
(function (Direction) {
|
|
2473
|
-
// (These are chosen to match the base levels, in bidi algorithm
|
|
2474
|
-
// terms, of spans in that direction.)
|
|
2475
|
-
/**
|
|
2476
|
-
Left-to-right.
|
|
2477
|
-
*/
|
|
2478
|
-
Direction[Direction["LTR"] = 0] = "LTR";
|
|
2479
|
-
/**
|
|
2480
|
-
Right-to-left.
|
|
2481
|
-
*/
|
|
2482
|
-
Direction[Direction["RTL"] = 1] = "RTL";
|
|
2483
|
-
})(exports.Direction || (exports.Direction = {}));
|
|
2484
|
-
const LTR = exports.Direction.LTR, RTL = exports.Direction.RTL;
|
|
2485
|
-
// Decode a string with each type encoded as log2(type)
|
|
2486
|
-
function dec(str) {
|
|
2487
|
-
let result = [];
|
|
2488
|
-
for (let i = 0; i < str.length; i++)
|
|
2489
|
-
result.push(1 << +str[i]);
|
|
2490
|
-
return result;
|
|
2491
|
-
}
|
|
2492
|
-
// Character types for codepoints 0 to 0xf8
|
|
2493
|
-
const LowTypes = dec("88888888888888888888888888888888888666888888787833333333337888888000000000000000000000000008888880000000000000000000000000088888888888888888888888888888888888887866668888088888663380888308888800000000000000000000000800000000000000000000000000000008");
|
|
2494
|
-
// Character types for codepoints 0x600 to 0x6f9
|
|
2495
|
-
const ArabicTypes = dec("4444448826627288999999999992222222222222222222222222222222222222222222222229999999999999999999994444444444644222822222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222999999949999999229989999223333333333");
|
|
2496
|
-
const Brackets = Object.create(null), BracketStack = [];
|
|
2497
|
-
// There's a lot more in
|
|
2498
|
-
// https://www.unicode.org/Public/UCD/latest/ucd/BidiBrackets.txt,
|
|
2499
|
-
// which are left out to keep code size down.
|
|
2500
|
-
for (let p of ["()", "[]", "{}"]) {
|
|
2501
|
-
let l = p.charCodeAt(0), r = p.charCodeAt(1);
|
|
2502
|
-
Brackets[l] = r;
|
|
2503
|
-
Brackets[r] = -l;
|
|
2504
|
-
}
|
|
2505
|
-
function charType(ch) {
|
|
2506
|
-
return ch <= 0xf7 ? LowTypes[ch] :
|
|
2507
|
-
0x590 <= ch && ch <= 0x5f4 ? 2 /* R */ :
|
|
2508
|
-
0x600 <= ch && ch <= 0x6f9 ? ArabicTypes[ch - 0x600] :
|
|
2509
|
-
0x6ee <= ch && ch <= 0x8ac ? 4 /* AL */ :
|
|
2510
|
-
0x2000 <= ch && ch <= 0x200b ? 256 /* NI */ :
|
|
2511
|
-
ch == 0x200c ? 256 /* NI */ : 1 /* L */;
|
|
2512
|
-
}
|
|
2513
|
-
const BidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
|
|
2514
|
-
/**
|
|
2515
|
-
Represents a contiguous range of text that has a single direction
|
|
2516
|
-
(as in left-to-right or right-to-left).
|
|
2517
|
-
*/
|
|
2518
|
-
class BidiSpan {
|
|
2519
|
-
/**
|
|
2520
|
-
@internal
|
|
2521
|
-
*/
|
|
2522
|
-
constructor(
|
|
2523
|
-
/**
|
|
2524
|
-
The start of the span (relative to the start of the line).
|
|
2525
|
-
*/
|
|
2526
|
-
from,
|
|
2527
|
-
/**
|
|
2528
|
-
The end of the span.
|
|
2529
|
-
*/
|
|
2530
|
-
to,
|
|
2531
|
-
/**
|
|
2532
|
-
The ["bidi
|
|
2533
|
-
level"](https://unicode.org/reports/tr9/#Basic_Display_Algorithm)
|
|
2534
|
-
of the span (in this context, 0 means
|
|
2535
|
-
left-to-right, 1 means right-to-left, 2 means left-to-right
|
|
2536
|
-
number inside right-to-left text).
|
|
2537
|
-
*/
|
|
2538
|
-
level) {
|
|
2539
|
-
this.from = from;
|
|
2540
|
-
this.to = to;
|
|
2541
|
-
this.level = level;
|
|
2542
|
-
}
|
|
2543
|
-
/**
|
|
2544
|
-
The direction of this span.
|
|
2545
|
-
*/
|
|
2546
|
-
get dir() { return this.level % 2 ? RTL : LTR; }
|
|
2547
|
-
/**
|
|
2548
|
-
@internal
|
|
2549
|
-
*/
|
|
2550
|
-
side(end, dir) { return (this.dir == dir) == end ? this.to : this.from; }
|
|
2551
|
-
/**
|
|
2552
|
-
@internal
|
|
2553
|
-
*/
|
|
2554
|
-
static find(order, index, level, assoc) {
|
|
2555
|
-
let maybe = -1;
|
|
2556
|
-
for (let i = 0; i < order.length; i++) {
|
|
2557
|
-
let span = order[i];
|
|
2558
|
-
if (span.from <= index && span.to >= index) {
|
|
2559
|
-
if (span.level == level)
|
|
2560
|
-
return i;
|
|
2561
|
-
// When multiple spans match, if assoc != 0, take the one that
|
|
2562
|
-
// covers that side, otherwise take the one with the minimum
|
|
2563
|
-
// level.
|
|
2564
|
-
if (maybe < 0 || (assoc != 0 ? (assoc < 0 ? span.from < index : span.to > index) : order[maybe].level > span.level))
|
|
2565
|
-
maybe = i;
|
|
2566
|
-
}
|
|
2567
|
-
}
|
|
2568
|
-
if (maybe < 0)
|
|
2569
|
-
throw new RangeError("Index out of range");
|
|
2570
|
-
return maybe;
|
|
2571
|
-
}
|
|
2572
|
-
}
|
|
2573
|
-
// Reused array of character types
|
|
2574
|
-
const types = [];
|
|
2575
|
-
function computeOrder(line, direction) {
|
|
2576
|
-
let len = line.length, outerType = direction == LTR ? 1 /* L */ : 2 /* R */, oppositeType = direction == LTR ? 2 /* R */ : 1 /* L */;
|
|
2577
|
-
if (!line || outerType == 1 /* L */ && !BidiRE.test(line))
|
|
2578
|
-
return trivialOrder(len);
|
|
2579
|
-
// W1. Examine each non-spacing mark (NSM) in the level run, and
|
|
2580
|
-
// change the type of the NSM to the type of the previous
|
|
2581
|
-
// character. If the NSM is at the start of the level run, it will
|
|
2582
|
-
// get the type of sor.
|
|
2583
|
-
// W2. Search backwards from each instance of a European number
|
|
2584
|
-
// until the first strong type (R, L, AL, or sor) is found. If an
|
|
2585
|
-
// AL is found, change the type of the European number to Arabic
|
|
2586
|
-
// number.
|
|
2587
|
-
// W3. Change all ALs to R.
|
|
2588
|
-
// (Left after this: L, R, EN, AN, ET, CS, NI)
|
|
2589
|
-
for (let i = 0, prev = outerType, prevStrong = outerType; i < len; i++) {
|
|
2590
|
-
let type = charType(line.charCodeAt(i));
|
|
2591
|
-
if (type == 512 /* NSM */)
|
|
2592
|
-
type = prev;
|
|
2593
|
-
else if (type == 8 /* EN */ && prevStrong == 4 /* AL */)
|
|
2594
|
-
type = 16 /* AN */;
|
|
2595
|
-
types[i] = type == 4 /* AL */ ? 2 /* R */ : type;
|
|
2596
|
-
if (type & 7 /* Strong */)
|
|
2597
|
-
prevStrong = type;
|
|
2598
|
-
prev = type;
|
|
2599
|
-
}
|
|
2600
|
-
// W5. A sequence of European terminators adjacent to European
|
|
2601
|
-
// numbers changes to all European numbers.
|
|
2602
|
-
// W6. Otherwise, separators and terminators change to Other
|
|
2603
|
-
// Neutral.
|
|
2604
|
-
// W7. Search backwards from each instance of a European number
|
|
2605
|
-
// until the first strong type (R, L, or sor) is found. If an L is
|
|
2606
|
-
// found, then change the type of the European number to L.
|
|
2607
|
-
// (Left after this: L, R, EN+AN, NI)
|
|
2608
|
-
for (let i = 0, prev = outerType, prevStrong = outerType; i < len; i++) {
|
|
2609
|
-
let type = types[i];
|
|
2610
|
-
if (type == 128 /* CS */) {
|
|
2611
|
-
if (i < len - 1 && prev == types[i + 1] && (prev & 24 /* Num */))
|
|
2612
|
-
type = types[i] = prev;
|
|
2613
|
-
else
|
|
2614
|
-
types[i] = 256 /* NI */;
|
|
2615
|
-
}
|
|
2616
|
-
else if (type == 64 /* ET */) {
|
|
2617
|
-
let end = i + 1;
|
|
2618
|
-
while (end < len && types[end] == 64 /* ET */)
|
|
2619
|
-
end++;
|
|
2620
|
-
let replace = (i && prev == 8 /* EN */) || (end < len && types[end] == 8 /* EN */) ? (prevStrong == 1 /* L */ ? 1 /* L */ : 8 /* EN */) : 256 /* NI */;
|
|
2621
|
-
for (let j = i; j < end; j++)
|
|
2622
|
-
types[j] = replace;
|
|
2623
|
-
i = end - 1;
|
|
2624
|
-
}
|
|
2625
|
-
else if (type == 8 /* EN */ && prevStrong == 1 /* L */) {
|
|
2626
|
-
types[i] = 1 /* L */;
|
|
2627
|
-
}
|
|
2628
|
-
prev = type;
|
|
2629
|
-
if (type & 7 /* Strong */)
|
|
2630
|
-
prevStrong = type;
|
|
2631
|
-
}
|
|
2632
|
-
// N0. Process bracket pairs in an isolating run sequence
|
|
2633
|
-
// sequentially in the logical order of the text positions of the
|
|
2634
|
-
// opening paired brackets using the logic given below. Within this
|
|
2635
|
-
// scope, bidirectional types EN and AN are treated as R.
|
|
2636
|
-
for (let i = 0, sI = 0, context = 0, ch, br, type; i < len; i++) {
|
|
2637
|
-
// Keeps [startIndex, type, strongSeen] triples for each open
|
|
2638
|
-
// bracket on BracketStack.
|
|
2639
|
-
if (br = Brackets[ch = line.charCodeAt(i)]) {
|
|
2640
|
-
if (br < 0) { // Closing bracket
|
|
2641
|
-
for (let sJ = sI - 3; sJ >= 0; sJ -= 3) {
|
|
2642
|
-
if (BracketStack[sJ + 1] == -br) {
|
|
2643
|
-
let flags = BracketStack[sJ + 2];
|
|
2644
|
-
let type = (flags & 2 /* EmbedInside */) ? outerType :
|
|
2645
|
-
!(flags & 4 /* OppositeInside */) ? 0 :
|
|
2646
|
-
(flags & 1 /* OppositeBefore */) ? oppositeType : outerType;
|
|
2647
|
-
if (type)
|
|
2648
|
-
types[i] = types[BracketStack[sJ]] = type;
|
|
2649
|
-
sI = sJ;
|
|
2650
|
-
break;
|
|
2651
|
-
}
|
|
2652
|
-
}
|
|
2653
|
-
}
|
|
2654
|
-
else if (BracketStack.length == 189 /* MaxDepth */) {
|
|
2655
|
-
break;
|
|
2656
|
-
}
|
|
2657
|
-
else {
|
|
2658
|
-
BracketStack[sI++] = i;
|
|
2659
|
-
BracketStack[sI++] = ch;
|
|
2660
|
-
BracketStack[sI++] = context;
|
|
2661
|
-
}
|
|
2662
|
-
}
|
|
2663
|
-
else if ((type = types[i]) == 2 /* R */ || type == 1 /* L */) {
|
|
2664
|
-
let embed = type == outerType;
|
|
2665
|
-
context = embed ? 0 : 1 /* OppositeBefore */;
|
|
2666
|
-
for (let sJ = sI - 3; sJ >= 0; sJ -= 3) {
|
|
2667
|
-
let cur = BracketStack[sJ + 2];
|
|
2668
|
-
if (cur & 2 /* EmbedInside */)
|
|
2669
|
-
break;
|
|
2670
|
-
if (embed) {
|
|
2671
|
-
BracketStack[sJ + 2] |= 2 /* EmbedInside */;
|
|
2672
|
-
}
|
|
2673
|
-
else {
|
|
2674
|
-
if (cur & 4 /* OppositeInside */)
|
|
2675
|
-
break;
|
|
2676
|
-
BracketStack[sJ + 2] |= 4 /* OppositeInside */;
|
|
2677
|
-
}
|
|
2573
|
+
// of being after the last element.
|
|
2574
|
+
let i = this.children.length;
|
|
2575
|
+
if (i)
|
|
2576
|
+
pos -= this.children[--i].length;
|
|
2577
|
+
return new ChildCursor(this.children, pos, i);
|
|
2578
|
+
}
|
|
2579
|
+
computeBlockGapDeco() {
|
|
2580
|
+
let deco = [], vs = this.view.viewState;
|
|
2581
|
+
for (let pos = 0, i = 0;; i++) {
|
|
2582
|
+
let next = i == vs.viewports.length ? null : vs.viewports[i];
|
|
2583
|
+
let end = next ? next.from - 1 : this.length;
|
|
2584
|
+
if (end > pos) {
|
|
2585
|
+
let height = vs.lineBlockAt(end).bottom - vs.lineBlockAt(pos).top;
|
|
2586
|
+
deco.push(Decoration.replace({ widget: new BlockGapWidget(height), block: true, inclusive: true }).range(pos, end));
|
|
2678
2587
|
}
|
|
2588
|
+
if (!next)
|
|
2589
|
+
break;
|
|
2590
|
+
pos = next.to + 1;
|
|
2679
2591
|
}
|
|
2592
|
+
return Decoration.set(deco);
|
|
2680
2593
|
}
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
if (types[i] == 256 /* NI */) {
|
|
2690
|
-
let end = i + 1;
|
|
2691
|
-
while (end < len && types[end] == 256 /* NI */)
|
|
2692
|
-
end++;
|
|
2693
|
-
let beforeL = (i ? types[i - 1] : outerType) == 1 /* L */;
|
|
2694
|
-
let afterL = (end < len ? types[end] : outerType) == 1 /* L */;
|
|
2695
|
-
let replace = beforeL == afterL ? (beforeL ? 1 /* L */ : 2 /* R */) : outerType;
|
|
2696
|
-
for (let j = i; j < end; j++)
|
|
2697
|
-
types[j] = replace;
|
|
2698
|
-
i = end - 1;
|
|
2699
|
-
}
|
|
2594
|
+
updateDeco() {
|
|
2595
|
+
return this.decorations = [
|
|
2596
|
+
...this.view.pluginField(PluginField.decorations),
|
|
2597
|
+
...this.view.state.facet(decorations),
|
|
2598
|
+
this.compositionDeco,
|
|
2599
|
+
this.computeBlockGapDeco(),
|
|
2600
|
+
this.view.viewState.lineGapDeco
|
|
2601
|
+
];
|
|
2700
2602
|
}
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
else {
|
|
2721
|
-
order.push(new BidiSpan(start, i, 0));
|
|
2603
|
+
scrollIntoView({ range, center }) {
|
|
2604
|
+
let rect = this.coordsAt(range.head, range.empty ? range.assoc : range.head > range.anchor ? -1 : 1), other;
|
|
2605
|
+
if (!rect)
|
|
2606
|
+
return;
|
|
2607
|
+
if (!range.empty && (other = this.coordsAt(range.anchor, range.anchor > range.head ? -1 : 1)))
|
|
2608
|
+
rect = { left: Math.min(rect.left, other.left), top: Math.min(rect.top, other.top),
|
|
2609
|
+
right: Math.max(rect.right, other.right), bottom: Math.max(rect.bottom, other.bottom) };
|
|
2610
|
+
let mLeft = 0, mRight = 0, mTop = 0, mBottom = 0;
|
|
2611
|
+
for (let margins of this.view.pluginField(PluginField.scrollMargins))
|
|
2612
|
+
if (margins) {
|
|
2613
|
+
let { left, right, top, bottom } = margins;
|
|
2614
|
+
if (left != null)
|
|
2615
|
+
mLeft = Math.max(mLeft, left);
|
|
2616
|
+
if (right != null)
|
|
2617
|
+
mRight = Math.max(mRight, right);
|
|
2618
|
+
if (top != null)
|
|
2619
|
+
mTop = Math.max(mTop, top);
|
|
2620
|
+
if (bottom != null)
|
|
2621
|
+
mBottom = Math.max(mBottom, bottom);
|
|
2722
2622
|
}
|
|
2723
|
-
|
|
2623
|
+
scrollRectIntoView(this.view.scrollDOM, {
|
|
2624
|
+
left: rect.left - mLeft, top: rect.top - mTop,
|
|
2625
|
+
right: rect.right + mRight, bottom: rect.bottom + mBottom
|
|
2626
|
+
}, range.head < range.anchor ? -1 : 1, center);
|
|
2627
|
+
}
|
|
2628
|
+
}
|
|
2629
|
+
function betweenUneditable(pos) {
|
|
2630
|
+
return pos.node.nodeType == 1 && pos.node.firstChild &&
|
|
2631
|
+
(pos.offset == 0 || pos.node.childNodes[pos.offset - 1].contentEditable == "false") &&
|
|
2632
|
+
(pos.offset == pos.node.childNodes.length || pos.node.childNodes[pos.offset].contentEditable == "false");
|
|
2633
|
+
}
|
|
2634
|
+
class BlockGapWidget extends WidgetType {
|
|
2635
|
+
constructor(height) {
|
|
2636
|
+
super();
|
|
2637
|
+
this.height = height;
|
|
2638
|
+
}
|
|
2639
|
+
toDOM() {
|
|
2640
|
+
let elt = document.createElement("div");
|
|
2641
|
+
this.updateDOM(elt);
|
|
2642
|
+
return elt;
|
|
2643
|
+
}
|
|
2644
|
+
eq(other) { return other.height == this.height; }
|
|
2645
|
+
updateDOM(elt) {
|
|
2646
|
+
elt.style.height = this.height + "px";
|
|
2647
|
+
return true;
|
|
2648
|
+
}
|
|
2649
|
+
get estimatedHeight() { return this.height; }
|
|
2650
|
+
}
|
|
2651
|
+
function computeCompositionDeco(view, changes) {
|
|
2652
|
+
let sel = view.observer.selectionRange;
|
|
2653
|
+
let textNode = sel.focusNode && nearbyTextNode(sel.focusNode, sel.focusOffset, 0);
|
|
2654
|
+
if (!textNode)
|
|
2655
|
+
return Decoration.none;
|
|
2656
|
+
let cView = view.docView.nearest(textNode);
|
|
2657
|
+
if (!cView)
|
|
2658
|
+
return Decoration.none;
|
|
2659
|
+
let from, to, topNode = textNode;
|
|
2660
|
+
if (cView instanceof LineView) {
|
|
2661
|
+
while (topNode.parentNode != cView.dom)
|
|
2662
|
+
topNode = topNode.parentNode;
|
|
2663
|
+
let prev = topNode.previousSibling;
|
|
2664
|
+
while (prev && !ContentView.get(prev))
|
|
2665
|
+
prev = prev.previousSibling;
|
|
2666
|
+
from = to = prev ? ContentView.get(prev).posAtEnd : cView.posAtStart;
|
|
2724
2667
|
}
|
|
2725
2668
|
else {
|
|
2726
|
-
for (
|
|
2727
|
-
let
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2669
|
+
for (;;) {
|
|
2670
|
+
let { parent } = cView;
|
|
2671
|
+
if (!parent)
|
|
2672
|
+
return Decoration.none;
|
|
2673
|
+
if (parent instanceof LineView)
|
|
2674
|
+
break;
|
|
2675
|
+
cView = parent;
|
|
2731
2676
|
}
|
|
2677
|
+
from = cView.posAtStart;
|
|
2678
|
+
to = from + cView.length;
|
|
2679
|
+
topNode = cView.dom;
|
|
2732
2680
|
}
|
|
2733
|
-
|
|
2681
|
+
let newFrom = changes.mapPos(from, 1), newTo = Math.max(newFrom, changes.mapPos(to, -1));
|
|
2682
|
+
let text = textNode.nodeValue, { state } = view;
|
|
2683
|
+
if (newTo - newFrom < text.length) {
|
|
2684
|
+
if (state.sliceDoc(newFrom, Math.min(state.doc.length, newFrom + text.length)) == text)
|
|
2685
|
+
newTo = newFrom + text.length;
|
|
2686
|
+
else if (state.sliceDoc(Math.max(0, newTo - text.length), newTo) == text)
|
|
2687
|
+
newFrom = newTo - text.length;
|
|
2688
|
+
else
|
|
2689
|
+
return Decoration.none;
|
|
2690
|
+
}
|
|
2691
|
+
else if (state.sliceDoc(newFrom, newTo) != text) {
|
|
2692
|
+
return Decoration.none;
|
|
2693
|
+
}
|
|
2694
|
+
return Decoration.set(Decoration.replace({ widget: new CompositionWidget(topNode, textNode) }).range(newFrom, newTo));
|
|
2734
2695
|
}
|
|
2735
|
-
|
|
2736
|
-
|
|
2696
|
+
class CompositionWidget extends WidgetType {
|
|
2697
|
+
constructor(top, text) {
|
|
2698
|
+
super();
|
|
2699
|
+
this.top = top;
|
|
2700
|
+
this.text = text;
|
|
2701
|
+
}
|
|
2702
|
+
eq(other) { return this.top == other.top && this.text == other.text; }
|
|
2703
|
+
toDOM() { return this.top; }
|
|
2704
|
+
ignoreEvent() { return false; }
|
|
2705
|
+
get customView() { return CompositionView; }
|
|
2737
2706
|
}
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2745
|
-
if (order[0].level != dir) {
|
|
2746
|
-
startIndex = order[0].side(false, dir);
|
|
2747
|
-
spanI = 0;
|
|
2707
|
+
function nearbyTextNode(node, offset, side) {
|
|
2708
|
+
for (;;) {
|
|
2709
|
+
if (node.nodeType == 3)
|
|
2710
|
+
return node;
|
|
2711
|
+
if (node.nodeType == 1 && offset > 0 && side <= 0) {
|
|
2712
|
+
node = node.childNodes[offset - 1];
|
|
2713
|
+
offset = maxOffset(node);
|
|
2748
2714
|
}
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2715
|
+
else if (node.nodeType == 1 && offset < node.childNodes.length && side >= 0) {
|
|
2716
|
+
node = node.childNodes[offset];
|
|
2717
|
+
offset = 0;
|
|
2718
|
+
}
|
|
2719
|
+
else {
|
|
2752
2720
|
return null;
|
|
2753
|
-
let last = order[order.length - 1];
|
|
2754
|
-
if (last.level != dir) {
|
|
2755
|
-
startIndex = last.side(true, dir);
|
|
2756
|
-
spanI = order.length - 1;
|
|
2757
2721
|
}
|
|
2758
2722
|
}
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2723
|
+
}
|
|
2724
|
+
function nextToUneditable(node, offset) {
|
|
2725
|
+
if (node.nodeType != 1)
|
|
2726
|
+
return 0;
|
|
2727
|
+
return (offset && node.childNodes[offset - 1].contentEditable == "false" ? 1 /* Before */ : 0) |
|
|
2728
|
+
(offset < node.childNodes.length && node.childNodes[offset].contentEditable == "false" ? 2 /* After */ : 0);
|
|
2729
|
+
}
|
|
2730
|
+
class DecorationComparator$1 {
|
|
2731
|
+
constructor() {
|
|
2732
|
+
this.changes = [];
|
|
2766
2733
|
}
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2734
|
+
compareRange(from, to) { addRange(from, to, this.changes); }
|
|
2735
|
+
comparePoint(from, to) { addRange(from, to, this.changes); }
|
|
2736
|
+
}
|
|
2737
|
+
function findChangedDeco(a, b, diff) {
|
|
2738
|
+
let comp = new DecorationComparator$1;
|
|
2739
|
+
rangeset.RangeSet.compare(a, b, diff, comp);
|
|
2740
|
+
return comp.changes;
|
|
2741
|
+
}
|
|
2742
|
+
function inUneditable(node, inside) {
|
|
2743
|
+
for (let cur = node; cur && cur != inside; cur = cur.assignedSlot || cur.parentNode) {
|
|
2744
|
+
if (cur.nodeType == 1 && cur.contentEditable == 'false') {
|
|
2745
|
+
return true;
|
|
2746
|
+
}
|
|
2747
|
+
}
|
|
2748
|
+
return false;
|
|
2778
2749
|
}
|
|
2779
2750
|
|
|
2780
2751
|
function groupAt(state$1, pos, bias = 1) {
|
|
@@ -2931,7 +2902,7 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
|
2931
2902
|
y = docTop + yOffset;
|
|
2932
2903
|
let lineStart = block.from;
|
|
2933
2904
|
// Clip x to the viewport sides
|
|
2934
|
-
x = Math.max(content.left + 1, Math.min(content.right - 1, x));
|
|
2905
|
+
x = Math.max(content.left + 1, Math.min(Math.max(content.right, content.left + view.docView.minWidth) - 1, x));
|
|
2935
2906
|
// If this is outside of the rendered viewport, we can't determine a position
|
|
2936
2907
|
if (lineStart < view.viewport.from)
|
|
2937
2908
|
return view.viewport.from == 0 ? 0 : posAtCoordsImprecise(view, content, block, x, y);
|
|
@@ -4174,12 +4145,12 @@ class HeightMapBranch extends HeightMap {
|
|
|
4174
4145
|
get break() { return this.flags & 1 /* Break */; }
|
|
4175
4146
|
blockAt(height, doc, top, offset) {
|
|
4176
4147
|
let mid = top + this.left.height;
|
|
4177
|
-
return height < mid
|
|
4148
|
+
return height < mid ? this.left.blockAt(height, doc, top, offset)
|
|
4178
4149
|
: this.right.blockAt(height, doc, mid, offset + this.left.length + this.break);
|
|
4179
4150
|
}
|
|
4180
4151
|
lineAt(value, type, doc, top, offset) {
|
|
4181
4152
|
let rightTop = top + this.left.height, rightOffset = offset + this.left.length + this.break;
|
|
4182
|
-
let left = type == QueryType.ByHeight ? value < rightTop
|
|
4153
|
+
let left = type == QueryType.ByHeight ? value < rightTop : value < rightOffset;
|
|
4183
4154
|
let base = left ? this.left.lineAt(value, type, doc, top, offset)
|
|
4184
4155
|
: this.right.lineAt(value, type, doc, rightTop, rightOffset);
|
|
4185
4156
|
if (this.break || (left ? base.to < rightOffset : base.from > rightOffset))
|
|
@@ -4320,7 +4291,9 @@ class NodeBuilder {
|
|
|
4320
4291
|
}
|
|
4321
4292
|
point(from, to, deco) {
|
|
4322
4293
|
if (from < to || deco.heightRelevant) {
|
|
4323
|
-
let height = deco.widget ?
|
|
4294
|
+
let height = deco.widget ? deco.widget.estimatedHeight : 0;
|
|
4295
|
+
if (height < 0)
|
|
4296
|
+
height = this.oracle.lineHeight;
|
|
4324
4297
|
let len = to - from;
|
|
4325
4298
|
if (deco.block) {
|
|
4326
4299
|
this.addBlock(new HeightMapBlock(len, height, deco.type));
|
|
@@ -5058,14 +5031,15 @@ const baseTheme = buildTheme("." + baseThemeID, {
|
|
|
5058
5031
|
},
|
|
5059
5032
|
".cm-placeholder": {
|
|
5060
5033
|
color: "#888",
|
|
5061
|
-
display: "inline-block"
|
|
5034
|
+
display: "inline-block",
|
|
5035
|
+
verticalAlign: "top",
|
|
5062
5036
|
},
|
|
5063
5037
|
".cm-button": {
|
|
5064
5038
|
verticalAlign: "middle",
|
|
5065
5039
|
color: "inherit",
|
|
5066
5040
|
fontSize: "70%",
|
|
5067
5041
|
padding: ".2em 1em",
|
|
5068
|
-
borderRadius: "
|
|
5042
|
+
borderRadius: "1px"
|
|
5069
5043
|
},
|
|
5070
5044
|
"&light .cm-button": {
|
|
5071
5045
|
backgroundImage: "linear-gradient(#eff1f5, #d9d9df)",
|
|
@@ -5387,6 +5361,7 @@ class DOMObserver {
|
|
|
5387
5361
|
for (let dom of this.scrollTargets)
|
|
5388
5362
|
dom.removeEventListener("scroll", this.onScroll);
|
|
5389
5363
|
window.removeEventListener("scroll", this.onScroll);
|
|
5364
|
+
this.dom.ownerDocument.removeEventListener("selectionchange", this.onSelectionChange);
|
|
5390
5365
|
clearTimeout(this.parentCheck);
|
|
5391
5366
|
clearTimeout(this.resizeTimeout);
|
|
5392
5367
|
}
|
|
@@ -5486,11 +5461,22 @@ function applyDOMChange(view, start, end, typeOver) {
|
|
|
5486
5461
|
};
|
|
5487
5462
|
if (change) {
|
|
5488
5463
|
let startState = view.state;
|
|
5464
|
+
if (browser.ios && view.inputState.flushIOSKey(view))
|
|
5465
|
+
return;
|
|
5489
5466
|
// Android browsers don't fire reasonable key events for enter,
|
|
5490
5467
|
// backspace, or delete. So this detects changes that look like
|
|
5491
5468
|
// they're caused by those keys, and reinterprets them as key
|
|
5492
|
-
// events.
|
|
5493
|
-
|
|
5469
|
+
// events. (Some of these keys are also handled by beforeinput
|
|
5470
|
+
// events and the pendingAndroidKey mechanism, but that's not
|
|
5471
|
+
// reliable in all situations.)
|
|
5472
|
+
if (browser.android &&
|
|
5473
|
+
((change.from == sel.from && change.to == sel.to &&
|
|
5474
|
+
change.insert.length == 1 && change.insert.lines == 2 &&
|
|
5475
|
+
dispatchKey(view.contentDOM, "Enter", 13)) ||
|
|
5476
|
+
(change.from == sel.from - 1 && change.to == sel.to && change.insert.length == 0 &&
|
|
5477
|
+
dispatchKey(view.contentDOM, "Backspace", 8)) ||
|
|
5478
|
+
(change.from == sel.from && change.to == sel.to + 1 && change.insert.length == 0 &&
|
|
5479
|
+
dispatchKey(view.contentDOM, "Delete", 46))))
|
|
5494
5480
|
return;
|
|
5495
5481
|
let text = change.insert.toString();
|
|
5496
5482
|
if (view.state.facet(inputHandler).some(h => h(view, change.from, change.to, text)))
|
|
@@ -5683,6 +5669,7 @@ class EditorView {
|
|
|
5683
5669
|
*/
|
|
5684
5670
|
config = {}) {
|
|
5685
5671
|
this.plugins = [];
|
|
5672
|
+
this.pluginMap = new Map;
|
|
5686
5673
|
this.editorAttrs = {};
|
|
5687
5674
|
this.contentAttrs = {};
|
|
5688
5675
|
this.bidiCache = [];
|
|
@@ -5714,7 +5701,9 @@ class EditorView {
|
|
|
5714
5701
|
this.dispatch = this.dispatch.bind(this);
|
|
5715
5702
|
this.root = (config.root || getRoot(config.parent) || document);
|
|
5716
5703
|
this.viewState = new ViewState(config.state || state.EditorState.create());
|
|
5717
|
-
this.plugins = this.state.facet(viewPlugin).map(spec => new PluginInstance(spec)
|
|
5704
|
+
this.plugins = this.state.facet(viewPlugin).map(spec => new PluginInstance(spec));
|
|
5705
|
+
for (let plugin of this.plugins)
|
|
5706
|
+
plugin.update(this);
|
|
5718
5707
|
this.observer = new DOMObserver(this, (from, to, typeOver) => {
|
|
5719
5708
|
applyDOMChange(this, from, to, typeOver);
|
|
5720
5709
|
}, event => {
|
|
@@ -5851,7 +5840,10 @@ class EditorView {
|
|
|
5851
5840
|
for (let plugin of this.plugins)
|
|
5852
5841
|
plugin.destroy(this);
|
|
5853
5842
|
this.viewState = new ViewState(newState);
|
|
5854
|
-
this.plugins = newState.facet(viewPlugin).map(spec => new PluginInstance(spec)
|
|
5843
|
+
this.plugins = newState.facet(viewPlugin).map(spec => new PluginInstance(spec));
|
|
5844
|
+
this.pluginMap.clear();
|
|
5845
|
+
for (let plugin of this.plugins)
|
|
5846
|
+
plugin.update(this);
|
|
5855
5847
|
this.docView = new DocView(this);
|
|
5856
5848
|
this.inputState.ensureHandlers(this);
|
|
5857
5849
|
this.mountStyles();
|
|
@@ -5882,6 +5874,7 @@ class EditorView {
|
|
|
5882
5874
|
if (plugin.mustUpdate != update)
|
|
5883
5875
|
plugin.destroy(this);
|
|
5884
5876
|
this.plugins = newPlugins;
|
|
5877
|
+
this.pluginMap.clear();
|
|
5885
5878
|
this.inputState.ensureHandlers(this);
|
|
5886
5879
|
}
|
|
5887
5880
|
else {
|
|
@@ -5889,7 +5882,7 @@ class EditorView {
|
|
|
5889
5882
|
p.mustUpdate = update;
|
|
5890
5883
|
}
|
|
5891
5884
|
for (let i = 0; i < this.plugins.length; i++)
|
|
5892
|
-
this.plugins[i]
|
|
5885
|
+
this.plugins[i].update(this);
|
|
5893
5886
|
}
|
|
5894
5887
|
/**
|
|
5895
5888
|
@internal
|
|
@@ -5978,7 +5971,7 @@ class EditorView {
|
|
|
5978
5971
|
this.state.facet(theme);
|
|
5979
5972
|
}
|
|
5980
5973
|
updateAttrs() {
|
|
5981
|
-
let editorAttrs =
|
|
5974
|
+
let editorAttrs = attrsFromFacet(this, editorAttributes, {
|
|
5982
5975
|
class: "cm-editor" + (this.hasFocus ? " cm-focused " : " ") + this.themeClasses
|
|
5983
5976
|
});
|
|
5984
5977
|
let contentAttrs = {
|
|
@@ -5994,7 +5987,7 @@ class EditorView {
|
|
|
5994
5987
|
};
|
|
5995
5988
|
if (this.state.readOnly)
|
|
5996
5989
|
contentAttrs["aria-readonly"] = "true";
|
|
5997
|
-
|
|
5990
|
+
attrsFromFacet(this, contentAttributes, contentAttrs);
|
|
5998
5991
|
this.observer.ignore(() => {
|
|
5999
5992
|
updateAttrs(this.contentDOM, this.contentAttrs, contentAttrs);
|
|
6000
5993
|
updateAttrs(this.dom, this.editorAttrs, editorAttrs);
|
|
@@ -6063,10 +6056,10 @@ class EditorView {
|
|
|
6063
6056
|
the return value of this method.
|
|
6064
6057
|
*/
|
|
6065
6058
|
plugin(plugin) {
|
|
6066
|
-
|
|
6067
|
-
|
|
6068
|
-
|
|
6069
|
-
return
|
|
6059
|
+
let known = this.pluginMap.get(plugin);
|
|
6060
|
+
if (known === undefined || known && known.spec != plugin)
|
|
6061
|
+
this.pluginMap.set(plugin, known = this.plugins.find(p => p.spec == plugin) || null);
|
|
6062
|
+
return known && known.update(this).value;
|
|
6070
6063
|
}
|
|
6071
6064
|
/**
|
|
6072
6065
|
The top position of the document, in screen coordinates. This
|
|
@@ -6553,6 +6546,14 @@ class CachedOrder {
|
|
|
6553
6546
|
return result;
|
|
6554
6547
|
}
|
|
6555
6548
|
}
|
|
6549
|
+
function attrsFromFacet(view, facet, base) {
|
|
6550
|
+
for (let sources = view.state.facet(facet), i = sources.length - 1; i >= 0; i--) {
|
|
6551
|
+
let source = sources[i], value = typeof source == "function" ? source(view) : source;
|
|
6552
|
+
if (value)
|
|
6553
|
+
combineAttrs(value, base);
|
|
6554
|
+
}
|
|
6555
|
+
return base;
|
|
6556
|
+
}
|
|
6556
6557
|
|
|
6557
6558
|
const currentPlatform = browser.mac ? "mac" : browser.windows ? "win" : browser.linux ? "linux" : "key";
|
|
6558
6559
|
function normalizeKeyName(name, platform) {
|
|
@@ -7205,35 +7206,29 @@ class TabWidget extends WidgetType {
|
|
|
7205
7206
|
}
|
|
7206
7207
|
|
|
7207
7208
|
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);
|
|
7209
|
+
constructor() {
|
|
7210
|
+
this.height = 1000;
|
|
7211
|
+
this.attrs = { style: "padding-bottom: 1000px" };
|
|
7220
7212
|
}
|
|
7221
7213
|
update(update) {
|
|
7222
|
-
|
|
7223
|
-
|
|
7214
|
+
let height = update.view.viewState.editorHeight - update.view.defaultLineHeight;
|
|
7215
|
+
if (height != this.height) {
|
|
7216
|
+
this.height = height;
|
|
7217
|
+
this.attrs = { style: `padding-bottom: ${height}px` };
|
|
7218
|
+
}
|
|
7224
7219
|
}
|
|
7225
7220
|
});
|
|
7226
7221
|
/**
|
|
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.
|
|
7222
|
+
Returns an extension that makes sure the content has a bottom
|
|
7223
|
+
margin equivalent to the height of the editor, minus one line
|
|
7224
|
+
height, so that every line in the document can be scrolled to the
|
|
7225
|
+
top of the editor.
|
|
7231
7226
|
|
|
7232
7227
|
This is only meaningful when the editor is scrollable, and should
|
|
7233
7228
|
not be enabled in editors that take the size of their content.
|
|
7234
7229
|
*/
|
|
7235
7230
|
function scrollPastEnd() {
|
|
7236
|
-
return plugin;
|
|
7231
|
+
return [plugin, contentAttributes.of(view => { var _a; return ((_a = view.plugin(plugin)) === null || _a === void 0 ? void 0 : _a.attrs) || null; })];
|
|
7237
7232
|
}
|
|
7238
7233
|
|
|
7239
7234
|
/**
|
|
@@ -7308,9 +7303,7 @@ const __test = { HeightMap, HeightOracle, MeasuredHeights, QueryType, ChangedRan
|
|
|
7308
7303
|
|
|
7309
7304
|
Object.defineProperty(exports, 'Range', {
|
|
7310
7305
|
enumerable: true,
|
|
7311
|
-
get: function () {
|
|
7312
|
-
return rangeset.Range;
|
|
7313
|
-
}
|
|
7306
|
+
get: function () { return rangeset.Range; }
|
|
7314
7307
|
});
|
|
7315
7308
|
exports.BidiSpan = BidiSpan;
|
|
7316
7309
|
exports.BlockInfo = BlockInfo;
|