@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.js
CHANGED
|
@@ -270,7 +270,7 @@ class DOMPos {
|
|
|
270
270
|
static before(dom, precise) { return new DOMPos(dom.parentNode, domIndex(dom), precise); }
|
|
271
271
|
static after(dom, precise) { return new DOMPos(dom.parentNode, domIndex(dom) + 1, precise); }
|
|
272
272
|
}
|
|
273
|
-
const
|
|
273
|
+
const noChildren = [];
|
|
274
274
|
class ContentView {
|
|
275
275
|
constructor() {
|
|
276
276
|
this.parent = null;
|
|
@@ -436,12 +436,12 @@ class ContentView {
|
|
|
436
436
|
v = parent;
|
|
437
437
|
}
|
|
438
438
|
}
|
|
439
|
-
replaceChildren(from, to, children =
|
|
439
|
+
replaceChildren(from, to, children = noChildren) {
|
|
440
440
|
this.markDirty();
|
|
441
441
|
for (let i = from; i < to; i++) {
|
|
442
442
|
let child = this.children[i];
|
|
443
443
|
if (child.parent == this)
|
|
444
|
-
child.
|
|
444
|
+
child.destroy();
|
|
445
445
|
}
|
|
446
446
|
this.children.splice(from, to - from, ...children);
|
|
447
447
|
for (let i = 0; i < children.length; i++)
|
|
@@ -463,6 +463,17 @@ class ContentView {
|
|
|
463
463
|
}
|
|
464
464
|
static get(node) { return node.cmView; }
|
|
465
465
|
get isEditable() { return true; }
|
|
466
|
+
merge(from, to, source, hasStart, openStart, openEnd) {
|
|
467
|
+
return false;
|
|
468
|
+
}
|
|
469
|
+
become(other) { return false; }
|
|
470
|
+
// When this is a zero-length view with a side, this should return a
|
|
471
|
+
// number <= 0 to indicate it is before its position, or a
|
|
472
|
+
// number > 0 when after its position.
|
|
473
|
+
getSide() { return 0; }
|
|
474
|
+
destroy() {
|
|
475
|
+
this.parent = null;
|
|
476
|
+
}
|
|
466
477
|
}
|
|
467
478
|
ContentView.prototype.breakAfter = 0;
|
|
468
479
|
// Remove a DOM node and return its next sibling.
|
|
@@ -490,6 +501,94 @@ class ChildCursor {
|
|
|
490
501
|
}
|
|
491
502
|
}
|
|
492
503
|
}
|
|
504
|
+
function replaceRange(parent, fromI, fromOff, toI, toOff, insert, breakAtStart, openStart, openEnd) {
|
|
505
|
+
let { children } = parent;
|
|
506
|
+
let before = children.length ? children[fromI] : null;
|
|
507
|
+
let last = insert.length ? insert[insert.length - 1] : null;
|
|
508
|
+
let breakAtEnd = last ? last.breakAfter : breakAtStart;
|
|
509
|
+
// Change within a single child
|
|
510
|
+
if (fromI == toI && before && !breakAtStart && !breakAtEnd && insert.length < 2 &&
|
|
511
|
+
before.merge(fromOff, toOff, insert.length ? last : null, fromOff == 0, openStart, openEnd))
|
|
512
|
+
return;
|
|
513
|
+
if (toI < children.length) {
|
|
514
|
+
let after = children[toI];
|
|
515
|
+
// Make sure the end of the child after the update is preserved in `after`
|
|
516
|
+
if (after && toOff < after.length) {
|
|
517
|
+
// If we're splitting a child, separate part of it to avoid that
|
|
518
|
+
// being mangled when updating the child before the update.
|
|
519
|
+
if (fromI == toI) {
|
|
520
|
+
after = after.split(toOff);
|
|
521
|
+
toOff = 0;
|
|
522
|
+
}
|
|
523
|
+
// If the element after the replacement should be merged with
|
|
524
|
+
// the last replacing element, update `content`
|
|
525
|
+
if (!breakAtEnd && last && after.merge(0, toOff, last, true, 0, openEnd)) {
|
|
526
|
+
insert[insert.length - 1] = after;
|
|
527
|
+
}
|
|
528
|
+
else {
|
|
529
|
+
// Remove the start of the after element, if necessary, and
|
|
530
|
+
// add it to `content`.
|
|
531
|
+
if (toOff)
|
|
532
|
+
after.merge(0, toOff, null, false, 0, openEnd);
|
|
533
|
+
insert.push(after);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
else if (after === null || after === void 0 ? void 0 : after.breakAfter) {
|
|
537
|
+
// The element at `toI` is entirely covered by this range.
|
|
538
|
+
// Preserve its line break, if any.
|
|
539
|
+
if (last)
|
|
540
|
+
last.breakAfter = 1;
|
|
541
|
+
else
|
|
542
|
+
breakAtStart = 1;
|
|
543
|
+
}
|
|
544
|
+
// Since we've handled the next element from the current elements
|
|
545
|
+
// now, make sure `toI` points after that.
|
|
546
|
+
toI++;
|
|
547
|
+
}
|
|
548
|
+
if (before) {
|
|
549
|
+
before.breakAfter = breakAtStart;
|
|
550
|
+
if (fromOff > 0) {
|
|
551
|
+
if (!breakAtStart && insert.length && before.merge(fromOff, before.length, insert[0], false, openStart, 0)) {
|
|
552
|
+
before.breakAfter = insert.shift().breakAfter;
|
|
553
|
+
}
|
|
554
|
+
else if (fromOff < before.length || before.children.length && before.children[before.children.length - 1].length == 0) {
|
|
555
|
+
before.merge(fromOff, before.length, null, false, openStart, 0);
|
|
556
|
+
}
|
|
557
|
+
fromI++;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
// Try to merge widgets on the boundaries of the replacement
|
|
561
|
+
while (fromI < toI && insert.length) {
|
|
562
|
+
if (children[toI - 1].become(insert[insert.length - 1])) {
|
|
563
|
+
toI--;
|
|
564
|
+
insert.pop();
|
|
565
|
+
openEnd = insert.length ? 0 : openStart;
|
|
566
|
+
}
|
|
567
|
+
else if (children[fromI].become(insert[0])) {
|
|
568
|
+
fromI++;
|
|
569
|
+
insert.shift();
|
|
570
|
+
openStart = insert.length ? 0 : openEnd;
|
|
571
|
+
}
|
|
572
|
+
else {
|
|
573
|
+
break;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
if (!insert.length && fromI && toI < children.length && !children[fromI - 1].breakAfter &&
|
|
577
|
+
children[toI].merge(0, 0, children[fromI - 1], false, openStart, openEnd))
|
|
578
|
+
fromI--;
|
|
579
|
+
if (fromI < toI || insert.length)
|
|
580
|
+
parent.replaceChildren(fromI, toI, insert);
|
|
581
|
+
}
|
|
582
|
+
function mergeChildrenInto(parent, from, to, insert, openStart, openEnd) {
|
|
583
|
+
let cur = parent.childCursor();
|
|
584
|
+
let { i: toI, off: toOff } = cur.findPos(to, 1);
|
|
585
|
+
let { i: fromI, off: fromOff } = cur.findPos(from, -1);
|
|
586
|
+
let dLen = from - to;
|
|
587
|
+
for (let view of insert)
|
|
588
|
+
dLen += view.length;
|
|
589
|
+
parent.length += dLen;
|
|
590
|
+
replaceRange(parent, fromI, fromOff, toI, toOff, insert, 0, openStart, openEnd);
|
|
591
|
+
}
|
|
493
592
|
|
|
494
593
|
let [nav, doc] = typeof navigator != "undefined"
|
|
495
594
|
? [navigator, document]
|
|
@@ -521,21 +620,8 @@ var browser = {
|
|
|
521
620
|
tabSize: doc.documentElement.style.tabSize != null ? "tab-size" : "-moz-tab-size"
|
|
522
621
|
};
|
|
523
622
|
|
|
524
|
-
const none$2 = [];
|
|
525
|
-
class InlineView extends ContentView {
|
|
526
|
-
/**
|
|
527
|
-
Return true when this view is equivalent to `other` and can take
|
|
528
|
-
on its role.
|
|
529
|
-
*/
|
|
530
|
-
become(_other) { return false; }
|
|
531
|
-
// When this is a zero-length view with a side, this should return a
|
|
532
|
-
// negative number to indicate it is before its position, or a
|
|
533
|
-
// positive number when after its position.
|
|
534
|
-
getSide() { return 0; }
|
|
535
|
-
}
|
|
536
|
-
InlineView.prototype.children = none$2;
|
|
537
623
|
const MaxJoinLen = 256;
|
|
538
|
-
class TextView extends
|
|
624
|
+
class TextView extends ContentView {
|
|
539
625
|
constructor(text) {
|
|
540
626
|
super();
|
|
541
627
|
this.text = text;
|
|
@@ -566,7 +652,7 @@ class TextView extends InlineView {
|
|
|
566
652
|
this.markDirty();
|
|
567
653
|
return true;
|
|
568
654
|
}
|
|
569
|
-
|
|
655
|
+
split(from) {
|
|
570
656
|
let result = new TextView(this.text.slice(from));
|
|
571
657
|
this.text = this.text.slice(0, from);
|
|
572
658
|
return result;
|
|
@@ -582,7 +668,7 @@ class TextView extends InlineView {
|
|
|
582
668
|
return textCoords(this.dom, pos, side);
|
|
583
669
|
}
|
|
584
670
|
}
|
|
585
|
-
class MarkView extends
|
|
671
|
+
class MarkView extends ContentView {
|
|
586
672
|
constructor(mark, children = [], length = 0) {
|
|
587
673
|
super();
|
|
588
674
|
this.mark = mark;
|
|
@@ -605,20 +691,20 @@ class MarkView extends InlineView {
|
|
|
605
691
|
this.createDOM();
|
|
606
692
|
super.sync(track);
|
|
607
693
|
}
|
|
608
|
-
merge(from, to, source, openStart, openEnd) {
|
|
694
|
+
merge(from, to, source, _hasStart, openStart, openEnd) {
|
|
609
695
|
if (source && (!(source instanceof MarkView && source.mark.eq(this.mark)) ||
|
|
610
696
|
(from && openStart <= 0) || (to < this.length && openEnd <= 0)))
|
|
611
697
|
return false;
|
|
612
|
-
|
|
698
|
+
mergeChildrenInto(this, from, to, source ? source.children : [], openStart - 1, openEnd - 1);
|
|
613
699
|
this.markDirty();
|
|
614
700
|
return true;
|
|
615
701
|
}
|
|
616
|
-
|
|
702
|
+
split(from) {
|
|
617
703
|
let result = [], off = 0, detachFrom = -1, i = 0;
|
|
618
704
|
for (let elt of this.children) {
|
|
619
705
|
let end = off + elt.length;
|
|
620
706
|
if (end > from)
|
|
621
|
-
result.push(off < from ? elt.
|
|
707
|
+
result.push(off < from ? elt.split(from - off) : elt);
|
|
622
708
|
if (detachFrom < 0 && off >= from)
|
|
623
709
|
detachFrom = i;
|
|
624
710
|
off = end;
|
|
@@ -626,8 +712,10 @@ class MarkView extends InlineView {
|
|
|
626
712
|
}
|
|
627
713
|
let length = this.length - from;
|
|
628
714
|
this.length = from;
|
|
629
|
-
if (detachFrom > -1)
|
|
630
|
-
this.
|
|
715
|
+
if (detachFrom > -1) {
|
|
716
|
+
this.children.length = detachFrom;
|
|
717
|
+
this.markDirty();
|
|
718
|
+
}
|
|
631
719
|
return new MarkView(this.mark, result, length);
|
|
632
720
|
}
|
|
633
721
|
domAtPos(pos) {
|
|
@@ -669,7 +757,7 @@ function textCoords(text, pos, side) {
|
|
|
669
757
|
return flatten ? flattenRect(rect, flatten < 0) : rect || null;
|
|
670
758
|
}
|
|
671
759
|
// Also used for collapsed ranges that don't have a placeholder widget!
|
|
672
|
-
class WidgetView extends
|
|
760
|
+
class WidgetView extends ContentView {
|
|
673
761
|
constructor(widget, length, side) {
|
|
674
762
|
super();
|
|
675
763
|
this.widget = widget;
|
|
@@ -679,7 +767,7 @@ class WidgetView extends InlineView {
|
|
|
679
767
|
static create(widget, length, side) {
|
|
680
768
|
return new (widget.customView || WidgetView)(widget, length, side);
|
|
681
769
|
}
|
|
682
|
-
|
|
770
|
+
split(from) {
|
|
683
771
|
let result = WidgetView.create(this.widget, this.length - from, this.side);
|
|
684
772
|
this.length -= from;
|
|
685
773
|
return result;
|
|
@@ -691,7 +779,7 @@ class WidgetView extends InlineView {
|
|
|
691
779
|
}
|
|
692
780
|
}
|
|
693
781
|
getSide() { return this.side; }
|
|
694
|
-
merge(from, to, source, openStart, openEnd) {
|
|
782
|
+
merge(from, to, source, hasStart, openStart, openEnd) {
|
|
695
783
|
if (source && (!(source instanceof WidgetView) || !this.widget.compare(source.widget) ||
|
|
696
784
|
from > 0 && openStart <= 0 || to < this.length && openEnd <= 0))
|
|
697
785
|
return false;
|
|
@@ -736,6 +824,11 @@ class WidgetView extends InlineView {
|
|
|
736
824
|
return (pos == 0 && side > 0 || pos == this.length && side <= 0) ? rect : flattenRect(rect, pos == 0);
|
|
737
825
|
}
|
|
738
826
|
get isEditable() { return false; }
|
|
827
|
+
destroy() {
|
|
828
|
+
super.destroy();
|
|
829
|
+
if (this.dom)
|
|
830
|
+
this.widget.destroy(this.dom);
|
|
831
|
+
}
|
|
739
832
|
}
|
|
740
833
|
class CompositionView extends WidgetView {
|
|
741
834
|
domAtPos(pos) { return new DOMPos(this.widget.text, pos); }
|
|
@@ -749,10 +842,13 @@ class CompositionView extends WidgetView {
|
|
|
749
842
|
coordsAt(pos, side) { return textCoords(this.widget.text, pos, side); }
|
|
750
843
|
get isEditable() { return true; }
|
|
751
844
|
}
|
|
845
|
+
// Use two characters on Android, to prevent Chrome from closing the
|
|
846
|
+
// virtual keyboard when backspacing after a widget (#602).
|
|
847
|
+
const ZeroWidthSpace = browser.android ? "\u200b\u200b" : "\u200b";
|
|
752
848
|
// These are drawn around uneditable widgets to avoid a number of
|
|
753
849
|
// browser bugs that show up when the cursor is directly next to
|
|
754
850
|
// uneditable inline content.
|
|
755
|
-
class WidgetBufferView extends
|
|
851
|
+
class WidgetBufferView extends ContentView {
|
|
756
852
|
constructor(side) {
|
|
757
853
|
super();
|
|
758
854
|
this.side = side;
|
|
@@ -762,15 +858,16 @@ class WidgetBufferView extends InlineView {
|
|
|
762
858
|
become(other) {
|
|
763
859
|
return other instanceof WidgetBufferView && other.side == this.side;
|
|
764
860
|
}
|
|
765
|
-
|
|
861
|
+
split() { return new WidgetBufferView(this.side); }
|
|
766
862
|
sync() {
|
|
767
863
|
if (!this.dom)
|
|
768
|
-
this.setDOM(document.createTextNode(
|
|
769
|
-
else if (this.dirty && this.dom.nodeValue !=
|
|
770
|
-
this.dom.nodeValue =
|
|
864
|
+
this.setDOM(document.createTextNode(ZeroWidthSpace));
|
|
865
|
+
else if (this.dirty && this.dom.nodeValue != ZeroWidthSpace)
|
|
866
|
+
this.dom.nodeValue = ZeroWidthSpace;
|
|
771
867
|
}
|
|
772
868
|
getSide() { return this.side; }
|
|
773
869
|
domAtPos(pos) { return DOMPos.before(this.dom); }
|
|
870
|
+
localPosFromDOM() { return 0; }
|
|
774
871
|
domBoundsAround() { return null; }
|
|
775
872
|
coordsAt(pos) {
|
|
776
873
|
let rects = clientRectsFor(this.dom);
|
|
@@ -780,90 +877,7 @@ class WidgetBufferView extends InlineView {
|
|
|
780
877
|
return Text.of([this.dom.nodeValue.replace(/\u200b/g, "")]);
|
|
781
878
|
}
|
|
782
879
|
}
|
|
783
|
-
|
|
784
|
-
let cur = parent.childCursor();
|
|
785
|
-
let { i: toI, off: toOff } = cur.findPos(to, 1);
|
|
786
|
-
let { i: fromI, off: fromOff } = cur.findPos(from, -1);
|
|
787
|
-
let dLen = from - to;
|
|
788
|
-
for (let view of elts)
|
|
789
|
-
dLen += view.length;
|
|
790
|
-
parent.length += dLen;
|
|
791
|
-
let { children } = parent;
|
|
792
|
-
// Both from and to point into the same child view
|
|
793
|
-
if (fromI == toI && fromOff) {
|
|
794
|
-
let start = children[fromI];
|
|
795
|
-
// Maybe just update that view and be done
|
|
796
|
-
if (elts.length == 1 && start.merge(fromOff, toOff, elts[0], openStart, openEnd))
|
|
797
|
-
return;
|
|
798
|
-
if (elts.length == 0) {
|
|
799
|
-
start.merge(fromOff, toOff, null, openStart, openEnd);
|
|
800
|
-
return;
|
|
801
|
-
}
|
|
802
|
-
// Otherwise split it, so that we don't have to worry about aliasing front/end afterwards
|
|
803
|
-
let after = start.slice(toOff);
|
|
804
|
-
if (after.merge(0, 0, elts[elts.length - 1], 0, openEnd))
|
|
805
|
-
elts[elts.length - 1] = after;
|
|
806
|
-
else
|
|
807
|
-
elts.push(after);
|
|
808
|
-
toI++;
|
|
809
|
-
openEnd = toOff = 0;
|
|
810
|
-
}
|
|
811
|
-
// Make sure start and end positions fall on node boundaries
|
|
812
|
-
// (fromOff/toOff are no longer used after this), and that if the
|
|
813
|
-
// start or end of the elts can be merged with adjacent nodes,
|
|
814
|
-
// this is done
|
|
815
|
-
if (toOff) {
|
|
816
|
-
let end = children[toI];
|
|
817
|
-
if (elts.length && end.merge(0, toOff, elts[elts.length - 1], 0, openEnd)) {
|
|
818
|
-
elts.pop();
|
|
819
|
-
openEnd = elts.length ? 0 : openStart;
|
|
820
|
-
}
|
|
821
|
-
else {
|
|
822
|
-
end.merge(0, toOff, null, 0, 0);
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
else if (toI < children.length && elts.length &&
|
|
826
|
-
children[toI].merge(0, 0, elts[elts.length - 1], 0, openEnd)) {
|
|
827
|
-
elts.pop();
|
|
828
|
-
openEnd = elts.length ? 0 : openStart;
|
|
829
|
-
}
|
|
830
|
-
if (fromOff) {
|
|
831
|
-
let start = children[fromI];
|
|
832
|
-
if (elts.length && start.merge(fromOff, start.length, elts[0], openStart, 0)) {
|
|
833
|
-
elts.shift();
|
|
834
|
-
openStart = elts.length ? 0 : openEnd;
|
|
835
|
-
}
|
|
836
|
-
else {
|
|
837
|
-
start.merge(fromOff, start.length, null, 0, 0);
|
|
838
|
-
}
|
|
839
|
-
fromI++;
|
|
840
|
-
}
|
|
841
|
-
else if (fromI && elts.length) {
|
|
842
|
-
let end = children[fromI - 1];
|
|
843
|
-
if (end.merge(end.length, end.length, elts[0], openStart, 0)) {
|
|
844
|
-
elts.shift();
|
|
845
|
-
openStart = elts.length ? 0 : openEnd;
|
|
846
|
-
}
|
|
847
|
-
}
|
|
848
|
-
// Then try to merge any mergeable nodes at the start and end of
|
|
849
|
-
// the changed range
|
|
850
|
-
while (fromI < toI && elts.length && children[toI - 1].become(elts[elts.length - 1])) {
|
|
851
|
-
elts.pop();
|
|
852
|
-
toI--;
|
|
853
|
-
openEnd = elts.length ? 0 : openStart;
|
|
854
|
-
}
|
|
855
|
-
while (fromI < toI && elts.length && children[fromI].become(elts[0])) {
|
|
856
|
-
elts.shift();
|
|
857
|
-
fromI++;
|
|
858
|
-
openStart = elts.length ? 0 : openEnd;
|
|
859
|
-
}
|
|
860
|
-
if (!elts.length && fromI && toI < children.length &&
|
|
861
|
-
children[toI].merge(0, 0, children[fromI - 1], openStart, openEnd))
|
|
862
|
-
fromI--;
|
|
863
|
-
// And if anything remains, splice the child array to insert the new elts
|
|
864
|
-
if (elts.length || fromI != toI)
|
|
865
|
-
parent.replaceChildren(fromI, toI, elts);
|
|
866
|
-
}
|
|
880
|
+
TextView.prototype.children = WidgetView.prototype.children = WidgetBufferView.prototype.children = noChildren;
|
|
867
881
|
function inlineDOMAtPos(dom, children, pos) {
|
|
868
882
|
let i = 0;
|
|
869
883
|
for (let off = 0; i < children.length; i++) {
|
|
@@ -1004,6 +1018,11 @@ class WidgetType {
|
|
|
1004
1018
|
@internal
|
|
1005
1019
|
*/
|
|
1006
1020
|
get customView() { return null; }
|
|
1021
|
+
/**
|
|
1022
|
+
This is called when the an instance of the widget is removed
|
|
1023
|
+
from the editor view.
|
|
1024
|
+
*/
|
|
1025
|
+
destroy(_dom) { }
|
|
1007
1026
|
}
|
|
1008
1027
|
/**
|
|
1009
1028
|
The different types of blocks that can occur in an editor view.
|
|
@@ -1082,8 +1101,9 @@ class Decoration extends RangeValue {
|
|
|
1082
1101
|
position.
|
|
1083
1102
|
*/
|
|
1084
1103
|
static widget(spec) {
|
|
1085
|
-
let side = spec.side || 0;
|
|
1086
|
-
|
|
1104
|
+
let side = spec.side || 0, block = !!spec.block;
|
|
1105
|
+
side += block ? (side > 0 ? 300000000 /* BlockAfter */ : -400000000 /* BlockBefore */) : (side > 0 ? 100000000 /* InlineAfter */ : -100000000 /* InlineBefore */);
|
|
1106
|
+
return new PointDecoration(spec, side, side, block, spec.widget || null, false);
|
|
1087
1107
|
}
|
|
1088
1108
|
/**
|
|
1089
1109
|
Create a replace decoration which replaces the given range with
|
|
@@ -1092,8 +1112,8 @@ class Decoration extends RangeValue {
|
|
|
1092
1112
|
static replace(spec) {
|
|
1093
1113
|
let block = !!spec.block;
|
|
1094
1114
|
let { start, end } = getInclusive(spec, block);
|
|
1095
|
-
let startSide =
|
|
1096
|
-
let endSide =
|
|
1115
|
+
let startSide = block ? (start ? -300000000 /* BlockIncStart */ : -1 /* InlineIncStart */) : 400000000 /* NonIncStart */;
|
|
1116
|
+
let endSide = block ? (end ? 200000000 /* BlockIncEnd */ : 1 /* InlineIncEnd */) : -500000000 /* NonIncEnd */;
|
|
1097
1117
|
return new PointDecoration(spec, startSide, endSide, block, spec.widget || null, true);
|
|
1098
1118
|
}
|
|
1099
1119
|
/**
|
|
@@ -1123,7 +1143,7 @@ Decoration.none = RangeSet.empty;
|
|
|
1123
1143
|
class MarkDecoration extends Decoration {
|
|
1124
1144
|
constructor(spec) {
|
|
1125
1145
|
let { start, end } = getInclusive(spec);
|
|
1126
|
-
super(
|
|
1146
|
+
super(start ? -1 /* InlineIncStart */ : 400000000 /* NonIncStart */, end ? 1 /* InlineIncEnd */ : -500000000 /* NonIncEnd */, null, spec);
|
|
1127
1147
|
this.tagName = spec.tagName || "span";
|
|
1128
1148
|
this.class = spec.class || "";
|
|
1129
1149
|
this.attrs = spec.attributes || null;
|
|
@@ -1144,7 +1164,7 @@ class MarkDecoration extends Decoration {
|
|
|
1144
1164
|
MarkDecoration.prototype.point = false;
|
|
1145
1165
|
class LineDecoration extends Decoration {
|
|
1146
1166
|
constructor(spec) {
|
|
1147
|
-
super(-
|
|
1167
|
+
super(-200000000 /* Line */, -200000000 /* Line */, null, spec);
|
|
1148
1168
|
}
|
|
1149
1169
|
eq(other) {
|
|
1150
1170
|
return other instanceof LineDecoration && attrsEq(this.spec.attributes, other.spec.attributes);
|
|
@@ -1162,12 +1182,12 @@ class PointDecoration extends Decoration {
|
|
|
1162
1182
|
super(startSide, endSide, widget, spec);
|
|
1163
1183
|
this.block = block;
|
|
1164
1184
|
this.isReplace = isReplace;
|
|
1165
|
-
this.mapMode = !block ? MapMode.TrackDel : startSide
|
|
1185
|
+
this.mapMode = !block ? MapMode.TrackDel : startSide <= 0 ? MapMode.TrackBefore : MapMode.TrackAfter;
|
|
1166
1186
|
}
|
|
1167
1187
|
// Only relevant when this.block == true
|
|
1168
1188
|
get type() {
|
|
1169
1189
|
return this.startSide < this.endSide ? BlockType.WidgetRange
|
|
1170
|
-
: this.startSide
|
|
1190
|
+
: this.startSide <= 0 ? BlockType.WidgetBefore : BlockType.WidgetAfter;
|
|
1171
1191
|
}
|
|
1172
1192
|
get heightRelevant() { return this.block || !!this.widget && this.widget.estimatedHeight >= 5; }
|
|
1173
1193
|
eq(other) {
|
|
@@ -1177,7 +1197,7 @@ class PointDecoration extends Decoration {
|
|
|
1177
1197
|
this.startSide == other.startSide && this.endSide == other.endSide;
|
|
1178
1198
|
}
|
|
1179
1199
|
range(from, to = from) {
|
|
1180
|
-
if (this.isReplace && (from > to || (from == to && this.startSide > 0 && this.endSide
|
|
1200
|
+
if (this.isReplace && (from > to || (from == to && this.startSide > 0 && this.endSide <= 0)))
|
|
1181
1201
|
throw new RangeError("Invalid range for replacement decoration");
|
|
1182
1202
|
if (!this.isReplace && to != from)
|
|
1183
1203
|
throw new RangeError("Widget decorations can only have zero-length ranges");
|
|
@@ -1214,16 +1234,16 @@ class LineView extends ContentView {
|
|
|
1214
1234
|
this.breakAfter = 0;
|
|
1215
1235
|
}
|
|
1216
1236
|
// Consumes source
|
|
1217
|
-
merge(from, to, source,
|
|
1237
|
+
merge(from, to, source, hasStart, openStart, openEnd) {
|
|
1218
1238
|
if (source) {
|
|
1219
1239
|
if (!(source instanceof LineView))
|
|
1220
1240
|
return false;
|
|
1221
1241
|
if (!this.dom)
|
|
1222
1242
|
source.transferDOM(this); // Reuse source.dom when appropriate
|
|
1223
1243
|
}
|
|
1224
|
-
if (
|
|
1244
|
+
if (hasStart)
|
|
1225
1245
|
this.setDeco(source ? source.attrs : null);
|
|
1226
|
-
|
|
1246
|
+
mergeChildrenInto(this, from, to, source ? source.children : [], openStart, openEnd);
|
|
1227
1247
|
return true;
|
|
1228
1248
|
}
|
|
1229
1249
|
split(at) {
|
|
@@ -1233,16 +1253,14 @@ class LineView extends ContentView {
|
|
|
1233
1253
|
return end;
|
|
1234
1254
|
let { i, off } = this.childPos(at);
|
|
1235
1255
|
if (off) {
|
|
1236
|
-
end.append(this.children[i].
|
|
1237
|
-
this.children[i].merge(off, this.children[i].length, null, 0, 0);
|
|
1256
|
+
end.append(this.children[i].split(off), 0);
|
|
1257
|
+
this.children[i].merge(off, this.children[i].length, null, false, 0, 0);
|
|
1238
1258
|
i++;
|
|
1239
1259
|
}
|
|
1240
1260
|
for (let j = i; j < this.children.length; j++)
|
|
1241
1261
|
end.append(this.children[j], 0);
|
|
1242
|
-
while (i > 0 && this.children[i - 1].length == 0)
|
|
1243
|
-
this.children[i
|
|
1244
|
-
i--;
|
|
1245
|
-
}
|
|
1262
|
+
while (i > 0 && this.children[i - 1].length == 0)
|
|
1263
|
+
this.children[--i].destroy();
|
|
1246
1264
|
this.children.length = i;
|
|
1247
1265
|
this.markDirty();
|
|
1248
1266
|
this.length = at;
|
|
@@ -1265,7 +1283,6 @@ class LineView extends ContentView {
|
|
|
1265
1283
|
this.attrs = attrs;
|
|
1266
1284
|
}
|
|
1267
1285
|
}
|
|
1268
|
-
// Only called when building a line view in ContentBuilder
|
|
1269
1286
|
append(child, openStart) {
|
|
1270
1287
|
joinInlineInto(this, child, openStart);
|
|
1271
1288
|
}
|
|
@@ -1322,7 +1339,7 @@ class LineView extends ContentView {
|
|
|
1322
1339
|
coordsAt(pos, side) {
|
|
1323
1340
|
return coordsInChildren(this, pos, side);
|
|
1324
1341
|
}
|
|
1325
|
-
|
|
1342
|
+
become(_other) { return false; }
|
|
1326
1343
|
get type() { return BlockType.Text; }
|
|
1327
1344
|
static find(docView, pos) {
|
|
1328
1345
|
for (let i = 0, off = 0;; i++) {
|
|
@@ -1337,7 +1354,6 @@ class LineView extends ContentView {
|
|
|
1337
1354
|
}
|
|
1338
1355
|
}
|
|
1339
1356
|
}
|
|
1340
|
-
const none$1 = [];
|
|
1341
1357
|
class BlockWidgetView extends ContentView {
|
|
1342
1358
|
constructor(widget, length, type) {
|
|
1343
1359
|
super();
|
|
@@ -1363,7 +1379,7 @@ class BlockWidgetView extends ContentView {
|
|
|
1363
1379
|
end.breakAfter = this.breakAfter;
|
|
1364
1380
|
return end;
|
|
1365
1381
|
}
|
|
1366
|
-
get children() { return
|
|
1382
|
+
get children() { return noChildren; }
|
|
1367
1383
|
sync() {
|
|
1368
1384
|
if (!this.dom || !this.widget.updateDOM(this.dom)) {
|
|
1369
1385
|
this.setDOM(this.widget.toDOM(this.editorView));
|
|
@@ -1374,7 +1390,7 @@ class BlockWidgetView extends ContentView {
|
|
|
1374
1390
|
return this.parent ? this.parent.view.state.doc.slice(this.posAtStart, this.posAtEnd) : Text$1.empty;
|
|
1375
1391
|
}
|
|
1376
1392
|
domBoundsAround() { return null; }
|
|
1377
|
-
|
|
1393
|
+
become(other) {
|
|
1378
1394
|
if (other instanceof BlockWidgetView && other.type == this.type &&
|
|
1379
1395
|
other.widget.constructor == this.widget.constructor) {
|
|
1380
1396
|
if (!other.widget.eq(this.widget))
|
|
@@ -1388,6 +1404,11 @@ class BlockWidgetView extends ContentView {
|
|
|
1388
1404
|
}
|
|
1389
1405
|
ignoreMutation() { return true; }
|
|
1390
1406
|
ignoreEvent(event) { return this.widget.ignoreEvent(event); }
|
|
1407
|
+
destroy() {
|
|
1408
|
+
super.destroy();
|
|
1409
|
+
if (this.dom)
|
|
1410
|
+
this.widget.destroy(this.dom);
|
|
1411
|
+
}
|
|
1391
1412
|
}
|
|
1392
1413
|
|
|
1393
1414
|
class ContentBuilder {
|
|
@@ -1723,36 +1744,39 @@ class PluginInstance {
|
|
|
1723
1744
|
this.value = null;
|
|
1724
1745
|
}
|
|
1725
1746
|
takeField(type, target) {
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1747
|
+
if (this.spec)
|
|
1748
|
+
for (let { field, get } of this.spec.fields)
|
|
1749
|
+
if (field == type)
|
|
1750
|
+
target.push(get(this.value));
|
|
1729
1751
|
}
|
|
1730
1752
|
update(view) {
|
|
1731
1753
|
if (!this.value) {
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1754
|
+
if (this.spec) {
|
|
1755
|
+
try {
|
|
1756
|
+
this.value = this.spec.create(view);
|
|
1757
|
+
}
|
|
1758
|
+
catch (e) {
|
|
1759
|
+
logException(view.state, e, "CodeMirror plugin crashed");
|
|
1760
|
+
this.deactivate();
|
|
1761
|
+
}
|
|
1738
1762
|
}
|
|
1739
1763
|
}
|
|
1740
1764
|
else if (this.mustUpdate) {
|
|
1741
1765
|
let update = this.mustUpdate;
|
|
1742
1766
|
this.mustUpdate = null;
|
|
1743
|
-
if (
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1767
|
+
if (this.value.update) {
|
|
1768
|
+
try {
|
|
1769
|
+
this.value.update(update);
|
|
1770
|
+
}
|
|
1771
|
+
catch (e) {
|
|
1772
|
+
logException(update.state, e, "CodeMirror plugin crashed");
|
|
1773
|
+
if (this.value.destroy)
|
|
1774
|
+
try {
|
|
1775
|
+
this.value.destroy();
|
|
1776
|
+
}
|
|
1777
|
+
catch (_) { }
|
|
1778
|
+
this.deactivate();
|
|
1779
|
+
}
|
|
1756
1780
|
}
|
|
1757
1781
|
}
|
|
1758
1782
|
return this;
|
|
@@ -1768,20 +1792,12 @@ class PluginInstance {
|
|
|
1768
1792
|
}
|
|
1769
1793
|
}
|
|
1770
1794
|
}
|
|
1795
|
+
deactivate() {
|
|
1796
|
+
this.spec = this.value = null;
|
|
1797
|
+
}
|
|
1771
1798
|
}
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
let result = {};
|
|
1775
|
-
for (let i = values.length - 1; i >= 0; i--)
|
|
1776
|
-
combineAttrs(values[i], result);
|
|
1777
|
-
return result;
|
|
1778
|
-
}
|
|
1779
|
-
const editorAttributes = /*@__PURE__*/Facet.define({
|
|
1780
|
-
combine: combineFacetAttrs
|
|
1781
|
-
});
|
|
1782
|
-
const contentAttributes = /*@__PURE__*/Facet.define({
|
|
1783
|
-
combine: combineFacetAttrs
|
|
1784
|
-
});
|
|
1799
|
+
const editorAttributes = /*@__PURE__*/Facet.define();
|
|
1800
|
+
const contentAttributes = /*@__PURE__*/Facet.define();
|
|
1785
1801
|
// Provide decorations
|
|
1786
1802
|
const decorations = /*@__PURE__*/Facet.define();
|
|
1787
1803
|
const styleModule = /*@__PURE__*/Facet.define();
|
|
@@ -1922,197 +1938,446 @@ class ViewUpdate {
|
|
|
1922
1938
|
get empty() { return this.flags == 0 && this.transactions.length == 0; }
|
|
1923
1939
|
}
|
|
1924
1940
|
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1941
|
+
/**
|
|
1942
|
+
Used to indicate [text direction](https://codemirror.net/6/docs/ref/#view.EditorView.textDirection).
|
|
1943
|
+
*/
|
|
1944
|
+
var Direction = /*@__PURE__*/(function (Direction) {
|
|
1945
|
+
// (These are chosen to match the base levels, in bidi algorithm
|
|
1946
|
+
// terms, of spans in that direction.)
|
|
1947
|
+
/**
|
|
1948
|
+
Left-to-right.
|
|
1949
|
+
*/
|
|
1950
|
+
Direction[Direction["LTR"] = 0] = "LTR";
|
|
1951
|
+
/**
|
|
1952
|
+
Right-to-left.
|
|
1953
|
+
*/
|
|
1954
|
+
Direction[Direction["RTL"] = 1] = "RTL";
|
|
1955
|
+
return Direction})(Direction || (Direction = {}));
|
|
1956
|
+
const LTR = Direction.LTR, RTL = Direction.RTL;
|
|
1957
|
+
// Decode a string with each type encoded as log2(type)
|
|
1958
|
+
function dec(str) {
|
|
1959
|
+
let result = [];
|
|
1960
|
+
for (let i = 0; i < str.length; i++)
|
|
1961
|
+
result.push(1 << +str[i]);
|
|
1962
|
+
return result;
|
|
1963
|
+
}
|
|
1964
|
+
// Character types for codepoints 0 to 0xf8
|
|
1965
|
+
const LowTypes = /*@__PURE__*/dec("88888888888888888888888888888888888666888888787833333333337888888000000000000000000000000008888880000000000000000000000000088888888888888888888888888888888888887866668888088888663380888308888800000000000000000000000800000000000000000000000000000008");
|
|
1966
|
+
// Character types for codepoints 0x600 to 0x6f9
|
|
1967
|
+
const ArabicTypes = /*@__PURE__*/dec("4444448826627288999999999992222222222222222222222222222222222222222222222229999999999999999999994444444444644222822222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222999999949999999229989999223333333333");
|
|
1968
|
+
const Brackets = /*@__PURE__*/Object.create(null), BracketStack = [];
|
|
1969
|
+
// There's a lot more in
|
|
1970
|
+
// https://www.unicode.org/Public/UCD/latest/ucd/BidiBrackets.txt,
|
|
1971
|
+
// which are left out to keep code size down.
|
|
1972
|
+
for (let p of ["()", "[]", "{}"]) {
|
|
1973
|
+
let l = /*@__PURE__*/p.charCodeAt(0), r = /*@__PURE__*/p.charCodeAt(1);
|
|
1974
|
+
Brackets[l] = r;
|
|
1975
|
+
Brackets[r] = -l;
|
|
1976
|
+
}
|
|
1977
|
+
function charType(ch) {
|
|
1978
|
+
return ch <= 0xf7 ? LowTypes[ch] :
|
|
1979
|
+
0x590 <= ch && ch <= 0x5f4 ? 2 /* R */ :
|
|
1980
|
+
0x600 <= ch && ch <= 0x6f9 ? ArabicTypes[ch - 0x600] :
|
|
1981
|
+
0x6ee <= ch && ch <= 0x8ac ? 4 /* AL */ :
|
|
1982
|
+
0x2000 <= ch && ch <= 0x200b ? 256 /* NI */ :
|
|
1983
|
+
ch == 0x200c ? 256 /* NI */ : 1 /* L */;
|
|
1984
|
+
}
|
|
1985
|
+
const BidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
|
|
1986
|
+
/**
|
|
1987
|
+
Represents a contiguous range of text that has a single direction
|
|
1988
|
+
(as in left-to-right or right-to-left).
|
|
1989
|
+
*/
|
|
1990
|
+
class BidiSpan {
|
|
1991
|
+
/**
|
|
1992
|
+
@internal
|
|
1993
|
+
*/
|
|
1994
|
+
constructor(
|
|
1995
|
+
/**
|
|
1996
|
+
The start of the span (relative to the start of the line).
|
|
1997
|
+
*/
|
|
1998
|
+
from,
|
|
1999
|
+
/**
|
|
2000
|
+
The end of the span.
|
|
2001
|
+
*/
|
|
2002
|
+
to,
|
|
2003
|
+
/**
|
|
2004
|
+
The ["bidi
|
|
2005
|
+
level"](https://unicode.org/reports/tr9/#Basic_Display_Algorithm)
|
|
2006
|
+
of the span (in this context, 0 means
|
|
2007
|
+
left-to-right, 1 means right-to-left, 2 means left-to-right
|
|
2008
|
+
number inside right-to-left text).
|
|
2009
|
+
*/
|
|
2010
|
+
level) {
|
|
2011
|
+
this.from = from;
|
|
2012
|
+
this.to = to;
|
|
2013
|
+
this.level = level;
|
|
1953
2014
|
}
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
// getSelection than the one that it actually shows to the user.
|
|
1979
|
-
// This forces a selection update when lines are joined to work
|
|
1980
|
-
// around that. Issue #54
|
|
1981
|
-
if ((browser.ie || browser.chrome) && !this.compositionDeco.size && update &&
|
|
1982
|
-
update.state.doc.lines != update.startState.doc.lines)
|
|
1983
|
-
this.forceSelection = true;
|
|
1984
|
-
let prevDeco = this.decorations, deco = this.updateDeco();
|
|
1985
|
-
let decoDiff = findChangedDeco(prevDeco, deco, update.changes);
|
|
1986
|
-
changedRanges = ChangedRange.extendWithRanges(changedRanges, decoDiff);
|
|
1987
|
-
if (this.dirty == 0 /* Not */ && changedRanges.length == 0) {
|
|
1988
|
-
return false;
|
|
1989
|
-
}
|
|
1990
|
-
else {
|
|
1991
|
-
this.updateInner(changedRanges, deco, update.startState.doc.length);
|
|
1992
|
-
if (update.transactions.length)
|
|
1993
|
-
this.lastUpdate = Date.now();
|
|
1994
|
-
return true;
|
|
2015
|
+
/**
|
|
2016
|
+
The direction of this span.
|
|
2017
|
+
*/
|
|
2018
|
+
get dir() { return this.level % 2 ? RTL : LTR; }
|
|
2019
|
+
/**
|
|
2020
|
+
@internal
|
|
2021
|
+
*/
|
|
2022
|
+
side(end, dir) { return (this.dir == dir) == end ? this.to : this.from; }
|
|
2023
|
+
/**
|
|
2024
|
+
@internal
|
|
2025
|
+
*/
|
|
2026
|
+
static find(order, index, level, assoc) {
|
|
2027
|
+
let maybe = -1;
|
|
2028
|
+
for (let i = 0; i < order.length; i++) {
|
|
2029
|
+
let span = order[i];
|
|
2030
|
+
if (span.from <= index && span.to >= index) {
|
|
2031
|
+
if (span.level == level)
|
|
2032
|
+
return i;
|
|
2033
|
+
// When multiple spans match, if assoc != 0, take the one that
|
|
2034
|
+
// covers that side, otherwise take the one with the minimum
|
|
2035
|
+
// level.
|
|
2036
|
+
if (maybe < 0 || (assoc != 0 ? (assoc < 0 ? span.from < index : span.to > index) : order[maybe].level > span.level))
|
|
2037
|
+
maybe = i;
|
|
2038
|
+
}
|
|
1995
2039
|
}
|
|
2040
|
+
if (maybe < 0)
|
|
2041
|
+
throw new RangeError("Index out of range");
|
|
2042
|
+
return maybe;
|
|
1996
2043
|
}
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2044
|
+
}
|
|
2045
|
+
// Reused array of character types
|
|
2046
|
+
const types = [];
|
|
2047
|
+
function computeOrder(line, direction) {
|
|
2048
|
+
let len = line.length, outerType = direction == LTR ? 1 /* L */ : 2 /* R */, oppositeType = direction == LTR ? 2 /* R */ : 1 /* L */;
|
|
2049
|
+
if (!line || outerType == 1 /* L */ && !BidiRE.test(line))
|
|
2050
|
+
return trivialOrder(len);
|
|
2051
|
+
// W1. Examine each non-spacing mark (NSM) in the level run, and
|
|
2052
|
+
// change the type of the NSM to the type of the previous
|
|
2053
|
+
// character. If the NSM is at the start of the level run, it will
|
|
2054
|
+
// get the type of sor.
|
|
2055
|
+
// W2. Search backwards from each instance of a European number
|
|
2056
|
+
// until the first strong type (R, L, AL, or sor) is found. If an
|
|
2057
|
+
// AL is found, change the type of the European number to Arabic
|
|
2058
|
+
// number.
|
|
2059
|
+
// W3. Change all ALs to R.
|
|
2060
|
+
// (Left after this: L, R, EN, AN, ET, CS, NI)
|
|
2061
|
+
for (let i = 0, prev = outerType, prevStrong = outerType; i < len; i++) {
|
|
2062
|
+
let type = charType(line.charCodeAt(i));
|
|
2063
|
+
if (type == 512 /* NSM */)
|
|
2064
|
+
type = prev;
|
|
2065
|
+
else if (type == 8 /* EN */ && prevStrong == 4 /* AL */)
|
|
2066
|
+
type = 16 /* AN */;
|
|
2067
|
+
types[i] = type == 4 /* AL */ ? 2 /* R */ : type;
|
|
2068
|
+
if (type & 7 /* Strong */)
|
|
2069
|
+
prevStrong = type;
|
|
2070
|
+
prev = type;
|
|
2071
|
+
}
|
|
2072
|
+
// W5. A sequence of European terminators adjacent to European
|
|
2073
|
+
// numbers changes to all European numbers.
|
|
2074
|
+
// W6. Otherwise, separators and terminators change to Other
|
|
2075
|
+
// Neutral.
|
|
2076
|
+
// W7. Search backwards from each instance of a European number
|
|
2077
|
+
// until the first strong type (R, L, or sor) is found. If an L is
|
|
2078
|
+
// found, then change the type of the European number to L.
|
|
2079
|
+
// (Left after this: L, R, EN+AN, NI)
|
|
2080
|
+
for (let i = 0, prev = outerType, prevStrong = outerType; i < len; i++) {
|
|
2081
|
+
let type = types[i];
|
|
2082
|
+
if (type == 128 /* CS */) {
|
|
2083
|
+
if (i < len - 1 && prev == types[i + 1] && (prev & 24 /* Num */))
|
|
2084
|
+
type = types[i] = prev;
|
|
2085
|
+
else
|
|
2086
|
+
types[i] = 256 /* NI */;
|
|
2002
2087
|
}
|
|
2003
|
-
else {
|
|
2004
|
-
|
|
2088
|
+
else if (type == 64 /* ET */) {
|
|
2089
|
+
let end = i + 1;
|
|
2090
|
+
while (end < len && types[end] == 64 /* ET */)
|
|
2091
|
+
end++;
|
|
2092
|
+
let replace = (i && prev == 8 /* EN */) || (end < len && types[end] == 8 /* EN */) ? (prevStrong == 1 /* L */ ? 1 /* L */ : 8 /* EN */) : 256 /* NI */;
|
|
2093
|
+
for (let j = i; j < end; j++)
|
|
2094
|
+
types[j] = replace;
|
|
2095
|
+
i = end - 1;
|
|
2005
2096
|
}
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
// update
|
|
2009
|
-
updateInner(changes, deco, oldLength) {
|
|
2010
|
-
this.view.viewState.mustMeasureContent = true;
|
|
2011
|
-
this.updateChildren(changes, deco, oldLength);
|
|
2012
|
-
let { observer } = this.view;
|
|
2013
|
-
observer.ignore(() => {
|
|
2014
|
-
// Lock the height during redrawing, since Chrome sometimes
|
|
2015
|
-
// messes with the scroll position during DOM mutation (though
|
|
2016
|
-
// no relayout is triggered and I cannot imagine how it can
|
|
2017
|
-
// recompute the scroll position without a layout)
|
|
2018
|
-
this.dom.style.height = this.view.viewState.contentHeight + "px";
|
|
2019
|
-
this.dom.style.minWidth = this.minWidth ? this.minWidth + "px" : "";
|
|
2020
|
-
// Chrome will sometimes, when DOM mutations occur directly
|
|
2021
|
-
// around the selection, get confused and report a different
|
|
2022
|
-
// selection from the one it displays (issue #218). This tries
|
|
2023
|
-
// to detect that situation.
|
|
2024
|
-
let track = browser.chrome || browser.ios ? { node: observer.selectionRange.focusNode, written: false } : undefined;
|
|
2025
|
-
this.sync(track);
|
|
2026
|
-
this.dirty = 0 /* Not */;
|
|
2027
|
-
if (track && (track.written || observer.selectionRange.focusNode != track.node))
|
|
2028
|
-
this.forceSelection = true;
|
|
2029
|
-
this.dom.style.height = "";
|
|
2030
|
-
});
|
|
2031
|
-
let gaps = [];
|
|
2032
|
-
if (this.view.viewport.from || this.view.viewport.to < this.view.state.doc.length)
|
|
2033
|
-
for (let child of this.children)
|
|
2034
|
-
if (child instanceof BlockWidgetView && child.widget instanceof BlockGapWidget)
|
|
2035
|
-
gaps.push(child.dom);
|
|
2036
|
-
observer.updateGaps(gaps);
|
|
2037
|
-
}
|
|
2038
|
-
updateChildren(changes, deco, oldLength) {
|
|
2039
|
-
let cursor = this.childCursor(oldLength);
|
|
2040
|
-
for (let i = changes.length - 1;; i--) {
|
|
2041
|
-
let next = i >= 0 ? changes[i] : null;
|
|
2042
|
-
if (!next)
|
|
2043
|
-
break;
|
|
2044
|
-
let { fromA, toA, fromB, toB } = next;
|
|
2045
|
-
let { content, breakAtStart, openStart, openEnd } = ContentBuilder.build(this.view.state.doc, fromB, toB, deco);
|
|
2046
|
-
let { i: toI, off: toOff } = cursor.findPos(toA, 1);
|
|
2047
|
-
let { i: fromI, off: fromOff } = cursor.findPos(fromA, -1);
|
|
2048
|
-
this.replaceRange(fromI, fromOff, toI, toOff, content, breakAtStart, openStart, openEnd);
|
|
2097
|
+
else if (type == 8 /* EN */ && prevStrong == 1 /* L */) {
|
|
2098
|
+
types[i] = 1 /* L */;
|
|
2049
2099
|
}
|
|
2100
|
+
prev = type;
|
|
2101
|
+
if (type & 7 /* Strong */)
|
|
2102
|
+
prevStrong = type;
|
|
2050
2103
|
}
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2104
|
+
// N0. Process bracket pairs in an isolating run sequence
|
|
2105
|
+
// sequentially in the logical order of the text positions of the
|
|
2106
|
+
// opening paired brackets using the logic given below. Within this
|
|
2107
|
+
// scope, bidirectional types EN and AN are treated as R.
|
|
2108
|
+
for (let i = 0, sI = 0, context = 0, ch, br, type; i < len; i++) {
|
|
2109
|
+
// Keeps [startIndex, type, strongSeen] triples for each open
|
|
2110
|
+
// bracket on BracketStack.
|
|
2111
|
+
if (br = Brackets[ch = line.charCodeAt(i)]) {
|
|
2112
|
+
if (br < 0) { // Closing bracket
|
|
2113
|
+
for (let sJ = sI - 3; sJ >= 0; sJ -= 3) {
|
|
2114
|
+
if (BracketStack[sJ + 1] == -br) {
|
|
2115
|
+
let flags = BracketStack[sJ + 2];
|
|
2116
|
+
let type = (flags & 2 /* EmbedInside */) ? outerType :
|
|
2117
|
+
!(flags & 4 /* OppositeInside */) ? 0 :
|
|
2118
|
+
(flags & 1 /* OppositeBefore */) ? oppositeType : outerType;
|
|
2119
|
+
if (type)
|
|
2120
|
+
types[i] = types[BracketStack[sJ]] = type;
|
|
2121
|
+
sI = sJ;
|
|
2122
|
+
break;
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
2066
2125
|
}
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
if (!breakAtEnd && last && after.merge(0, toOff, last, true, 0, openEnd)) {
|
|
2070
|
-
content[content.length - 1] = after;
|
|
2126
|
+
else if (BracketStack.length == 189 /* MaxDepth */) {
|
|
2127
|
+
break;
|
|
2071
2128
|
}
|
|
2072
2129
|
else {
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
after.merge(0, toOff, null, false, 0, openEnd);
|
|
2077
|
-
content.push(after);
|
|
2130
|
+
BracketStack[sI++] = i;
|
|
2131
|
+
BracketStack[sI++] = ch;
|
|
2132
|
+
BracketStack[sI++] = context;
|
|
2078
2133
|
}
|
|
2079
2134
|
}
|
|
2080
|
-
else if (
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2135
|
+
else if ((type = types[i]) == 2 /* R */ || type == 1 /* L */) {
|
|
2136
|
+
let embed = type == outerType;
|
|
2137
|
+
context = embed ? 0 : 1 /* OppositeBefore */;
|
|
2138
|
+
for (let sJ = sI - 3; sJ >= 0; sJ -= 3) {
|
|
2139
|
+
let cur = BracketStack[sJ + 2];
|
|
2140
|
+
if (cur & 2 /* EmbedInside */)
|
|
2141
|
+
break;
|
|
2142
|
+
if (embed) {
|
|
2143
|
+
BracketStack[sJ + 2] |= 2 /* EmbedInside */;
|
|
2144
|
+
}
|
|
2145
|
+
else {
|
|
2146
|
+
if (cur & 4 /* OppositeInside */)
|
|
2147
|
+
break;
|
|
2148
|
+
BracketStack[sJ + 2] |= 4 /* OppositeInside */;
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2087
2151
|
}
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2152
|
+
}
|
|
2153
|
+
// N1. A sequence of neutrals takes the direction of the
|
|
2154
|
+
// surrounding strong text if the text on both sides has the same
|
|
2155
|
+
// direction. European and Arabic numbers act as if they were R in
|
|
2156
|
+
// terms of their influence on neutrals. Start-of-level-run (sor)
|
|
2157
|
+
// and end-of-level-run (eor) are used at level run boundaries.
|
|
2158
|
+
// N2. Any remaining neutrals take the embedding direction.
|
|
2159
|
+
// (Left after this: L, R, EN+AN)
|
|
2160
|
+
for (let i = 0; i < len; i++) {
|
|
2161
|
+
if (types[i] == 256 /* NI */) {
|
|
2162
|
+
let end = i + 1;
|
|
2163
|
+
while (end < len && types[end] == 256 /* NI */)
|
|
2164
|
+
end++;
|
|
2165
|
+
let beforeL = (i ? types[i - 1] : outerType) == 1 /* L */;
|
|
2166
|
+
let afterL = (end < len ? types[end] : outerType) == 1 /* L */;
|
|
2167
|
+
let replace = beforeL == afterL ? (beforeL ? 1 /* L */ : 2 /* R */) : outerType;
|
|
2168
|
+
for (let j = i; j < end; j++)
|
|
2169
|
+
types[j] = replace;
|
|
2170
|
+
i = end - 1;
|
|
2171
|
+
}
|
|
2172
|
+
}
|
|
2173
|
+
// Here we depart from the documented algorithm, in order to avoid
|
|
2174
|
+
// building up an actual levels array. Since there are only three
|
|
2175
|
+
// levels (0, 1, 2) in an implementation that doesn't take
|
|
2176
|
+
// explicit embedding into account, we can build up the order on
|
|
2177
|
+
// the fly, without following the level-based algorithm.
|
|
2178
|
+
let order = [];
|
|
2179
|
+
if (outerType == 1 /* L */) {
|
|
2180
|
+
for (let i = 0; i < len;) {
|
|
2181
|
+
let start = i, rtl = types[i++] != 1 /* L */;
|
|
2182
|
+
while (i < len && rtl == (types[i] != 1 /* L */))
|
|
2183
|
+
i++;
|
|
2184
|
+
if (rtl) {
|
|
2185
|
+
for (let j = i; j > start;) {
|
|
2186
|
+
let end = j, l = types[--j] != 2 /* R */;
|
|
2187
|
+
while (j > start && l == (types[j - 1] != 2 /* R */))
|
|
2188
|
+
j--;
|
|
2189
|
+
order.push(new BidiSpan(j, end, l ? 2 : 1));
|
|
2190
|
+
}
|
|
2095
2191
|
}
|
|
2096
|
-
else
|
|
2097
|
-
|
|
2192
|
+
else {
|
|
2193
|
+
order.push(new BidiSpan(start, i, 0));
|
|
2098
2194
|
}
|
|
2099
|
-
fromI++;
|
|
2100
|
-
}
|
|
2101
|
-
// Try to merge widgets on the boundaries of the replacement
|
|
2102
|
-
while (fromI < toI && content.length) {
|
|
2103
|
-
if (this.children[toI - 1].match(content[content.length - 1]))
|
|
2104
|
-
toI--, content.pop();
|
|
2105
|
-
else if (this.children[fromI].match(content[0]))
|
|
2106
|
-
fromI++, content.shift();
|
|
2107
|
-
else
|
|
2108
|
-
break;
|
|
2109
2195
|
}
|
|
2110
|
-
if (fromI < toI || content.length)
|
|
2111
|
-
this.replaceChildren(fromI, toI, content);
|
|
2112
2196
|
}
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2197
|
+
else {
|
|
2198
|
+
for (let i = 0; i < len;) {
|
|
2199
|
+
let start = i, rtl = types[i++] == 2 /* R */;
|
|
2200
|
+
while (i < len && rtl == (types[i] == 2 /* R */))
|
|
2201
|
+
i++;
|
|
2202
|
+
order.push(new BidiSpan(start, i, rtl ? 1 : 2));
|
|
2203
|
+
}
|
|
2204
|
+
}
|
|
2205
|
+
return order;
|
|
2206
|
+
}
|
|
2207
|
+
function trivialOrder(length) {
|
|
2208
|
+
return [new BidiSpan(0, length, 0)];
|
|
2209
|
+
}
|
|
2210
|
+
let movedOver = "";
|
|
2211
|
+
function moveVisually(line, order, dir, start, forward) {
|
|
2212
|
+
var _a;
|
|
2213
|
+
let startIndex = start.head - line.from, spanI = -1;
|
|
2214
|
+
if (startIndex == 0) {
|
|
2215
|
+
if (!forward || !line.length)
|
|
2216
|
+
return null;
|
|
2217
|
+
if (order[0].level != dir) {
|
|
2218
|
+
startIndex = order[0].side(false, dir);
|
|
2219
|
+
spanI = 0;
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
else if (startIndex == line.length) {
|
|
2223
|
+
if (forward)
|
|
2224
|
+
return null;
|
|
2225
|
+
let last = order[order.length - 1];
|
|
2226
|
+
if (last.level != dir) {
|
|
2227
|
+
startIndex = last.side(true, dir);
|
|
2228
|
+
spanI = order.length - 1;
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
if (spanI < 0)
|
|
2232
|
+
spanI = BidiSpan.find(order, startIndex, (_a = start.bidiLevel) !== null && _a !== void 0 ? _a : -1, start.assoc);
|
|
2233
|
+
let span = order[spanI];
|
|
2234
|
+
// End of span. (But not end of line--that was checked for above.)
|
|
2235
|
+
if (startIndex == span.side(forward, dir)) {
|
|
2236
|
+
span = order[spanI += forward ? 1 : -1];
|
|
2237
|
+
startIndex = span.side(!forward, dir);
|
|
2238
|
+
}
|
|
2239
|
+
let indexForward = forward == (span.dir == dir);
|
|
2240
|
+
let nextIndex = findClusterBreak(line.text, startIndex, indexForward);
|
|
2241
|
+
movedOver = line.text.slice(Math.min(startIndex, nextIndex), Math.max(startIndex, nextIndex));
|
|
2242
|
+
if (nextIndex != span.side(forward, dir))
|
|
2243
|
+
return EditorSelection.cursor(nextIndex + line.from, indexForward ? -1 : 1, span.level);
|
|
2244
|
+
let nextSpan = spanI == (forward ? order.length - 1 : 0) ? null : order[spanI + (forward ? 1 : -1)];
|
|
2245
|
+
if (!nextSpan && span.level != dir)
|
|
2246
|
+
return EditorSelection.cursor(forward ? line.to : line.from, forward ? -1 : 1, dir);
|
|
2247
|
+
if (nextSpan && nextSpan.level < span.level)
|
|
2248
|
+
return EditorSelection.cursor(nextSpan.side(!forward, dir) + line.from, forward ? 1 : -1, nextSpan.level);
|
|
2249
|
+
return EditorSelection.cursor(nextIndex + line.from, forward ? -1 : 1, span.level);
|
|
2250
|
+
}
|
|
2251
|
+
|
|
2252
|
+
class DocView extends ContentView {
|
|
2253
|
+
constructor(view) {
|
|
2254
|
+
super();
|
|
2255
|
+
this.view = view;
|
|
2256
|
+
this.compositionDeco = Decoration.none;
|
|
2257
|
+
this.decorations = [];
|
|
2258
|
+
// Track a minimum width for the editor. When measuring sizes in
|
|
2259
|
+
// measureVisibleLineHeights, this is updated to point at the width
|
|
2260
|
+
// of a given element and its extent in the document. When a change
|
|
2261
|
+
// happens in that range, these are reset. That way, once we've seen
|
|
2262
|
+
// a line/element of a given length, we keep the editor wide enough
|
|
2263
|
+
// to fit at least that element, until it is changed, at which point
|
|
2264
|
+
// we forget it again.
|
|
2265
|
+
this.minWidth = 0;
|
|
2266
|
+
this.minWidthFrom = 0;
|
|
2267
|
+
this.minWidthTo = 0;
|
|
2268
|
+
// Track whether the DOM selection was set in a lossy way, so that
|
|
2269
|
+
// we don't mess it up when reading it back it
|
|
2270
|
+
this.impreciseAnchor = null;
|
|
2271
|
+
this.impreciseHead = null;
|
|
2272
|
+
this.forceSelection = false;
|
|
2273
|
+
// Used by the resize observer to ignore resizes that we caused
|
|
2274
|
+
// ourselves
|
|
2275
|
+
this.lastUpdate = Date.now();
|
|
2276
|
+
this.setDOM(view.contentDOM);
|
|
2277
|
+
this.children = [new LineView];
|
|
2278
|
+
this.children[0].setParent(this);
|
|
2279
|
+
this.updateInner([new ChangedRange(0, 0, 0, view.state.doc.length)], this.updateDeco(), 0);
|
|
2280
|
+
}
|
|
2281
|
+
get root() { return this.view.root; }
|
|
2282
|
+
get editorView() { return this.view; }
|
|
2283
|
+
get length() { return this.view.state.doc.length; }
|
|
2284
|
+
// Update the document view to a given state. scrollIntoView can be
|
|
2285
|
+
// used as a hint to compute a new viewport that includes that
|
|
2286
|
+
// position, if we know the editor is going to scroll that position
|
|
2287
|
+
// into view.
|
|
2288
|
+
update(update) {
|
|
2289
|
+
let changedRanges = update.changedRanges;
|
|
2290
|
+
if (this.minWidth > 0 && changedRanges.length) {
|
|
2291
|
+
if (!changedRanges.every(({ fromA, toA }) => toA < this.minWidthFrom || fromA > this.minWidthTo)) {
|
|
2292
|
+
this.minWidth = this.minWidthFrom = this.minWidthTo = 0;
|
|
2293
|
+
}
|
|
2294
|
+
else {
|
|
2295
|
+
this.minWidthFrom = update.changes.mapPos(this.minWidthFrom, 1);
|
|
2296
|
+
this.minWidthTo = update.changes.mapPos(this.minWidthTo, 1);
|
|
2297
|
+
}
|
|
2298
|
+
}
|
|
2299
|
+
if (this.view.inputState.composing < 0)
|
|
2300
|
+
this.compositionDeco = Decoration.none;
|
|
2301
|
+
else if (update.transactions.length)
|
|
2302
|
+
this.compositionDeco = computeCompositionDeco(this.view, update.changes);
|
|
2303
|
+
// When the DOM nodes around the selection are moved to another
|
|
2304
|
+
// parent, Chrome sometimes reports a different selection through
|
|
2305
|
+
// getSelection than the one that it actually shows to the user.
|
|
2306
|
+
// This forces a selection update when lines are joined to work
|
|
2307
|
+
// around that. Issue #54
|
|
2308
|
+
if ((browser.ie || browser.chrome) && !this.compositionDeco.size && update &&
|
|
2309
|
+
update.state.doc.lines != update.startState.doc.lines)
|
|
2310
|
+
this.forceSelection = true;
|
|
2311
|
+
let prevDeco = this.decorations, deco = this.updateDeco();
|
|
2312
|
+
let decoDiff = findChangedDeco(prevDeco, deco, update.changes);
|
|
2313
|
+
changedRanges = ChangedRange.extendWithRanges(changedRanges, decoDiff);
|
|
2314
|
+
if (this.dirty == 0 /* Not */ && changedRanges.length == 0) {
|
|
2315
|
+
return false;
|
|
2316
|
+
}
|
|
2317
|
+
else {
|
|
2318
|
+
this.updateInner(changedRanges, deco, update.startState.doc.length);
|
|
2319
|
+
if (update.transactions.length)
|
|
2320
|
+
this.lastUpdate = Date.now();
|
|
2321
|
+
return true;
|
|
2322
|
+
}
|
|
2323
|
+
}
|
|
2324
|
+
reset(sel) {
|
|
2325
|
+
if (this.dirty) {
|
|
2326
|
+
this.view.observer.ignore(() => this.view.docView.sync());
|
|
2327
|
+
this.dirty = 0 /* Not */;
|
|
2328
|
+
this.updateSelection(true);
|
|
2329
|
+
}
|
|
2330
|
+
else {
|
|
2331
|
+
this.updateSelection();
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2334
|
+
// Used by update and the constructor do perform the actual DOM
|
|
2335
|
+
// update
|
|
2336
|
+
updateInner(changes, deco, oldLength) {
|
|
2337
|
+
this.view.viewState.mustMeasureContent = true;
|
|
2338
|
+
this.updateChildren(changes, deco, oldLength);
|
|
2339
|
+
let { observer } = this.view;
|
|
2340
|
+
observer.ignore(() => {
|
|
2341
|
+
// Lock the height during redrawing, since Chrome sometimes
|
|
2342
|
+
// messes with the scroll position during DOM mutation (though
|
|
2343
|
+
// no relayout is triggered and I cannot imagine how it can
|
|
2344
|
+
// recompute the scroll position without a layout)
|
|
2345
|
+
this.dom.style.height = this.view.viewState.contentHeight + "px";
|
|
2346
|
+
this.dom.style.minWidth = this.minWidth ? this.minWidth + "px" : "";
|
|
2347
|
+
// Chrome will sometimes, when DOM mutations occur directly
|
|
2348
|
+
// around the selection, get confused and report a different
|
|
2349
|
+
// selection from the one it displays (issue #218). This tries
|
|
2350
|
+
// to detect that situation.
|
|
2351
|
+
let track = browser.chrome || browser.ios ? { node: observer.selectionRange.focusNode, written: false } : undefined;
|
|
2352
|
+
this.sync(track);
|
|
2353
|
+
this.dirty = 0 /* Not */;
|
|
2354
|
+
if (track && (track.written || observer.selectionRange.focusNode != track.node))
|
|
2355
|
+
this.forceSelection = true;
|
|
2356
|
+
this.dom.style.height = "";
|
|
2357
|
+
});
|
|
2358
|
+
let gaps = [];
|
|
2359
|
+
if (this.view.viewport.from || this.view.viewport.to < this.view.state.doc.length)
|
|
2360
|
+
for (let child of this.children)
|
|
2361
|
+
if (child instanceof BlockWidgetView && child.widget instanceof BlockGapWidget)
|
|
2362
|
+
gaps.push(child.dom);
|
|
2363
|
+
observer.updateGaps(gaps);
|
|
2364
|
+
}
|
|
2365
|
+
updateChildren(changes, deco, oldLength) {
|
|
2366
|
+
let cursor = this.childCursor(oldLength);
|
|
2367
|
+
for (let i = changes.length - 1;; i--) {
|
|
2368
|
+
let next = i >= 0 ? changes[i] : null;
|
|
2369
|
+
if (!next)
|
|
2370
|
+
break;
|
|
2371
|
+
let { fromA, toA, fromB, toB } = next;
|
|
2372
|
+
let { content, breakAtStart, openStart, openEnd } = ContentBuilder.build(this.view.state.doc, fromB, toB, deco);
|
|
2373
|
+
let { i: toI, off: toOff } = cursor.findPos(toA, 1);
|
|
2374
|
+
let { i: fromI, off: fromOff } = cursor.findPos(fromA, -1);
|
|
2375
|
+
replaceRange(this, fromI, fromOff, toI, toOff, content, breakAtStart, openStart, openEnd);
|
|
2376
|
+
}
|
|
2377
|
+
}
|
|
2378
|
+
// Sync the DOM selection to this.state.selection
|
|
2379
|
+
updateSelection(mustRead = false, fromPointer = false) {
|
|
2380
|
+
if (mustRead)
|
|
2116
2381
|
this.view.observer.readSelectionRange();
|
|
2117
2382
|
if (!(fromPointer || this.mayControlSelection()) ||
|
|
2118
2383
|
browser.ios && this.view.inputState.rapidCompositionStart)
|
|
@@ -2246,18 +2511,30 @@ class DocView extends ContentView {
|
|
|
2246
2511
|
}
|
|
2247
2512
|
measureVisibleLineHeights() {
|
|
2248
2513
|
let result = [], { from, to } = this.view.viewState.viewport;
|
|
2249
|
-
let
|
|
2514
|
+
let contentWidth = this.view.contentDOM.clientWidth;
|
|
2515
|
+
let isWider = contentWidth > Math.max(this.view.scrollDOM.clientWidth, this.minWidth) + 1;
|
|
2516
|
+
let widest = -1;
|
|
2250
2517
|
for (let pos = 0, i = 0; i < this.children.length; i++) {
|
|
2251
2518
|
let child = this.children[i], end = pos + child.length;
|
|
2252
2519
|
if (end > to)
|
|
2253
2520
|
break;
|
|
2254
2521
|
if (pos >= from) {
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
if (
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2522
|
+
let childRect = child.dom.getBoundingClientRect();
|
|
2523
|
+
result.push(childRect.height);
|
|
2524
|
+
if (isWider) {
|
|
2525
|
+
let last = child.dom.lastChild;
|
|
2526
|
+
let rects = last ? clientRectsFor(last) : [];
|
|
2527
|
+
if (rects.length) {
|
|
2528
|
+
let rect = rects[rects.length - 1];
|
|
2529
|
+
let width = this.view.textDirection == Direction.LTR ? rect.right - childRect.left
|
|
2530
|
+
: childRect.right - rect.left;
|
|
2531
|
+
if (width > widest) {
|
|
2532
|
+
widest = width;
|
|
2533
|
+
this.minWidth = contentWidth;
|
|
2534
|
+
this.minWidthFrom = pos;
|
|
2535
|
+
this.minWidthTo = end;
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2261
2538
|
}
|
|
2262
2539
|
}
|
|
2263
2540
|
pos = end + child.breakAfter;
|
|
@@ -2287,489 +2564,183 @@ class DocView extends ContentView {
|
|
|
2287
2564
|
}
|
|
2288
2565
|
childCursor(pos = this.length) {
|
|
2289
2566
|
// Move back to start of last element when possible, so that
|
|
2290
|
-
// `ChildCursor.findPos` doesn't have to deal with the edge case
|
|
2291
|
-
// of being after the last element.
|
|
2292
|
-
let i = this.children.length;
|
|
2293
|
-
if (i)
|
|
2294
|
-
pos -= this.children[--i].length;
|
|
2295
|
-
return new ChildCursor(this.children, pos, i);
|
|
2296
|
-
}
|
|
2297
|
-
computeBlockGapDeco() {
|
|
2298
|
-
let deco = [], vs = this.view.viewState;
|
|
2299
|
-
for (let pos = 0, i = 0;; i++) {
|
|
2300
|
-
let next = i == vs.viewports.length ? null : vs.viewports[i];
|
|
2301
|
-
let end = next ? next.from - 1 : this.length;
|
|
2302
|
-
if (end > pos) {
|
|
2303
|
-
let height = vs.lineBlockAt(end).bottom - vs.lineBlockAt(pos).top;
|
|
2304
|
-
deco.push(Decoration.replace({ widget: new BlockGapWidget(height), block: true, inclusive: true }).range(pos, end));
|
|
2305
|
-
}
|
|
2306
|
-
if (!next)
|
|
2307
|
-
break;
|
|
2308
|
-
pos = next.to + 1;
|
|
2309
|
-
}
|
|
2310
|
-
return Decoration.set(deco);
|
|
2311
|
-
}
|
|
2312
|
-
updateDeco() {
|
|
2313
|
-
return this.decorations = [
|
|
2314
|
-
...this.view.pluginField(PluginField.decorations),
|
|
2315
|
-
...this.view.state.facet(decorations),
|
|
2316
|
-
this.compositionDeco,
|
|
2317
|
-
this.computeBlockGapDeco(),
|
|
2318
|
-
this.view.viewState.lineGapDeco
|
|
2319
|
-
];
|
|
2320
|
-
}
|
|
2321
|
-
scrollIntoView({ range, center }) {
|
|
2322
|
-
let rect = this.coordsAt(range.head, range.empty ? range.assoc : range.head > range.anchor ? -1 : 1), other;
|
|
2323
|
-
if (!rect)
|
|
2324
|
-
return;
|
|
2325
|
-
if (!range.empty && (other = this.coordsAt(range.anchor, range.anchor > range.head ? -1 : 1)))
|
|
2326
|
-
rect = { left: Math.min(rect.left, other.left), top: Math.min(rect.top, other.top),
|
|
2327
|
-
right: Math.max(rect.right, other.right), bottom: Math.max(rect.bottom, other.bottom) };
|
|
2328
|
-
let mLeft = 0, mRight = 0, mTop = 0, mBottom = 0;
|
|
2329
|
-
for (let margins of this.view.pluginField(PluginField.scrollMargins))
|
|
2330
|
-
if (margins) {
|
|
2331
|
-
let { left, right, top, bottom } = margins;
|
|
2332
|
-
if (left != null)
|
|
2333
|
-
mLeft = Math.max(mLeft, left);
|
|
2334
|
-
if (right != null)
|
|
2335
|
-
mRight = Math.max(mRight, right);
|
|
2336
|
-
if (top != null)
|
|
2337
|
-
mTop = Math.max(mTop, top);
|
|
2338
|
-
if (bottom != null)
|
|
2339
|
-
mBottom = Math.max(mBottom, bottom);
|
|
2340
|
-
}
|
|
2341
|
-
scrollRectIntoView(this.view.scrollDOM, {
|
|
2342
|
-
left: rect.left - mLeft, top: rect.top - mTop,
|
|
2343
|
-
right: rect.right + mRight, bottom: rect.bottom + mBottom
|
|
2344
|
-
}, range.head < range.anchor ? -1 : 1, center);
|
|
2345
|
-
}
|
|
2346
|
-
}
|
|
2347
|
-
function betweenUneditable(pos) {
|
|
2348
|
-
return pos.node.nodeType == 1 && pos.node.firstChild &&
|
|
2349
|
-
(pos.offset == 0 || pos.node.childNodes[pos.offset - 1].contentEditable == "false") &&
|
|
2350
|
-
(pos.offset == pos.node.childNodes.length || pos.node.childNodes[pos.offset].contentEditable == "false");
|
|
2351
|
-
}
|
|
2352
|
-
class BlockGapWidget extends WidgetType {
|
|
2353
|
-
constructor(height) {
|
|
2354
|
-
super();
|
|
2355
|
-
this.height = height;
|
|
2356
|
-
}
|
|
2357
|
-
toDOM() {
|
|
2358
|
-
let elt = document.createElement("div");
|
|
2359
|
-
this.updateDOM(elt);
|
|
2360
|
-
return elt;
|
|
2361
|
-
}
|
|
2362
|
-
eq(other) { return other.height == this.height; }
|
|
2363
|
-
updateDOM(elt) {
|
|
2364
|
-
elt.style.height = this.height + "px";
|
|
2365
|
-
return true;
|
|
2366
|
-
}
|
|
2367
|
-
get estimatedHeight() { return this.height; }
|
|
2368
|
-
}
|
|
2369
|
-
function computeCompositionDeco(view, changes) {
|
|
2370
|
-
let sel = view.observer.selectionRange;
|
|
2371
|
-
let textNode = sel.focusNode && nearbyTextNode(sel.focusNode, sel.focusOffset, 0);
|
|
2372
|
-
if (!textNode)
|
|
2373
|
-
return Decoration.none;
|
|
2374
|
-
let cView = view.docView.nearest(textNode);
|
|
2375
|
-
let from, to, topNode = textNode;
|
|
2376
|
-
if (cView instanceof InlineView) {
|
|
2377
|
-
while (cView.parent instanceof InlineView)
|
|
2378
|
-
cView = cView.parent;
|
|
2379
|
-
from = cView.posAtStart;
|
|
2380
|
-
to = from + cView.length;
|
|
2381
|
-
topNode = cView.dom;
|
|
2382
|
-
}
|
|
2383
|
-
else if (cView instanceof LineView) {
|
|
2384
|
-
while (topNode.parentNode != cView.dom)
|
|
2385
|
-
topNode = topNode.parentNode;
|
|
2386
|
-
let prev = topNode.previousSibling;
|
|
2387
|
-
while (prev && !ContentView.get(prev))
|
|
2388
|
-
prev = prev.previousSibling;
|
|
2389
|
-
from = to = prev ? ContentView.get(prev).posAtEnd : cView.posAtStart;
|
|
2390
|
-
}
|
|
2391
|
-
else {
|
|
2392
|
-
return Decoration.none;
|
|
2393
|
-
}
|
|
2394
|
-
let newFrom = changes.mapPos(from, 1), newTo = Math.max(newFrom, changes.mapPos(to, -1));
|
|
2395
|
-
let text = textNode.nodeValue, { state } = view;
|
|
2396
|
-
if (newTo - newFrom < text.length) {
|
|
2397
|
-
if (state.sliceDoc(newFrom, Math.min(state.doc.length, newFrom + text.length)) == text)
|
|
2398
|
-
newTo = newFrom + text.length;
|
|
2399
|
-
else if (state.sliceDoc(Math.max(0, newTo - text.length), newTo) == text)
|
|
2400
|
-
newFrom = newTo - text.length;
|
|
2401
|
-
else
|
|
2402
|
-
return Decoration.none;
|
|
2403
|
-
}
|
|
2404
|
-
else if (state.sliceDoc(newFrom, newTo) != text) {
|
|
2405
|
-
return Decoration.none;
|
|
2406
|
-
}
|
|
2407
|
-
return Decoration.set(Decoration.replace({ widget: new CompositionWidget(topNode, textNode) }).range(newFrom, newTo));
|
|
2408
|
-
}
|
|
2409
|
-
class CompositionWidget extends WidgetType {
|
|
2410
|
-
constructor(top, text) {
|
|
2411
|
-
super();
|
|
2412
|
-
this.top = top;
|
|
2413
|
-
this.text = text;
|
|
2414
|
-
}
|
|
2415
|
-
eq(other) { return this.top == other.top && this.text == other.text; }
|
|
2416
|
-
toDOM() { return this.top; }
|
|
2417
|
-
ignoreEvent() { return false; }
|
|
2418
|
-
get customView() { return CompositionView; }
|
|
2419
|
-
}
|
|
2420
|
-
function nearbyTextNode(node, offset, side) {
|
|
2421
|
-
for (;;) {
|
|
2422
|
-
if (node.nodeType == 3)
|
|
2423
|
-
return node;
|
|
2424
|
-
if (node.nodeType == 1 && offset > 0 && side <= 0) {
|
|
2425
|
-
node = node.childNodes[offset - 1];
|
|
2426
|
-
offset = maxOffset(node);
|
|
2427
|
-
}
|
|
2428
|
-
else if (node.nodeType == 1 && offset < node.childNodes.length && side >= 0) {
|
|
2429
|
-
node = node.childNodes[offset];
|
|
2430
|
-
offset = 0;
|
|
2431
|
-
}
|
|
2432
|
-
else {
|
|
2433
|
-
return null;
|
|
2434
|
-
}
|
|
2435
|
-
}
|
|
2436
|
-
}
|
|
2437
|
-
function nextToUneditable(node, offset) {
|
|
2438
|
-
if (node.nodeType != 1)
|
|
2439
|
-
return 0;
|
|
2440
|
-
return (offset && node.childNodes[offset - 1].contentEditable == "false" ? 1 /* Before */ : 0) |
|
|
2441
|
-
(offset < node.childNodes.length && node.childNodes[offset].contentEditable == "false" ? 2 /* After */ : 0);
|
|
2442
|
-
}
|
|
2443
|
-
class DecorationComparator$1 {
|
|
2444
|
-
constructor() {
|
|
2445
|
-
this.changes = [];
|
|
2446
|
-
}
|
|
2447
|
-
compareRange(from, to) { addRange(from, to, this.changes); }
|
|
2448
|
-
comparePoint(from, to) { addRange(from, to, this.changes); }
|
|
2449
|
-
}
|
|
2450
|
-
function findChangedDeco(a, b, diff) {
|
|
2451
|
-
let comp = new DecorationComparator$1;
|
|
2452
|
-
RangeSet.compare(a, b, diff, comp);
|
|
2453
|
-
return comp.changes;
|
|
2454
|
-
}
|
|
2455
|
-
function inUneditable(node, inside) {
|
|
2456
|
-
for (let cur = node; cur && cur != inside; cur = cur.assignedSlot || cur.parentNode) {
|
|
2457
|
-
if (cur.nodeType == 1 && cur.contentEditable == 'false') {
|
|
2458
|
-
return true;
|
|
2459
|
-
}
|
|
2460
|
-
}
|
|
2461
|
-
return false;
|
|
2462
|
-
}
|
|
2463
|
-
|
|
2464
|
-
/**
|
|
2465
|
-
Used to indicate [text direction](https://codemirror.net/6/docs/ref/#view.EditorView.textDirection).
|
|
2466
|
-
*/
|
|
2467
|
-
var Direction = /*@__PURE__*/(function (Direction) {
|
|
2468
|
-
// (These are chosen to match the base levels, in bidi algorithm
|
|
2469
|
-
// terms, of spans in that direction.)
|
|
2470
|
-
/**
|
|
2471
|
-
Left-to-right.
|
|
2472
|
-
*/
|
|
2473
|
-
Direction[Direction["LTR"] = 0] = "LTR";
|
|
2474
|
-
/**
|
|
2475
|
-
Right-to-left.
|
|
2476
|
-
*/
|
|
2477
|
-
Direction[Direction["RTL"] = 1] = "RTL";
|
|
2478
|
-
return Direction})(Direction || (Direction = {}));
|
|
2479
|
-
const LTR = Direction.LTR, RTL = Direction.RTL;
|
|
2480
|
-
// Decode a string with each type encoded as log2(type)
|
|
2481
|
-
function dec(str) {
|
|
2482
|
-
let result = [];
|
|
2483
|
-
for (let i = 0; i < str.length; i++)
|
|
2484
|
-
result.push(1 << +str[i]);
|
|
2485
|
-
return result;
|
|
2486
|
-
}
|
|
2487
|
-
// Character types for codepoints 0 to 0xf8
|
|
2488
|
-
const LowTypes = /*@__PURE__*/dec("88888888888888888888888888888888888666888888787833333333337888888000000000000000000000000008888880000000000000000000000000088888888888888888888888888888888888887866668888088888663380888308888800000000000000000000000800000000000000000000000000000008");
|
|
2489
|
-
// Character types for codepoints 0x600 to 0x6f9
|
|
2490
|
-
const ArabicTypes = /*@__PURE__*/dec("4444448826627288999999999992222222222222222222222222222222222222222222222229999999999999999999994444444444644222822222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222999999949999999229989999223333333333");
|
|
2491
|
-
const Brackets = /*@__PURE__*/Object.create(null), BracketStack = [];
|
|
2492
|
-
// There's a lot more in
|
|
2493
|
-
// https://www.unicode.org/Public/UCD/latest/ucd/BidiBrackets.txt,
|
|
2494
|
-
// which are left out to keep code size down.
|
|
2495
|
-
for (let p of ["()", "[]", "{}"]) {
|
|
2496
|
-
let l = /*@__PURE__*/p.charCodeAt(0), r = /*@__PURE__*/p.charCodeAt(1);
|
|
2497
|
-
Brackets[l] = r;
|
|
2498
|
-
Brackets[r] = -l;
|
|
2499
|
-
}
|
|
2500
|
-
function charType(ch) {
|
|
2501
|
-
return ch <= 0xf7 ? LowTypes[ch] :
|
|
2502
|
-
0x590 <= ch && ch <= 0x5f4 ? 2 /* R */ :
|
|
2503
|
-
0x600 <= ch && ch <= 0x6f9 ? ArabicTypes[ch - 0x600] :
|
|
2504
|
-
0x6ee <= ch && ch <= 0x8ac ? 4 /* AL */ :
|
|
2505
|
-
0x2000 <= ch && ch <= 0x200b ? 256 /* NI */ :
|
|
2506
|
-
ch == 0x200c ? 256 /* NI */ : 1 /* L */;
|
|
2507
|
-
}
|
|
2508
|
-
const BidiRE = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
|
|
2509
|
-
/**
|
|
2510
|
-
Represents a contiguous range of text that has a single direction
|
|
2511
|
-
(as in left-to-right or right-to-left).
|
|
2512
|
-
*/
|
|
2513
|
-
class BidiSpan {
|
|
2514
|
-
/**
|
|
2515
|
-
@internal
|
|
2516
|
-
*/
|
|
2517
|
-
constructor(
|
|
2518
|
-
/**
|
|
2519
|
-
The start of the span (relative to the start of the line).
|
|
2520
|
-
*/
|
|
2521
|
-
from,
|
|
2522
|
-
/**
|
|
2523
|
-
The end of the span.
|
|
2524
|
-
*/
|
|
2525
|
-
to,
|
|
2526
|
-
/**
|
|
2527
|
-
The ["bidi
|
|
2528
|
-
level"](https://unicode.org/reports/tr9/#Basic_Display_Algorithm)
|
|
2529
|
-
of the span (in this context, 0 means
|
|
2530
|
-
left-to-right, 1 means right-to-left, 2 means left-to-right
|
|
2531
|
-
number inside right-to-left text).
|
|
2532
|
-
*/
|
|
2533
|
-
level) {
|
|
2534
|
-
this.from = from;
|
|
2535
|
-
this.to = to;
|
|
2536
|
-
this.level = level;
|
|
2537
|
-
}
|
|
2538
|
-
/**
|
|
2539
|
-
The direction of this span.
|
|
2540
|
-
*/
|
|
2541
|
-
get dir() { return this.level % 2 ? RTL : LTR; }
|
|
2542
|
-
/**
|
|
2543
|
-
@internal
|
|
2544
|
-
*/
|
|
2545
|
-
side(end, dir) { return (this.dir == dir) == end ? this.to : this.from; }
|
|
2546
|
-
/**
|
|
2547
|
-
@internal
|
|
2548
|
-
*/
|
|
2549
|
-
static find(order, index, level, assoc) {
|
|
2550
|
-
let maybe = -1;
|
|
2551
|
-
for (let i = 0; i < order.length; i++) {
|
|
2552
|
-
let span = order[i];
|
|
2553
|
-
if (span.from <= index && span.to >= index) {
|
|
2554
|
-
if (span.level == level)
|
|
2555
|
-
return i;
|
|
2556
|
-
// When multiple spans match, if assoc != 0, take the one that
|
|
2557
|
-
// covers that side, otherwise take the one with the minimum
|
|
2558
|
-
// level.
|
|
2559
|
-
if (maybe < 0 || (assoc != 0 ? (assoc < 0 ? span.from < index : span.to > index) : order[maybe].level > span.level))
|
|
2560
|
-
maybe = i;
|
|
2561
|
-
}
|
|
2562
|
-
}
|
|
2563
|
-
if (maybe < 0)
|
|
2564
|
-
throw new RangeError("Index out of range");
|
|
2565
|
-
return maybe;
|
|
2566
|
-
}
|
|
2567
|
-
}
|
|
2568
|
-
// Reused array of character types
|
|
2569
|
-
const types = [];
|
|
2570
|
-
function computeOrder(line, direction) {
|
|
2571
|
-
let len = line.length, outerType = direction == LTR ? 1 /* L */ : 2 /* R */, oppositeType = direction == LTR ? 2 /* R */ : 1 /* L */;
|
|
2572
|
-
if (!line || outerType == 1 /* L */ && !BidiRE.test(line))
|
|
2573
|
-
return trivialOrder(len);
|
|
2574
|
-
// W1. Examine each non-spacing mark (NSM) in the level run, and
|
|
2575
|
-
// change the type of the NSM to the type of the previous
|
|
2576
|
-
// character. If the NSM is at the start of the level run, it will
|
|
2577
|
-
// get the type of sor.
|
|
2578
|
-
// W2. Search backwards from each instance of a European number
|
|
2579
|
-
// until the first strong type (R, L, AL, or sor) is found. If an
|
|
2580
|
-
// AL is found, change the type of the European number to Arabic
|
|
2581
|
-
// number.
|
|
2582
|
-
// W3. Change all ALs to R.
|
|
2583
|
-
// (Left after this: L, R, EN, AN, ET, CS, NI)
|
|
2584
|
-
for (let i = 0, prev = outerType, prevStrong = outerType; i < len; i++) {
|
|
2585
|
-
let type = charType(line.charCodeAt(i));
|
|
2586
|
-
if (type == 512 /* NSM */)
|
|
2587
|
-
type = prev;
|
|
2588
|
-
else if (type == 8 /* EN */ && prevStrong == 4 /* AL */)
|
|
2589
|
-
type = 16 /* AN */;
|
|
2590
|
-
types[i] = type == 4 /* AL */ ? 2 /* R */ : type;
|
|
2591
|
-
if (type & 7 /* Strong */)
|
|
2592
|
-
prevStrong = type;
|
|
2593
|
-
prev = type;
|
|
2594
|
-
}
|
|
2595
|
-
// W5. A sequence of European terminators adjacent to European
|
|
2596
|
-
// numbers changes to all European numbers.
|
|
2597
|
-
// W6. Otherwise, separators and terminators change to Other
|
|
2598
|
-
// Neutral.
|
|
2599
|
-
// W7. Search backwards from each instance of a European number
|
|
2600
|
-
// until the first strong type (R, L, or sor) is found. If an L is
|
|
2601
|
-
// found, then change the type of the European number to L.
|
|
2602
|
-
// (Left after this: L, R, EN+AN, NI)
|
|
2603
|
-
for (let i = 0, prev = outerType, prevStrong = outerType; i < len; i++) {
|
|
2604
|
-
let type = types[i];
|
|
2605
|
-
if (type == 128 /* CS */) {
|
|
2606
|
-
if (i < len - 1 && prev == types[i + 1] && (prev & 24 /* Num */))
|
|
2607
|
-
type = types[i] = prev;
|
|
2608
|
-
else
|
|
2609
|
-
types[i] = 256 /* NI */;
|
|
2610
|
-
}
|
|
2611
|
-
else if (type == 64 /* ET */) {
|
|
2612
|
-
let end = i + 1;
|
|
2613
|
-
while (end < len && types[end] == 64 /* ET */)
|
|
2614
|
-
end++;
|
|
2615
|
-
let replace = (i && prev == 8 /* EN */) || (end < len && types[end] == 8 /* EN */) ? (prevStrong == 1 /* L */ ? 1 /* L */ : 8 /* EN */) : 256 /* NI */;
|
|
2616
|
-
for (let j = i; j < end; j++)
|
|
2617
|
-
types[j] = replace;
|
|
2618
|
-
i = end - 1;
|
|
2619
|
-
}
|
|
2620
|
-
else if (type == 8 /* EN */ && prevStrong == 1 /* L */) {
|
|
2621
|
-
types[i] = 1 /* L */;
|
|
2622
|
-
}
|
|
2623
|
-
prev = type;
|
|
2624
|
-
if (type & 7 /* Strong */)
|
|
2625
|
-
prevStrong = type;
|
|
2626
|
-
}
|
|
2627
|
-
// N0. Process bracket pairs in an isolating run sequence
|
|
2628
|
-
// sequentially in the logical order of the text positions of the
|
|
2629
|
-
// opening paired brackets using the logic given below. Within this
|
|
2630
|
-
// scope, bidirectional types EN and AN are treated as R.
|
|
2631
|
-
for (let i = 0, sI = 0, context = 0, ch, br, type; i < len; i++) {
|
|
2632
|
-
// Keeps [startIndex, type, strongSeen] triples for each open
|
|
2633
|
-
// bracket on BracketStack.
|
|
2634
|
-
if (br = Brackets[ch = line.charCodeAt(i)]) {
|
|
2635
|
-
if (br < 0) { // Closing bracket
|
|
2636
|
-
for (let sJ = sI - 3; sJ >= 0; sJ -= 3) {
|
|
2637
|
-
if (BracketStack[sJ + 1] == -br) {
|
|
2638
|
-
let flags = BracketStack[sJ + 2];
|
|
2639
|
-
let type = (flags & 2 /* EmbedInside */) ? outerType :
|
|
2640
|
-
!(flags & 4 /* OppositeInside */) ? 0 :
|
|
2641
|
-
(flags & 1 /* OppositeBefore */) ? oppositeType : outerType;
|
|
2642
|
-
if (type)
|
|
2643
|
-
types[i] = types[BracketStack[sJ]] = type;
|
|
2644
|
-
sI = sJ;
|
|
2645
|
-
break;
|
|
2646
|
-
}
|
|
2647
|
-
}
|
|
2648
|
-
}
|
|
2649
|
-
else if (BracketStack.length == 189 /* MaxDepth */) {
|
|
2650
|
-
break;
|
|
2651
|
-
}
|
|
2652
|
-
else {
|
|
2653
|
-
BracketStack[sI++] = i;
|
|
2654
|
-
BracketStack[sI++] = ch;
|
|
2655
|
-
BracketStack[sI++] = context;
|
|
2656
|
-
}
|
|
2657
|
-
}
|
|
2658
|
-
else if ((type = types[i]) == 2 /* R */ || type == 1 /* L */) {
|
|
2659
|
-
let embed = type == outerType;
|
|
2660
|
-
context = embed ? 0 : 1 /* OppositeBefore */;
|
|
2661
|
-
for (let sJ = sI - 3; sJ >= 0; sJ -= 3) {
|
|
2662
|
-
let cur = BracketStack[sJ + 2];
|
|
2663
|
-
if (cur & 2 /* EmbedInside */)
|
|
2664
|
-
break;
|
|
2665
|
-
if (embed) {
|
|
2666
|
-
BracketStack[sJ + 2] |= 2 /* EmbedInside */;
|
|
2667
|
-
}
|
|
2668
|
-
else {
|
|
2669
|
-
if (cur & 4 /* OppositeInside */)
|
|
2670
|
-
break;
|
|
2671
|
-
BracketStack[sJ + 2] |= 4 /* OppositeInside */;
|
|
2672
|
-
}
|
|
2567
|
+
// `ChildCursor.findPos` doesn't have to deal with the edge case
|
|
2568
|
+
// of being after the last element.
|
|
2569
|
+
let i = this.children.length;
|
|
2570
|
+
if (i)
|
|
2571
|
+
pos -= this.children[--i].length;
|
|
2572
|
+
return new ChildCursor(this.children, pos, i);
|
|
2573
|
+
}
|
|
2574
|
+
computeBlockGapDeco() {
|
|
2575
|
+
let deco = [], vs = this.view.viewState;
|
|
2576
|
+
for (let pos = 0, i = 0;; i++) {
|
|
2577
|
+
let next = i == vs.viewports.length ? null : vs.viewports[i];
|
|
2578
|
+
let end = next ? next.from - 1 : this.length;
|
|
2579
|
+
if (end > pos) {
|
|
2580
|
+
let height = vs.lineBlockAt(end).bottom - vs.lineBlockAt(pos).top;
|
|
2581
|
+
deco.push(Decoration.replace({ widget: new BlockGapWidget(height), block: true, inclusive: true }).range(pos, end));
|
|
2673
2582
|
}
|
|
2583
|
+
if (!next)
|
|
2584
|
+
break;
|
|
2585
|
+
pos = next.to + 1;
|
|
2674
2586
|
}
|
|
2587
|
+
return Decoration.set(deco);
|
|
2675
2588
|
}
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
if (types[i] == 256 /* NI */) {
|
|
2685
|
-
let end = i + 1;
|
|
2686
|
-
while (end < len && types[end] == 256 /* NI */)
|
|
2687
|
-
end++;
|
|
2688
|
-
let beforeL = (i ? types[i - 1] : outerType) == 1 /* L */;
|
|
2689
|
-
let afterL = (end < len ? types[end] : outerType) == 1 /* L */;
|
|
2690
|
-
let replace = beforeL == afterL ? (beforeL ? 1 /* L */ : 2 /* R */) : outerType;
|
|
2691
|
-
for (let j = i; j < end; j++)
|
|
2692
|
-
types[j] = replace;
|
|
2693
|
-
i = end - 1;
|
|
2694
|
-
}
|
|
2589
|
+
updateDeco() {
|
|
2590
|
+
return this.decorations = [
|
|
2591
|
+
...this.view.pluginField(PluginField.decorations),
|
|
2592
|
+
...this.view.state.facet(decorations),
|
|
2593
|
+
this.compositionDeco,
|
|
2594
|
+
this.computeBlockGapDeco(),
|
|
2595
|
+
this.view.viewState.lineGapDeco
|
|
2596
|
+
];
|
|
2695
2597
|
}
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
else {
|
|
2716
|
-
order.push(new BidiSpan(start, i, 0));
|
|
2598
|
+
scrollIntoView({ range, center }) {
|
|
2599
|
+
let rect = this.coordsAt(range.head, range.empty ? range.assoc : range.head > range.anchor ? -1 : 1), other;
|
|
2600
|
+
if (!rect)
|
|
2601
|
+
return;
|
|
2602
|
+
if (!range.empty && (other = this.coordsAt(range.anchor, range.anchor > range.head ? -1 : 1)))
|
|
2603
|
+
rect = { left: Math.min(rect.left, other.left), top: Math.min(rect.top, other.top),
|
|
2604
|
+
right: Math.max(rect.right, other.right), bottom: Math.max(rect.bottom, other.bottom) };
|
|
2605
|
+
let mLeft = 0, mRight = 0, mTop = 0, mBottom = 0;
|
|
2606
|
+
for (let margins of this.view.pluginField(PluginField.scrollMargins))
|
|
2607
|
+
if (margins) {
|
|
2608
|
+
let { left, right, top, bottom } = margins;
|
|
2609
|
+
if (left != null)
|
|
2610
|
+
mLeft = Math.max(mLeft, left);
|
|
2611
|
+
if (right != null)
|
|
2612
|
+
mRight = Math.max(mRight, right);
|
|
2613
|
+
if (top != null)
|
|
2614
|
+
mTop = Math.max(mTop, top);
|
|
2615
|
+
if (bottom != null)
|
|
2616
|
+
mBottom = Math.max(mBottom, bottom);
|
|
2717
2617
|
}
|
|
2718
|
-
|
|
2618
|
+
scrollRectIntoView(this.view.scrollDOM, {
|
|
2619
|
+
left: rect.left - mLeft, top: rect.top - mTop,
|
|
2620
|
+
right: rect.right + mRight, bottom: rect.bottom + mBottom
|
|
2621
|
+
}, range.head < range.anchor ? -1 : 1, center);
|
|
2622
|
+
}
|
|
2623
|
+
}
|
|
2624
|
+
function betweenUneditable(pos) {
|
|
2625
|
+
return pos.node.nodeType == 1 && pos.node.firstChild &&
|
|
2626
|
+
(pos.offset == 0 || pos.node.childNodes[pos.offset - 1].contentEditable == "false") &&
|
|
2627
|
+
(pos.offset == pos.node.childNodes.length || pos.node.childNodes[pos.offset].contentEditable == "false");
|
|
2628
|
+
}
|
|
2629
|
+
class BlockGapWidget extends WidgetType {
|
|
2630
|
+
constructor(height) {
|
|
2631
|
+
super();
|
|
2632
|
+
this.height = height;
|
|
2633
|
+
}
|
|
2634
|
+
toDOM() {
|
|
2635
|
+
let elt = document.createElement("div");
|
|
2636
|
+
this.updateDOM(elt);
|
|
2637
|
+
return elt;
|
|
2638
|
+
}
|
|
2639
|
+
eq(other) { return other.height == this.height; }
|
|
2640
|
+
updateDOM(elt) {
|
|
2641
|
+
elt.style.height = this.height + "px";
|
|
2642
|
+
return true;
|
|
2643
|
+
}
|
|
2644
|
+
get estimatedHeight() { return this.height; }
|
|
2645
|
+
}
|
|
2646
|
+
function computeCompositionDeco(view, changes) {
|
|
2647
|
+
let sel = view.observer.selectionRange;
|
|
2648
|
+
let textNode = sel.focusNode && nearbyTextNode(sel.focusNode, sel.focusOffset, 0);
|
|
2649
|
+
if (!textNode)
|
|
2650
|
+
return Decoration.none;
|
|
2651
|
+
let cView = view.docView.nearest(textNode);
|
|
2652
|
+
if (!cView)
|
|
2653
|
+
return Decoration.none;
|
|
2654
|
+
let from, to, topNode = textNode;
|
|
2655
|
+
if (cView instanceof LineView) {
|
|
2656
|
+
while (topNode.parentNode != cView.dom)
|
|
2657
|
+
topNode = topNode.parentNode;
|
|
2658
|
+
let prev = topNode.previousSibling;
|
|
2659
|
+
while (prev && !ContentView.get(prev))
|
|
2660
|
+
prev = prev.previousSibling;
|
|
2661
|
+
from = to = prev ? ContentView.get(prev).posAtEnd : cView.posAtStart;
|
|
2719
2662
|
}
|
|
2720
2663
|
else {
|
|
2721
|
-
for (
|
|
2722
|
-
let
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2664
|
+
for (;;) {
|
|
2665
|
+
let { parent } = cView;
|
|
2666
|
+
if (!parent)
|
|
2667
|
+
return Decoration.none;
|
|
2668
|
+
if (parent instanceof LineView)
|
|
2669
|
+
break;
|
|
2670
|
+
cView = parent;
|
|
2726
2671
|
}
|
|
2672
|
+
from = cView.posAtStart;
|
|
2673
|
+
to = from + cView.length;
|
|
2674
|
+
topNode = cView.dom;
|
|
2727
2675
|
}
|
|
2728
|
-
|
|
2676
|
+
let newFrom = changes.mapPos(from, 1), newTo = Math.max(newFrom, changes.mapPos(to, -1));
|
|
2677
|
+
let text = textNode.nodeValue, { state } = view;
|
|
2678
|
+
if (newTo - newFrom < text.length) {
|
|
2679
|
+
if (state.sliceDoc(newFrom, Math.min(state.doc.length, newFrom + text.length)) == text)
|
|
2680
|
+
newTo = newFrom + text.length;
|
|
2681
|
+
else if (state.sliceDoc(Math.max(0, newTo - text.length), newTo) == text)
|
|
2682
|
+
newFrom = newTo - text.length;
|
|
2683
|
+
else
|
|
2684
|
+
return Decoration.none;
|
|
2685
|
+
}
|
|
2686
|
+
else if (state.sliceDoc(newFrom, newTo) != text) {
|
|
2687
|
+
return Decoration.none;
|
|
2688
|
+
}
|
|
2689
|
+
return Decoration.set(Decoration.replace({ widget: new CompositionWidget(topNode, textNode) }).range(newFrom, newTo));
|
|
2729
2690
|
}
|
|
2730
|
-
|
|
2731
|
-
|
|
2691
|
+
class CompositionWidget extends WidgetType {
|
|
2692
|
+
constructor(top, text) {
|
|
2693
|
+
super();
|
|
2694
|
+
this.top = top;
|
|
2695
|
+
this.text = text;
|
|
2696
|
+
}
|
|
2697
|
+
eq(other) { return this.top == other.top && this.text == other.text; }
|
|
2698
|
+
toDOM() { return this.top; }
|
|
2699
|
+
ignoreEvent() { return false; }
|
|
2700
|
+
get customView() { return CompositionView; }
|
|
2732
2701
|
}
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
if (order[0].level != dir) {
|
|
2741
|
-
startIndex = order[0].side(false, dir);
|
|
2742
|
-
spanI = 0;
|
|
2702
|
+
function nearbyTextNode(node, offset, side) {
|
|
2703
|
+
for (;;) {
|
|
2704
|
+
if (node.nodeType == 3)
|
|
2705
|
+
return node;
|
|
2706
|
+
if (node.nodeType == 1 && offset > 0 && side <= 0) {
|
|
2707
|
+
node = node.childNodes[offset - 1];
|
|
2708
|
+
offset = maxOffset(node);
|
|
2743
2709
|
}
|
|
2744
|
-
|
|
2745
|
-
|
|
2746
|
-
|
|
2710
|
+
else if (node.nodeType == 1 && offset < node.childNodes.length && side >= 0) {
|
|
2711
|
+
node = node.childNodes[offset];
|
|
2712
|
+
offset = 0;
|
|
2713
|
+
}
|
|
2714
|
+
else {
|
|
2747
2715
|
return null;
|
|
2748
|
-
let last = order[order.length - 1];
|
|
2749
|
-
if (last.level != dir) {
|
|
2750
|
-
startIndex = last.side(true, dir);
|
|
2751
|
-
spanI = order.length - 1;
|
|
2752
2716
|
}
|
|
2753
2717
|
}
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2718
|
+
}
|
|
2719
|
+
function nextToUneditable(node, offset) {
|
|
2720
|
+
if (node.nodeType != 1)
|
|
2721
|
+
return 0;
|
|
2722
|
+
return (offset && node.childNodes[offset - 1].contentEditable == "false" ? 1 /* Before */ : 0) |
|
|
2723
|
+
(offset < node.childNodes.length && node.childNodes[offset].contentEditable == "false" ? 2 /* After */ : 0);
|
|
2724
|
+
}
|
|
2725
|
+
class DecorationComparator$1 {
|
|
2726
|
+
constructor() {
|
|
2727
|
+
this.changes = [];
|
|
2761
2728
|
}
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2767
|
-
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2729
|
+
compareRange(from, to) { addRange(from, to, this.changes); }
|
|
2730
|
+
comparePoint(from, to) { addRange(from, to, this.changes); }
|
|
2731
|
+
}
|
|
2732
|
+
function findChangedDeco(a, b, diff) {
|
|
2733
|
+
let comp = new DecorationComparator$1;
|
|
2734
|
+
RangeSet.compare(a, b, diff, comp);
|
|
2735
|
+
return comp.changes;
|
|
2736
|
+
}
|
|
2737
|
+
function inUneditable(node, inside) {
|
|
2738
|
+
for (let cur = node; cur && cur != inside; cur = cur.assignedSlot || cur.parentNode) {
|
|
2739
|
+
if (cur.nodeType == 1 && cur.contentEditable == 'false') {
|
|
2740
|
+
return true;
|
|
2741
|
+
}
|
|
2742
|
+
}
|
|
2743
|
+
return false;
|
|
2773
2744
|
}
|
|
2774
2745
|
|
|
2775
2746
|
function groupAt(state, pos, bias = 1) {
|
|
@@ -2926,7 +2897,7 @@ function posAtCoords(view, { x, y }, precise, bias = -1) {
|
|
|
2926
2897
|
y = docTop + yOffset;
|
|
2927
2898
|
let lineStart = block.from;
|
|
2928
2899
|
// Clip x to the viewport sides
|
|
2929
|
-
x = Math.max(content.left + 1, Math.min(content.right - 1, x));
|
|
2900
|
+
x = Math.max(content.left + 1, Math.min(Math.max(content.right, content.left + view.docView.minWidth) - 1, x));
|
|
2930
2901
|
// If this is outside of the rendered viewport, we can't determine a position
|
|
2931
2902
|
if (lineStart < view.viewport.from)
|
|
2932
2903
|
return view.viewport.from == 0 ? 0 : posAtCoordsImprecise(view, content, block, x, y);
|
|
@@ -4168,12 +4139,12 @@ class HeightMapBranch extends HeightMap {
|
|
|
4168
4139
|
get break() { return this.flags & 1 /* Break */; }
|
|
4169
4140
|
blockAt(height, doc, top, offset) {
|
|
4170
4141
|
let mid = top + this.left.height;
|
|
4171
|
-
return height < mid
|
|
4142
|
+
return height < mid ? this.left.blockAt(height, doc, top, offset)
|
|
4172
4143
|
: this.right.blockAt(height, doc, mid, offset + this.left.length + this.break);
|
|
4173
4144
|
}
|
|
4174
4145
|
lineAt(value, type, doc, top, offset) {
|
|
4175
4146
|
let rightTop = top + this.left.height, rightOffset = offset + this.left.length + this.break;
|
|
4176
|
-
let left = type == QueryType.ByHeight ? value < rightTop
|
|
4147
|
+
let left = type == QueryType.ByHeight ? value < rightTop : value < rightOffset;
|
|
4177
4148
|
let base = left ? this.left.lineAt(value, type, doc, top, offset)
|
|
4178
4149
|
: this.right.lineAt(value, type, doc, rightTop, rightOffset);
|
|
4179
4150
|
if (this.break || (left ? base.to < rightOffset : base.from > rightOffset))
|
|
@@ -4314,7 +4285,9 @@ class NodeBuilder {
|
|
|
4314
4285
|
}
|
|
4315
4286
|
point(from, to, deco) {
|
|
4316
4287
|
if (from < to || deco.heightRelevant) {
|
|
4317
|
-
let height = deco.widget ?
|
|
4288
|
+
let height = deco.widget ? deco.widget.estimatedHeight : 0;
|
|
4289
|
+
if (height < 0)
|
|
4290
|
+
height = this.oracle.lineHeight;
|
|
4318
4291
|
let len = to - from;
|
|
4319
4292
|
if (deco.block) {
|
|
4320
4293
|
this.addBlock(new HeightMapBlock(len, height, deco.type));
|
|
@@ -5052,14 +5025,15 @@ const baseTheme = /*@__PURE__*/buildTheme("." + baseThemeID, {
|
|
|
5052
5025
|
},
|
|
5053
5026
|
".cm-placeholder": {
|
|
5054
5027
|
color: "#888",
|
|
5055
|
-
display: "inline-block"
|
|
5028
|
+
display: "inline-block",
|
|
5029
|
+
verticalAlign: "top",
|
|
5056
5030
|
},
|
|
5057
5031
|
".cm-button": {
|
|
5058
5032
|
verticalAlign: "middle",
|
|
5059
5033
|
color: "inherit",
|
|
5060
5034
|
fontSize: "70%",
|
|
5061
5035
|
padding: ".2em 1em",
|
|
5062
|
-
borderRadius: "
|
|
5036
|
+
borderRadius: "1px"
|
|
5063
5037
|
},
|
|
5064
5038
|
"&light .cm-button": {
|
|
5065
5039
|
backgroundImage: "linear-gradient(#eff1f5, #d9d9df)",
|
|
@@ -5381,6 +5355,7 @@ class DOMObserver {
|
|
|
5381
5355
|
for (let dom of this.scrollTargets)
|
|
5382
5356
|
dom.removeEventListener("scroll", this.onScroll);
|
|
5383
5357
|
window.removeEventListener("scroll", this.onScroll);
|
|
5358
|
+
this.dom.ownerDocument.removeEventListener("selectionchange", this.onSelectionChange);
|
|
5384
5359
|
clearTimeout(this.parentCheck);
|
|
5385
5360
|
clearTimeout(this.resizeTimeout);
|
|
5386
5361
|
}
|
|
@@ -5480,11 +5455,22 @@ function applyDOMChange(view, start, end, typeOver) {
|
|
|
5480
5455
|
};
|
|
5481
5456
|
if (change) {
|
|
5482
5457
|
let startState = view.state;
|
|
5458
|
+
if (browser.ios && view.inputState.flushIOSKey(view))
|
|
5459
|
+
return;
|
|
5483
5460
|
// Android browsers don't fire reasonable key events for enter,
|
|
5484
5461
|
// backspace, or delete. So this detects changes that look like
|
|
5485
5462
|
// they're caused by those keys, and reinterprets them as key
|
|
5486
|
-
// events.
|
|
5487
|
-
|
|
5463
|
+
// events. (Some of these keys are also handled by beforeinput
|
|
5464
|
+
// events and the pendingAndroidKey mechanism, but that's not
|
|
5465
|
+
// reliable in all situations.)
|
|
5466
|
+
if (browser.android &&
|
|
5467
|
+
((change.from == sel.from && change.to == sel.to &&
|
|
5468
|
+
change.insert.length == 1 && change.insert.lines == 2 &&
|
|
5469
|
+
dispatchKey(view.contentDOM, "Enter", 13)) ||
|
|
5470
|
+
(change.from == sel.from - 1 && change.to == sel.to && change.insert.length == 0 &&
|
|
5471
|
+
dispatchKey(view.contentDOM, "Backspace", 8)) ||
|
|
5472
|
+
(change.from == sel.from && change.to == sel.to + 1 && change.insert.length == 0 &&
|
|
5473
|
+
dispatchKey(view.contentDOM, "Delete", 46))))
|
|
5488
5474
|
return;
|
|
5489
5475
|
let text = change.insert.toString();
|
|
5490
5476
|
if (view.state.facet(inputHandler).some(h => h(view, change.from, change.to, text)))
|
|
@@ -5677,6 +5663,7 @@ class EditorView {
|
|
|
5677
5663
|
*/
|
|
5678
5664
|
config = {}) {
|
|
5679
5665
|
this.plugins = [];
|
|
5666
|
+
this.pluginMap = new Map;
|
|
5680
5667
|
this.editorAttrs = {};
|
|
5681
5668
|
this.contentAttrs = {};
|
|
5682
5669
|
this.bidiCache = [];
|
|
@@ -5708,7 +5695,9 @@ class EditorView {
|
|
|
5708
5695
|
this.dispatch = this.dispatch.bind(this);
|
|
5709
5696
|
this.root = (config.root || getRoot(config.parent) || document);
|
|
5710
5697
|
this.viewState = new ViewState(config.state || EditorState.create());
|
|
5711
|
-
this.plugins = this.state.facet(viewPlugin).map(spec => new PluginInstance(spec)
|
|
5698
|
+
this.plugins = this.state.facet(viewPlugin).map(spec => new PluginInstance(spec));
|
|
5699
|
+
for (let plugin of this.plugins)
|
|
5700
|
+
plugin.update(this);
|
|
5712
5701
|
this.observer = new DOMObserver(this, (from, to, typeOver) => {
|
|
5713
5702
|
applyDOMChange(this, from, to, typeOver);
|
|
5714
5703
|
}, event => {
|
|
@@ -5845,7 +5834,10 @@ class EditorView {
|
|
|
5845
5834
|
for (let plugin of this.plugins)
|
|
5846
5835
|
plugin.destroy(this);
|
|
5847
5836
|
this.viewState = new ViewState(newState);
|
|
5848
|
-
this.plugins = newState.facet(viewPlugin).map(spec => new PluginInstance(spec)
|
|
5837
|
+
this.plugins = newState.facet(viewPlugin).map(spec => new PluginInstance(spec));
|
|
5838
|
+
this.pluginMap.clear();
|
|
5839
|
+
for (let plugin of this.plugins)
|
|
5840
|
+
plugin.update(this);
|
|
5849
5841
|
this.docView = new DocView(this);
|
|
5850
5842
|
this.inputState.ensureHandlers(this);
|
|
5851
5843
|
this.mountStyles();
|
|
@@ -5876,6 +5868,7 @@ class EditorView {
|
|
|
5876
5868
|
if (plugin.mustUpdate != update)
|
|
5877
5869
|
plugin.destroy(this);
|
|
5878
5870
|
this.plugins = newPlugins;
|
|
5871
|
+
this.pluginMap.clear();
|
|
5879
5872
|
this.inputState.ensureHandlers(this);
|
|
5880
5873
|
}
|
|
5881
5874
|
else {
|
|
@@ -5883,7 +5876,7 @@ class EditorView {
|
|
|
5883
5876
|
p.mustUpdate = update;
|
|
5884
5877
|
}
|
|
5885
5878
|
for (let i = 0; i < this.plugins.length; i++)
|
|
5886
|
-
this.plugins[i]
|
|
5879
|
+
this.plugins[i].update(this);
|
|
5887
5880
|
}
|
|
5888
5881
|
/**
|
|
5889
5882
|
@internal
|
|
@@ -5972,7 +5965,7 @@ class EditorView {
|
|
|
5972
5965
|
this.state.facet(theme);
|
|
5973
5966
|
}
|
|
5974
5967
|
updateAttrs() {
|
|
5975
|
-
let editorAttrs =
|
|
5968
|
+
let editorAttrs = attrsFromFacet(this, editorAttributes, {
|
|
5976
5969
|
class: "cm-editor" + (this.hasFocus ? " cm-focused " : " ") + this.themeClasses
|
|
5977
5970
|
});
|
|
5978
5971
|
let contentAttrs = {
|
|
@@ -5988,7 +5981,7 @@ class EditorView {
|
|
|
5988
5981
|
};
|
|
5989
5982
|
if (this.state.readOnly)
|
|
5990
5983
|
contentAttrs["aria-readonly"] = "true";
|
|
5991
|
-
|
|
5984
|
+
attrsFromFacet(this, contentAttributes, contentAttrs);
|
|
5992
5985
|
this.observer.ignore(() => {
|
|
5993
5986
|
updateAttrs(this.contentDOM, this.contentAttrs, contentAttrs);
|
|
5994
5987
|
updateAttrs(this.dom, this.editorAttrs, editorAttrs);
|
|
@@ -6057,10 +6050,10 @@ class EditorView {
|
|
|
6057
6050
|
the return value of this method.
|
|
6058
6051
|
*/
|
|
6059
6052
|
plugin(plugin) {
|
|
6060
|
-
|
|
6061
|
-
|
|
6062
|
-
|
|
6063
|
-
return
|
|
6053
|
+
let known = this.pluginMap.get(plugin);
|
|
6054
|
+
if (known === undefined || known && known.spec != plugin)
|
|
6055
|
+
this.pluginMap.set(plugin, known = this.plugins.find(p => p.spec == plugin) || null);
|
|
6056
|
+
return known && known.update(this).value;
|
|
6064
6057
|
}
|
|
6065
6058
|
/**
|
|
6066
6059
|
The top position of the document, in screen coordinates. This
|
|
@@ -6547,6 +6540,14 @@ class CachedOrder {
|
|
|
6547
6540
|
return result;
|
|
6548
6541
|
}
|
|
6549
6542
|
}
|
|
6543
|
+
function attrsFromFacet(view, facet, base) {
|
|
6544
|
+
for (let sources = view.state.facet(facet), i = sources.length - 1; i >= 0; i--) {
|
|
6545
|
+
let source = sources[i], value = typeof source == "function" ? source(view) : source;
|
|
6546
|
+
if (value)
|
|
6547
|
+
combineAttrs(value, base);
|
|
6548
|
+
}
|
|
6549
|
+
return base;
|
|
6550
|
+
}
|
|
6550
6551
|
|
|
6551
6552
|
const currentPlatform = browser.mac ? "mac" : browser.windows ? "win" : browser.linux ? "linux" : "key";
|
|
6552
6553
|
function normalizeKeyName(name, platform) {
|
|
@@ -7199,35 +7200,29 @@ class TabWidget extends WidgetType {
|
|
|
7199
7200
|
}
|
|
7200
7201
|
|
|
7201
7202
|
const plugin = /*@__PURE__*/ViewPlugin.fromClass(class {
|
|
7202
|
-
constructor(
|
|
7203
|
-
this.height =
|
|
7204
|
-
this.
|
|
7205
|
-
read: view => Math.max(0, view.scrollDOM.clientHeight - view.defaultLineHeight),
|
|
7206
|
-
write: (value, view) => {
|
|
7207
|
-
if (Math.abs(value - this.height) > 1) {
|
|
7208
|
-
this.height = value;
|
|
7209
|
-
view.contentDOM.style.paddingBottom = value + "px";
|
|
7210
|
-
}
|
|
7211
|
-
}
|
|
7212
|
-
};
|
|
7213
|
-
view.requestMeasure(this.measure);
|
|
7203
|
+
constructor() {
|
|
7204
|
+
this.height = 1000;
|
|
7205
|
+
this.attrs = { style: "padding-bottom: 1000px" };
|
|
7214
7206
|
}
|
|
7215
7207
|
update(update) {
|
|
7216
|
-
|
|
7217
|
-
|
|
7208
|
+
let height = update.view.viewState.editorHeight - update.view.defaultLineHeight;
|
|
7209
|
+
if (height != this.height) {
|
|
7210
|
+
this.height = height;
|
|
7211
|
+
this.attrs = { style: `padding-bottom: ${height}px` };
|
|
7212
|
+
}
|
|
7218
7213
|
}
|
|
7219
7214
|
});
|
|
7220
7215
|
/**
|
|
7221
|
-
Returns
|
|
7222
|
-
equivalent to the height of the editor, minus one line
|
|
7223
|
-
that every line in the document can be scrolled to the
|
|
7224
|
-
editor.
|
|
7216
|
+
Returns an extension that makes sure the content has a bottom
|
|
7217
|
+
margin equivalent to the height of the editor, minus one line
|
|
7218
|
+
height, so that every line in the document can be scrolled to the
|
|
7219
|
+
top of the editor.
|
|
7225
7220
|
|
|
7226
7221
|
This is only meaningful when the editor is scrollable, and should
|
|
7227
7222
|
not be enabled in editors that take the size of their content.
|
|
7228
7223
|
*/
|
|
7229
7224
|
function scrollPastEnd() {
|
|
7230
|
-
return plugin;
|
|
7225
|
+
return [plugin, contentAttributes.of(view => { var _a; return ((_a = view.plugin(plugin)) === null || _a === void 0 ? void 0 : _a.attrs) || null; })];
|
|
7231
7226
|
}
|
|
7232
7227
|
|
|
7233
7228
|
/**
|