@codemirror/view 6.14.1 → 6.15.1
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 +24 -0
- package/dist/index.cjs +366 -378
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +367 -379
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -100,13 +100,15 @@ function windowRect(win) {
|
|
|
100
100
|
}
|
|
101
101
|
function scrollRectIntoView(dom, rect, side, x, y, xMargin, yMargin, ltr) {
|
|
102
102
|
let doc = dom.ownerDocument, win = doc.defaultView || window;
|
|
103
|
-
for (let cur = dom; cur;) {
|
|
103
|
+
for (let cur = dom, stop = false; cur && !stop;) {
|
|
104
104
|
if (cur.nodeType == 1) { // Element
|
|
105
105
|
let bounding, top = cur == doc.body;
|
|
106
106
|
if (top) {
|
|
107
107
|
bounding = windowRect(win);
|
|
108
108
|
}
|
|
109
109
|
else {
|
|
110
|
+
if (/^(fixed|sticky)$/.test(getComputedStyle(cur).position))
|
|
111
|
+
stop = true;
|
|
110
112
|
if (cur.scrollHeight <= cur.clientHeight && cur.scrollWidth <= cur.clientWidth) {
|
|
111
113
|
cur = cur.assignedSlot || cur.parentNode;
|
|
112
114
|
continue;
|
|
@@ -338,7 +340,7 @@ class ContentView {
|
|
|
338
340
|
constructor() {
|
|
339
341
|
this.parent = null;
|
|
340
342
|
this.dom = null;
|
|
341
|
-
this.
|
|
343
|
+
this.flags = 2 /* NodeDirty */;
|
|
342
344
|
}
|
|
343
345
|
get overrideDOMText() { return null; }
|
|
344
346
|
get posAtStart() {
|
|
@@ -360,18 +362,18 @@ class ContentView {
|
|
|
360
362
|
return this.posBefore(view) + view.length;
|
|
361
363
|
}
|
|
362
364
|
sync(view, track) {
|
|
363
|
-
if (this.
|
|
365
|
+
if (this.flags & 2 /* NodeDirty */) {
|
|
364
366
|
let parent = this.dom;
|
|
365
367
|
let prev = null, next;
|
|
366
368
|
for (let child of this.children) {
|
|
367
|
-
if (child.
|
|
368
|
-
if (!child.dom && (next = prev ? prev.nextSibling : parent.firstChild)
|
|
369
|
+
if (child.flags & 7 /* Dirty */) {
|
|
370
|
+
if (!child.dom && (next = prev ? prev.nextSibling : parent.firstChild)) {
|
|
369
371
|
let contentView = ContentView.get(next);
|
|
370
372
|
if (!contentView || !contentView.parent && contentView.canReuseDOM(child))
|
|
371
373
|
child.reuseDOM(next);
|
|
372
374
|
}
|
|
373
375
|
child.sync(view, track);
|
|
374
|
-
child.
|
|
376
|
+
child.flags &= ~7 /* Dirty */;
|
|
375
377
|
}
|
|
376
378
|
next = prev ? prev.nextSibling : parent.firstChild;
|
|
377
379
|
if (track && !track.written && track.node == parent && next != child.dom)
|
|
@@ -391,11 +393,11 @@ class ContentView {
|
|
|
391
393
|
while (next)
|
|
392
394
|
next = rm$1(next);
|
|
393
395
|
}
|
|
394
|
-
else if (this.
|
|
396
|
+
else if (this.flags & 1 /* ChildDirty */) {
|
|
395
397
|
for (let child of this.children)
|
|
396
|
-
if (child.
|
|
398
|
+
if (child.flags & 7 /* Dirty */) {
|
|
397
399
|
child.sync(view, track);
|
|
398
|
-
child.
|
|
400
|
+
child.flags &= ~7 /* Dirty */;
|
|
399
401
|
}
|
|
400
402
|
}
|
|
401
403
|
}
|
|
@@ -460,23 +462,23 @@ class ContentView {
|
|
|
460
462
|
endDOM: toI < this.children.length && toI >= 0 ? this.children[toI].dom : null };
|
|
461
463
|
}
|
|
462
464
|
markDirty(andParent = false) {
|
|
463
|
-
this.
|
|
465
|
+
this.flags |= 2 /* NodeDirty */;
|
|
464
466
|
this.markParentsDirty(andParent);
|
|
465
467
|
}
|
|
466
468
|
markParentsDirty(childList) {
|
|
467
469
|
for (let parent = this.parent; parent; parent = parent.parent) {
|
|
468
470
|
if (childList)
|
|
469
|
-
parent.
|
|
470
|
-
if (parent.
|
|
471
|
+
parent.flags |= 2 /* NodeDirty */;
|
|
472
|
+
if (parent.flags & 1 /* ChildDirty */)
|
|
471
473
|
return;
|
|
472
|
-
parent.
|
|
474
|
+
parent.flags |= 1 /* ChildDirty */;
|
|
473
475
|
childList = false;
|
|
474
476
|
}
|
|
475
477
|
}
|
|
476
478
|
setParent(parent) {
|
|
477
479
|
if (this.parent != parent) {
|
|
478
480
|
this.parent = parent;
|
|
479
|
-
if (this.
|
|
481
|
+
if (this.flags & 7 /* Dirty */)
|
|
480
482
|
this.markParentsDirty(true);
|
|
481
483
|
}
|
|
482
484
|
}
|
|
@@ -527,7 +529,9 @@ class ContentView {
|
|
|
527
529
|
return false;
|
|
528
530
|
}
|
|
529
531
|
become(other) { return false; }
|
|
530
|
-
canReuseDOM(other) {
|
|
532
|
+
canReuseDOM(other) {
|
|
533
|
+
return other.constructor == this.constructor && !((this.flags | other.flags) & 8 /* Composition */);
|
|
534
|
+
}
|
|
531
535
|
// When this is a zero-length view with a side, this should return a
|
|
532
536
|
// number <= 0 to indicate it is before its position, or a
|
|
533
537
|
// number > 0 when after its position.
|
|
@@ -651,6 +655,113 @@ function mergeChildrenInto(parent, from, to, insert, openStart, openEnd) {
|
|
|
651
655
|
replaceRange(parent, fromI, fromOff, toI, toOff, insert, 0, openStart, openEnd);
|
|
652
656
|
}
|
|
653
657
|
|
|
658
|
+
const LineBreakPlaceholder = "\uffff";
|
|
659
|
+
class DOMReader {
|
|
660
|
+
constructor(points, state$1) {
|
|
661
|
+
this.points = points;
|
|
662
|
+
this.text = "";
|
|
663
|
+
this.lineSeparator = state$1.facet(state.EditorState.lineSeparator);
|
|
664
|
+
}
|
|
665
|
+
append(text) {
|
|
666
|
+
this.text += text;
|
|
667
|
+
}
|
|
668
|
+
lineBreak() {
|
|
669
|
+
this.text += LineBreakPlaceholder;
|
|
670
|
+
}
|
|
671
|
+
readRange(start, end) {
|
|
672
|
+
if (!start)
|
|
673
|
+
return this;
|
|
674
|
+
let parent = start.parentNode;
|
|
675
|
+
for (let cur = start;;) {
|
|
676
|
+
this.findPointBefore(parent, cur);
|
|
677
|
+
let oldLen = this.text.length;
|
|
678
|
+
this.readNode(cur);
|
|
679
|
+
let next = cur.nextSibling;
|
|
680
|
+
if (next == end)
|
|
681
|
+
break;
|
|
682
|
+
let view = ContentView.get(cur), nextView = ContentView.get(next);
|
|
683
|
+
if (view && nextView ? view.breakAfter :
|
|
684
|
+
(view ? view.breakAfter : isBlockElement(cur)) ||
|
|
685
|
+
(isBlockElement(next) && (cur.nodeName != "BR" || cur.cmIgnore) && this.text.length > oldLen))
|
|
686
|
+
this.lineBreak();
|
|
687
|
+
cur = next;
|
|
688
|
+
}
|
|
689
|
+
this.findPointBefore(parent, end);
|
|
690
|
+
return this;
|
|
691
|
+
}
|
|
692
|
+
readTextNode(node) {
|
|
693
|
+
let text = node.nodeValue;
|
|
694
|
+
for (let point of this.points)
|
|
695
|
+
if (point.node == node)
|
|
696
|
+
point.pos = this.text.length + Math.min(point.offset, text.length);
|
|
697
|
+
for (let off = 0, re = this.lineSeparator ? null : /\r\n?|\n/g;;) {
|
|
698
|
+
let nextBreak = -1, breakSize = 1, m;
|
|
699
|
+
if (this.lineSeparator) {
|
|
700
|
+
nextBreak = text.indexOf(this.lineSeparator, off);
|
|
701
|
+
breakSize = this.lineSeparator.length;
|
|
702
|
+
}
|
|
703
|
+
else if (m = re.exec(text)) {
|
|
704
|
+
nextBreak = m.index;
|
|
705
|
+
breakSize = m[0].length;
|
|
706
|
+
}
|
|
707
|
+
this.append(text.slice(off, nextBreak < 0 ? text.length : nextBreak));
|
|
708
|
+
if (nextBreak < 0)
|
|
709
|
+
break;
|
|
710
|
+
this.lineBreak();
|
|
711
|
+
if (breakSize > 1)
|
|
712
|
+
for (let point of this.points)
|
|
713
|
+
if (point.node == node && point.pos > this.text.length)
|
|
714
|
+
point.pos -= breakSize - 1;
|
|
715
|
+
off = nextBreak + breakSize;
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
readNode(node) {
|
|
719
|
+
if (node.cmIgnore)
|
|
720
|
+
return;
|
|
721
|
+
let view = ContentView.get(node);
|
|
722
|
+
let fromView = view && view.overrideDOMText;
|
|
723
|
+
if (fromView != null) {
|
|
724
|
+
this.findPointInside(node, fromView.length);
|
|
725
|
+
for (let i = fromView.iter(); !i.next().done;) {
|
|
726
|
+
if (i.lineBreak)
|
|
727
|
+
this.lineBreak();
|
|
728
|
+
else
|
|
729
|
+
this.append(i.value);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
else if (node.nodeType == 3) {
|
|
733
|
+
this.readTextNode(node);
|
|
734
|
+
}
|
|
735
|
+
else if (node.nodeName == "BR") {
|
|
736
|
+
if (node.nextSibling)
|
|
737
|
+
this.lineBreak();
|
|
738
|
+
}
|
|
739
|
+
else if (node.nodeType == 1) {
|
|
740
|
+
this.readRange(node.firstChild, null);
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
findPointBefore(node, next) {
|
|
744
|
+
for (let point of this.points)
|
|
745
|
+
if (point.node == node && node.childNodes[point.offset] == next)
|
|
746
|
+
point.pos = this.text.length;
|
|
747
|
+
}
|
|
748
|
+
findPointInside(node, maxLen) {
|
|
749
|
+
for (let point of this.points)
|
|
750
|
+
if (node.nodeType == 3 ? point.node == node : node.contains(point.node))
|
|
751
|
+
point.pos = this.text.length + Math.min(maxLen, point.offset);
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
function isBlockElement(node) {
|
|
755
|
+
return node.nodeType == 1 && /^(DIV|P|LI|UL|OL|BLOCKQUOTE|DD|DT|H\d|SECTION|PRE)$/.test(node.nodeName);
|
|
756
|
+
}
|
|
757
|
+
class DOMPoint {
|
|
758
|
+
constructor(node, offset) {
|
|
759
|
+
this.node = node;
|
|
760
|
+
this.offset = offset;
|
|
761
|
+
this.pos = -1;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
|
|
654
765
|
let nav = typeof navigator != "undefined" ? navigator : { userAgent: "", vendor: "", platform: "" };
|
|
655
766
|
let doc = typeof document != "undefined" ? document : { documentElement: { style: {} } };
|
|
656
767
|
const ie_edge = /Edge\/(\d+)/.exec(nav.userAgent);
|
|
@@ -704,7 +815,10 @@ class TextView extends ContentView {
|
|
|
704
815
|
this.createDOM(dom);
|
|
705
816
|
}
|
|
706
817
|
merge(from, to, source) {
|
|
707
|
-
if (
|
|
818
|
+
if ((this.flags & 8 /* Composition */) ||
|
|
819
|
+
source && (!(source instanceof TextView) ||
|
|
820
|
+
this.length - (to - from) + source.length > MaxJoinLen ||
|
|
821
|
+
(source.flags & 8 /* Composition */)))
|
|
708
822
|
return false;
|
|
709
823
|
this.text = this.text.slice(0, from) + (source ? source.text : "") + this.text.slice(to);
|
|
710
824
|
this.markDirty();
|
|
@@ -714,6 +828,7 @@ class TextView extends ContentView {
|
|
|
714
828
|
let result = new TextView(this.text.slice(from));
|
|
715
829
|
this.text = this.text.slice(0, from);
|
|
716
830
|
this.markDirty();
|
|
831
|
+
result.flags |= this.flags & 8 /* Composition */;
|
|
717
832
|
return result;
|
|
718
833
|
}
|
|
719
834
|
localPosFromDOM(node, offset) {
|
|
@@ -745,16 +860,19 @@ class MarkView extends ContentView {
|
|
|
745
860
|
dom.setAttribute(name, this.mark.attrs[name]);
|
|
746
861
|
return dom;
|
|
747
862
|
}
|
|
863
|
+
canReuseDOM(other) {
|
|
864
|
+
return super.canReuseDOM(other) && !((this.flags | other.flags) & 8 /* Composition */);
|
|
865
|
+
}
|
|
748
866
|
reuseDOM(node) {
|
|
749
867
|
if (node.nodeName == this.mark.tagName.toUpperCase()) {
|
|
750
868
|
this.setDOM(node);
|
|
751
|
-
this.
|
|
869
|
+
this.flags |= 4 /* AttrsDirty */ | 2 /* NodeDirty */;
|
|
752
870
|
}
|
|
753
871
|
}
|
|
754
872
|
sync(view, track) {
|
|
755
873
|
if (!this.dom)
|
|
756
874
|
this.setDOM(this.setAttrs(document.createElement(this.mark.tagName)));
|
|
757
|
-
else if (this.
|
|
875
|
+
else if (this.flags & 4 /* AttrsDirty */)
|
|
758
876
|
this.setAttrs(this.dom);
|
|
759
877
|
super.sync(view, track);
|
|
760
878
|
}
|
|
@@ -833,7 +951,7 @@ class WidgetView extends ContentView {
|
|
|
833
951
|
this.prevWidget = null;
|
|
834
952
|
}
|
|
835
953
|
static create(widget, length, side) {
|
|
836
|
-
return new
|
|
954
|
+
return new WidgetView(widget, length, side);
|
|
837
955
|
}
|
|
838
956
|
split(from) {
|
|
839
957
|
let result = WidgetView.create(this.widget, this.length - from, this.side);
|
|
@@ -911,129 +1029,6 @@ class WidgetView extends ContentView {
|
|
|
911
1029
|
this.widget.destroy(this.dom);
|
|
912
1030
|
}
|
|
913
1031
|
}
|
|
914
|
-
class CompositionView extends WidgetView {
|
|
915
|
-
domAtPos(pos) {
|
|
916
|
-
let { topView, text } = this.widget;
|
|
917
|
-
if (!topView)
|
|
918
|
-
return new DOMPos(text, Math.min(pos, text.nodeValue.length));
|
|
919
|
-
return scanCompositionTree(pos, 0, topView, text, this.length - topView.length, (v, p) => v.domAtPos(p), (text, p) => new DOMPos(text, Math.min(p, text.nodeValue.length)));
|
|
920
|
-
}
|
|
921
|
-
sync() { this.setDOM(this.widget.toDOM()); }
|
|
922
|
-
localPosFromDOM(node, offset) {
|
|
923
|
-
let { topView, text } = this.widget;
|
|
924
|
-
if (!topView)
|
|
925
|
-
return Math.min(offset, this.length);
|
|
926
|
-
return posFromDOMInCompositionTree(node, offset, topView, text, this.length - topView.length);
|
|
927
|
-
}
|
|
928
|
-
ignoreMutation() { return false; }
|
|
929
|
-
get overrideDOMText() { return null; }
|
|
930
|
-
coordsAt(pos, side) {
|
|
931
|
-
let { topView, text } = this.widget;
|
|
932
|
-
if (!topView)
|
|
933
|
-
return textCoords(text, pos, side);
|
|
934
|
-
return scanCompositionTree(pos, side, topView, text, this.length - topView.length, (v, pos, side) => v.coordsAt(pos, side), (text, pos, side) => textCoords(text, pos, side));
|
|
935
|
-
}
|
|
936
|
-
destroy() {
|
|
937
|
-
var _a;
|
|
938
|
-
super.destroy();
|
|
939
|
-
(_a = this.widget.topView) === null || _a === void 0 ? void 0 : _a.destroy();
|
|
940
|
-
}
|
|
941
|
-
get isEditable() { return true; }
|
|
942
|
-
canReuseDOM() { return true; }
|
|
943
|
-
}
|
|
944
|
-
// Uses the old structure of a chunk of content view frozen for
|
|
945
|
-
// composition to try and find a reasonable DOM location for the given
|
|
946
|
-
// offset.
|
|
947
|
-
function scanCompositionTree(pos, side, view, text, dLen, enterView, fromText) {
|
|
948
|
-
if (view instanceof MarkView) {
|
|
949
|
-
for (let child = view.dom.firstChild; child; child = child.nextSibling) {
|
|
950
|
-
let desc = ContentView.get(child);
|
|
951
|
-
if (!desc) {
|
|
952
|
-
let inner = scanCompositionNode(pos, side, child, fromText);
|
|
953
|
-
if (typeof inner != "number")
|
|
954
|
-
return inner;
|
|
955
|
-
pos = inner;
|
|
956
|
-
}
|
|
957
|
-
else {
|
|
958
|
-
let hasComp = contains(child, text);
|
|
959
|
-
let len = desc.length + (hasComp ? dLen : 0);
|
|
960
|
-
if (pos < len || pos == len && desc.getSide() <= 0)
|
|
961
|
-
return hasComp ? scanCompositionTree(pos, side, desc, text, dLen, enterView, fromText) : enterView(desc, pos, side);
|
|
962
|
-
pos -= len;
|
|
963
|
-
}
|
|
964
|
-
}
|
|
965
|
-
return enterView(view, view.length, -1);
|
|
966
|
-
}
|
|
967
|
-
else if (view.dom == text) {
|
|
968
|
-
return fromText(text, pos, side);
|
|
969
|
-
}
|
|
970
|
-
else {
|
|
971
|
-
return enterView(view, pos, side);
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
function scanCompositionNode(pos, side, node, fromText) {
|
|
975
|
-
if (node.nodeType == 3) {
|
|
976
|
-
let len = node.nodeValue.length;
|
|
977
|
-
if (pos <= len)
|
|
978
|
-
return fromText(node, pos, side);
|
|
979
|
-
pos -= len;
|
|
980
|
-
}
|
|
981
|
-
else if (node.nodeType == 1 && node.contentEditable != "false") {
|
|
982
|
-
for (let child = node.firstChild; child; child = child.nextSibling) {
|
|
983
|
-
let inner = scanCompositionNode(pos, side, child, fromText);
|
|
984
|
-
if (typeof inner != "number")
|
|
985
|
-
return inner;
|
|
986
|
-
pos = inner;
|
|
987
|
-
}
|
|
988
|
-
}
|
|
989
|
-
return pos;
|
|
990
|
-
}
|
|
991
|
-
function posFromDOMInCompositionTree(node, offset, view, text, dLen) {
|
|
992
|
-
if (view instanceof MarkView) {
|
|
993
|
-
let pos = 0;
|
|
994
|
-
for (let child = view.dom.firstChild; child; child = child.nextSibling) {
|
|
995
|
-
let childView = ContentView.get(child);
|
|
996
|
-
if (childView) {
|
|
997
|
-
let hasComp = contains(child, text);
|
|
998
|
-
if (contains(child, node))
|
|
999
|
-
return pos + (hasComp ? posFromDOMInCompositionTree(node, offset, childView, text, dLen)
|
|
1000
|
-
: childView.localPosFromDOM(node, offset));
|
|
1001
|
-
pos += childView.length + (hasComp ? dLen : 0);
|
|
1002
|
-
}
|
|
1003
|
-
else {
|
|
1004
|
-
let inner = posFromDOMInOpaqueNode(node, offset, child);
|
|
1005
|
-
if (inner.result != null)
|
|
1006
|
-
return pos + inner.result;
|
|
1007
|
-
pos += inner.size;
|
|
1008
|
-
}
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1011
|
-
else if (view.dom == text) {
|
|
1012
|
-
return Math.min(offset, text.nodeValue.length);
|
|
1013
|
-
}
|
|
1014
|
-
return view.localPosFromDOM(node, offset);
|
|
1015
|
-
}
|
|
1016
|
-
function posFromDOMInOpaqueNode(node, offset, target) {
|
|
1017
|
-
if (target.nodeType == 3) {
|
|
1018
|
-
return node == target ? { result: offset } : { size: target.nodeValue.length };
|
|
1019
|
-
}
|
|
1020
|
-
else if (target.nodeType == 1 && target.contentEditable != "false") {
|
|
1021
|
-
let pos = 0;
|
|
1022
|
-
for (let child = target.firstChild, i = 0;; child = child.nextSibling, i++) {
|
|
1023
|
-
if (node == target && i == offset)
|
|
1024
|
-
return { result: pos };
|
|
1025
|
-
if (!child)
|
|
1026
|
-
return { size: pos };
|
|
1027
|
-
let inner = posFromDOMInOpaqueNode(node, offset, child);
|
|
1028
|
-
if (inner.result != null)
|
|
1029
|
-
return { result: offset + inner.result };
|
|
1030
|
-
pos += inner.size;
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
|
-
else {
|
|
1034
|
-
return target.contains(node) ? { result: 0 } : { size: 0 };
|
|
1035
|
-
}
|
|
1036
|
-
}
|
|
1037
1032
|
// These are drawn around uneditable widgets to avoid a number of
|
|
1038
1033
|
// browser bugs that show up when the cursor is directly next to
|
|
1039
1034
|
// uneditable inline content.
|
|
@@ -1153,16 +1148,20 @@ function combineAttrs(source, target) {
|
|
|
1153
1148
|
}
|
|
1154
1149
|
return target;
|
|
1155
1150
|
}
|
|
1156
|
-
|
|
1151
|
+
const noAttrs = Object.create(null);
|
|
1152
|
+
function attrsEq(a, b, ignore) {
|
|
1157
1153
|
if (a == b)
|
|
1158
1154
|
return true;
|
|
1159
|
-
if (!a
|
|
1160
|
-
|
|
1155
|
+
if (!a)
|
|
1156
|
+
a = noAttrs;
|
|
1157
|
+
if (!b)
|
|
1158
|
+
b = noAttrs;
|
|
1161
1159
|
let keysA = Object.keys(a), keysB = Object.keys(b);
|
|
1162
|
-
if (keysA.length
|
|
1160
|
+
if (keysA.length - (ignore && keysA.indexOf(ignore) > -1 ? 1 : 0) !=
|
|
1161
|
+
keysB.length - (ignore && keysB.indexOf(ignore) > -1 ? 1 : 0))
|
|
1163
1162
|
return false;
|
|
1164
1163
|
for (let key of keysA) {
|
|
1165
|
-
if (keysB.indexOf(key) == -1 || a[key] !== b[key])
|
|
1164
|
+
if (key != ignore && (keysB.indexOf(key) == -1 || a[key] !== b[key]))
|
|
1166
1165
|
return false;
|
|
1167
1166
|
}
|
|
1168
1167
|
return true;
|
|
@@ -1179,6 +1178,14 @@ function updateAttrs(dom, prev, attrs) {
|
|
|
1179
1178
|
dom.setAttribute(changed = name, attrs[name]);
|
|
1180
1179
|
return !!changed;
|
|
1181
1180
|
}
|
|
1181
|
+
function getAttrs(dom) {
|
|
1182
|
+
let attrs = Object.create(null);
|
|
1183
|
+
for (let i = 0; i < dom.attributes.length; i++) {
|
|
1184
|
+
let attr = dom.attributes[i];
|
|
1185
|
+
attrs[attr.name] = attr.value;
|
|
1186
|
+
}
|
|
1187
|
+
return attrs;
|
|
1188
|
+
}
|
|
1182
1189
|
|
|
1183
1190
|
/**
|
|
1184
1191
|
Widgets added to the content are described by subclasses of this
|
|
@@ -1243,10 +1250,6 @@ class WidgetType {
|
|
|
1243
1250
|
/**
|
|
1244
1251
|
@internal
|
|
1245
1252
|
*/
|
|
1246
|
-
get customView() { return null; }
|
|
1247
|
-
/**
|
|
1248
|
-
@internal
|
|
1249
|
-
*/
|
|
1250
1253
|
get isHidden() { return false; }
|
|
1251
1254
|
/**
|
|
1252
1255
|
This is called when the an instance of the widget is removed
|
|
@@ -1385,11 +1388,12 @@ class MarkDecoration extends Decoration {
|
|
|
1385
1388
|
this.attrs = spec.attributes || null;
|
|
1386
1389
|
}
|
|
1387
1390
|
eq(other) {
|
|
1391
|
+
var _a, _b;
|
|
1388
1392
|
return this == other ||
|
|
1389
1393
|
other instanceof MarkDecoration &&
|
|
1390
1394
|
this.tagName == other.tagName &&
|
|
1391
|
-
this.class == other.class &&
|
|
1392
|
-
attrsEq(this.attrs, other.attrs);
|
|
1395
|
+
(this.class || ((_a = this.attrs) === null || _a === void 0 ? void 0 : _a.class)) == (other.class || ((_b = other.attrs) === null || _b === void 0 ? void 0 : _b.class)) &&
|
|
1396
|
+
attrsEq(this.attrs, other.attrs, "class");
|
|
1393
1397
|
}
|
|
1394
1398
|
range(from, to = from) {
|
|
1395
1399
|
if (from >= to)
|
|
@@ -1541,7 +1545,7 @@ class LineView extends ContentView {
|
|
|
1541
1545
|
reuseDOM(node) {
|
|
1542
1546
|
if (node.nodeName == "DIV") {
|
|
1543
1547
|
this.setDOM(node);
|
|
1544
|
-
this.
|
|
1548
|
+
this.flags |= 4 /* AttrsDirty */ | 2 /* NodeDirty */;
|
|
1545
1549
|
}
|
|
1546
1550
|
}
|
|
1547
1551
|
sync(view, track) {
|
|
@@ -1551,7 +1555,7 @@ class LineView extends ContentView {
|
|
|
1551
1555
|
this.dom.className = "cm-line";
|
|
1552
1556
|
this.prevAttrs = this.attrs ? null : undefined;
|
|
1553
1557
|
}
|
|
1554
|
-
else if (this.
|
|
1558
|
+
else if (this.flags & 4 /* AttrsDirty */) {
|
|
1555
1559
|
clearAttributes(this.dom);
|
|
1556
1560
|
this.dom.className = "cm-line";
|
|
1557
1561
|
this.prevAttrs = this.attrs ? null : undefined;
|
|
@@ -2492,121 +2496,14 @@ function moveVisually(line, order, dir, start, forward) {
|
|
|
2492
2496
|
return state.EditorSelection.cursor(nextIndex + line.from, forward ? -1 : 1, span.level);
|
|
2493
2497
|
}
|
|
2494
2498
|
|
|
2495
|
-
const LineBreakPlaceholder = "\uffff";
|
|
2496
|
-
class DOMReader {
|
|
2497
|
-
constructor(points, state$1) {
|
|
2498
|
-
this.points = points;
|
|
2499
|
-
this.text = "";
|
|
2500
|
-
this.lineSeparator = state$1.facet(state.EditorState.lineSeparator);
|
|
2501
|
-
}
|
|
2502
|
-
append(text) {
|
|
2503
|
-
this.text += text;
|
|
2504
|
-
}
|
|
2505
|
-
lineBreak() {
|
|
2506
|
-
this.text += LineBreakPlaceholder;
|
|
2507
|
-
}
|
|
2508
|
-
readRange(start, end) {
|
|
2509
|
-
if (!start)
|
|
2510
|
-
return this;
|
|
2511
|
-
let parent = start.parentNode;
|
|
2512
|
-
for (let cur = start;;) {
|
|
2513
|
-
this.findPointBefore(parent, cur);
|
|
2514
|
-
let oldLen = this.text.length;
|
|
2515
|
-
this.readNode(cur);
|
|
2516
|
-
let next = cur.nextSibling;
|
|
2517
|
-
if (next == end)
|
|
2518
|
-
break;
|
|
2519
|
-
let view = ContentView.get(cur), nextView = ContentView.get(next);
|
|
2520
|
-
if (view && nextView ? view.breakAfter :
|
|
2521
|
-
(view ? view.breakAfter : isBlockElement(cur)) ||
|
|
2522
|
-
(isBlockElement(next) && (cur.nodeName != "BR" || cur.cmIgnore) && this.text.length > oldLen))
|
|
2523
|
-
this.lineBreak();
|
|
2524
|
-
cur = next;
|
|
2525
|
-
}
|
|
2526
|
-
this.findPointBefore(parent, end);
|
|
2527
|
-
return this;
|
|
2528
|
-
}
|
|
2529
|
-
readTextNode(node) {
|
|
2530
|
-
let text = node.nodeValue;
|
|
2531
|
-
for (let point of this.points)
|
|
2532
|
-
if (point.node == node)
|
|
2533
|
-
point.pos = this.text.length + Math.min(point.offset, text.length);
|
|
2534
|
-
for (let off = 0, re = this.lineSeparator ? null : /\r\n?|\n/g;;) {
|
|
2535
|
-
let nextBreak = -1, breakSize = 1, m;
|
|
2536
|
-
if (this.lineSeparator) {
|
|
2537
|
-
nextBreak = text.indexOf(this.lineSeparator, off);
|
|
2538
|
-
breakSize = this.lineSeparator.length;
|
|
2539
|
-
}
|
|
2540
|
-
else if (m = re.exec(text)) {
|
|
2541
|
-
nextBreak = m.index;
|
|
2542
|
-
breakSize = m[0].length;
|
|
2543
|
-
}
|
|
2544
|
-
this.append(text.slice(off, nextBreak < 0 ? text.length : nextBreak));
|
|
2545
|
-
if (nextBreak < 0)
|
|
2546
|
-
break;
|
|
2547
|
-
this.lineBreak();
|
|
2548
|
-
if (breakSize > 1)
|
|
2549
|
-
for (let point of this.points)
|
|
2550
|
-
if (point.node == node && point.pos > this.text.length)
|
|
2551
|
-
point.pos -= breakSize - 1;
|
|
2552
|
-
off = nextBreak + breakSize;
|
|
2553
|
-
}
|
|
2554
|
-
}
|
|
2555
|
-
readNode(node) {
|
|
2556
|
-
if (node.cmIgnore)
|
|
2557
|
-
return;
|
|
2558
|
-
let view = ContentView.get(node);
|
|
2559
|
-
let fromView = view && view.overrideDOMText;
|
|
2560
|
-
if (fromView != null) {
|
|
2561
|
-
this.findPointInside(node, fromView.length);
|
|
2562
|
-
for (let i = fromView.iter(); !i.next().done;) {
|
|
2563
|
-
if (i.lineBreak)
|
|
2564
|
-
this.lineBreak();
|
|
2565
|
-
else
|
|
2566
|
-
this.append(i.value);
|
|
2567
|
-
}
|
|
2568
|
-
}
|
|
2569
|
-
else if (node.nodeType == 3) {
|
|
2570
|
-
this.readTextNode(node);
|
|
2571
|
-
}
|
|
2572
|
-
else if (node.nodeName == "BR") {
|
|
2573
|
-
if (node.nextSibling)
|
|
2574
|
-
this.lineBreak();
|
|
2575
|
-
}
|
|
2576
|
-
else if (node.nodeType == 1) {
|
|
2577
|
-
this.readRange(node.firstChild, null);
|
|
2578
|
-
}
|
|
2579
|
-
}
|
|
2580
|
-
findPointBefore(node, next) {
|
|
2581
|
-
for (let point of this.points)
|
|
2582
|
-
if (point.node == node && node.childNodes[point.offset] == next)
|
|
2583
|
-
point.pos = this.text.length;
|
|
2584
|
-
}
|
|
2585
|
-
findPointInside(node, maxLen) {
|
|
2586
|
-
for (let point of this.points)
|
|
2587
|
-
if (node.nodeType == 3 ? point.node == node : node.contains(point.node))
|
|
2588
|
-
point.pos = this.text.length + Math.min(maxLen, point.offset);
|
|
2589
|
-
}
|
|
2590
|
-
}
|
|
2591
|
-
function isBlockElement(node) {
|
|
2592
|
-
return node.nodeType == 1 && /^(DIV|P|LI|UL|OL|BLOCKQUOTE|DD|DT|H\d|SECTION|PRE)$/.test(node.nodeName);
|
|
2593
|
-
}
|
|
2594
|
-
class DOMPoint {
|
|
2595
|
-
constructor(node, offset) {
|
|
2596
|
-
this.node = node;
|
|
2597
|
-
this.offset = offset;
|
|
2598
|
-
this.pos = -1;
|
|
2599
|
-
}
|
|
2600
|
-
}
|
|
2601
|
-
|
|
2602
2499
|
class DocView extends ContentView {
|
|
2603
2500
|
constructor(view) {
|
|
2604
2501
|
super();
|
|
2605
2502
|
this.view = view;
|
|
2606
|
-
this.compositionDeco = Decoration.none;
|
|
2607
|
-
this.compositionNode = null;
|
|
2608
2503
|
this.decorations = [];
|
|
2609
2504
|
this.dynamicDecorationMap = [];
|
|
2505
|
+
this.hasComposition = null;
|
|
2506
|
+
this.markedForComposition = new Set;
|
|
2610
2507
|
// Track a minimum width for the editor. When measuring sizes in
|
|
2611
2508
|
// measureVisibleLineHeights, this is updated to point at the width
|
|
2612
2509
|
// of a given element and its extent in the document. When a change
|
|
@@ -2629,7 +2526,7 @@ class DocView extends ContentView {
|
|
|
2629
2526
|
this.children = [new LineView];
|
|
2630
2527
|
this.children[0].setParent(this);
|
|
2631
2528
|
this.updateDeco();
|
|
2632
|
-
this.updateInner([new ChangedRange(0, 0, 0, view.state.doc.length)], 0);
|
|
2529
|
+
this.updateInner([new ChangedRange(0, 0, 0, view.state.doc.length)], 0, null);
|
|
2633
2530
|
}
|
|
2634
2531
|
get length() { return this.view.state.doc.length; }
|
|
2635
2532
|
// Update the document view to a given state.
|
|
@@ -2644,24 +2541,30 @@ class DocView extends ContentView {
|
|
|
2644
2541
|
this.minWidthTo = update.changes.mapPos(this.minWidthTo, 1);
|
|
2645
2542
|
}
|
|
2646
2543
|
}
|
|
2647
|
-
|
|
2648
|
-
|
|
2544
|
+
let composition = this.view.inputState.composing < 0 ? null : findCompositionRange(this.view, update.changes);
|
|
2545
|
+
if (this.hasComposition) {
|
|
2546
|
+
this.markedForComposition.clear();
|
|
2547
|
+
let { from, to } = this.hasComposition;
|
|
2548
|
+
changedRanges = new ChangedRange(from, to, update.changes.mapPos(from, -1), update.changes.mapPos(to, 1))
|
|
2549
|
+
.addToSet(changedRanges.slice());
|
|
2550
|
+
}
|
|
2551
|
+
this.hasComposition = composition ? { from: composition.range.fromB, to: composition.range.toB } : null;
|
|
2649
2552
|
// When the DOM nodes around the selection are moved to another
|
|
2650
2553
|
// parent, Chrome sometimes reports a different selection through
|
|
2651
2554
|
// getSelection than the one that it actually shows to the user.
|
|
2652
2555
|
// This forces a selection update when lines are joined to work
|
|
2653
2556
|
// around that. Issue #54
|
|
2654
|
-
if ((browser.ie || browser.chrome) && !
|
|
2557
|
+
if ((browser.ie || browser.chrome) && !composition && update &&
|
|
2655
2558
|
update.state.doc.lines != update.startState.doc.lines)
|
|
2656
2559
|
this.forceSelection = true;
|
|
2657
2560
|
let prevDeco = this.decorations, deco = this.updateDeco();
|
|
2658
2561
|
let decoDiff = findChangedDeco(prevDeco, deco, update.changes);
|
|
2659
2562
|
changedRanges = ChangedRange.extendWithRanges(changedRanges, decoDiff);
|
|
2660
|
-
if (this.
|
|
2563
|
+
if (!(this.flags & 7 /* Dirty */) && changedRanges.length == 0) {
|
|
2661
2564
|
return false;
|
|
2662
2565
|
}
|
|
2663
2566
|
else {
|
|
2664
|
-
this.updateInner(changedRanges, update.startState.doc.length);
|
|
2567
|
+
this.updateInner(changedRanges, update.startState.doc.length, composition);
|
|
2665
2568
|
if (update.transactions.length)
|
|
2666
2569
|
this.lastUpdate = Date.now();
|
|
2667
2570
|
return true;
|
|
@@ -2669,9 +2572,9 @@ class DocView extends ContentView {
|
|
|
2669
2572
|
}
|
|
2670
2573
|
// Used by update and the constructor do perform the actual DOM
|
|
2671
2574
|
// update
|
|
2672
|
-
updateInner(changes, oldLength) {
|
|
2575
|
+
updateInner(changes, oldLength, composition) {
|
|
2673
2576
|
this.view.viewState.mustMeasureContent = true;
|
|
2674
|
-
this.updateChildren(changes, oldLength);
|
|
2577
|
+
this.updateChildren(changes, oldLength, composition);
|
|
2675
2578
|
let { observer } = this.view;
|
|
2676
2579
|
observer.ignore(() => {
|
|
2677
2580
|
// Lock the height during redrawing, since Chrome sometimes
|
|
@@ -2686,11 +2589,12 @@ class DocView extends ContentView {
|
|
|
2686
2589
|
// to detect that situation.
|
|
2687
2590
|
let track = browser.chrome || browser.ios ? { node: observer.selectionRange.focusNode, written: false } : undefined;
|
|
2688
2591
|
this.sync(this.view, track);
|
|
2689
|
-
this.
|
|
2592
|
+
this.flags &= ~7 /* Dirty */;
|
|
2690
2593
|
if (track && (track.written || observer.selectionRange.focusNode != track.node))
|
|
2691
2594
|
this.forceSelection = true;
|
|
2692
2595
|
this.dom.style.height = "";
|
|
2693
2596
|
});
|
|
2597
|
+
this.markedForComposition.forEach(cView => cView.flags &= ~8 /* Composition */);
|
|
2694
2598
|
let gaps = [];
|
|
2695
2599
|
if (this.view.viewport.from || this.view.viewport.to < this.view.state.doc.length)
|
|
2696
2600
|
for (let child of this.children)
|
|
@@ -2698,18 +2602,71 @@ class DocView extends ContentView {
|
|
|
2698
2602
|
gaps.push(child.dom);
|
|
2699
2603
|
observer.updateGaps(gaps);
|
|
2700
2604
|
}
|
|
2701
|
-
updateChildren(changes, oldLength) {
|
|
2605
|
+
updateChildren(changes, oldLength, composition) {
|
|
2606
|
+
let ranges = composition ? composition.range.addToSet(changes.slice()) : changes;
|
|
2702
2607
|
let cursor = this.childCursor(oldLength);
|
|
2703
|
-
for (let i =
|
|
2704
|
-
let next = i >= 0 ?
|
|
2608
|
+
for (let i = ranges.length - 1;; i--) {
|
|
2609
|
+
let next = i >= 0 ? ranges[i] : null;
|
|
2705
2610
|
if (!next)
|
|
2706
2611
|
break;
|
|
2707
|
-
let { fromA, toA, fromB, toB } = next;
|
|
2708
|
-
|
|
2612
|
+
let { fromA, toA, fromB, toB } = next, content, breakAtStart, openStart, openEnd;
|
|
2613
|
+
if (composition && composition.range.fromB < toB && composition.range.toB > fromB) {
|
|
2614
|
+
let before = ContentBuilder.build(this.view.state.doc, fromB, composition.range.fromB, this.decorations, this.dynamicDecorationMap);
|
|
2615
|
+
let after = ContentBuilder.build(this.view.state.doc, composition.range.toB, toB, this.decorations, this.dynamicDecorationMap);
|
|
2616
|
+
breakAtStart = before.breakAtStart;
|
|
2617
|
+
openStart = before.openStart;
|
|
2618
|
+
openEnd = after.openEnd;
|
|
2619
|
+
let compLine = this.compositionView(composition);
|
|
2620
|
+
if (after.content.length) {
|
|
2621
|
+
compLine.breakAfter = after.content[0].breakAfter;
|
|
2622
|
+
if (compLine.merge(compLine.length, compLine.length, after.content[0], false, after.openStart, 0))
|
|
2623
|
+
after.content.shift();
|
|
2624
|
+
}
|
|
2625
|
+
if (before.content.length) {
|
|
2626
|
+
if (compLine.merge(0, 0, before.content[before.content.length - 1], true, 0, before.openEnd))
|
|
2627
|
+
before.content.pop();
|
|
2628
|
+
}
|
|
2629
|
+
content = before.content.concat(compLine).concat(after.content);
|
|
2630
|
+
}
|
|
2631
|
+
else {
|
|
2632
|
+
({ content, breakAtStart, openStart, openEnd } =
|
|
2633
|
+
ContentBuilder.build(this.view.state.doc, fromB, toB, this.decorations, this.dynamicDecorationMap));
|
|
2634
|
+
}
|
|
2709
2635
|
let { i: toI, off: toOff } = cursor.findPos(toA, 1);
|
|
2710
2636
|
let { i: fromI, off: fromOff } = cursor.findPos(fromA, -1);
|
|
2711
2637
|
replaceRange(this, fromI, fromOff, toI, toOff, content, breakAtStart, openStart, openEnd);
|
|
2712
2638
|
}
|
|
2639
|
+
if (composition)
|
|
2640
|
+
this.fixCompositionDOM(composition);
|
|
2641
|
+
}
|
|
2642
|
+
compositionView(composition) {
|
|
2643
|
+
let cur = new TextView(composition.text.nodeValue);
|
|
2644
|
+
cur.flags |= 8 /* Composition */;
|
|
2645
|
+
for (let { deco } of composition.marks)
|
|
2646
|
+
cur = new MarkView(deco, [cur], cur.length);
|
|
2647
|
+
let line = new LineView;
|
|
2648
|
+
line.append(cur, 0);
|
|
2649
|
+
return line;
|
|
2650
|
+
}
|
|
2651
|
+
fixCompositionDOM(composition) {
|
|
2652
|
+
let fix = (dom, cView) => {
|
|
2653
|
+
cView.flags |= 8 /* Composition */;
|
|
2654
|
+
this.markedForComposition.add(cView);
|
|
2655
|
+
let prev = ContentView.get(dom);
|
|
2656
|
+
if (prev != cView) {
|
|
2657
|
+
if (prev)
|
|
2658
|
+
prev.dom = null;
|
|
2659
|
+
cView.setDOM(dom);
|
|
2660
|
+
}
|
|
2661
|
+
};
|
|
2662
|
+
let pos = this.childPos(composition.range.fromB, 1);
|
|
2663
|
+
let cView = this.children[pos.i];
|
|
2664
|
+
fix(composition.line, cView);
|
|
2665
|
+
for (let i = composition.marks.length - 1; i >= -1; i--) {
|
|
2666
|
+
pos = cView.childPos(pos.off, 1);
|
|
2667
|
+
cView = cView.children[pos.i];
|
|
2668
|
+
fix(i >= 0 ? composition.marks[i].node : composition.text, cView);
|
|
2669
|
+
}
|
|
2713
2670
|
}
|
|
2714
2671
|
// Sync the DOM selection to this.state.selection
|
|
2715
2672
|
updateSelection(mustRead = false, fromPointer = false) {
|
|
@@ -2728,7 +2685,7 @@ class DocView extends ContentView {
|
|
|
2728
2685
|
let head = main.empty ? anchor : this.domAtPos(main.head);
|
|
2729
2686
|
// Always reset on Firefox when next to an uneditable node to
|
|
2730
2687
|
// avoid invisible cursor bugs (#111)
|
|
2731
|
-
if (browser.gecko && main.empty && !this.
|
|
2688
|
+
if (browser.gecko && main.empty && !this.hasComposition && betweenUneditable(anchor)) {
|
|
2732
2689
|
let dummy = document.createTextNode("");
|
|
2733
2690
|
this.view.observer.ignore(() => anchor.node.insertBefore(dummy, anchor.node.childNodes[anchor.offset] || null));
|
|
2734
2691
|
anchor = head = new DOMPos(dummy, 0);
|
|
@@ -2800,7 +2757,7 @@ class DocView extends ContentView {
|
|
|
2800
2757
|
this.impreciseHead = head.precise ? null : new DOMPos(domSel.focusNode, domSel.focusOffset);
|
|
2801
2758
|
}
|
|
2802
2759
|
enforceCursorAssoc() {
|
|
2803
|
-
if (this.
|
|
2760
|
+
if (this.hasComposition)
|
|
2804
2761
|
return;
|
|
2805
2762
|
let { view } = this, cursor = view.state.selection.main;
|
|
2806
2763
|
let sel = getSelection(view.root);
|
|
@@ -2910,6 +2867,7 @@ class DocView extends ContentView {
|
|
|
2910
2867
|
let dummy = document.createElement("div"), lineHeight, charWidth, textHeight;
|
|
2911
2868
|
dummy.className = "cm-line";
|
|
2912
2869
|
dummy.style.width = "99999px";
|
|
2870
|
+
dummy.style.position = "absolute";
|
|
2913
2871
|
dummy.textContent = "abc def ghi jkl mno pqr stu";
|
|
2914
2872
|
this.view.observer.ignore(() => {
|
|
2915
2873
|
this.dom.appendChild(dummy);
|
|
@@ -2959,7 +2917,6 @@ class DocView extends ContentView {
|
|
|
2959
2917
|
this.dynamicDecorationMap[i] = false;
|
|
2960
2918
|
return this.decorations = [
|
|
2961
2919
|
...allDeco,
|
|
2962
|
-
this.compositionDeco,
|
|
2963
2920
|
this.computeBlockGapDeco(),
|
|
2964
2921
|
this.view.viewState.lineGapDeco
|
|
2965
2922
|
];
|
|
@@ -3002,83 +2959,86 @@ class BlockGapWidget extends WidgetType {
|
|
|
3002
2959
|
}
|
|
3003
2960
|
get estimatedHeight() { return this.height; }
|
|
3004
2961
|
}
|
|
3005
|
-
function
|
|
2962
|
+
function findCompositionNode(view) {
|
|
3006
2963
|
let sel = view.observer.selectionRange;
|
|
3007
2964
|
let textNode = sel.focusNode && nearbyTextNode(sel.focusNode, sel.focusOffset, 0);
|
|
3008
2965
|
if (!textNode)
|
|
3009
2966
|
return null;
|
|
3010
|
-
let cView =
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
while (topNode.parentNode != cView.dom)
|
|
3016
|
-
topNode = topNode.parentNode;
|
|
3017
|
-
let prev = topNode.previousSibling;
|
|
3018
|
-
while (prev && !ContentView.get(prev))
|
|
3019
|
-
prev = prev.previousSibling;
|
|
3020
|
-
let pos = prev ? ContentView.get(prev).posAtEnd : cView.posAtStart;
|
|
3021
|
-
return { from: pos, to: pos, node: topNode, text: textNode };
|
|
2967
|
+
let cView = ContentView.get(textNode);
|
|
2968
|
+
let from, to;
|
|
2969
|
+
if (cView instanceof TextView) {
|
|
2970
|
+
from = cView.posAtStart;
|
|
2971
|
+
to = from + cView.length;
|
|
3022
2972
|
}
|
|
3023
2973
|
else {
|
|
3024
|
-
for (;;) {
|
|
3025
|
-
let
|
|
3026
|
-
|
|
2974
|
+
up: for (let offset = 0, node = textNode;;) {
|
|
2975
|
+
for (let sibling = node.previousSibling, cView; sibling; sibling = sibling.previousSibling) {
|
|
2976
|
+
if (cView = ContentView.get(sibling)) {
|
|
2977
|
+
from = to = cView.posAtEnd + offset;
|
|
2978
|
+
break up;
|
|
2979
|
+
}
|
|
2980
|
+
let reader = new DOMReader([], view.state);
|
|
2981
|
+
reader.readNode(sibling);
|
|
2982
|
+
if (reader.text.indexOf(LineBreakPlaceholder) > -1)
|
|
2983
|
+
return null;
|
|
2984
|
+
offset += reader.text.length;
|
|
2985
|
+
}
|
|
2986
|
+
node = node.parentNode;
|
|
2987
|
+
if (!node)
|
|
3027
2988
|
return null;
|
|
3028
|
-
|
|
2989
|
+
let parentView = ContentView.get(node);
|
|
2990
|
+
if (parentView) {
|
|
2991
|
+
from = to = parentView.posAtStart + offset;
|
|
3029
2992
|
break;
|
|
3030
|
-
|
|
3031
|
-
}
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
}
|
|
3035
|
-
}
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
let
|
|
3042
|
-
let
|
|
3043
|
-
|
|
3044
|
-
if (
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
if (state.doc.sliceString(
|
|
3053
|
-
|
|
3054
|
-
else if (state.doc.sliceString(
|
|
3055
|
-
|
|
2993
|
+
}
|
|
2994
|
+
}
|
|
2995
|
+
}
|
|
2996
|
+
let { main } = view.state.selection;
|
|
2997
|
+
return from > main.head || to < main.head ? null : { from, to, node: textNode };
|
|
2998
|
+
}
|
|
2999
|
+
function findCompositionRange(view, changes) {
|
|
3000
|
+
let found = findCompositionNode(view);
|
|
3001
|
+
if (!found)
|
|
3002
|
+
return null;
|
|
3003
|
+
let { from: fromA, to: toA, node: textNode } = found;
|
|
3004
|
+
let fromB = changes.mapPos(fromA, -1), toB = changes.mapPos(toA, 1);
|
|
3005
|
+
let text = textNode.nodeValue;
|
|
3006
|
+
// Don't try to preserve multi-line compositions
|
|
3007
|
+
if (/[\n\r]/.test(text))
|
|
3008
|
+
return null;
|
|
3009
|
+
if (toB - fromB != text.length) {
|
|
3010
|
+
// If there is a length mismatch, see if mapping non-inclusively helps
|
|
3011
|
+
let fromB2 = changes.mapPos(fromA, 1), toB2 = changes.mapPos(toA, -1);
|
|
3012
|
+
if (toB2 - fromB2 == text.length)
|
|
3013
|
+
fromB = fromB2, toB = toB2;
|
|
3014
|
+
// See if we can find an instance of the text at either side
|
|
3015
|
+
else if (view.state.doc.sliceString(toB - text.length, toB) == text)
|
|
3016
|
+
fromB = toB - text.length;
|
|
3017
|
+
else if (view.state.doc.sliceString(fromB, fromB + text.length) == text)
|
|
3018
|
+
toB = fromB + text.length;
|
|
3019
|
+
// Not found
|
|
3056
3020
|
else
|
|
3057
|
-
return
|
|
3058
|
-
}
|
|
3059
|
-
|
|
3060
|
-
return
|
|
3061
|
-
|
|
3062
|
-
let
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3021
|
+
return null;
|
|
3022
|
+
}
|
|
3023
|
+
if (view.state.doc.sliceString(fromB, toB) != text)
|
|
3024
|
+
return null;
|
|
3025
|
+
let marks = [];
|
|
3026
|
+
let range = new ChangedRange(fromA, toA, fromB, toB);
|
|
3027
|
+
for (let parent = textNode.parentNode;; parent = parent.parentNode) {
|
|
3028
|
+
let parentView = ContentView.get(parent);
|
|
3029
|
+
if (parentView instanceof MarkView)
|
|
3030
|
+
marks.push({ node: parent, deco: parentView.mark });
|
|
3031
|
+
else if (parentView instanceof LineView || parent.nodeName == "DIV" && parent.parentNode == view.contentDOM)
|
|
3032
|
+
return { range, text: textNode, marks, line: parent };
|
|
3033
|
+
else if (parent != view.contentDOM)
|
|
3034
|
+
marks.push({ node: parent, deco: new MarkDecoration({
|
|
3035
|
+
inclusive: true,
|
|
3036
|
+
attributes: getAttrs(parent),
|
|
3037
|
+
tagName: parent.tagName.toLowerCase()
|
|
3038
|
+
}) });
|
|
3039
|
+
else
|
|
3040
|
+
return null;
|
|
3077
3041
|
}
|
|
3078
|
-
eq(other) { return this.top == other.top && this.text == other.text; }
|
|
3079
|
-
toDOM() { return this.top; }
|
|
3080
|
-
ignoreEvent() { return false; }
|
|
3081
|
-
get customView() { return CompositionView; }
|
|
3082
3042
|
}
|
|
3083
3043
|
function nearbyTextNode(startNode, startOffset, side) {
|
|
3084
3044
|
if (side <= 0)
|
|
@@ -3739,9 +3699,13 @@ const dragScrollMargin = 6;
|
|
|
3739
3699
|
function dragScrollSpeed(dist) {
|
|
3740
3700
|
return Math.max(0, dist) * 0.7 + 8;
|
|
3741
3701
|
}
|
|
3702
|
+
function dist(a, b) {
|
|
3703
|
+
return Math.max(Math.abs(a.clientX - b.clientX), Math.abs(a.clientY - b.clientY));
|
|
3704
|
+
}
|
|
3742
3705
|
class MouseSelection {
|
|
3743
3706
|
constructor(view, startEvent, style, mustSelect) {
|
|
3744
3707
|
this.view = view;
|
|
3708
|
+
this.startEvent = startEvent;
|
|
3745
3709
|
this.style = style;
|
|
3746
3710
|
this.mustSelect = mustSelect;
|
|
3747
3711
|
this.scrollSpeed = { x: 0, y: 0 };
|
|
@@ -3768,7 +3732,7 @@ class MouseSelection {
|
|
|
3768
3732
|
var _a;
|
|
3769
3733
|
if (event.buttons == 0)
|
|
3770
3734
|
return this.destroy();
|
|
3771
|
-
if (this.dragging
|
|
3735
|
+
if (this.dragging || this.dragging == null && dist(this.startEvent, event) < 10)
|
|
3772
3736
|
return;
|
|
3773
3737
|
this.select(this.lastEvent = event);
|
|
3774
3738
|
let sx = 0, sy = 0;
|
|
@@ -3847,7 +3811,7 @@ class MouseSelection {
|
|
|
3847
3811
|
select(event) {
|
|
3848
3812
|
let { view } = this, selection = this.skipAtoms(this.style.get(event, this.extend, this.multiple));
|
|
3849
3813
|
if (this.mustSelect || !selection.eq(view.state.selection) ||
|
|
3850
|
-
selection.main.assoc != view.state.selection.main.assoc)
|
|
3814
|
+
selection.main.assoc != view.state.selection.main.assoc && this.dragging === false)
|
|
3851
3815
|
this.view.dispatch({
|
|
3852
3816
|
selection,
|
|
3853
3817
|
userEvent: "select.pointer"
|
|
@@ -4266,7 +4230,7 @@ handlers.compositionend = view => {
|
|
|
4266
4230
|
// Otherwise, make sure that, if no changes come in soon, the
|
|
4267
4231
|
// composition view is cleared.
|
|
4268
4232
|
setTimeout(() => {
|
|
4269
|
-
if (view.inputState.composing < 0 && view.docView.
|
|
4233
|
+
if (view.inputState.composing < 0 && view.docView.hasComposition)
|
|
4270
4234
|
view.update([]);
|
|
4271
4235
|
}, 50);
|
|
4272
4236
|
}
|
|
@@ -5983,7 +5947,7 @@ function applyDOMChange(view, domChange) {
|
|
|
5983
5947
|
if (startState.selection.ranges.length > 1 && view.inputState.composing >= 0 &&
|
|
5984
5948
|
change.to <= sel.to && change.to >= sel.to - 10) {
|
|
5985
5949
|
let replaced = view.state.sliceDoc(change.from, change.to);
|
|
5986
|
-
let
|
|
5950
|
+
let composition = findCompositionNode(view) || view.state.doc.lineAt(sel.head);
|
|
5987
5951
|
let offset = sel.to - change.to, size = sel.to - sel.from;
|
|
5988
5952
|
tr = startState.changeByRange(range => {
|
|
5989
5953
|
if (range.from == sel.from && range.to == sel.to)
|
|
@@ -5994,7 +5958,7 @@ function applyDOMChange(view, domChange) {
|
|
|
5994
5958
|
// changes in the same node work without aborting
|
|
5995
5959
|
// composition, so cursors in the composition range are
|
|
5996
5960
|
// ignored.
|
|
5997
|
-
|
|
5961
|
+
composition && range.to >= composition.from && range.from <= composition.to)
|
|
5998
5962
|
return { range };
|
|
5999
5963
|
let rangeChanges = startState.changes({ from, to, insert: change.insert }), selOff = range.to - sel.to;
|
|
6000
5964
|
return {
|
|
@@ -6455,7 +6419,7 @@ class DOMObserver {
|
|
|
6455
6419
|
return null;
|
|
6456
6420
|
cView.markDirty(rec.type == "attributes");
|
|
6457
6421
|
if (rec.type == "attributes")
|
|
6458
|
-
cView.
|
|
6422
|
+
cView.flags |= 4 /* AttrsDirty */;
|
|
6459
6423
|
if (rec.type == "childList") {
|
|
6460
6424
|
let childBefore = findChild(cView, rec.previousSibling || rec.target.previousSibling, -1);
|
|
6461
6425
|
let childAfter = findChild(cView, rec.nextSibling || rec.target.nextSibling, 1);
|
|
@@ -7629,7 +7593,7 @@ function buildKeymap(bindings, platform = currentPlatform) {
|
|
|
7629
7593
|
else if (current != is)
|
|
7630
7594
|
throw new Error("Key binding " + name + " is used both as a regular binding and as a multi-stroke prefix");
|
|
7631
7595
|
};
|
|
7632
|
-
let add = (scope, key, command, preventDefault) => {
|
|
7596
|
+
let add = (scope, key, command, preventDefault, stopPropagation) => {
|
|
7633
7597
|
var _a, _b;
|
|
7634
7598
|
let scopeObj = bound[scope] || (bound[scope] = Object.create(null));
|
|
7635
7599
|
let parts = key.split(/ (?!$)/).map(k => normalizeKeyName(k, platform));
|
|
@@ -7639,6 +7603,7 @@ function buildKeymap(bindings, platform = currentPlatform) {
|
|
|
7639
7603
|
if (!scopeObj[prefix])
|
|
7640
7604
|
scopeObj[prefix] = {
|
|
7641
7605
|
preventDefault: true,
|
|
7606
|
+
stopPropagation: false,
|
|
7642
7607
|
run: [(view) => {
|
|
7643
7608
|
let ourObj = storedPrefix = { view, prefix, scope };
|
|
7644
7609
|
setTimeout(() => { if (storedPrefix == ourObj)
|
|
@@ -7649,11 +7614,17 @@ function buildKeymap(bindings, platform = currentPlatform) {
|
|
|
7649
7614
|
}
|
|
7650
7615
|
let full = parts.join(" ");
|
|
7651
7616
|
checkPrefix(full, false);
|
|
7652
|
-
let binding = scopeObj[full] || (scopeObj[full] = {
|
|
7617
|
+
let binding = scopeObj[full] || (scopeObj[full] = {
|
|
7618
|
+
preventDefault: false,
|
|
7619
|
+
stopPropagation: false,
|
|
7620
|
+
run: ((_b = (_a = scopeObj._any) === null || _a === void 0 ? void 0 : _a.run) === null || _b === void 0 ? void 0 : _b.slice()) || []
|
|
7621
|
+
});
|
|
7653
7622
|
if (command)
|
|
7654
7623
|
binding.run.push(command);
|
|
7655
7624
|
if (preventDefault)
|
|
7656
7625
|
binding.preventDefault = true;
|
|
7626
|
+
if (stopPropagation)
|
|
7627
|
+
binding.stopPropagation = true;
|
|
7657
7628
|
};
|
|
7658
7629
|
for (let b of bindings) {
|
|
7659
7630
|
let scopes = b.scope ? b.scope.split(" ") : ["editor"];
|
|
@@ -7661,7 +7632,7 @@ function buildKeymap(bindings, platform = currentPlatform) {
|
|
|
7661
7632
|
for (let scope of scopes) {
|
|
7662
7633
|
let scopeObj = bound[scope] || (bound[scope] = Object.create(null));
|
|
7663
7634
|
if (!scopeObj._any)
|
|
7664
|
-
scopeObj._any = { preventDefault: false, run: [] };
|
|
7635
|
+
scopeObj._any = { preventDefault: false, stopPropagation: false, run: [] };
|
|
7665
7636
|
for (let key in scopeObj)
|
|
7666
7637
|
scopeObj[key].run.push(b.any);
|
|
7667
7638
|
}
|
|
@@ -7669,9 +7640,9 @@ function buildKeymap(bindings, platform = currentPlatform) {
|
|
|
7669
7640
|
if (!name)
|
|
7670
7641
|
continue;
|
|
7671
7642
|
for (let scope of scopes) {
|
|
7672
|
-
add(scope, name, b.run, b.preventDefault);
|
|
7643
|
+
add(scope, name, b.run, b.preventDefault, b.stopPropagation);
|
|
7673
7644
|
if (b.shift)
|
|
7674
|
-
add(scope, "Shift-" + name, b.shift, b.preventDefault);
|
|
7645
|
+
add(scope, "Shift-" + name, b.shift, b.preventDefault, b.stopPropagation);
|
|
7675
7646
|
}
|
|
7676
7647
|
}
|
|
7677
7648
|
return bound;
|
|
@@ -7679,11 +7650,13 @@ function buildKeymap(bindings, platform = currentPlatform) {
|
|
|
7679
7650
|
function runHandlers(map, event, view, scope) {
|
|
7680
7651
|
let name = w3cKeyname.keyName(event);
|
|
7681
7652
|
let charCode = state.codePointAt(name, 0), isChar = state.codePointSize(charCode) == name.length && name != " ";
|
|
7682
|
-
let prefix = "",
|
|
7653
|
+
let prefix = "", handled = false, prevented = false, stopPropagation = false;
|
|
7683
7654
|
if (storedPrefix && storedPrefix.view == view && storedPrefix.scope == scope) {
|
|
7684
7655
|
prefix = storedPrefix.prefix + " ";
|
|
7685
|
-
if (
|
|
7656
|
+
if (modifierCodes.indexOf(event.keyCode) < 0) {
|
|
7657
|
+
prevented = true;
|
|
7686
7658
|
storedPrefix = null;
|
|
7659
|
+
}
|
|
7687
7660
|
}
|
|
7688
7661
|
let ran = new Set;
|
|
7689
7662
|
let runFor = (binding) => {
|
|
@@ -7691,36 +7664,49 @@ function runHandlers(map, event, view, scope) {
|
|
|
7691
7664
|
for (let cmd of binding.run)
|
|
7692
7665
|
if (!ran.has(cmd)) {
|
|
7693
7666
|
ran.add(cmd);
|
|
7694
|
-
if (cmd(view, event))
|
|
7667
|
+
if (cmd(view, event)) {
|
|
7668
|
+
if (binding.stopPropagation)
|
|
7669
|
+
stopPropagation = true;
|
|
7695
7670
|
return true;
|
|
7671
|
+
}
|
|
7696
7672
|
}
|
|
7697
|
-
if (binding.preventDefault)
|
|
7698
|
-
|
|
7673
|
+
if (binding.preventDefault) {
|
|
7674
|
+
if (binding.stopPropagation)
|
|
7675
|
+
stopPropagation = true;
|
|
7676
|
+
prevented = true;
|
|
7677
|
+
}
|
|
7699
7678
|
}
|
|
7700
7679
|
return false;
|
|
7701
7680
|
};
|
|
7702
7681
|
let scopeObj = map[scope], baseName, shiftName;
|
|
7703
7682
|
if (scopeObj) {
|
|
7704
|
-
if (runFor(scopeObj[prefix + modifiers(name, event, !isChar)]))
|
|
7705
|
-
|
|
7706
|
-
|
|
7683
|
+
if (runFor(scopeObj[prefix + modifiers(name, event, !isChar)])) {
|
|
7684
|
+
handled = true;
|
|
7685
|
+
}
|
|
7686
|
+
else if (isChar && (event.altKey || event.metaKey || event.ctrlKey) &&
|
|
7707
7687
|
// Ctrl-Alt may be used for AltGr on Windows
|
|
7708
7688
|
!(browser.windows && event.ctrlKey && event.altKey) &&
|
|
7709
7689
|
(baseName = w3cKeyname.base[event.keyCode]) && baseName != name) {
|
|
7710
|
-
if (runFor(scopeObj[prefix + modifiers(baseName, event, true)]))
|
|
7711
|
-
|
|
7690
|
+
if (runFor(scopeObj[prefix + modifiers(baseName, event, true)])) {
|
|
7691
|
+
handled = true;
|
|
7692
|
+
}
|
|
7712
7693
|
else if (event.shiftKey && (shiftName = w3cKeyname.shift[event.keyCode]) != name && shiftName != baseName &&
|
|
7713
|
-
runFor(scopeObj[prefix + modifiers(shiftName, event, false)]))
|
|
7714
|
-
|
|
7694
|
+
runFor(scopeObj[prefix + modifiers(shiftName, event, false)])) {
|
|
7695
|
+
handled = true;
|
|
7696
|
+
}
|
|
7715
7697
|
}
|
|
7716
|
-
else if (isChar && event.shiftKey
|
|
7717
|
-
|
|
7718
|
-
|
|
7698
|
+
else if (isChar && event.shiftKey &&
|
|
7699
|
+
runFor(scopeObj[prefix + modifiers(name, event, true)])) {
|
|
7700
|
+
handled = true;
|
|
7719
7701
|
}
|
|
7720
|
-
if (runFor(scopeObj._any))
|
|
7721
|
-
|
|
7702
|
+
if (!handled && runFor(scopeObj._any))
|
|
7703
|
+
handled = true;
|
|
7722
7704
|
}
|
|
7723
|
-
|
|
7705
|
+
if (prevented)
|
|
7706
|
+
handled = true;
|
|
7707
|
+
if (handled && stopPropagation)
|
|
7708
|
+
event.stopPropagation();
|
|
7709
|
+
return handled;
|
|
7724
7710
|
}
|
|
7725
7711
|
|
|
7726
7712
|
/**
|
|
@@ -8507,7 +8493,9 @@ function placeholder(content) {
|
|
|
8507
8493
|
return ViewPlugin.fromClass(class {
|
|
8508
8494
|
constructor(view) {
|
|
8509
8495
|
this.view = view;
|
|
8510
|
-
this.placeholder =
|
|
8496
|
+
this.placeholder = content
|
|
8497
|
+
? Decoration.set([Decoration.widget({ widget: new Placeholder(content), side: 1 }).range(0)])
|
|
8498
|
+
: Decoration.none;
|
|
8511
8499
|
}
|
|
8512
8500
|
get decorations() { return this.view.state.doc.length ? Decoration.none : this.placeholder; }
|
|
8513
8501
|
}, { decorations: v => v.decorations });
|