@codemirror/view 6.14.0 → 6.15.0
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 +32 -0
- package/dist/index.cjs +391 -407
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +392 -408
- 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;
|
|
@@ -320,6 +322,9 @@ function atElementStart(doc, selection) {
|
|
|
320
322
|
}
|
|
321
323
|
}
|
|
322
324
|
}
|
|
325
|
+
function isScrolledToBottom(elt) {
|
|
326
|
+
return elt.scrollTop > Math.max(1, elt.scrollHeight - elt.clientHeight - 4);
|
|
327
|
+
}
|
|
323
328
|
|
|
324
329
|
class DOMPos {
|
|
325
330
|
constructor(node, offset, precise = true) {
|
|
@@ -335,7 +340,7 @@ class ContentView {
|
|
|
335
340
|
constructor() {
|
|
336
341
|
this.parent = null;
|
|
337
342
|
this.dom = null;
|
|
338
|
-
this.
|
|
343
|
+
this.flags = 2 /* NodeDirty */;
|
|
339
344
|
}
|
|
340
345
|
get overrideDOMText() { return null; }
|
|
341
346
|
get posAtStart() {
|
|
@@ -357,18 +362,18 @@ class ContentView {
|
|
|
357
362
|
return this.posBefore(view) + view.length;
|
|
358
363
|
}
|
|
359
364
|
sync(view, track) {
|
|
360
|
-
if (this.
|
|
365
|
+
if (this.flags & 2 /* NodeDirty */) {
|
|
361
366
|
let parent = this.dom;
|
|
362
367
|
let prev = null, next;
|
|
363
368
|
for (let child of this.children) {
|
|
364
|
-
if (child.
|
|
369
|
+
if (child.flags & 7 /* Dirty */) {
|
|
365
370
|
if (!child.dom && (next = prev ? prev.nextSibling : parent.firstChild)) {
|
|
366
371
|
let contentView = ContentView.get(next);
|
|
367
372
|
if (!contentView || !contentView.parent && contentView.canReuseDOM(child))
|
|
368
373
|
child.reuseDOM(next);
|
|
369
374
|
}
|
|
370
375
|
child.sync(view, track);
|
|
371
|
-
child.
|
|
376
|
+
child.flags &= ~7 /* Dirty */;
|
|
372
377
|
}
|
|
373
378
|
next = prev ? prev.nextSibling : parent.firstChild;
|
|
374
379
|
if (track && !track.written && track.node == parent && next != child.dom)
|
|
@@ -388,11 +393,11 @@ class ContentView {
|
|
|
388
393
|
while (next)
|
|
389
394
|
next = rm$1(next);
|
|
390
395
|
}
|
|
391
|
-
else if (this.
|
|
396
|
+
else if (this.flags & 1 /* ChildDirty */) {
|
|
392
397
|
for (let child of this.children)
|
|
393
|
-
if (child.
|
|
398
|
+
if (child.flags & 7 /* Dirty */) {
|
|
394
399
|
child.sync(view, track);
|
|
395
|
-
child.
|
|
400
|
+
child.flags &= ~7 /* Dirty */;
|
|
396
401
|
}
|
|
397
402
|
}
|
|
398
403
|
}
|
|
@@ -457,23 +462,23 @@ class ContentView {
|
|
|
457
462
|
endDOM: toI < this.children.length && toI >= 0 ? this.children[toI].dom : null };
|
|
458
463
|
}
|
|
459
464
|
markDirty(andParent = false) {
|
|
460
|
-
this.
|
|
465
|
+
this.flags |= 2 /* NodeDirty */;
|
|
461
466
|
this.markParentsDirty(andParent);
|
|
462
467
|
}
|
|
463
468
|
markParentsDirty(childList) {
|
|
464
469
|
for (let parent = this.parent; parent; parent = parent.parent) {
|
|
465
470
|
if (childList)
|
|
466
|
-
parent.
|
|
467
|
-
if (parent.
|
|
471
|
+
parent.flags |= 2 /* NodeDirty */;
|
|
472
|
+
if (parent.flags & 1 /* ChildDirty */)
|
|
468
473
|
return;
|
|
469
|
-
parent.
|
|
474
|
+
parent.flags |= 1 /* ChildDirty */;
|
|
470
475
|
childList = false;
|
|
471
476
|
}
|
|
472
477
|
}
|
|
473
478
|
setParent(parent) {
|
|
474
479
|
if (this.parent != parent) {
|
|
475
480
|
this.parent = parent;
|
|
476
|
-
if (this.
|
|
481
|
+
if (this.flags & 7 /* Dirty */)
|
|
477
482
|
this.markParentsDirty(true);
|
|
478
483
|
}
|
|
479
484
|
}
|
|
@@ -524,7 +529,9 @@ class ContentView {
|
|
|
524
529
|
return false;
|
|
525
530
|
}
|
|
526
531
|
become(other) { return false; }
|
|
527
|
-
canReuseDOM(other) {
|
|
532
|
+
canReuseDOM(other) {
|
|
533
|
+
return other.constructor == this.constructor && !((this.flags | other.flags) & 8 /* Composition */);
|
|
534
|
+
}
|
|
528
535
|
// When this is a zero-length view with a side, this should return a
|
|
529
536
|
// number <= 0 to indicate it is before its position, or a
|
|
530
537
|
// number > 0 when after its position.
|
|
@@ -648,6 +655,113 @@ function mergeChildrenInto(parent, from, to, insert, openStart, openEnd) {
|
|
|
648
655
|
replaceRange(parent, fromI, fromOff, toI, toOff, insert, 0, openStart, openEnd);
|
|
649
656
|
}
|
|
650
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
|
+
|
|
651
765
|
let nav = typeof navigator != "undefined" ? navigator : { userAgent: "", vendor: "", platform: "" };
|
|
652
766
|
let doc = typeof document != "undefined" ? document : { documentElement: { style: {} } };
|
|
653
767
|
const ie_edge = /Edge\/(\d+)/.exec(nav.userAgent);
|
|
@@ -701,7 +815,10 @@ class TextView extends ContentView {
|
|
|
701
815
|
this.createDOM(dom);
|
|
702
816
|
}
|
|
703
817
|
merge(from, to, source) {
|
|
704
|
-
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 */)))
|
|
705
822
|
return false;
|
|
706
823
|
this.text = this.text.slice(0, from) + (source ? source.text : "") + this.text.slice(to);
|
|
707
824
|
this.markDirty();
|
|
@@ -711,6 +828,7 @@ class TextView extends ContentView {
|
|
|
711
828
|
let result = new TextView(this.text.slice(from));
|
|
712
829
|
this.text = this.text.slice(0, from);
|
|
713
830
|
this.markDirty();
|
|
831
|
+
result.flags |= this.flags & 8 /* Composition */;
|
|
714
832
|
return result;
|
|
715
833
|
}
|
|
716
834
|
localPosFromDOM(node, offset) {
|
|
@@ -742,16 +860,19 @@ class MarkView extends ContentView {
|
|
|
742
860
|
dom.setAttribute(name, this.mark.attrs[name]);
|
|
743
861
|
return dom;
|
|
744
862
|
}
|
|
863
|
+
canReuseDOM(other) {
|
|
864
|
+
return super.canReuseDOM(other) && !((this.flags | other.flags) & 8 /* Composition */);
|
|
865
|
+
}
|
|
745
866
|
reuseDOM(node) {
|
|
746
867
|
if (node.nodeName == this.mark.tagName.toUpperCase()) {
|
|
747
868
|
this.setDOM(node);
|
|
748
|
-
this.
|
|
869
|
+
this.flags |= 4 /* AttrsDirty */ | 2 /* NodeDirty */;
|
|
749
870
|
}
|
|
750
871
|
}
|
|
751
872
|
sync(view, track) {
|
|
752
873
|
if (!this.dom)
|
|
753
874
|
this.setDOM(this.setAttrs(document.createElement(this.mark.tagName)));
|
|
754
|
-
else if (this.
|
|
875
|
+
else if (this.flags & 4 /* AttrsDirty */)
|
|
755
876
|
this.setAttrs(this.dom);
|
|
756
877
|
super.sync(view, track);
|
|
757
878
|
}
|
|
@@ -830,7 +951,7 @@ class WidgetView extends ContentView {
|
|
|
830
951
|
this.prevWidget = null;
|
|
831
952
|
}
|
|
832
953
|
static create(widget, length, side) {
|
|
833
|
-
return new
|
|
954
|
+
return new WidgetView(widget, length, side);
|
|
834
955
|
}
|
|
835
956
|
split(from) {
|
|
836
957
|
let result = WidgetView.create(this.widget, this.length - from, this.side);
|
|
@@ -908,129 +1029,6 @@ class WidgetView extends ContentView {
|
|
|
908
1029
|
this.widget.destroy(this.dom);
|
|
909
1030
|
}
|
|
910
1031
|
}
|
|
911
|
-
class CompositionView extends WidgetView {
|
|
912
|
-
domAtPos(pos) {
|
|
913
|
-
let { topView, text } = this.widget;
|
|
914
|
-
if (!topView)
|
|
915
|
-
return new DOMPos(text, Math.min(pos, text.nodeValue.length));
|
|
916
|
-
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)));
|
|
917
|
-
}
|
|
918
|
-
sync() { this.setDOM(this.widget.toDOM()); }
|
|
919
|
-
localPosFromDOM(node, offset) {
|
|
920
|
-
let { topView, text } = this.widget;
|
|
921
|
-
if (!topView)
|
|
922
|
-
return Math.min(offset, this.length);
|
|
923
|
-
return posFromDOMInCompositionTree(node, offset, topView, text, this.length - topView.length);
|
|
924
|
-
}
|
|
925
|
-
ignoreMutation() { return false; }
|
|
926
|
-
get overrideDOMText() { return null; }
|
|
927
|
-
coordsAt(pos, side) {
|
|
928
|
-
let { topView, text } = this.widget;
|
|
929
|
-
if (!topView)
|
|
930
|
-
return textCoords(text, pos, side);
|
|
931
|
-
return scanCompositionTree(pos, side, topView, text, this.length - topView.length, (v, pos, side) => v.coordsAt(pos, side), (text, pos, side) => textCoords(text, pos, side));
|
|
932
|
-
}
|
|
933
|
-
destroy() {
|
|
934
|
-
var _a;
|
|
935
|
-
super.destroy();
|
|
936
|
-
(_a = this.widget.topView) === null || _a === void 0 ? void 0 : _a.destroy();
|
|
937
|
-
}
|
|
938
|
-
get isEditable() { return true; }
|
|
939
|
-
canReuseDOM() { return true; }
|
|
940
|
-
}
|
|
941
|
-
// Uses the old structure of a chunk of content view frozen for
|
|
942
|
-
// composition to try and find a reasonable DOM location for the given
|
|
943
|
-
// offset.
|
|
944
|
-
function scanCompositionTree(pos, side, view, text, dLen, enterView, fromText) {
|
|
945
|
-
if (view instanceof MarkView) {
|
|
946
|
-
for (let child = view.dom.firstChild; child; child = child.nextSibling) {
|
|
947
|
-
let desc = ContentView.get(child);
|
|
948
|
-
if (!desc) {
|
|
949
|
-
let inner = scanCompositionNode(pos, side, child, fromText);
|
|
950
|
-
if (typeof inner != "number")
|
|
951
|
-
return inner;
|
|
952
|
-
pos = inner;
|
|
953
|
-
}
|
|
954
|
-
else {
|
|
955
|
-
let hasComp = contains(child, text);
|
|
956
|
-
let len = desc.length + (hasComp ? dLen : 0);
|
|
957
|
-
if (pos < len || pos == len && desc.getSide() <= 0)
|
|
958
|
-
return hasComp ? scanCompositionTree(pos, side, desc, text, dLen, enterView, fromText) : enterView(desc, pos, side);
|
|
959
|
-
pos -= len;
|
|
960
|
-
}
|
|
961
|
-
}
|
|
962
|
-
return enterView(view, view.length, -1);
|
|
963
|
-
}
|
|
964
|
-
else if (view.dom == text) {
|
|
965
|
-
return fromText(text, pos, side);
|
|
966
|
-
}
|
|
967
|
-
else {
|
|
968
|
-
return enterView(view, pos, side);
|
|
969
|
-
}
|
|
970
|
-
}
|
|
971
|
-
function scanCompositionNode(pos, side, node, fromText) {
|
|
972
|
-
if (node.nodeType == 3) {
|
|
973
|
-
let len = node.nodeValue.length;
|
|
974
|
-
if (pos <= len)
|
|
975
|
-
return fromText(node, pos, side);
|
|
976
|
-
pos -= len;
|
|
977
|
-
}
|
|
978
|
-
else if (node.nodeType == 1 && node.contentEditable != "false") {
|
|
979
|
-
for (let child = node.firstChild; child; child = child.nextSibling) {
|
|
980
|
-
let inner = scanCompositionNode(pos, side, child, fromText);
|
|
981
|
-
if (typeof inner != "number")
|
|
982
|
-
return inner;
|
|
983
|
-
pos = inner;
|
|
984
|
-
}
|
|
985
|
-
}
|
|
986
|
-
return pos;
|
|
987
|
-
}
|
|
988
|
-
function posFromDOMInCompositionTree(node, offset, view, text, dLen) {
|
|
989
|
-
if (view instanceof MarkView) {
|
|
990
|
-
let pos = 0;
|
|
991
|
-
for (let child = view.dom.firstChild; child; child = child.nextSibling) {
|
|
992
|
-
let childView = ContentView.get(child);
|
|
993
|
-
if (childView) {
|
|
994
|
-
let hasComp = contains(child, text);
|
|
995
|
-
if (contains(child, node))
|
|
996
|
-
return pos + (hasComp ? posFromDOMInCompositionTree(node, offset, childView, text, dLen)
|
|
997
|
-
: childView.localPosFromDOM(node, offset));
|
|
998
|
-
pos += childView.length + (hasComp ? dLen : 0);
|
|
999
|
-
}
|
|
1000
|
-
else {
|
|
1001
|
-
let inner = posFromDOMInOpaqueNode(node, offset, child);
|
|
1002
|
-
if (inner.result != null)
|
|
1003
|
-
return pos + inner.result;
|
|
1004
|
-
pos += inner.size;
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
}
|
|
1008
|
-
else if (view.dom == text) {
|
|
1009
|
-
return Math.min(offset, text.nodeValue.length);
|
|
1010
|
-
}
|
|
1011
|
-
return view.localPosFromDOM(node, offset);
|
|
1012
|
-
}
|
|
1013
|
-
function posFromDOMInOpaqueNode(node, offset, target) {
|
|
1014
|
-
if (target.nodeType == 3) {
|
|
1015
|
-
return node == target ? { result: offset } : { size: target.nodeValue.length };
|
|
1016
|
-
}
|
|
1017
|
-
else if (target.nodeType == 1 && target.contentEditable != "false") {
|
|
1018
|
-
let pos = 0;
|
|
1019
|
-
for (let child = target.firstChild, i = 0;; child = child.nextSibling, i++) {
|
|
1020
|
-
if (node == target && i == offset)
|
|
1021
|
-
return { result: pos };
|
|
1022
|
-
if (!child)
|
|
1023
|
-
return { size: pos };
|
|
1024
|
-
let inner = posFromDOMInOpaqueNode(node, offset, child);
|
|
1025
|
-
if (inner.result != null)
|
|
1026
|
-
return { result: offset + inner.result };
|
|
1027
|
-
pos += inner.size;
|
|
1028
|
-
}
|
|
1029
|
-
}
|
|
1030
|
-
else {
|
|
1031
|
-
return target.contains(node) ? { result: 0 } : { size: 0 };
|
|
1032
|
-
}
|
|
1033
|
-
}
|
|
1034
1032
|
// These are drawn around uneditable widgets to avoid a number of
|
|
1035
1033
|
// browser bugs that show up when the cursor is directly next to
|
|
1036
1034
|
// uneditable inline content.
|
|
@@ -1150,16 +1148,20 @@ function combineAttrs(source, target) {
|
|
|
1150
1148
|
}
|
|
1151
1149
|
return target;
|
|
1152
1150
|
}
|
|
1153
|
-
|
|
1151
|
+
const noAttrs = Object.create(null);
|
|
1152
|
+
function attrsEq(a, b, ignore) {
|
|
1154
1153
|
if (a == b)
|
|
1155
1154
|
return true;
|
|
1156
|
-
if (!a
|
|
1157
|
-
|
|
1155
|
+
if (!a)
|
|
1156
|
+
a = noAttrs;
|
|
1157
|
+
if (!b)
|
|
1158
|
+
b = noAttrs;
|
|
1158
1159
|
let keysA = Object.keys(a), keysB = Object.keys(b);
|
|
1159
|
-
if (keysA.length
|
|
1160
|
+
if (keysA.length - (ignore && keysA.indexOf(ignore) > -1 ? 1 : 0) !=
|
|
1161
|
+
keysB.length - (ignore && keysB.indexOf(ignore) > -1 ? 1 : 0))
|
|
1160
1162
|
return false;
|
|
1161
1163
|
for (let key of keysA) {
|
|
1162
|
-
if (keysB.indexOf(key) == -1 || a[key] !== b[key])
|
|
1164
|
+
if (key != ignore && (keysB.indexOf(key) == -1 || a[key] !== b[key]))
|
|
1163
1165
|
return false;
|
|
1164
1166
|
}
|
|
1165
1167
|
return true;
|
|
@@ -1176,6 +1178,14 @@ function updateAttrs(dom, prev, attrs) {
|
|
|
1176
1178
|
dom.setAttribute(changed = name, attrs[name]);
|
|
1177
1179
|
return !!changed;
|
|
1178
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
|
+
}
|
|
1179
1189
|
|
|
1180
1190
|
/**
|
|
1181
1191
|
Widgets added to the content are described by subclasses of this
|
|
@@ -1240,10 +1250,6 @@ class WidgetType {
|
|
|
1240
1250
|
/**
|
|
1241
1251
|
@internal
|
|
1242
1252
|
*/
|
|
1243
|
-
get customView() { return null; }
|
|
1244
|
-
/**
|
|
1245
|
-
@internal
|
|
1246
|
-
*/
|
|
1247
1253
|
get isHidden() { return false; }
|
|
1248
1254
|
/**
|
|
1249
1255
|
This is called when the an instance of the widget is removed
|
|
@@ -1382,11 +1388,12 @@ class MarkDecoration extends Decoration {
|
|
|
1382
1388
|
this.attrs = spec.attributes || null;
|
|
1383
1389
|
}
|
|
1384
1390
|
eq(other) {
|
|
1391
|
+
var _a, _b;
|
|
1385
1392
|
return this == other ||
|
|
1386
1393
|
other instanceof MarkDecoration &&
|
|
1387
1394
|
this.tagName == other.tagName &&
|
|
1388
|
-
this.class == other.class &&
|
|
1389
|
-
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");
|
|
1390
1397
|
}
|
|
1391
1398
|
range(from, to = from) {
|
|
1392
1399
|
if (from >= to)
|
|
@@ -1538,7 +1545,7 @@ class LineView extends ContentView {
|
|
|
1538
1545
|
reuseDOM(node) {
|
|
1539
1546
|
if (node.nodeName == "DIV") {
|
|
1540
1547
|
this.setDOM(node);
|
|
1541
|
-
this.
|
|
1548
|
+
this.flags |= 4 /* AttrsDirty */ | 2 /* NodeDirty */;
|
|
1542
1549
|
}
|
|
1543
1550
|
}
|
|
1544
1551
|
sync(view, track) {
|
|
@@ -1548,7 +1555,7 @@ class LineView extends ContentView {
|
|
|
1548
1555
|
this.dom.className = "cm-line";
|
|
1549
1556
|
this.prevAttrs = this.attrs ? null : undefined;
|
|
1550
1557
|
}
|
|
1551
|
-
else if (this.
|
|
1558
|
+
else if (this.flags & 4 /* AttrsDirty */) {
|
|
1552
1559
|
clearAttributes(this.dom);
|
|
1553
1560
|
this.dom.className = "cm-line";
|
|
1554
1561
|
this.prevAttrs = this.attrs ? null : undefined;
|
|
@@ -2489,120 +2496,14 @@ function moveVisually(line, order, dir, start, forward) {
|
|
|
2489
2496
|
return state.EditorSelection.cursor(nextIndex + line.from, forward ? -1 : 1, span.level);
|
|
2490
2497
|
}
|
|
2491
2498
|
|
|
2492
|
-
const LineBreakPlaceholder = "\uffff";
|
|
2493
|
-
class DOMReader {
|
|
2494
|
-
constructor(points, state$1) {
|
|
2495
|
-
this.points = points;
|
|
2496
|
-
this.text = "";
|
|
2497
|
-
this.lineSeparator = state$1.facet(state.EditorState.lineSeparator);
|
|
2498
|
-
}
|
|
2499
|
-
append(text) {
|
|
2500
|
-
this.text += text;
|
|
2501
|
-
}
|
|
2502
|
-
lineBreak() {
|
|
2503
|
-
this.text += LineBreakPlaceholder;
|
|
2504
|
-
}
|
|
2505
|
-
readRange(start, end) {
|
|
2506
|
-
if (!start)
|
|
2507
|
-
return this;
|
|
2508
|
-
let parent = start.parentNode;
|
|
2509
|
-
for (let cur = start;;) {
|
|
2510
|
-
this.findPointBefore(parent, cur);
|
|
2511
|
-
let oldLen = this.text.length;
|
|
2512
|
-
this.readNode(cur);
|
|
2513
|
-
let next = cur.nextSibling;
|
|
2514
|
-
if (next == end)
|
|
2515
|
-
break;
|
|
2516
|
-
let view = ContentView.get(cur), nextView = ContentView.get(next);
|
|
2517
|
-
if (view && nextView ? view.breakAfter :
|
|
2518
|
-
(view ? view.breakAfter : isBlockElement(cur)) ||
|
|
2519
|
-
(isBlockElement(next) && (cur.nodeName != "BR" || cur.cmIgnore) && this.text.length > oldLen))
|
|
2520
|
-
this.lineBreak();
|
|
2521
|
-
cur = next;
|
|
2522
|
-
}
|
|
2523
|
-
this.findPointBefore(parent, end);
|
|
2524
|
-
return this;
|
|
2525
|
-
}
|
|
2526
|
-
readTextNode(node) {
|
|
2527
|
-
let text = node.nodeValue;
|
|
2528
|
-
for (let point of this.points)
|
|
2529
|
-
if (point.node == node)
|
|
2530
|
-
point.pos = this.text.length + Math.min(point.offset, text.length);
|
|
2531
|
-
for (let off = 0, re = this.lineSeparator ? null : /\r\n?|\n/g;;) {
|
|
2532
|
-
let nextBreak = -1, breakSize = 1, m;
|
|
2533
|
-
if (this.lineSeparator) {
|
|
2534
|
-
nextBreak = text.indexOf(this.lineSeparator, off);
|
|
2535
|
-
breakSize = this.lineSeparator.length;
|
|
2536
|
-
}
|
|
2537
|
-
else if (m = re.exec(text)) {
|
|
2538
|
-
nextBreak = m.index;
|
|
2539
|
-
breakSize = m[0].length;
|
|
2540
|
-
}
|
|
2541
|
-
this.append(text.slice(off, nextBreak < 0 ? text.length : nextBreak));
|
|
2542
|
-
if (nextBreak < 0)
|
|
2543
|
-
break;
|
|
2544
|
-
this.lineBreak();
|
|
2545
|
-
if (breakSize > 1)
|
|
2546
|
-
for (let point of this.points)
|
|
2547
|
-
if (point.node == node && point.pos > this.text.length)
|
|
2548
|
-
point.pos -= breakSize - 1;
|
|
2549
|
-
off = nextBreak + breakSize;
|
|
2550
|
-
}
|
|
2551
|
-
}
|
|
2552
|
-
readNode(node) {
|
|
2553
|
-
if (node.cmIgnore)
|
|
2554
|
-
return;
|
|
2555
|
-
let view = ContentView.get(node);
|
|
2556
|
-
let fromView = view && view.overrideDOMText;
|
|
2557
|
-
if (fromView != null) {
|
|
2558
|
-
this.findPointInside(node, fromView.length);
|
|
2559
|
-
for (let i = fromView.iter(); !i.next().done;) {
|
|
2560
|
-
if (i.lineBreak)
|
|
2561
|
-
this.lineBreak();
|
|
2562
|
-
else
|
|
2563
|
-
this.append(i.value);
|
|
2564
|
-
}
|
|
2565
|
-
}
|
|
2566
|
-
else if (node.nodeType == 3) {
|
|
2567
|
-
this.readTextNode(node);
|
|
2568
|
-
}
|
|
2569
|
-
else if (node.nodeName == "BR") {
|
|
2570
|
-
if (node.nextSibling)
|
|
2571
|
-
this.lineBreak();
|
|
2572
|
-
}
|
|
2573
|
-
else if (node.nodeType == 1) {
|
|
2574
|
-
this.readRange(node.firstChild, null);
|
|
2575
|
-
}
|
|
2576
|
-
}
|
|
2577
|
-
findPointBefore(node, next) {
|
|
2578
|
-
for (let point of this.points)
|
|
2579
|
-
if (point.node == node && node.childNodes[point.offset] == next)
|
|
2580
|
-
point.pos = this.text.length;
|
|
2581
|
-
}
|
|
2582
|
-
findPointInside(node, maxLen) {
|
|
2583
|
-
for (let point of this.points)
|
|
2584
|
-
if (node.nodeType == 3 ? point.node == node : node.contains(point.node))
|
|
2585
|
-
point.pos = this.text.length + Math.min(maxLen, point.offset);
|
|
2586
|
-
}
|
|
2587
|
-
}
|
|
2588
|
-
function isBlockElement(node) {
|
|
2589
|
-
return node.nodeType == 1 && /^(DIV|P|LI|UL|OL|BLOCKQUOTE|DD|DT|H\d|SECTION|PRE)$/.test(node.nodeName);
|
|
2590
|
-
}
|
|
2591
|
-
class DOMPoint {
|
|
2592
|
-
constructor(node, offset) {
|
|
2593
|
-
this.node = node;
|
|
2594
|
-
this.offset = offset;
|
|
2595
|
-
this.pos = -1;
|
|
2596
|
-
}
|
|
2597
|
-
}
|
|
2598
|
-
|
|
2599
2499
|
class DocView extends ContentView {
|
|
2600
2500
|
constructor(view) {
|
|
2601
2501
|
super();
|
|
2602
2502
|
this.view = view;
|
|
2603
|
-
this.compositionDeco = Decoration.none;
|
|
2604
2503
|
this.decorations = [];
|
|
2605
2504
|
this.dynamicDecorationMap = [];
|
|
2505
|
+
this.hasComposition = false;
|
|
2506
|
+
this.markedForComposition = new Set;
|
|
2606
2507
|
// Track a minimum width for the editor. When measuring sizes in
|
|
2607
2508
|
// measureVisibleLineHeights, this is updated to point at the width
|
|
2608
2509
|
// of a given element and its extent in the document. When a change
|
|
@@ -2625,7 +2526,7 @@ class DocView extends ContentView {
|
|
|
2625
2526
|
this.children = [new LineView];
|
|
2626
2527
|
this.children[0].setParent(this);
|
|
2627
2528
|
this.updateDeco();
|
|
2628
|
-
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);
|
|
2629
2530
|
}
|
|
2630
2531
|
get length() { return this.view.state.doc.length; }
|
|
2631
2532
|
// Update the document view to a given state.
|
|
@@ -2640,26 +2541,26 @@ class DocView extends ContentView {
|
|
|
2640
2541
|
this.minWidthTo = update.changes.mapPos(this.minWidthTo, 1);
|
|
2641
2542
|
}
|
|
2642
2543
|
}
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2544
|
+
let composition = this.view.inputState.composing < 0 ? null : findCompositionRange(this.view, update.changes);
|
|
2545
|
+
if (this.hasComposition)
|
|
2546
|
+
this.markedForComposition.clear();
|
|
2547
|
+
this.hasComposition = !!composition;
|
|
2647
2548
|
// When the DOM nodes around the selection are moved to another
|
|
2648
2549
|
// parent, Chrome sometimes reports a different selection through
|
|
2649
2550
|
// getSelection than the one that it actually shows to the user.
|
|
2650
2551
|
// This forces a selection update when lines are joined to work
|
|
2651
2552
|
// around that. Issue #54
|
|
2652
|
-
if ((browser.ie || browser.chrome) && !
|
|
2553
|
+
if ((browser.ie || browser.chrome) && !composition && update &&
|
|
2653
2554
|
update.state.doc.lines != update.startState.doc.lines)
|
|
2654
2555
|
this.forceSelection = true;
|
|
2655
2556
|
let prevDeco = this.decorations, deco = this.updateDeco();
|
|
2656
2557
|
let decoDiff = findChangedDeco(prevDeco, deco, update.changes);
|
|
2657
2558
|
changedRanges = ChangedRange.extendWithRanges(changedRanges, decoDiff);
|
|
2658
|
-
if (this.
|
|
2559
|
+
if (!(this.flags & 7 /* Dirty */) && changedRanges.length == 0) {
|
|
2659
2560
|
return false;
|
|
2660
2561
|
}
|
|
2661
2562
|
else {
|
|
2662
|
-
this.updateInner(changedRanges, update.startState.doc.length);
|
|
2563
|
+
this.updateInner(changedRanges, update.startState.doc.length, composition);
|
|
2663
2564
|
if (update.transactions.length)
|
|
2664
2565
|
this.lastUpdate = Date.now();
|
|
2665
2566
|
return true;
|
|
@@ -2667,9 +2568,9 @@ class DocView extends ContentView {
|
|
|
2667
2568
|
}
|
|
2668
2569
|
// Used by update and the constructor do perform the actual DOM
|
|
2669
2570
|
// update
|
|
2670
|
-
updateInner(changes, oldLength) {
|
|
2571
|
+
updateInner(changes, oldLength, composition) {
|
|
2671
2572
|
this.view.viewState.mustMeasureContent = true;
|
|
2672
|
-
this.updateChildren(changes, oldLength);
|
|
2573
|
+
this.updateChildren(changes, oldLength, composition);
|
|
2673
2574
|
let { observer } = this.view;
|
|
2674
2575
|
observer.ignore(() => {
|
|
2675
2576
|
// Lock the height during redrawing, since Chrome sometimes
|
|
@@ -2684,11 +2585,12 @@ class DocView extends ContentView {
|
|
|
2684
2585
|
// to detect that situation.
|
|
2685
2586
|
let track = browser.chrome || browser.ios ? { node: observer.selectionRange.focusNode, written: false } : undefined;
|
|
2686
2587
|
this.sync(this.view, track);
|
|
2687
|
-
this.
|
|
2588
|
+
this.flags &= ~7 /* Dirty */;
|
|
2688
2589
|
if (track && (track.written || observer.selectionRange.focusNode != track.node))
|
|
2689
2590
|
this.forceSelection = true;
|
|
2690
2591
|
this.dom.style.height = "";
|
|
2691
2592
|
});
|
|
2593
|
+
this.markedForComposition.forEach(cView => cView.flags &= ~8 /* Composition */);
|
|
2692
2594
|
let gaps = [];
|
|
2693
2595
|
if (this.view.viewport.from || this.view.viewport.to < this.view.state.doc.length)
|
|
2694
2596
|
for (let child of this.children)
|
|
@@ -2696,18 +2598,62 @@ class DocView extends ContentView {
|
|
|
2696
2598
|
gaps.push(child.dom);
|
|
2697
2599
|
observer.updateGaps(gaps);
|
|
2698
2600
|
}
|
|
2699
|
-
updateChildren(changes, oldLength) {
|
|
2601
|
+
updateChildren(changes, oldLength, composition) {
|
|
2602
|
+
let ranges = composition ? composition.range.addToSet(changes.slice()) : changes;
|
|
2700
2603
|
let cursor = this.childCursor(oldLength);
|
|
2701
|
-
for (let i =
|
|
2702
|
-
let next = i >= 0 ?
|
|
2604
|
+
for (let i = ranges.length - 1;; i--) {
|
|
2605
|
+
let next = i >= 0 ? ranges[i] : null;
|
|
2703
2606
|
if (!next)
|
|
2704
2607
|
break;
|
|
2705
|
-
let { fromA, toA, fromB, toB } = next;
|
|
2706
|
-
|
|
2608
|
+
let { fromA, toA, fromB, toB } = next, content, breakAtStart, openStart, openEnd;
|
|
2609
|
+
if (composition && composition.range.fromB < toB && composition.range.toB > fromB) {
|
|
2610
|
+
let before = ContentBuilder.build(this.view.state.doc, fromB, composition.range.fromB, this.decorations, this.dynamicDecorationMap);
|
|
2611
|
+
let after = ContentBuilder.build(this.view.state.doc, composition.range.toB, toB, this.decorations, this.dynamicDecorationMap);
|
|
2612
|
+
breakAtStart = before.breakAtStart;
|
|
2613
|
+
openStart = before.openStart;
|
|
2614
|
+
openEnd = after.openEnd;
|
|
2615
|
+
let compLine = this.compositionView(composition);
|
|
2616
|
+
compLine.merge(compLine.length, compLine.length, after.content[0], false, after.openStart, 0);
|
|
2617
|
+
compLine.merge(0, 0, before.content[before.content.length - 1], true, 0, before.openEnd);
|
|
2618
|
+
content = before.content.slice(0, before.content.length - 1).concat(compLine).concat(after.content.slice(1));
|
|
2619
|
+
}
|
|
2620
|
+
else {
|
|
2621
|
+
({ content, breakAtStart, openStart, openEnd } =
|
|
2622
|
+
ContentBuilder.build(this.view.state.doc, fromB, toB, this.decorations, this.dynamicDecorationMap));
|
|
2623
|
+
}
|
|
2707
2624
|
let { i: toI, off: toOff } = cursor.findPos(toA, 1);
|
|
2708
2625
|
let { i: fromI, off: fromOff } = cursor.findPos(fromA, -1);
|
|
2709
2626
|
replaceRange(this, fromI, fromOff, toI, toOff, content, breakAtStart, openStart, openEnd);
|
|
2710
2627
|
}
|
|
2628
|
+
if (composition)
|
|
2629
|
+
this.fixCompositionDOM(composition);
|
|
2630
|
+
}
|
|
2631
|
+
compositionView(composition) {
|
|
2632
|
+
let cur = new TextView(composition.text.nodeValue);
|
|
2633
|
+
cur.flags |= 8 /* Composition */;
|
|
2634
|
+
for (let { deco } of composition.marks)
|
|
2635
|
+
cur = new MarkView(deco, [cur], cur.length);
|
|
2636
|
+
let line = new LineView;
|
|
2637
|
+
line.append(cur, 0);
|
|
2638
|
+
return line;
|
|
2639
|
+
}
|
|
2640
|
+
fixCompositionDOM(composition) {
|
|
2641
|
+
let fix = (dom, cView) => {
|
|
2642
|
+
cView.flags |= 8 /* Composition */;
|
|
2643
|
+
this.markedForComposition.add(cView);
|
|
2644
|
+
let prev = ContentView.get(dom);
|
|
2645
|
+
if (prev)
|
|
2646
|
+
prev.dom = null;
|
|
2647
|
+
cView.setDOM(dom);
|
|
2648
|
+
};
|
|
2649
|
+
let pos = this.childPos(composition.range.fromB, 1);
|
|
2650
|
+
let cView = this.children[pos.i];
|
|
2651
|
+
fix(composition.line, cView);
|
|
2652
|
+
for (let i = composition.marks.length - 1; i >= -1; i--) {
|
|
2653
|
+
pos = cView.childPos(pos.off, 1);
|
|
2654
|
+
cView = cView.children[pos.i];
|
|
2655
|
+
fix(i >= 0 ? composition.marks[i].node : composition.text, cView);
|
|
2656
|
+
}
|
|
2711
2657
|
}
|
|
2712
2658
|
// Sync the DOM selection to this.state.selection
|
|
2713
2659
|
updateSelection(mustRead = false, fromPointer = false) {
|
|
@@ -2726,7 +2672,7 @@ class DocView extends ContentView {
|
|
|
2726
2672
|
let head = main.empty ? anchor : this.domAtPos(main.head);
|
|
2727
2673
|
// Always reset on Firefox when next to an uneditable node to
|
|
2728
2674
|
// avoid invisible cursor bugs (#111)
|
|
2729
|
-
if (browser.gecko && main.empty && !this.
|
|
2675
|
+
if (browser.gecko && main.empty && !this.hasComposition && betweenUneditable(anchor)) {
|
|
2730
2676
|
let dummy = document.createTextNode("");
|
|
2731
2677
|
this.view.observer.ignore(() => anchor.node.insertBefore(dummy, anchor.node.childNodes[anchor.offset] || null));
|
|
2732
2678
|
anchor = head = new DOMPos(dummy, 0);
|
|
@@ -2798,7 +2744,7 @@ class DocView extends ContentView {
|
|
|
2798
2744
|
this.impreciseHead = head.precise ? null : new DOMPos(domSel.focusNode, domSel.focusOffset);
|
|
2799
2745
|
}
|
|
2800
2746
|
enforceCursorAssoc() {
|
|
2801
|
-
if (this.
|
|
2747
|
+
if (this.hasComposition)
|
|
2802
2748
|
return;
|
|
2803
2749
|
let { view } = this, cursor = view.state.selection.main;
|
|
2804
2750
|
let sel = getSelection(view.root);
|
|
@@ -2908,6 +2854,7 @@ class DocView extends ContentView {
|
|
|
2908
2854
|
let dummy = document.createElement("div"), lineHeight, charWidth, textHeight;
|
|
2909
2855
|
dummy.className = "cm-line";
|
|
2910
2856
|
dummy.style.width = "99999px";
|
|
2857
|
+
dummy.style.position = "absolute";
|
|
2911
2858
|
dummy.textContent = "abc def ghi jkl mno pqr stu";
|
|
2912
2859
|
this.view.observer.ignore(() => {
|
|
2913
2860
|
this.dom.appendChild(dummy);
|
|
@@ -2957,7 +2904,6 @@ class DocView extends ContentView {
|
|
|
2957
2904
|
this.dynamicDecorationMap[i] = false;
|
|
2958
2905
|
return this.decorations = [
|
|
2959
2906
|
...allDeco,
|
|
2960
|
-
this.compositionDeco,
|
|
2961
2907
|
this.computeBlockGapDeco(),
|
|
2962
2908
|
this.view.viewState.lineGapDeco
|
|
2963
2909
|
];
|
|
@@ -3000,81 +2946,85 @@ class BlockGapWidget extends WidgetType {
|
|
|
3000
2946
|
}
|
|
3001
2947
|
get estimatedHeight() { return this.height; }
|
|
3002
2948
|
}
|
|
3003
|
-
function
|
|
2949
|
+
function findCompositionNode(view) {
|
|
3004
2950
|
let sel = view.observer.selectionRange;
|
|
3005
2951
|
let textNode = sel.focusNode && nearbyTextNode(sel.focusNode, sel.focusOffset, 0);
|
|
3006
2952
|
if (!textNode)
|
|
3007
2953
|
return null;
|
|
3008
|
-
let cView =
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
while (topNode.parentNode != cView.dom)
|
|
3014
|
-
topNode = topNode.parentNode;
|
|
3015
|
-
let prev = topNode.previousSibling;
|
|
3016
|
-
while (prev && !ContentView.get(prev))
|
|
3017
|
-
prev = prev.previousSibling;
|
|
3018
|
-
let pos = prev ? ContentView.get(prev).posAtEnd : cView.posAtStart;
|
|
3019
|
-
return { from: pos, to: pos, node: topNode, text: textNode };
|
|
2954
|
+
let cView = ContentView.get(textNode);
|
|
2955
|
+
let from, to;
|
|
2956
|
+
if (cView instanceof TextView) {
|
|
2957
|
+
from = cView.posAtStart;
|
|
2958
|
+
to = from + cView.length;
|
|
3020
2959
|
}
|
|
3021
2960
|
else {
|
|
3022
|
-
for (;;) {
|
|
3023
|
-
let
|
|
3024
|
-
|
|
2961
|
+
up: for (let offset = 0, node = textNode;;) {
|
|
2962
|
+
for (let sibling = node.previousSibling, cView; sibling; sibling = sibling.previousSibling) {
|
|
2963
|
+
if (cView = ContentView.get(sibling)) {
|
|
2964
|
+
from = to = cView.posAtEnd + offset;
|
|
2965
|
+
break up;
|
|
2966
|
+
}
|
|
2967
|
+
let reader = new DOMReader([], view.state);
|
|
2968
|
+
reader.readNode(sibling);
|
|
2969
|
+
if (reader.text.indexOf(LineBreakPlaceholder) > -1)
|
|
2970
|
+
return null;
|
|
2971
|
+
offset += reader.text.length;
|
|
2972
|
+
}
|
|
2973
|
+
node = node.parentNode;
|
|
2974
|
+
if (!node)
|
|
3025
2975
|
return null;
|
|
3026
|
-
|
|
2976
|
+
let parentView = ContentView.get(node);
|
|
2977
|
+
if (parentView) {
|
|
2978
|
+
from = to = parentView.posAtStart + offset;
|
|
3027
2979
|
break;
|
|
3028
|
-
|
|
2980
|
+
}
|
|
3029
2981
|
}
|
|
3030
|
-
let from = cView.posAtStart;
|
|
3031
|
-
return { from, to: from + cView.length, node: cView.dom, text: textNode };
|
|
3032
2982
|
}
|
|
2983
|
+
return { from, to, node: textNode };
|
|
3033
2984
|
}
|
|
3034
|
-
function
|
|
3035
|
-
let
|
|
3036
|
-
if (!
|
|
3037
|
-
return
|
|
3038
|
-
let { from, to, node
|
|
3039
|
-
let
|
|
3040
|
-
let
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
if
|
|
3050
|
-
|
|
3051
|
-
|
|
3052
|
-
|
|
2985
|
+
function findCompositionRange(view, changes) {
|
|
2986
|
+
let found = findCompositionNode(view);
|
|
2987
|
+
if (!found)
|
|
2988
|
+
return null;
|
|
2989
|
+
let { from: fromA, to: toA, node: textNode } = found;
|
|
2990
|
+
let fromB = changes.mapPos(fromA, -1), toB = changes.mapPos(toA, 1);
|
|
2991
|
+
let text = textNode.nodeValue;
|
|
2992
|
+
// Don't try to preserve multi-line compositions
|
|
2993
|
+
if (/[\n\r]/.test(text))
|
|
2994
|
+
return null;
|
|
2995
|
+
if (toB - fromB != text.length) {
|
|
2996
|
+
// If there is a length mismatch, see if mapping non-inclusively helps
|
|
2997
|
+
let fromB2 = changes.mapPos(fromA, 1), toB2 = changes.mapPos(toA, -1);
|
|
2998
|
+
if (toB2 - fromB2 == text.length)
|
|
2999
|
+
fromB = fromB2, toB = toB2;
|
|
3000
|
+
// See if we can find an instance of the text at either side
|
|
3001
|
+
else if (view.state.doc.sliceString(toB - text.length, toB) == text)
|
|
3002
|
+
fromB = toB - text.length;
|
|
3003
|
+
else if (view.state.doc.sliceString(fromB, fromB + text.length) == text)
|
|
3004
|
+
toB = fromB + text.length;
|
|
3005
|
+
// Not found
|
|
3053
3006
|
else
|
|
3054
|
-
return
|
|
3055
|
-
}
|
|
3056
|
-
else if (state.doc.sliceString(newFrom, newTo) != text) {
|
|
3057
|
-
return Decoration.none;
|
|
3007
|
+
return null;
|
|
3058
3008
|
}
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
}
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3009
|
+
if (view.state.doc.sliceString(fromB, toB) != text)
|
|
3010
|
+
return null;
|
|
3011
|
+
let marks = [];
|
|
3012
|
+
let range = new ChangedRange(fromA, toA, fromB, toB);
|
|
3013
|
+
for (let parent = textNode.parentNode;; parent = parent.parentNode) {
|
|
3014
|
+
let parentView = ContentView.get(parent);
|
|
3015
|
+
if (parentView instanceof MarkView)
|
|
3016
|
+
marks.push({ node: parent, deco: parentView.mark });
|
|
3017
|
+
else if (parentView instanceof LineView || parent.nodeName == "DIV" && parent.parentNode == view.contentDOM)
|
|
3018
|
+
return { range, text: textNode, marks, line: parent };
|
|
3019
|
+
else if (parent != view.contentDOM)
|
|
3020
|
+
marks.push({ node: parent, deco: new MarkDecoration({
|
|
3021
|
+
inclusive: true,
|
|
3022
|
+
attributes: getAttrs(parent),
|
|
3023
|
+
tagName: parent.tagName.toLowerCase()
|
|
3024
|
+
}) });
|
|
3025
|
+
else
|
|
3026
|
+
return null;
|
|
3073
3027
|
}
|
|
3074
|
-
eq(other) { return this.top == other.top && this.text == other.text; }
|
|
3075
|
-
toDOM() { return this.top; }
|
|
3076
|
-
ignoreEvent() { return false; }
|
|
3077
|
-
get customView() { return CompositionView; }
|
|
3078
3028
|
}
|
|
3079
3029
|
function nearbyTextNode(startNode, startOffset, side) {
|
|
3080
3030
|
if (side <= 0)
|
|
@@ -3725,6 +3675,7 @@ class InputState {
|
|
|
3725
3675
|
const PendingKeys = [
|
|
3726
3676
|
{ key: "Backspace", keyCode: 8, inputType: "deleteContentBackward" },
|
|
3727
3677
|
{ key: "Enter", keyCode: 13, inputType: "insertParagraph" },
|
|
3678
|
+
{ key: "Enter", keyCode: 13, inputType: "insertLineBreak" },
|
|
3728
3679
|
{ key: "Delete", keyCode: 46, inputType: "deleteContentForward" }
|
|
3729
3680
|
];
|
|
3730
3681
|
const EmacsyPendingKeys = "dthko";
|
|
@@ -3734,9 +3685,13 @@ const dragScrollMargin = 6;
|
|
|
3734
3685
|
function dragScrollSpeed(dist) {
|
|
3735
3686
|
return Math.max(0, dist) * 0.7 + 8;
|
|
3736
3687
|
}
|
|
3688
|
+
function dist(a, b) {
|
|
3689
|
+
return Math.max(Math.abs(a.clientX - b.clientX), Math.abs(a.clientY - b.clientY));
|
|
3690
|
+
}
|
|
3737
3691
|
class MouseSelection {
|
|
3738
3692
|
constructor(view, startEvent, style, mustSelect) {
|
|
3739
3693
|
this.view = view;
|
|
3694
|
+
this.startEvent = startEvent;
|
|
3740
3695
|
this.style = style;
|
|
3741
3696
|
this.mustSelect = mustSelect;
|
|
3742
3697
|
this.scrollSpeed = { x: 0, y: 0 };
|
|
@@ -3763,7 +3718,7 @@ class MouseSelection {
|
|
|
3763
3718
|
var _a;
|
|
3764
3719
|
if (event.buttons == 0)
|
|
3765
3720
|
return this.destroy();
|
|
3766
|
-
if (this.dragging
|
|
3721
|
+
if (this.dragging || this.dragging == null && dist(this.startEvent, event) < 10)
|
|
3767
3722
|
return;
|
|
3768
3723
|
this.select(this.lastEvent = event);
|
|
3769
3724
|
let sx = 0, sy = 0;
|
|
@@ -3842,7 +3797,7 @@ class MouseSelection {
|
|
|
3842
3797
|
select(event) {
|
|
3843
3798
|
let { view } = this, selection = this.skipAtoms(this.style.get(event, this.extend, this.multiple));
|
|
3844
3799
|
if (this.mustSelect || !selection.eq(view.state.selection) ||
|
|
3845
|
-
selection.main.assoc != view.state.selection.main.assoc)
|
|
3800
|
+
selection.main.assoc != view.state.selection.main.assoc && this.dragging === false)
|
|
3846
3801
|
this.view.dispatch({
|
|
3847
3802
|
selection,
|
|
3848
3803
|
userEvent: "select.pointer"
|
|
@@ -3969,7 +3924,7 @@ handlers.mousedown = (view, event) => {
|
|
|
3969
3924
|
if (!style && event.button == 0)
|
|
3970
3925
|
style = basicMouseSelection(view, event);
|
|
3971
3926
|
if (style) {
|
|
3972
|
-
let mustFocus = view.
|
|
3927
|
+
let mustFocus = !view.hasFocus;
|
|
3973
3928
|
view.inputState.startMouseSelection(new MouseSelection(view, event, style, mustFocus));
|
|
3974
3929
|
if (mustFocus)
|
|
3975
3930
|
view.observer.ignore(() => focusPreventScroll(view.contentDOM));
|
|
@@ -4261,7 +4216,7 @@ handlers.compositionend = view => {
|
|
|
4261
4216
|
// Otherwise, make sure that, if no changes come in soon, the
|
|
4262
4217
|
// composition view is cleared.
|
|
4263
4218
|
setTimeout(() => {
|
|
4264
|
-
if (view.inputState.composing < 0 && view.docView.
|
|
4219
|
+
if (view.inputState.composing < 0 && view.docView.hasComposition)
|
|
4265
4220
|
view.update([]);
|
|
4266
4221
|
}, 50);
|
|
4267
4222
|
}
|
|
@@ -5166,7 +5121,7 @@ class ViewState {
|
|
|
5166
5121
|
let contentChanges = update.changedRanges;
|
|
5167
5122
|
let heightChanges = ChangedRange.extendWithRanges(contentChanges, heightRelevantDecoChanges(prevDeco, this.stateDeco, update ? update.changes : state.ChangeSet.empty(this.state.doc.length)));
|
|
5168
5123
|
let prevHeight = this.heightMap.height;
|
|
5169
|
-
let scrollAnchor = this.scrolledToBottom ? null : this.
|
|
5124
|
+
let scrollAnchor = this.scrolledToBottom ? null : this.scrollAnchorAt(this.scrollTop);
|
|
5170
5125
|
this.heightMap = this.heightMap.applyChanges(this.stateDeco, update.startState.doc, this.heightOracle.setDoc(this.state.doc), heightChanges);
|
|
5171
5126
|
if (this.heightMap.height != prevHeight)
|
|
5172
5127
|
update.flags |= 2 /* Height */;
|
|
@@ -5226,7 +5181,7 @@ class ViewState {
|
|
|
5226
5181
|
this.scrollAnchorHeight = -1;
|
|
5227
5182
|
this.scrollTop = view.scrollDOM.scrollTop;
|
|
5228
5183
|
}
|
|
5229
|
-
this.scrolledToBottom =
|
|
5184
|
+
this.scrolledToBottom = isScrolledToBottom(view.scrollDOM);
|
|
5230
5185
|
// Pixel viewport
|
|
5231
5186
|
let pixelViewport = (this.printing ? fullPixelRange : visiblePixelRange)(dom, this.paddingTop);
|
|
5232
5187
|
let dTop = pixelViewport.top - this.pixelViewport.top, dBottom = pixelViewport.bottom - this.pixelViewport.bottom;
|
|
@@ -5469,6 +5424,10 @@ class ViewState {
|
|
|
5469
5424
|
lineBlockAtHeight(height) {
|
|
5470
5425
|
return scaleBlock(this.heightMap.lineAt(this.scaler.fromDOM(height), QueryType.ByHeight, this.heightOracle, 0, 0), this.scaler);
|
|
5471
5426
|
}
|
|
5427
|
+
scrollAnchorAt(scrollTop) {
|
|
5428
|
+
let block = this.lineBlockAtHeight(scrollTop + 8);
|
|
5429
|
+
return block.from >= this.viewport.from || this.viewportLines[0].top - scrollTop > 200 ? block : this.viewportLines[0];
|
|
5430
|
+
}
|
|
5472
5431
|
elementAtHeight(height) {
|
|
5473
5432
|
return scaleBlock(this.heightMap.blockAt(this.scaler.fromDOM(height), this.heightOracle, 0, 0), this.scaler);
|
|
5474
5433
|
}
|
|
@@ -5974,7 +5933,7 @@ function applyDOMChange(view, domChange) {
|
|
|
5974
5933
|
if (startState.selection.ranges.length > 1 && view.inputState.composing >= 0 &&
|
|
5975
5934
|
change.to <= sel.to && change.to >= sel.to - 10) {
|
|
5976
5935
|
let replaced = view.state.sliceDoc(change.from, change.to);
|
|
5977
|
-
let
|
|
5936
|
+
let composition = findCompositionNode(view) || view.state.doc.lineAt(sel.head);
|
|
5978
5937
|
let offset = sel.to - change.to, size = sel.to - sel.from;
|
|
5979
5938
|
tr = startState.changeByRange(range => {
|
|
5980
5939
|
if (range.from == sel.from && range.to == sel.to)
|
|
@@ -5985,7 +5944,7 @@ function applyDOMChange(view, domChange) {
|
|
|
5985
5944
|
// changes in the same node work without aborting
|
|
5986
5945
|
// composition, so cursors in the composition range are
|
|
5987
5946
|
// ignored.
|
|
5988
|
-
|
|
5947
|
+
composition && range.to >= composition.from && range.from <= composition.to)
|
|
5989
5948
|
return { range };
|
|
5990
5949
|
let rangeChanges = startState.changes({ from, to, insert: change.insert }), selOff = range.to - sel.to;
|
|
5991
5950
|
return {
|
|
@@ -6446,7 +6405,7 @@ class DOMObserver {
|
|
|
6446
6405
|
return null;
|
|
6447
6406
|
cView.markDirty(rec.type == "attributes");
|
|
6448
6407
|
if (rec.type == "attributes")
|
|
6449
|
-
cView.
|
|
6408
|
+
cView.flags |= 4 /* AttrsDirty */;
|
|
6450
6409
|
if (rec.type == "childList") {
|
|
6451
6410
|
let childBefore = findChild(cView, rec.previousSibling || rec.target.previousSibling, -1);
|
|
6452
6411
|
let childAfter = findChild(cView, rec.nextSibling || rec.target.nextSibling, 1);
|
|
@@ -6841,22 +6800,23 @@ class EditorView {
|
|
|
6841
6800
|
let updated = null;
|
|
6842
6801
|
let sDOM = this.scrollDOM, { scrollTop } = sDOM;
|
|
6843
6802
|
let { scrollAnchorPos, scrollAnchorHeight } = this.viewState;
|
|
6803
|
+
if (scrollTop != this.viewState.scrollTop)
|
|
6804
|
+
scrollAnchorHeight = -1;
|
|
6844
6805
|
this.viewState.scrollAnchorHeight = -1;
|
|
6845
|
-
if (scrollAnchorHeight < 0 || scrollTop != this.viewState.scrollTop) {
|
|
6846
|
-
if (scrollTop > sDOM.scrollHeight - sDOM.clientHeight - 4) {
|
|
6847
|
-
scrollAnchorPos = -1;
|
|
6848
|
-
scrollAnchorHeight = this.viewState.heightMap.height;
|
|
6849
|
-
}
|
|
6850
|
-
else {
|
|
6851
|
-
let block = this.viewState.lineBlockAtHeight(scrollTop);
|
|
6852
|
-
scrollAnchorPos = block.from;
|
|
6853
|
-
scrollAnchorHeight = block.top;
|
|
6854
|
-
}
|
|
6855
|
-
}
|
|
6856
6806
|
try {
|
|
6857
6807
|
for (let i = 0;; i++) {
|
|
6808
|
+
if (scrollAnchorHeight < 0) {
|
|
6809
|
+
if (isScrolledToBottom(sDOM)) {
|
|
6810
|
+
scrollAnchorPos = -1;
|
|
6811
|
+
scrollAnchorHeight = this.viewState.heightMap.height;
|
|
6812
|
+
}
|
|
6813
|
+
else {
|
|
6814
|
+
let block = this.viewState.scrollAnchorAt(scrollTop);
|
|
6815
|
+
scrollAnchorPos = block.from;
|
|
6816
|
+
scrollAnchorHeight = block.top;
|
|
6817
|
+
}
|
|
6818
|
+
}
|
|
6858
6819
|
this.updateState = 1 /* Measuring */;
|
|
6859
|
-
let oldViewport = this.viewport;
|
|
6860
6820
|
let changed = this.viewState.measure(this);
|
|
6861
6821
|
if (!changed && !this.measureRequests.length && this.viewState.scrollTarget == null)
|
|
6862
6822
|
break;
|
|
@@ -6879,7 +6839,7 @@ class EditorView {
|
|
|
6879
6839
|
return BadMeasure;
|
|
6880
6840
|
}
|
|
6881
6841
|
});
|
|
6882
|
-
let update = ViewUpdate.create(this, this.state, []), redrawn = false
|
|
6842
|
+
let update = ViewUpdate.create(this, this.state, []), redrawn = false;
|
|
6883
6843
|
update.flags |= changed;
|
|
6884
6844
|
if (!updated)
|
|
6885
6845
|
updated = update;
|
|
@@ -6903,28 +6863,28 @@ class EditorView {
|
|
|
6903
6863
|
logException(this.state, e);
|
|
6904
6864
|
}
|
|
6905
6865
|
}
|
|
6906
|
-
if (this.viewState.editorHeight) {
|
|
6907
|
-
if (this.viewState.scrollTarget) {
|
|
6908
|
-
this.docView.scrollIntoView(this.viewState.scrollTarget);
|
|
6909
|
-
this.viewState.scrollTarget = null;
|
|
6910
|
-
scrolled = true;
|
|
6911
|
-
}
|
|
6912
|
-
else if (scrollAnchorHeight > -1) {
|
|
6913
|
-
let newAnchorHeight = scrollAnchorPos < 0 ? this.viewState.heightMap.height :
|
|
6914
|
-
this.viewState.lineBlockAt(scrollAnchorPos).top;
|
|
6915
|
-
let diff = newAnchorHeight - scrollAnchorHeight;
|
|
6916
|
-
if (diff > 1 || diff < -1) {
|
|
6917
|
-
sDOM.scrollTop = scrollTop + diff;
|
|
6918
|
-
scrolled = true;
|
|
6919
|
-
}
|
|
6920
|
-
}
|
|
6921
|
-
}
|
|
6922
6866
|
if (redrawn)
|
|
6923
6867
|
this.docView.updateSelection(true);
|
|
6924
|
-
if (
|
|
6925
|
-
|
|
6868
|
+
if (!update.viewportChanged && this.measureRequests.length == 0) {
|
|
6869
|
+
if (this.viewState.editorHeight) {
|
|
6870
|
+
if (this.viewState.scrollTarget) {
|
|
6871
|
+
this.docView.scrollIntoView(this.viewState.scrollTarget);
|
|
6872
|
+
this.viewState.scrollTarget = null;
|
|
6873
|
+
continue;
|
|
6874
|
+
}
|
|
6875
|
+
else {
|
|
6876
|
+
let newAnchorHeight = scrollAnchorPos < 0 ? this.viewState.heightMap.height :
|
|
6877
|
+
this.viewState.lineBlockAt(scrollAnchorPos).top;
|
|
6878
|
+
let diff = newAnchorHeight - scrollAnchorHeight;
|
|
6879
|
+
if (diff > 1 || diff < -1) {
|
|
6880
|
+
scrollTop = sDOM.scrollTop = scrollTop + diff;
|
|
6881
|
+
scrollAnchorHeight = -1;
|
|
6882
|
+
continue;
|
|
6883
|
+
}
|
|
6884
|
+
}
|
|
6885
|
+
}
|
|
6926
6886
|
break;
|
|
6927
|
-
|
|
6887
|
+
}
|
|
6928
6888
|
}
|
|
6929
6889
|
}
|
|
6930
6890
|
finally {
|
|
@@ -7619,7 +7579,7 @@ function buildKeymap(bindings, platform = currentPlatform) {
|
|
|
7619
7579
|
else if (current != is)
|
|
7620
7580
|
throw new Error("Key binding " + name + " is used both as a regular binding and as a multi-stroke prefix");
|
|
7621
7581
|
};
|
|
7622
|
-
let add = (scope, key, command, preventDefault) => {
|
|
7582
|
+
let add = (scope, key, command, preventDefault, stopPropagation) => {
|
|
7623
7583
|
var _a, _b;
|
|
7624
7584
|
let scopeObj = bound[scope] || (bound[scope] = Object.create(null));
|
|
7625
7585
|
let parts = key.split(/ (?!$)/).map(k => normalizeKeyName(k, platform));
|
|
@@ -7629,6 +7589,7 @@ function buildKeymap(bindings, platform = currentPlatform) {
|
|
|
7629
7589
|
if (!scopeObj[prefix])
|
|
7630
7590
|
scopeObj[prefix] = {
|
|
7631
7591
|
preventDefault: true,
|
|
7592
|
+
stopPropagation: false,
|
|
7632
7593
|
run: [(view) => {
|
|
7633
7594
|
let ourObj = storedPrefix = { view, prefix, scope };
|
|
7634
7595
|
setTimeout(() => { if (storedPrefix == ourObj)
|
|
@@ -7639,11 +7600,17 @@ function buildKeymap(bindings, platform = currentPlatform) {
|
|
|
7639
7600
|
}
|
|
7640
7601
|
let full = parts.join(" ");
|
|
7641
7602
|
checkPrefix(full, false);
|
|
7642
|
-
let binding = scopeObj[full] || (scopeObj[full] = {
|
|
7603
|
+
let binding = scopeObj[full] || (scopeObj[full] = {
|
|
7604
|
+
preventDefault: false,
|
|
7605
|
+
stopPropagation: false,
|
|
7606
|
+
run: ((_b = (_a = scopeObj._any) === null || _a === void 0 ? void 0 : _a.run) === null || _b === void 0 ? void 0 : _b.slice()) || []
|
|
7607
|
+
});
|
|
7643
7608
|
if (command)
|
|
7644
7609
|
binding.run.push(command);
|
|
7645
7610
|
if (preventDefault)
|
|
7646
7611
|
binding.preventDefault = true;
|
|
7612
|
+
if (stopPropagation)
|
|
7613
|
+
binding.stopPropagation = true;
|
|
7647
7614
|
};
|
|
7648
7615
|
for (let b of bindings) {
|
|
7649
7616
|
let scopes = b.scope ? b.scope.split(" ") : ["editor"];
|
|
@@ -7651,7 +7618,7 @@ function buildKeymap(bindings, platform = currentPlatform) {
|
|
|
7651
7618
|
for (let scope of scopes) {
|
|
7652
7619
|
let scopeObj = bound[scope] || (bound[scope] = Object.create(null));
|
|
7653
7620
|
if (!scopeObj._any)
|
|
7654
|
-
scopeObj._any = { preventDefault: false, run: [] };
|
|
7621
|
+
scopeObj._any = { preventDefault: false, stopPropagation: false, run: [] };
|
|
7655
7622
|
for (let key in scopeObj)
|
|
7656
7623
|
scopeObj[key].run.push(b.any);
|
|
7657
7624
|
}
|
|
@@ -7659,9 +7626,9 @@ function buildKeymap(bindings, platform = currentPlatform) {
|
|
|
7659
7626
|
if (!name)
|
|
7660
7627
|
continue;
|
|
7661
7628
|
for (let scope of scopes) {
|
|
7662
|
-
add(scope, name, b.run, b.preventDefault);
|
|
7629
|
+
add(scope, name, b.run, b.preventDefault, b.stopPropagation);
|
|
7663
7630
|
if (b.shift)
|
|
7664
|
-
add(scope, "Shift-" + name, b.shift, b.preventDefault);
|
|
7631
|
+
add(scope, "Shift-" + name, b.shift, b.preventDefault, b.stopPropagation);
|
|
7665
7632
|
}
|
|
7666
7633
|
}
|
|
7667
7634
|
return bound;
|
|
@@ -7669,11 +7636,13 @@ function buildKeymap(bindings, platform = currentPlatform) {
|
|
|
7669
7636
|
function runHandlers(map, event, view, scope) {
|
|
7670
7637
|
let name = w3cKeyname.keyName(event);
|
|
7671
7638
|
let charCode = state.codePointAt(name, 0), isChar = state.codePointSize(charCode) == name.length && name != " ";
|
|
7672
|
-
let prefix = "",
|
|
7639
|
+
let prefix = "", handled = false, prevented = false, stopPropagation = false;
|
|
7673
7640
|
if (storedPrefix && storedPrefix.view == view && storedPrefix.scope == scope) {
|
|
7674
7641
|
prefix = storedPrefix.prefix + " ";
|
|
7675
|
-
if (
|
|
7642
|
+
if (modifierCodes.indexOf(event.keyCode) < 0) {
|
|
7643
|
+
prevented = true;
|
|
7676
7644
|
storedPrefix = null;
|
|
7645
|
+
}
|
|
7677
7646
|
}
|
|
7678
7647
|
let ran = new Set;
|
|
7679
7648
|
let runFor = (binding) => {
|
|
@@ -7681,36 +7650,49 @@ function runHandlers(map, event, view, scope) {
|
|
|
7681
7650
|
for (let cmd of binding.run)
|
|
7682
7651
|
if (!ran.has(cmd)) {
|
|
7683
7652
|
ran.add(cmd);
|
|
7684
|
-
if (cmd(view, event))
|
|
7653
|
+
if (cmd(view, event)) {
|
|
7654
|
+
if (binding.stopPropagation)
|
|
7655
|
+
stopPropagation = true;
|
|
7685
7656
|
return true;
|
|
7657
|
+
}
|
|
7686
7658
|
}
|
|
7687
|
-
if (binding.preventDefault)
|
|
7688
|
-
|
|
7659
|
+
if (binding.preventDefault) {
|
|
7660
|
+
if (binding.stopPropagation)
|
|
7661
|
+
stopPropagation = true;
|
|
7662
|
+
prevented = true;
|
|
7663
|
+
}
|
|
7689
7664
|
}
|
|
7690
7665
|
return false;
|
|
7691
7666
|
};
|
|
7692
7667
|
let scopeObj = map[scope], baseName, shiftName;
|
|
7693
7668
|
if (scopeObj) {
|
|
7694
|
-
if (runFor(scopeObj[prefix + modifiers(name, event, !isChar)]))
|
|
7695
|
-
|
|
7696
|
-
|
|
7669
|
+
if (runFor(scopeObj[prefix + modifiers(name, event, !isChar)])) {
|
|
7670
|
+
handled = true;
|
|
7671
|
+
}
|
|
7672
|
+
else if (isChar && (event.altKey || event.metaKey || event.ctrlKey) &&
|
|
7697
7673
|
// Ctrl-Alt may be used for AltGr on Windows
|
|
7698
7674
|
!(browser.windows && event.ctrlKey && event.altKey) &&
|
|
7699
7675
|
(baseName = w3cKeyname.base[event.keyCode]) && baseName != name) {
|
|
7700
|
-
if (runFor(scopeObj[prefix + modifiers(baseName, event, true)]))
|
|
7701
|
-
|
|
7676
|
+
if (runFor(scopeObj[prefix + modifiers(baseName, event, true)])) {
|
|
7677
|
+
handled = true;
|
|
7678
|
+
}
|
|
7702
7679
|
else if (event.shiftKey && (shiftName = w3cKeyname.shift[event.keyCode]) != name && shiftName != baseName &&
|
|
7703
|
-
runFor(scopeObj[prefix + modifiers(shiftName, event, false)]))
|
|
7704
|
-
|
|
7680
|
+
runFor(scopeObj[prefix + modifiers(shiftName, event, false)])) {
|
|
7681
|
+
handled = true;
|
|
7682
|
+
}
|
|
7705
7683
|
}
|
|
7706
|
-
else if (isChar && event.shiftKey
|
|
7707
|
-
|
|
7708
|
-
|
|
7684
|
+
else if (isChar && event.shiftKey &&
|
|
7685
|
+
runFor(scopeObj[prefix + modifiers(name, event, true)])) {
|
|
7686
|
+
handled = true;
|
|
7709
7687
|
}
|
|
7710
|
-
if (runFor(scopeObj._any))
|
|
7711
|
-
|
|
7688
|
+
if (!handled && runFor(scopeObj._any))
|
|
7689
|
+
handled = true;
|
|
7712
7690
|
}
|
|
7713
|
-
|
|
7691
|
+
if (prevented)
|
|
7692
|
+
handled = true;
|
|
7693
|
+
if (handled && stopPropagation)
|
|
7694
|
+
event.stopPropagation();
|
|
7695
|
+
return handled;
|
|
7714
7696
|
}
|
|
7715
7697
|
|
|
7716
7698
|
/**
|
|
@@ -8497,7 +8479,9 @@ function placeholder(content) {
|
|
|
8497
8479
|
return ViewPlugin.fromClass(class {
|
|
8498
8480
|
constructor(view) {
|
|
8499
8481
|
this.view = view;
|
|
8500
|
-
this.placeholder =
|
|
8482
|
+
this.placeholder = content
|
|
8483
|
+
? Decoration.set([Decoration.widget({ widget: new Placeholder(content), side: 1 }).range(0)])
|
|
8484
|
+
: Decoration.none;
|
|
8501
8485
|
}
|
|
8502
8486
|
get decorations() { return this.view.state.doc.length ? Decoration.none : this.placeholder; }
|
|
8503
8487
|
}, { decorations: v => v.decorations });
|