@codemirror/view 6.14.1 → 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 +18 -0
- package/dist/index.cjs +352 -378
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +353 -379
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Text, RangeSet, MapMode, RangeValue, Facet, StateEffect, ChangeSet, findClusterBreak, EditorSelection,
|
|
1
|
+
import { EditorState, Text, RangeSet, MapMode, RangeValue, Facet, StateEffect, ChangeSet, findClusterBreak, EditorSelection, findColumn, CharCategory, Annotation, Prec, Transaction, codePointAt, codePointSize, combineConfig, StateField, RangeSetBuilder, countColumn } from '@codemirror/state';
|
|
2
2
|
import { StyleModule } from 'style-mod';
|
|
3
3
|
import { keyName, base, shift } from 'w3c-keyname';
|
|
4
4
|
|
|
@@ -96,13 +96,15 @@ function windowRect(win) {
|
|
|
96
96
|
}
|
|
97
97
|
function scrollRectIntoView(dom, rect, side, x, y, xMargin, yMargin, ltr) {
|
|
98
98
|
let doc = dom.ownerDocument, win = doc.defaultView || window;
|
|
99
|
-
for (let cur = dom; cur;) {
|
|
99
|
+
for (let cur = dom, stop = false; cur && !stop;) {
|
|
100
100
|
if (cur.nodeType == 1) { // Element
|
|
101
101
|
let bounding, top = cur == doc.body;
|
|
102
102
|
if (top) {
|
|
103
103
|
bounding = windowRect(win);
|
|
104
104
|
}
|
|
105
105
|
else {
|
|
106
|
+
if (/^(fixed|sticky)$/.test(getComputedStyle(cur).position))
|
|
107
|
+
stop = true;
|
|
106
108
|
if (cur.scrollHeight <= cur.clientHeight && cur.scrollWidth <= cur.clientWidth) {
|
|
107
109
|
cur = cur.assignedSlot || cur.parentNode;
|
|
108
110
|
continue;
|
|
@@ -334,7 +336,7 @@ class ContentView {
|
|
|
334
336
|
constructor() {
|
|
335
337
|
this.parent = null;
|
|
336
338
|
this.dom = null;
|
|
337
|
-
this.
|
|
339
|
+
this.flags = 2 /* NodeDirty */;
|
|
338
340
|
}
|
|
339
341
|
get overrideDOMText() { return null; }
|
|
340
342
|
get posAtStart() {
|
|
@@ -356,18 +358,18 @@ class ContentView {
|
|
|
356
358
|
return this.posBefore(view) + view.length;
|
|
357
359
|
}
|
|
358
360
|
sync(view, track) {
|
|
359
|
-
if (this.
|
|
361
|
+
if (this.flags & 2 /* NodeDirty */) {
|
|
360
362
|
let parent = this.dom;
|
|
361
363
|
let prev = null, next;
|
|
362
364
|
for (let child of this.children) {
|
|
363
|
-
if (child.
|
|
364
|
-
if (!child.dom && (next = prev ? prev.nextSibling : parent.firstChild)
|
|
365
|
+
if (child.flags & 7 /* Dirty */) {
|
|
366
|
+
if (!child.dom && (next = prev ? prev.nextSibling : parent.firstChild)) {
|
|
365
367
|
let contentView = ContentView.get(next);
|
|
366
368
|
if (!contentView || !contentView.parent && contentView.canReuseDOM(child))
|
|
367
369
|
child.reuseDOM(next);
|
|
368
370
|
}
|
|
369
371
|
child.sync(view, track);
|
|
370
|
-
child.
|
|
372
|
+
child.flags &= ~7 /* Dirty */;
|
|
371
373
|
}
|
|
372
374
|
next = prev ? prev.nextSibling : parent.firstChild;
|
|
373
375
|
if (track && !track.written && track.node == parent && next != child.dom)
|
|
@@ -387,11 +389,11 @@ class ContentView {
|
|
|
387
389
|
while (next)
|
|
388
390
|
next = rm$1(next);
|
|
389
391
|
}
|
|
390
|
-
else if (this.
|
|
392
|
+
else if (this.flags & 1 /* ChildDirty */) {
|
|
391
393
|
for (let child of this.children)
|
|
392
|
-
if (child.
|
|
394
|
+
if (child.flags & 7 /* Dirty */) {
|
|
393
395
|
child.sync(view, track);
|
|
394
|
-
child.
|
|
396
|
+
child.flags &= ~7 /* Dirty */;
|
|
395
397
|
}
|
|
396
398
|
}
|
|
397
399
|
}
|
|
@@ -456,23 +458,23 @@ class ContentView {
|
|
|
456
458
|
endDOM: toI < this.children.length && toI >= 0 ? this.children[toI].dom : null };
|
|
457
459
|
}
|
|
458
460
|
markDirty(andParent = false) {
|
|
459
|
-
this.
|
|
461
|
+
this.flags |= 2 /* NodeDirty */;
|
|
460
462
|
this.markParentsDirty(andParent);
|
|
461
463
|
}
|
|
462
464
|
markParentsDirty(childList) {
|
|
463
465
|
for (let parent = this.parent; parent; parent = parent.parent) {
|
|
464
466
|
if (childList)
|
|
465
|
-
parent.
|
|
466
|
-
if (parent.
|
|
467
|
+
parent.flags |= 2 /* NodeDirty */;
|
|
468
|
+
if (parent.flags & 1 /* ChildDirty */)
|
|
467
469
|
return;
|
|
468
|
-
parent.
|
|
470
|
+
parent.flags |= 1 /* ChildDirty */;
|
|
469
471
|
childList = false;
|
|
470
472
|
}
|
|
471
473
|
}
|
|
472
474
|
setParent(parent) {
|
|
473
475
|
if (this.parent != parent) {
|
|
474
476
|
this.parent = parent;
|
|
475
|
-
if (this.
|
|
477
|
+
if (this.flags & 7 /* Dirty */)
|
|
476
478
|
this.markParentsDirty(true);
|
|
477
479
|
}
|
|
478
480
|
}
|
|
@@ -523,7 +525,9 @@ class ContentView {
|
|
|
523
525
|
return false;
|
|
524
526
|
}
|
|
525
527
|
become(other) { return false; }
|
|
526
|
-
canReuseDOM(other) {
|
|
528
|
+
canReuseDOM(other) {
|
|
529
|
+
return other.constructor == this.constructor && !((this.flags | other.flags) & 8 /* Composition */);
|
|
530
|
+
}
|
|
527
531
|
// When this is a zero-length view with a side, this should return a
|
|
528
532
|
// number <= 0 to indicate it is before its position, or a
|
|
529
533
|
// number > 0 when after its position.
|
|
@@ -647,6 +651,113 @@ function mergeChildrenInto(parent, from, to, insert, openStart, openEnd) {
|
|
|
647
651
|
replaceRange(parent, fromI, fromOff, toI, toOff, insert, 0, openStart, openEnd);
|
|
648
652
|
}
|
|
649
653
|
|
|
654
|
+
const LineBreakPlaceholder = "\uffff";
|
|
655
|
+
class DOMReader {
|
|
656
|
+
constructor(points, state) {
|
|
657
|
+
this.points = points;
|
|
658
|
+
this.text = "";
|
|
659
|
+
this.lineSeparator = state.facet(EditorState.lineSeparator);
|
|
660
|
+
}
|
|
661
|
+
append(text) {
|
|
662
|
+
this.text += text;
|
|
663
|
+
}
|
|
664
|
+
lineBreak() {
|
|
665
|
+
this.text += LineBreakPlaceholder;
|
|
666
|
+
}
|
|
667
|
+
readRange(start, end) {
|
|
668
|
+
if (!start)
|
|
669
|
+
return this;
|
|
670
|
+
let parent = start.parentNode;
|
|
671
|
+
for (let cur = start;;) {
|
|
672
|
+
this.findPointBefore(parent, cur);
|
|
673
|
+
let oldLen = this.text.length;
|
|
674
|
+
this.readNode(cur);
|
|
675
|
+
let next = cur.nextSibling;
|
|
676
|
+
if (next == end)
|
|
677
|
+
break;
|
|
678
|
+
let view = ContentView.get(cur), nextView = ContentView.get(next);
|
|
679
|
+
if (view && nextView ? view.breakAfter :
|
|
680
|
+
(view ? view.breakAfter : isBlockElement(cur)) ||
|
|
681
|
+
(isBlockElement(next) && (cur.nodeName != "BR" || cur.cmIgnore) && this.text.length > oldLen))
|
|
682
|
+
this.lineBreak();
|
|
683
|
+
cur = next;
|
|
684
|
+
}
|
|
685
|
+
this.findPointBefore(parent, end);
|
|
686
|
+
return this;
|
|
687
|
+
}
|
|
688
|
+
readTextNode(node) {
|
|
689
|
+
let text = node.nodeValue;
|
|
690
|
+
for (let point of this.points)
|
|
691
|
+
if (point.node == node)
|
|
692
|
+
point.pos = this.text.length + Math.min(point.offset, text.length);
|
|
693
|
+
for (let off = 0, re = this.lineSeparator ? null : /\r\n?|\n/g;;) {
|
|
694
|
+
let nextBreak = -1, breakSize = 1, m;
|
|
695
|
+
if (this.lineSeparator) {
|
|
696
|
+
nextBreak = text.indexOf(this.lineSeparator, off);
|
|
697
|
+
breakSize = this.lineSeparator.length;
|
|
698
|
+
}
|
|
699
|
+
else if (m = re.exec(text)) {
|
|
700
|
+
nextBreak = m.index;
|
|
701
|
+
breakSize = m[0].length;
|
|
702
|
+
}
|
|
703
|
+
this.append(text.slice(off, nextBreak < 0 ? text.length : nextBreak));
|
|
704
|
+
if (nextBreak < 0)
|
|
705
|
+
break;
|
|
706
|
+
this.lineBreak();
|
|
707
|
+
if (breakSize > 1)
|
|
708
|
+
for (let point of this.points)
|
|
709
|
+
if (point.node == node && point.pos > this.text.length)
|
|
710
|
+
point.pos -= breakSize - 1;
|
|
711
|
+
off = nextBreak + breakSize;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
readNode(node) {
|
|
715
|
+
if (node.cmIgnore)
|
|
716
|
+
return;
|
|
717
|
+
let view = ContentView.get(node);
|
|
718
|
+
let fromView = view && view.overrideDOMText;
|
|
719
|
+
if (fromView != null) {
|
|
720
|
+
this.findPointInside(node, fromView.length);
|
|
721
|
+
for (let i = fromView.iter(); !i.next().done;) {
|
|
722
|
+
if (i.lineBreak)
|
|
723
|
+
this.lineBreak();
|
|
724
|
+
else
|
|
725
|
+
this.append(i.value);
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
else if (node.nodeType == 3) {
|
|
729
|
+
this.readTextNode(node);
|
|
730
|
+
}
|
|
731
|
+
else if (node.nodeName == "BR") {
|
|
732
|
+
if (node.nextSibling)
|
|
733
|
+
this.lineBreak();
|
|
734
|
+
}
|
|
735
|
+
else if (node.nodeType == 1) {
|
|
736
|
+
this.readRange(node.firstChild, null);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
findPointBefore(node, next) {
|
|
740
|
+
for (let point of this.points)
|
|
741
|
+
if (point.node == node && node.childNodes[point.offset] == next)
|
|
742
|
+
point.pos = this.text.length;
|
|
743
|
+
}
|
|
744
|
+
findPointInside(node, maxLen) {
|
|
745
|
+
for (let point of this.points)
|
|
746
|
+
if (node.nodeType == 3 ? point.node == node : node.contains(point.node))
|
|
747
|
+
point.pos = this.text.length + Math.min(maxLen, point.offset);
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
function isBlockElement(node) {
|
|
751
|
+
return node.nodeType == 1 && /^(DIV|P|LI|UL|OL|BLOCKQUOTE|DD|DT|H\d|SECTION|PRE)$/.test(node.nodeName);
|
|
752
|
+
}
|
|
753
|
+
class DOMPoint {
|
|
754
|
+
constructor(node, offset) {
|
|
755
|
+
this.node = node;
|
|
756
|
+
this.offset = offset;
|
|
757
|
+
this.pos = -1;
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
|
|
650
761
|
let nav = typeof navigator != "undefined" ? navigator : { userAgent: "", vendor: "", platform: "" };
|
|
651
762
|
let doc = typeof document != "undefined" ? document : { documentElement: { style: {} } };
|
|
652
763
|
const ie_edge = /*@__PURE__*//Edge\/(\d+)/.exec(nav.userAgent);
|
|
@@ -700,7 +811,10 @@ class TextView extends ContentView {
|
|
|
700
811
|
this.createDOM(dom);
|
|
701
812
|
}
|
|
702
813
|
merge(from, to, source) {
|
|
703
|
-
if (
|
|
814
|
+
if ((this.flags & 8 /* Composition */) ||
|
|
815
|
+
source && (!(source instanceof TextView) ||
|
|
816
|
+
this.length - (to - from) + source.length > MaxJoinLen ||
|
|
817
|
+
(source.flags & 8 /* Composition */)))
|
|
704
818
|
return false;
|
|
705
819
|
this.text = this.text.slice(0, from) + (source ? source.text : "") + this.text.slice(to);
|
|
706
820
|
this.markDirty();
|
|
@@ -710,6 +824,7 @@ class TextView extends ContentView {
|
|
|
710
824
|
let result = new TextView(this.text.slice(from));
|
|
711
825
|
this.text = this.text.slice(0, from);
|
|
712
826
|
this.markDirty();
|
|
827
|
+
result.flags |= this.flags & 8 /* Composition */;
|
|
713
828
|
return result;
|
|
714
829
|
}
|
|
715
830
|
localPosFromDOM(node, offset) {
|
|
@@ -741,16 +856,19 @@ class MarkView extends ContentView {
|
|
|
741
856
|
dom.setAttribute(name, this.mark.attrs[name]);
|
|
742
857
|
return dom;
|
|
743
858
|
}
|
|
859
|
+
canReuseDOM(other) {
|
|
860
|
+
return super.canReuseDOM(other) && !((this.flags | other.flags) & 8 /* Composition */);
|
|
861
|
+
}
|
|
744
862
|
reuseDOM(node) {
|
|
745
863
|
if (node.nodeName == this.mark.tagName.toUpperCase()) {
|
|
746
864
|
this.setDOM(node);
|
|
747
|
-
this.
|
|
865
|
+
this.flags |= 4 /* AttrsDirty */ | 2 /* NodeDirty */;
|
|
748
866
|
}
|
|
749
867
|
}
|
|
750
868
|
sync(view, track) {
|
|
751
869
|
if (!this.dom)
|
|
752
870
|
this.setDOM(this.setAttrs(document.createElement(this.mark.tagName)));
|
|
753
|
-
else if (this.
|
|
871
|
+
else if (this.flags & 4 /* AttrsDirty */)
|
|
754
872
|
this.setAttrs(this.dom);
|
|
755
873
|
super.sync(view, track);
|
|
756
874
|
}
|
|
@@ -829,7 +947,7 @@ class WidgetView extends ContentView {
|
|
|
829
947
|
this.prevWidget = null;
|
|
830
948
|
}
|
|
831
949
|
static create(widget, length, side) {
|
|
832
|
-
return new
|
|
950
|
+
return new WidgetView(widget, length, side);
|
|
833
951
|
}
|
|
834
952
|
split(from) {
|
|
835
953
|
let result = WidgetView.create(this.widget, this.length - from, this.side);
|
|
@@ -907,129 +1025,6 @@ class WidgetView extends ContentView {
|
|
|
907
1025
|
this.widget.destroy(this.dom);
|
|
908
1026
|
}
|
|
909
1027
|
}
|
|
910
|
-
class CompositionView extends WidgetView {
|
|
911
|
-
domAtPos(pos) {
|
|
912
|
-
let { topView, text } = this.widget;
|
|
913
|
-
if (!topView)
|
|
914
|
-
return new DOMPos(text, Math.min(pos, text.nodeValue.length));
|
|
915
|
-
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)));
|
|
916
|
-
}
|
|
917
|
-
sync() { this.setDOM(this.widget.toDOM()); }
|
|
918
|
-
localPosFromDOM(node, offset) {
|
|
919
|
-
let { topView, text } = this.widget;
|
|
920
|
-
if (!topView)
|
|
921
|
-
return Math.min(offset, this.length);
|
|
922
|
-
return posFromDOMInCompositionTree(node, offset, topView, text, this.length - topView.length);
|
|
923
|
-
}
|
|
924
|
-
ignoreMutation() { return false; }
|
|
925
|
-
get overrideDOMText() { return null; }
|
|
926
|
-
coordsAt(pos, side) {
|
|
927
|
-
let { topView, text } = this.widget;
|
|
928
|
-
if (!topView)
|
|
929
|
-
return textCoords(text, pos, side);
|
|
930
|
-
return scanCompositionTree(pos, side, topView, text, this.length - topView.length, (v, pos, side) => v.coordsAt(pos, side), (text, pos, side) => textCoords(text, pos, side));
|
|
931
|
-
}
|
|
932
|
-
destroy() {
|
|
933
|
-
var _a;
|
|
934
|
-
super.destroy();
|
|
935
|
-
(_a = this.widget.topView) === null || _a === void 0 ? void 0 : _a.destroy();
|
|
936
|
-
}
|
|
937
|
-
get isEditable() { return true; }
|
|
938
|
-
canReuseDOM() { return true; }
|
|
939
|
-
}
|
|
940
|
-
// Uses the old structure of a chunk of content view frozen for
|
|
941
|
-
// composition to try and find a reasonable DOM location for the given
|
|
942
|
-
// offset.
|
|
943
|
-
function scanCompositionTree(pos, side, view, text, dLen, enterView, fromText) {
|
|
944
|
-
if (view instanceof MarkView) {
|
|
945
|
-
for (let child = view.dom.firstChild; child; child = child.nextSibling) {
|
|
946
|
-
let desc = ContentView.get(child);
|
|
947
|
-
if (!desc) {
|
|
948
|
-
let inner = scanCompositionNode(pos, side, child, fromText);
|
|
949
|
-
if (typeof inner != "number")
|
|
950
|
-
return inner;
|
|
951
|
-
pos = inner;
|
|
952
|
-
}
|
|
953
|
-
else {
|
|
954
|
-
let hasComp = contains(child, text);
|
|
955
|
-
let len = desc.length + (hasComp ? dLen : 0);
|
|
956
|
-
if (pos < len || pos == len && desc.getSide() <= 0)
|
|
957
|
-
return hasComp ? scanCompositionTree(pos, side, desc, text, dLen, enterView, fromText) : enterView(desc, pos, side);
|
|
958
|
-
pos -= len;
|
|
959
|
-
}
|
|
960
|
-
}
|
|
961
|
-
return enterView(view, view.length, -1);
|
|
962
|
-
}
|
|
963
|
-
else if (view.dom == text) {
|
|
964
|
-
return fromText(text, pos, side);
|
|
965
|
-
}
|
|
966
|
-
else {
|
|
967
|
-
return enterView(view, pos, side);
|
|
968
|
-
}
|
|
969
|
-
}
|
|
970
|
-
function scanCompositionNode(pos, side, node, fromText) {
|
|
971
|
-
if (node.nodeType == 3) {
|
|
972
|
-
let len = node.nodeValue.length;
|
|
973
|
-
if (pos <= len)
|
|
974
|
-
return fromText(node, pos, side);
|
|
975
|
-
pos -= len;
|
|
976
|
-
}
|
|
977
|
-
else if (node.nodeType == 1 && node.contentEditable != "false") {
|
|
978
|
-
for (let child = node.firstChild; child; child = child.nextSibling) {
|
|
979
|
-
let inner = scanCompositionNode(pos, side, child, fromText);
|
|
980
|
-
if (typeof inner != "number")
|
|
981
|
-
return inner;
|
|
982
|
-
pos = inner;
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
return pos;
|
|
986
|
-
}
|
|
987
|
-
function posFromDOMInCompositionTree(node, offset, view, text, dLen) {
|
|
988
|
-
if (view instanceof MarkView) {
|
|
989
|
-
let pos = 0;
|
|
990
|
-
for (let child = view.dom.firstChild; child; child = child.nextSibling) {
|
|
991
|
-
let childView = ContentView.get(child);
|
|
992
|
-
if (childView) {
|
|
993
|
-
let hasComp = contains(child, text);
|
|
994
|
-
if (contains(child, node))
|
|
995
|
-
return pos + (hasComp ? posFromDOMInCompositionTree(node, offset, childView, text, dLen)
|
|
996
|
-
: childView.localPosFromDOM(node, offset));
|
|
997
|
-
pos += childView.length + (hasComp ? dLen : 0);
|
|
998
|
-
}
|
|
999
|
-
else {
|
|
1000
|
-
let inner = posFromDOMInOpaqueNode(node, offset, child);
|
|
1001
|
-
if (inner.result != null)
|
|
1002
|
-
return pos + inner.result;
|
|
1003
|
-
pos += inner.size;
|
|
1004
|
-
}
|
|
1005
|
-
}
|
|
1006
|
-
}
|
|
1007
|
-
else if (view.dom == text) {
|
|
1008
|
-
return Math.min(offset, text.nodeValue.length);
|
|
1009
|
-
}
|
|
1010
|
-
return view.localPosFromDOM(node, offset);
|
|
1011
|
-
}
|
|
1012
|
-
function posFromDOMInOpaqueNode(node, offset, target) {
|
|
1013
|
-
if (target.nodeType == 3) {
|
|
1014
|
-
return node == target ? { result: offset } : { size: target.nodeValue.length };
|
|
1015
|
-
}
|
|
1016
|
-
else if (target.nodeType == 1 && target.contentEditable != "false") {
|
|
1017
|
-
let pos = 0;
|
|
1018
|
-
for (let child = target.firstChild, i = 0;; child = child.nextSibling, i++) {
|
|
1019
|
-
if (node == target && i == offset)
|
|
1020
|
-
return { result: pos };
|
|
1021
|
-
if (!child)
|
|
1022
|
-
return { size: pos };
|
|
1023
|
-
let inner = posFromDOMInOpaqueNode(node, offset, child);
|
|
1024
|
-
if (inner.result != null)
|
|
1025
|
-
return { result: offset + inner.result };
|
|
1026
|
-
pos += inner.size;
|
|
1027
|
-
}
|
|
1028
|
-
}
|
|
1029
|
-
else {
|
|
1030
|
-
return target.contains(node) ? { result: 0 } : { size: 0 };
|
|
1031
|
-
}
|
|
1032
|
-
}
|
|
1033
1028
|
// These are drawn around uneditable widgets to avoid a number of
|
|
1034
1029
|
// browser bugs that show up when the cursor is directly next to
|
|
1035
1030
|
// uneditable inline content.
|
|
@@ -1149,16 +1144,20 @@ function combineAttrs(source, target) {
|
|
|
1149
1144
|
}
|
|
1150
1145
|
return target;
|
|
1151
1146
|
}
|
|
1152
|
-
|
|
1147
|
+
const noAttrs = /*@__PURE__*/Object.create(null);
|
|
1148
|
+
function attrsEq(a, b, ignore) {
|
|
1153
1149
|
if (a == b)
|
|
1154
1150
|
return true;
|
|
1155
|
-
if (!a
|
|
1156
|
-
|
|
1151
|
+
if (!a)
|
|
1152
|
+
a = noAttrs;
|
|
1153
|
+
if (!b)
|
|
1154
|
+
b = noAttrs;
|
|
1157
1155
|
let keysA = Object.keys(a), keysB = Object.keys(b);
|
|
1158
|
-
if (keysA.length
|
|
1156
|
+
if (keysA.length - (ignore && keysA.indexOf(ignore) > -1 ? 1 : 0) !=
|
|
1157
|
+
keysB.length - (ignore && keysB.indexOf(ignore) > -1 ? 1 : 0))
|
|
1159
1158
|
return false;
|
|
1160
1159
|
for (let key of keysA) {
|
|
1161
|
-
if (keysB.indexOf(key) == -1 || a[key] !== b[key])
|
|
1160
|
+
if (key != ignore && (keysB.indexOf(key) == -1 || a[key] !== b[key]))
|
|
1162
1161
|
return false;
|
|
1163
1162
|
}
|
|
1164
1163
|
return true;
|
|
@@ -1175,6 +1174,14 @@ function updateAttrs(dom, prev, attrs) {
|
|
|
1175
1174
|
dom.setAttribute(changed = name, attrs[name]);
|
|
1176
1175
|
return !!changed;
|
|
1177
1176
|
}
|
|
1177
|
+
function getAttrs(dom) {
|
|
1178
|
+
let attrs = Object.create(null);
|
|
1179
|
+
for (let i = 0; i < dom.attributes.length; i++) {
|
|
1180
|
+
let attr = dom.attributes[i];
|
|
1181
|
+
attrs[attr.name] = attr.value;
|
|
1182
|
+
}
|
|
1183
|
+
return attrs;
|
|
1184
|
+
}
|
|
1178
1185
|
|
|
1179
1186
|
/**
|
|
1180
1187
|
Widgets added to the content are described by subclasses of this
|
|
@@ -1239,10 +1246,6 @@ class WidgetType {
|
|
|
1239
1246
|
/**
|
|
1240
1247
|
@internal
|
|
1241
1248
|
*/
|
|
1242
|
-
get customView() { return null; }
|
|
1243
|
-
/**
|
|
1244
|
-
@internal
|
|
1245
|
-
*/
|
|
1246
1249
|
get isHidden() { return false; }
|
|
1247
1250
|
/**
|
|
1248
1251
|
This is called when the an instance of the widget is removed
|
|
@@ -1380,11 +1383,12 @@ class MarkDecoration extends Decoration {
|
|
|
1380
1383
|
this.attrs = spec.attributes || null;
|
|
1381
1384
|
}
|
|
1382
1385
|
eq(other) {
|
|
1386
|
+
var _a, _b;
|
|
1383
1387
|
return this == other ||
|
|
1384
1388
|
other instanceof MarkDecoration &&
|
|
1385
1389
|
this.tagName == other.tagName &&
|
|
1386
|
-
this.class == other.class &&
|
|
1387
|
-
attrsEq(this.attrs, other.attrs);
|
|
1390
|
+
(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)) &&
|
|
1391
|
+
attrsEq(this.attrs, other.attrs, "class");
|
|
1388
1392
|
}
|
|
1389
1393
|
range(from, to = from) {
|
|
1390
1394
|
if (from >= to)
|
|
@@ -1536,7 +1540,7 @@ class LineView extends ContentView {
|
|
|
1536
1540
|
reuseDOM(node) {
|
|
1537
1541
|
if (node.nodeName == "DIV") {
|
|
1538
1542
|
this.setDOM(node);
|
|
1539
|
-
this.
|
|
1543
|
+
this.flags |= 4 /* AttrsDirty */ | 2 /* NodeDirty */;
|
|
1540
1544
|
}
|
|
1541
1545
|
}
|
|
1542
1546
|
sync(view, track) {
|
|
@@ -1546,7 +1550,7 @@ class LineView extends ContentView {
|
|
|
1546
1550
|
this.dom.className = "cm-line";
|
|
1547
1551
|
this.prevAttrs = this.attrs ? null : undefined;
|
|
1548
1552
|
}
|
|
1549
|
-
else if (this.
|
|
1553
|
+
else if (this.flags & 4 /* AttrsDirty */) {
|
|
1550
1554
|
clearAttributes(this.dom);
|
|
1551
1555
|
this.dom.className = "cm-line";
|
|
1552
1556
|
this.prevAttrs = this.attrs ? null : undefined;
|
|
@@ -2486,121 +2490,14 @@ function moveVisually(line, order, dir, start, forward) {
|
|
|
2486
2490
|
return EditorSelection.cursor(nextIndex + line.from, forward ? -1 : 1, span.level);
|
|
2487
2491
|
}
|
|
2488
2492
|
|
|
2489
|
-
const LineBreakPlaceholder = "\uffff";
|
|
2490
|
-
class DOMReader {
|
|
2491
|
-
constructor(points, state) {
|
|
2492
|
-
this.points = points;
|
|
2493
|
-
this.text = "";
|
|
2494
|
-
this.lineSeparator = state.facet(EditorState.lineSeparator);
|
|
2495
|
-
}
|
|
2496
|
-
append(text) {
|
|
2497
|
-
this.text += text;
|
|
2498
|
-
}
|
|
2499
|
-
lineBreak() {
|
|
2500
|
-
this.text += LineBreakPlaceholder;
|
|
2501
|
-
}
|
|
2502
|
-
readRange(start, end) {
|
|
2503
|
-
if (!start)
|
|
2504
|
-
return this;
|
|
2505
|
-
let parent = start.parentNode;
|
|
2506
|
-
for (let cur = start;;) {
|
|
2507
|
-
this.findPointBefore(parent, cur);
|
|
2508
|
-
let oldLen = this.text.length;
|
|
2509
|
-
this.readNode(cur);
|
|
2510
|
-
let next = cur.nextSibling;
|
|
2511
|
-
if (next == end)
|
|
2512
|
-
break;
|
|
2513
|
-
let view = ContentView.get(cur), nextView = ContentView.get(next);
|
|
2514
|
-
if (view && nextView ? view.breakAfter :
|
|
2515
|
-
(view ? view.breakAfter : isBlockElement(cur)) ||
|
|
2516
|
-
(isBlockElement(next) && (cur.nodeName != "BR" || cur.cmIgnore) && this.text.length > oldLen))
|
|
2517
|
-
this.lineBreak();
|
|
2518
|
-
cur = next;
|
|
2519
|
-
}
|
|
2520
|
-
this.findPointBefore(parent, end);
|
|
2521
|
-
return this;
|
|
2522
|
-
}
|
|
2523
|
-
readTextNode(node) {
|
|
2524
|
-
let text = node.nodeValue;
|
|
2525
|
-
for (let point of this.points)
|
|
2526
|
-
if (point.node == node)
|
|
2527
|
-
point.pos = this.text.length + Math.min(point.offset, text.length);
|
|
2528
|
-
for (let off = 0, re = this.lineSeparator ? null : /\r\n?|\n/g;;) {
|
|
2529
|
-
let nextBreak = -1, breakSize = 1, m;
|
|
2530
|
-
if (this.lineSeparator) {
|
|
2531
|
-
nextBreak = text.indexOf(this.lineSeparator, off);
|
|
2532
|
-
breakSize = this.lineSeparator.length;
|
|
2533
|
-
}
|
|
2534
|
-
else if (m = re.exec(text)) {
|
|
2535
|
-
nextBreak = m.index;
|
|
2536
|
-
breakSize = m[0].length;
|
|
2537
|
-
}
|
|
2538
|
-
this.append(text.slice(off, nextBreak < 0 ? text.length : nextBreak));
|
|
2539
|
-
if (nextBreak < 0)
|
|
2540
|
-
break;
|
|
2541
|
-
this.lineBreak();
|
|
2542
|
-
if (breakSize > 1)
|
|
2543
|
-
for (let point of this.points)
|
|
2544
|
-
if (point.node == node && point.pos > this.text.length)
|
|
2545
|
-
point.pos -= breakSize - 1;
|
|
2546
|
-
off = nextBreak + breakSize;
|
|
2547
|
-
}
|
|
2548
|
-
}
|
|
2549
|
-
readNode(node) {
|
|
2550
|
-
if (node.cmIgnore)
|
|
2551
|
-
return;
|
|
2552
|
-
let view = ContentView.get(node);
|
|
2553
|
-
let fromView = view && view.overrideDOMText;
|
|
2554
|
-
if (fromView != null) {
|
|
2555
|
-
this.findPointInside(node, fromView.length);
|
|
2556
|
-
for (let i = fromView.iter(); !i.next().done;) {
|
|
2557
|
-
if (i.lineBreak)
|
|
2558
|
-
this.lineBreak();
|
|
2559
|
-
else
|
|
2560
|
-
this.append(i.value);
|
|
2561
|
-
}
|
|
2562
|
-
}
|
|
2563
|
-
else if (node.nodeType == 3) {
|
|
2564
|
-
this.readTextNode(node);
|
|
2565
|
-
}
|
|
2566
|
-
else if (node.nodeName == "BR") {
|
|
2567
|
-
if (node.nextSibling)
|
|
2568
|
-
this.lineBreak();
|
|
2569
|
-
}
|
|
2570
|
-
else if (node.nodeType == 1) {
|
|
2571
|
-
this.readRange(node.firstChild, null);
|
|
2572
|
-
}
|
|
2573
|
-
}
|
|
2574
|
-
findPointBefore(node, next) {
|
|
2575
|
-
for (let point of this.points)
|
|
2576
|
-
if (point.node == node && node.childNodes[point.offset] == next)
|
|
2577
|
-
point.pos = this.text.length;
|
|
2578
|
-
}
|
|
2579
|
-
findPointInside(node, maxLen) {
|
|
2580
|
-
for (let point of this.points)
|
|
2581
|
-
if (node.nodeType == 3 ? point.node == node : node.contains(point.node))
|
|
2582
|
-
point.pos = this.text.length + Math.min(maxLen, point.offset);
|
|
2583
|
-
}
|
|
2584
|
-
}
|
|
2585
|
-
function isBlockElement(node) {
|
|
2586
|
-
return node.nodeType == 1 && /^(DIV|P|LI|UL|OL|BLOCKQUOTE|DD|DT|H\d|SECTION|PRE)$/.test(node.nodeName);
|
|
2587
|
-
}
|
|
2588
|
-
class DOMPoint {
|
|
2589
|
-
constructor(node, offset) {
|
|
2590
|
-
this.node = node;
|
|
2591
|
-
this.offset = offset;
|
|
2592
|
-
this.pos = -1;
|
|
2593
|
-
}
|
|
2594
|
-
}
|
|
2595
|
-
|
|
2596
2493
|
class DocView extends ContentView {
|
|
2597
2494
|
constructor(view) {
|
|
2598
2495
|
super();
|
|
2599
2496
|
this.view = view;
|
|
2600
|
-
this.compositionDeco = Decoration.none;
|
|
2601
|
-
this.compositionNode = null;
|
|
2602
2497
|
this.decorations = [];
|
|
2603
2498
|
this.dynamicDecorationMap = [];
|
|
2499
|
+
this.hasComposition = false;
|
|
2500
|
+
this.markedForComposition = new Set;
|
|
2604
2501
|
// Track a minimum width for the editor. When measuring sizes in
|
|
2605
2502
|
// measureVisibleLineHeights, this is updated to point at the width
|
|
2606
2503
|
// of a given element and its extent in the document. When a change
|
|
@@ -2623,7 +2520,7 @@ class DocView extends ContentView {
|
|
|
2623
2520
|
this.children = [new LineView];
|
|
2624
2521
|
this.children[0].setParent(this);
|
|
2625
2522
|
this.updateDeco();
|
|
2626
|
-
this.updateInner([new ChangedRange(0, 0, 0, view.state.doc.length)], 0);
|
|
2523
|
+
this.updateInner([new ChangedRange(0, 0, 0, view.state.doc.length)], 0, null);
|
|
2627
2524
|
}
|
|
2628
2525
|
get length() { return this.view.state.doc.length; }
|
|
2629
2526
|
// Update the document view to a given state.
|
|
@@ -2638,24 +2535,26 @@ class DocView extends ContentView {
|
|
|
2638
2535
|
this.minWidthTo = update.changes.mapPos(this.minWidthTo, 1);
|
|
2639
2536
|
}
|
|
2640
2537
|
}
|
|
2641
|
-
|
|
2642
|
-
|
|
2538
|
+
let composition = this.view.inputState.composing < 0 ? null : findCompositionRange(this.view, update.changes);
|
|
2539
|
+
if (this.hasComposition)
|
|
2540
|
+
this.markedForComposition.clear();
|
|
2541
|
+
this.hasComposition = !!composition;
|
|
2643
2542
|
// When the DOM nodes around the selection are moved to another
|
|
2644
2543
|
// parent, Chrome sometimes reports a different selection through
|
|
2645
2544
|
// getSelection than the one that it actually shows to the user.
|
|
2646
2545
|
// This forces a selection update when lines are joined to work
|
|
2647
2546
|
// around that. Issue #54
|
|
2648
|
-
if ((browser.ie || browser.chrome) && !
|
|
2547
|
+
if ((browser.ie || browser.chrome) && !composition && update &&
|
|
2649
2548
|
update.state.doc.lines != update.startState.doc.lines)
|
|
2650
2549
|
this.forceSelection = true;
|
|
2651
2550
|
let prevDeco = this.decorations, deco = this.updateDeco();
|
|
2652
2551
|
let decoDiff = findChangedDeco(prevDeco, deco, update.changes);
|
|
2653
2552
|
changedRanges = ChangedRange.extendWithRanges(changedRanges, decoDiff);
|
|
2654
|
-
if (this.
|
|
2553
|
+
if (!(this.flags & 7 /* Dirty */) && changedRanges.length == 0) {
|
|
2655
2554
|
return false;
|
|
2656
2555
|
}
|
|
2657
2556
|
else {
|
|
2658
|
-
this.updateInner(changedRanges, update.startState.doc.length);
|
|
2557
|
+
this.updateInner(changedRanges, update.startState.doc.length, composition);
|
|
2659
2558
|
if (update.transactions.length)
|
|
2660
2559
|
this.lastUpdate = Date.now();
|
|
2661
2560
|
return true;
|
|
@@ -2663,9 +2562,9 @@ class DocView extends ContentView {
|
|
|
2663
2562
|
}
|
|
2664
2563
|
// Used by update and the constructor do perform the actual DOM
|
|
2665
2564
|
// update
|
|
2666
|
-
updateInner(changes, oldLength) {
|
|
2565
|
+
updateInner(changes, oldLength, composition) {
|
|
2667
2566
|
this.view.viewState.mustMeasureContent = true;
|
|
2668
|
-
this.updateChildren(changes, oldLength);
|
|
2567
|
+
this.updateChildren(changes, oldLength, composition);
|
|
2669
2568
|
let { observer } = this.view;
|
|
2670
2569
|
observer.ignore(() => {
|
|
2671
2570
|
// Lock the height during redrawing, since Chrome sometimes
|
|
@@ -2680,11 +2579,12 @@ class DocView extends ContentView {
|
|
|
2680
2579
|
// to detect that situation.
|
|
2681
2580
|
let track = browser.chrome || browser.ios ? { node: observer.selectionRange.focusNode, written: false } : undefined;
|
|
2682
2581
|
this.sync(this.view, track);
|
|
2683
|
-
this.
|
|
2582
|
+
this.flags &= ~7 /* Dirty */;
|
|
2684
2583
|
if (track && (track.written || observer.selectionRange.focusNode != track.node))
|
|
2685
2584
|
this.forceSelection = true;
|
|
2686
2585
|
this.dom.style.height = "";
|
|
2687
2586
|
});
|
|
2587
|
+
this.markedForComposition.forEach(cView => cView.flags &= ~8 /* Composition */);
|
|
2688
2588
|
let gaps = [];
|
|
2689
2589
|
if (this.view.viewport.from || this.view.viewport.to < this.view.state.doc.length)
|
|
2690
2590
|
for (let child of this.children)
|
|
@@ -2692,18 +2592,62 @@ class DocView extends ContentView {
|
|
|
2692
2592
|
gaps.push(child.dom);
|
|
2693
2593
|
observer.updateGaps(gaps);
|
|
2694
2594
|
}
|
|
2695
|
-
updateChildren(changes, oldLength) {
|
|
2595
|
+
updateChildren(changes, oldLength, composition) {
|
|
2596
|
+
let ranges = composition ? composition.range.addToSet(changes.slice()) : changes;
|
|
2696
2597
|
let cursor = this.childCursor(oldLength);
|
|
2697
|
-
for (let i =
|
|
2698
|
-
let next = i >= 0 ?
|
|
2598
|
+
for (let i = ranges.length - 1;; i--) {
|
|
2599
|
+
let next = i >= 0 ? ranges[i] : null;
|
|
2699
2600
|
if (!next)
|
|
2700
2601
|
break;
|
|
2701
|
-
let { fromA, toA, fromB, toB } = next;
|
|
2702
|
-
|
|
2602
|
+
let { fromA, toA, fromB, toB } = next, content, breakAtStart, openStart, openEnd;
|
|
2603
|
+
if (composition && composition.range.fromB < toB && composition.range.toB > fromB) {
|
|
2604
|
+
let before = ContentBuilder.build(this.view.state.doc, fromB, composition.range.fromB, this.decorations, this.dynamicDecorationMap);
|
|
2605
|
+
let after = ContentBuilder.build(this.view.state.doc, composition.range.toB, toB, this.decorations, this.dynamicDecorationMap);
|
|
2606
|
+
breakAtStart = before.breakAtStart;
|
|
2607
|
+
openStart = before.openStart;
|
|
2608
|
+
openEnd = after.openEnd;
|
|
2609
|
+
let compLine = this.compositionView(composition);
|
|
2610
|
+
compLine.merge(compLine.length, compLine.length, after.content[0], false, after.openStart, 0);
|
|
2611
|
+
compLine.merge(0, 0, before.content[before.content.length - 1], true, 0, before.openEnd);
|
|
2612
|
+
content = before.content.slice(0, before.content.length - 1).concat(compLine).concat(after.content.slice(1));
|
|
2613
|
+
}
|
|
2614
|
+
else {
|
|
2615
|
+
({ content, breakAtStart, openStart, openEnd } =
|
|
2616
|
+
ContentBuilder.build(this.view.state.doc, fromB, toB, this.decorations, this.dynamicDecorationMap));
|
|
2617
|
+
}
|
|
2703
2618
|
let { i: toI, off: toOff } = cursor.findPos(toA, 1);
|
|
2704
2619
|
let { i: fromI, off: fromOff } = cursor.findPos(fromA, -1);
|
|
2705
2620
|
replaceRange(this, fromI, fromOff, toI, toOff, content, breakAtStart, openStart, openEnd);
|
|
2706
2621
|
}
|
|
2622
|
+
if (composition)
|
|
2623
|
+
this.fixCompositionDOM(composition);
|
|
2624
|
+
}
|
|
2625
|
+
compositionView(composition) {
|
|
2626
|
+
let cur = new TextView(composition.text.nodeValue);
|
|
2627
|
+
cur.flags |= 8 /* Composition */;
|
|
2628
|
+
for (let { deco } of composition.marks)
|
|
2629
|
+
cur = new MarkView(deco, [cur], cur.length);
|
|
2630
|
+
let line = new LineView;
|
|
2631
|
+
line.append(cur, 0);
|
|
2632
|
+
return line;
|
|
2633
|
+
}
|
|
2634
|
+
fixCompositionDOM(composition) {
|
|
2635
|
+
let fix = (dom, cView) => {
|
|
2636
|
+
cView.flags |= 8 /* Composition */;
|
|
2637
|
+
this.markedForComposition.add(cView);
|
|
2638
|
+
let prev = ContentView.get(dom);
|
|
2639
|
+
if (prev)
|
|
2640
|
+
prev.dom = null;
|
|
2641
|
+
cView.setDOM(dom);
|
|
2642
|
+
};
|
|
2643
|
+
let pos = this.childPos(composition.range.fromB, 1);
|
|
2644
|
+
let cView = this.children[pos.i];
|
|
2645
|
+
fix(composition.line, cView);
|
|
2646
|
+
for (let i = composition.marks.length - 1; i >= -1; i--) {
|
|
2647
|
+
pos = cView.childPos(pos.off, 1);
|
|
2648
|
+
cView = cView.children[pos.i];
|
|
2649
|
+
fix(i >= 0 ? composition.marks[i].node : composition.text, cView);
|
|
2650
|
+
}
|
|
2707
2651
|
}
|
|
2708
2652
|
// Sync the DOM selection to this.state.selection
|
|
2709
2653
|
updateSelection(mustRead = false, fromPointer = false) {
|
|
@@ -2722,7 +2666,7 @@ class DocView extends ContentView {
|
|
|
2722
2666
|
let head = main.empty ? anchor : this.domAtPos(main.head);
|
|
2723
2667
|
// Always reset on Firefox when next to an uneditable node to
|
|
2724
2668
|
// avoid invisible cursor bugs (#111)
|
|
2725
|
-
if (browser.gecko && main.empty && !this.
|
|
2669
|
+
if (browser.gecko && main.empty && !this.hasComposition && betweenUneditable(anchor)) {
|
|
2726
2670
|
let dummy = document.createTextNode("");
|
|
2727
2671
|
this.view.observer.ignore(() => anchor.node.insertBefore(dummy, anchor.node.childNodes[anchor.offset] || null));
|
|
2728
2672
|
anchor = head = new DOMPos(dummy, 0);
|
|
@@ -2794,7 +2738,7 @@ class DocView extends ContentView {
|
|
|
2794
2738
|
this.impreciseHead = head.precise ? null : new DOMPos(domSel.focusNode, domSel.focusOffset);
|
|
2795
2739
|
}
|
|
2796
2740
|
enforceCursorAssoc() {
|
|
2797
|
-
if (this.
|
|
2741
|
+
if (this.hasComposition)
|
|
2798
2742
|
return;
|
|
2799
2743
|
let { view } = this, cursor = view.state.selection.main;
|
|
2800
2744
|
let sel = getSelection(view.root);
|
|
@@ -2904,6 +2848,7 @@ class DocView extends ContentView {
|
|
|
2904
2848
|
let dummy = document.createElement("div"), lineHeight, charWidth, textHeight;
|
|
2905
2849
|
dummy.className = "cm-line";
|
|
2906
2850
|
dummy.style.width = "99999px";
|
|
2851
|
+
dummy.style.position = "absolute";
|
|
2907
2852
|
dummy.textContent = "abc def ghi jkl mno pqr stu";
|
|
2908
2853
|
this.view.observer.ignore(() => {
|
|
2909
2854
|
this.dom.appendChild(dummy);
|
|
@@ -2953,7 +2898,6 @@ class DocView extends ContentView {
|
|
|
2953
2898
|
this.dynamicDecorationMap[i] = false;
|
|
2954
2899
|
return this.decorations = [
|
|
2955
2900
|
...allDeco,
|
|
2956
|
-
this.compositionDeco,
|
|
2957
2901
|
this.computeBlockGapDeco(),
|
|
2958
2902
|
this.view.viewState.lineGapDeco
|
|
2959
2903
|
];
|
|
@@ -2996,83 +2940,85 @@ class BlockGapWidget extends WidgetType {
|
|
|
2996
2940
|
}
|
|
2997
2941
|
get estimatedHeight() { return this.height; }
|
|
2998
2942
|
}
|
|
2999
|
-
function
|
|
2943
|
+
function findCompositionNode(view) {
|
|
3000
2944
|
let sel = view.observer.selectionRange;
|
|
3001
2945
|
let textNode = sel.focusNode && nearbyTextNode(sel.focusNode, sel.focusOffset, 0);
|
|
3002
2946
|
if (!textNode)
|
|
3003
2947
|
return null;
|
|
3004
|
-
let cView =
|
|
3005
|
-
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
while (topNode.parentNode != cView.dom)
|
|
3010
|
-
topNode = topNode.parentNode;
|
|
3011
|
-
let prev = topNode.previousSibling;
|
|
3012
|
-
while (prev && !ContentView.get(prev))
|
|
3013
|
-
prev = prev.previousSibling;
|
|
3014
|
-
let pos = prev ? ContentView.get(prev).posAtEnd : cView.posAtStart;
|
|
3015
|
-
return { from: pos, to: pos, node: topNode, text: textNode };
|
|
2948
|
+
let cView = ContentView.get(textNode);
|
|
2949
|
+
let from, to;
|
|
2950
|
+
if (cView instanceof TextView) {
|
|
2951
|
+
from = cView.posAtStart;
|
|
2952
|
+
to = from + cView.length;
|
|
3016
2953
|
}
|
|
3017
2954
|
else {
|
|
3018
|
-
for (;;) {
|
|
3019
|
-
let
|
|
3020
|
-
|
|
2955
|
+
up: for (let offset = 0, node = textNode;;) {
|
|
2956
|
+
for (let sibling = node.previousSibling, cView; sibling; sibling = sibling.previousSibling) {
|
|
2957
|
+
if (cView = ContentView.get(sibling)) {
|
|
2958
|
+
from = to = cView.posAtEnd + offset;
|
|
2959
|
+
break up;
|
|
2960
|
+
}
|
|
2961
|
+
let reader = new DOMReader([], view.state);
|
|
2962
|
+
reader.readNode(sibling);
|
|
2963
|
+
if (reader.text.indexOf(LineBreakPlaceholder) > -1)
|
|
2964
|
+
return null;
|
|
2965
|
+
offset += reader.text.length;
|
|
2966
|
+
}
|
|
2967
|
+
node = node.parentNode;
|
|
2968
|
+
if (!node)
|
|
3021
2969
|
return null;
|
|
3022
|
-
|
|
2970
|
+
let parentView = ContentView.get(node);
|
|
2971
|
+
if (parentView) {
|
|
2972
|
+
from = to = parentView.posAtStart + offset;
|
|
3023
2973
|
break;
|
|
3024
|
-
|
|
3025
|
-
}
|
|
3026
|
-
|
|
3027
|
-
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
let
|
|
3036
|
-
|
|
3037
|
-
|
|
3038
|
-
|
|
3039
|
-
|
|
3040
|
-
|
|
3041
|
-
|
|
3042
|
-
|
|
3043
|
-
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
|
|
3048
|
-
|
|
3049
|
-
|
|
2974
|
+
}
|
|
2975
|
+
}
|
|
2976
|
+
}
|
|
2977
|
+
return { from, to, node: textNode };
|
|
2978
|
+
}
|
|
2979
|
+
function findCompositionRange(view, changes) {
|
|
2980
|
+
let found = findCompositionNode(view);
|
|
2981
|
+
if (!found)
|
|
2982
|
+
return null;
|
|
2983
|
+
let { from: fromA, to: toA, node: textNode } = found;
|
|
2984
|
+
let fromB = changes.mapPos(fromA, -1), toB = changes.mapPos(toA, 1);
|
|
2985
|
+
let text = textNode.nodeValue;
|
|
2986
|
+
// Don't try to preserve multi-line compositions
|
|
2987
|
+
if (/[\n\r]/.test(text))
|
|
2988
|
+
return null;
|
|
2989
|
+
if (toB - fromB != text.length) {
|
|
2990
|
+
// If there is a length mismatch, see if mapping non-inclusively helps
|
|
2991
|
+
let fromB2 = changes.mapPos(fromA, 1), toB2 = changes.mapPos(toA, -1);
|
|
2992
|
+
if (toB2 - fromB2 == text.length)
|
|
2993
|
+
fromB = fromB2, toB = toB2;
|
|
2994
|
+
// See if we can find an instance of the text at either side
|
|
2995
|
+
else if (view.state.doc.sliceString(toB - text.length, toB) == text)
|
|
2996
|
+
fromB = toB - text.length;
|
|
2997
|
+
else if (view.state.doc.sliceString(fromB, fromB + text.length) == text)
|
|
2998
|
+
toB = fromB + text.length;
|
|
2999
|
+
// Not found
|
|
3050
3000
|
else
|
|
3051
|
-
return
|
|
3052
|
-
}
|
|
3053
|
-
|
|
3054
|
-
return
|
|
3055
|
-
|
|
3056
|
-
let
|
|
3057
|
-
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3001
|
+
return null;
|
|
3002
|
+
}
|
|
3003
|
+
if (view.state.doc.sliceString(fromB, toB) != text)
|
|
3004
|
+
return null;
|
|
3005
|
+
let marks = [];
|
|
3006
|
+
let range = new ChangedRange(fromA, toA, fromB, toB);
|
|
3007
|
+
for (let parent = textNode.parentNode;; parent = parent.parentNode) {
|
|
3008
|
+
let parentView = ContentView.get(parent);
|
|
3009
|
+
if (parentView instanceof MarkView)
|
|
3010
|
+
marks.push({ node: parent, deco: parentView.mark });
|
|
3011
|
+
else if (parentView instanceof LineView || parent.nodeName == "DIV" && parent.parentNode == view.contentDOM)
|
|
3012
|
+
return { range, text: textNode, marks, line: parent };
|
|
3013
|
+
else if (parent != view.contentDOM)
|
|
3014
|
+
marks.push({ node: parent, deco: new MarkDecoration({
|
|
3015
|
+
inclusive: true,
|
|
3016
|
+
attributes: getAttrs(parent),
|
|
3017
|
+
tagName: parent.tagName.toLowerCase()
|
|
3018
|
+
}) });
|
|
3019
|
+
else
|
|
3020
|
+
return null;
|
|
3071
3021
|
}
|
|
3072
|
-
eq(other) { return this.top == other.top && this.text == other.text; }
|
|
3073
|
-
toDOM() { return this.top; }
|
|
3074
|
-
ignoreEvent() { return false; }
|
|
3075
|
-
get customView() { return CompositionView; }
|
|
3076
3022
|
}
|
|
3077
3023
|
function nearbyTextNode(startNode, startOffset, side) {
|
|
3078
3024
|
if (side <= 0)
|
|
@@ -3733,9 +3679,13 @@ const dragScrollMargin = 6;
|
|
|
3733
3679
|
function dragScrollSpeed(dist) {
|
|
3734
3680
|
return Math.max(0, dist) * 0.7 + 8;
|
|
3735
3681
|
}
|
|
3682
|
+
function dist(a, b) {
|
|
3683
|
+
return Math.max(Math.abs(a.clientX - b.clientX), Math.abs(a.clientY - b.clientY));
|
|
3684
|
+
}
|
|
3736
3685
|
class MouseSelection {
|
|
3737
3686
|
constructor(view, startEvent, style, mustSelect) {
|
|
3738
3687
|
this.view = view;
|
|
3688
|
+
this.startEvent = startEvent;
|
|
3739
3689
|
this.style = style;
|
|
3740
3690
|
this.mustSelect = mustSelect;
|
|
3741
3691
|
this.scrollSpeed = { x: 0, y: 0 };
|
|
@@ -3762,7 +3712,7 @@ class MouseSelection {
|
|
|
3762
3712
|
var _a;
|
|
3763
3713
|
if (event.buttons == 0)
|
|
3764
3714
|
return this.destroy();
|
|
3765
|
-
if (this.dragging
|
|
3715
|
+
if (this.dragging || this.dragging == null && dist(this.startEvent, event) < 10)
|
|
3766
3716
|
return;
|
|
3767
3717
|
this.select(this.lastEvent = event);
|
|
3768
3718
|
let sx = 0, sy = 0;
|
|
@@ -3841,7 +3791,7 @@ class MouseSelection {
|
|
|
3841
3791
|
select(event) {
|
|
3842
3792
|
let { view } = this, selection = this.skipAtoms(this.style.get(event, this.extend, this.multiple));
|
|
3843
3793
|
if (this.mustSelect || !selection.eq(view.state.selection) ||
|
|
3844
|
-
selection.main.assoc != view.state.selection.main.assoc)
|
|
3794
|
+
selection.main.assoc != view.state.selection.main.assoc && this.dragging === false)
|
|
3845
3795
|
this.view.dispatch({
|
|
3846
3796
|
selection,
|
|
3847
3797
|
userEvent: "select.pointer"
|
|
@@ -4260,7 +4210,7 @@ handlers.compositionend = view => {
|
|
|
4260
4210
|
// Otherwise, make sure that, if no changes come in soon, the
|
|
4261
4211
|
// composition view is cleared.
|
|
4262
4212
|
setTimeout(() => {
|
|
4263
|
-
if (view.inputState.composing < 0 && view.docView.
|
|
4213
|
+
if (view.inputState.composing < 0 && view.docView.hasComposition)
|
|
4264
4214
|
view.update([]);
|
|
4265
4215
|
}, 50);
|
|
4266
4216
|
}
|
|
@@ -5976,7 +5926,7 @@ function applyDOMChange(view, domChange) {
|
|
|
5976
5926
|
if (startState.selection.ranges.length > 1 && view.inputState.composing >= 0 &&
|
|
5977
5927
|
change.to <= sel.to && change.to >= sel.to - 10) {
|
|
5978
5928
|
let replaced = view.state.sliceDoc(change.from, change.to);
|
|
5979
|
-
let
|
|
5929
|
+
let composition = findCompositionNode(view) || view.state.doc.lineAt(sel.head);
|
|
5980
5930
|
let offset = sel.to - change.to, size = sel.to - sel.from;
|
|
5981
5931
|
tr = startState.changeByRange(range => {
|
|
5982
5932
|
if (range.from == sel.from && range.to == sel.to)
|
|
@@ -5987,7 +5937,7 @@ function applyDOMChange(view, domChange) {
|
|
|
5987
5937
|
// changes in the same node work without aborting
|
|
5988
5938
|
// composition, so cursors in the composition range are
|
|
5989
5939
|
// ignored.
|
|
5990
|
-
|
|
5940
|
+
composition && range.to >= composition.from && range.from <= composition.to)
|
|
5991
5941
|
return { range };
|
|
5992
5942
|
let rangeChanges = startState.changes({ from, to, insert: change.insert }), selOff = range.to - sel.to;
|
|
5993
5943
|
return {
|
|
@@ -6448,7 +6398,7 @@ class DOMObserver {
|
|
|
6448
6398
|
return null;
|
|
6449
6399
|
cView.markDirty(rec.type == "attributes");
|
|
6450
6400
|
if (rec.type == "attributes")
|
|
6451
|
-
cView.
|
|
6401
|
+
cView.flags |= 4 /* AttrsDirty */;
|
|
6452
6402
|
if (rec.type == "childList") {
|
|
6453
6403
|
let childBefore = findChild(cView, rec.previousSibling || rec.target.previousSibling, -1);
|
|
6454
6404
|
let childAfter = findChild(cView, rec.nextSibling || rec.target.nextSibling, 1);
|
|
@@ -7622,7 +7572,7 @@ function buildKeymap(bindings, platform = currentPlatform) {
|
|
|
7622
7572
|
else if (current != is)
|
|
7623
7573
|
throw new Error("Key binding " + name + " is used both as a regular binding and as a multi-stroke prefix");
|
|
7624
7574
|
};
|
|
7625
|
-
let add = (scope, key, command, preventDefault) => {
|
|
7575
|
+
let add = (scope, key, command, preventDefault, stopPropagation) => {
|
|
7626
7576
|
var _a, _b;
|
|
7627
7577
|
let scopeObj = bound[scope] || (bound[scope] = Object.create(null));
|
|
7628
7578
|
let parts = key.split(/ (?!$)/).map(k => normalizeKeyName(k, platform));
|
|
@@ -7632,6 +7582,7 @@ function buildKeymap(bindings, platform = currentPlatform) {
|
|
|
7632
7582
|
if (!scopeObj[prefix])
|
|
7633
7583
|
scopeObj[prefix] = {
|
|
7634
7584
|
preventDefault: true,
|
|
7585
|
+
stopPropagation: false,
|
|
7635
7586
|
run: [(view) => {
|
|
7636
7587
|
let ourObj = storedPrefix = { view, prefix, scope };
|
|
7637
7588
|
setTimeout(() => { if (storedPrefix == ourObj)
|
|
@@ -7642,11 +7593,17 @@ function buildKeymap(bindings, platform = currentPlatform) {
|
|
|
7642
7593
|
}
|
|
7643
7594
|
let full = parts.join(" ");
|
|
7644
7595
|
checkPrefix(full, false);
|
|
7645
|
-
let binding = scopeObj[full] || (scopeObj[full] = {
|
|
7596
|
+
let binding = scopeObj[full] || (scopeObj[full] = {
|
|
7597
|
+
preventDefault: false,
|
|
7598
|
+
stopPropagation: false,
|
|
7599
|
+
run: ((_b = (_a = scopeObj._any) === null || _a === void 0 ? void 0 : _a.run) === null || _b === void 0 ? void 0 : _b.slice()) || []
|
|
7600
|
+
});
|
|
7646
7601
|
if (command)
|
|
7647
7602
|
binding.run.push(command);
|
|
7648
7603
|
if (preventDefault)
|
|
7649
7604
|
binding.preventDefault = true;
|
|
7605
|
+
if (stopPropagation)
|
|
7606
|
+
binding.stopPropagation = true;
|
|
7650
7607
|
};
|
|
7651
7608
|
for (let b of bindings) {
|
|
7652
7609
|
let scopes = b.scope ? b.scope.split(" ") : ["editor"];
|
|
@@ -7654,7 +7611,7 @@ function buildKeymap(bindings, platform = currentPlatform) {
|
|
|
7654
7611
|
for (let scope of scopes) {
|
|
7655
7612
|
let scopeObj = bound[scope] || (bound[scope] = Object.create(null));
|
|
7656
7613
|
if (!scopeObj._any)
|
|
7657
|
-
scopeObj._any = { preventDefault: false, run: [] };
|
|
7614
|
+
scopeObj._any = { preventDefault: false, stopPropagation: false, run: [] };
|
|
7658
7615
|
for (let key in scopeObj)
|
|
7659
7616
|
scopeObj[key].run.push(b.any);
|
|
7660
7617
|
}
|
|
@@ -7662,9 +7619,9 @@ function buildKeymap(bindings, platform = currentPlatform) {
|
|
|
7662
7619
|
if (!name)
|
|
7663
7620
|
continue;
|
|
7664
7621
|
for (let scope of scopes) {
|
|
7665
|
-
add(scope, name, b.run, b.preventDefault);
|
|
7622
|
+
add(scope, name, b.run, b.preventDefault, b.stopPropagation);
|
|
7666
7623
|
if (b.shift)
|
|
7667
|
-
add(scope, "Shift-" + name, b.shift, b.preventDefault);
|
|
7624
|
+
add(scope, "Shift-" + name, b.shift, b.preventDefault, b.stopPropagation);
|
|
7668
7625
|
}
|
|
7669
7626
|
}
|
|
7670
7627
|
return bound;
|
|
@@ -7672,11 +7629,13 @@ function buildKeymap(bindings, platform = currentPlatform) {
|
|
|
7672
7629
|
function runHandlers(map, event, view, scope) {
|
|
7673
7630
|
let name = keyName(event);
|
|
7674
7631
|
let charCode = codePointAt(name, 0), isChar = codePointSize(charCode) == name.length && name != " ";
|
|
7675
|
-
let prefix = "",
|
|
7632
|
+
let prefix = "", handled = false, prevented = false, stopPropagation = false;
|
|
7676
7633
|
if (storedPrefix && storedPrefix.view == view && storedPrefix.scope == scope) {
|
|
7677
7634
|
prefix = storedPrefix.prefix + " ";
|
|
7678
|
-
if (
|
|
7635
|
+
if (modifierCodes.indexOf(event.keyCode) < 0) {
|
|
7636
|
+
prevented = true;
|
|
7679
7637
|
storedPrefix = null;
|
|
7638
|
+
}
|
|
7680
7639
|
}
|
|
7681
7640
|
let ran = new Set;
|
|
7682
7641
|
let runFor = (binding) => {
|
|
@@ -7684,36 +7643,49 @@ function runHandlers(map, event, view, scope) {
|
|
|
7684
7643
|
for (let cmd of binding.run)
|
|
7685
7644
|
if (!ran.has(cmd)) {
|
|
7686
7645
|
ran.add(cmd);
|
|
7687
|
-
if (cmd(view, event))
|
|
7646
|
+
if (cmd(view, event)) {
|
|
7647
|
+
if (binding.stopPropagation)
|
|
7648
|
+
stopPropagation = true;
|
|
7688
7649
|
return true;
|
|
7650
|
+
}
|
|
7689
7651
|
}
|
|
7690
|
-
if (binding.preventDefault)
|
|
7691
|
-
|
|
7652
|
+
if (binding.preventDefault) {
|
|
7653
|
+
if (binding.stopPropagation)
|
|
7654
|
+
stopPropagation = true;
|
|
7655
|
+
prevented = true;
|
|
7656
|
+
}
|
|
7692
7657
|
}
|
|
7693
7658
|
return false;
|
|
7694
7659
|
};
|
|
7695
7660
|
let scopeObj = map[scope], baseName, shiftName;
|
|
7696
7661
|
if (scopeObj) {
|
|
7697
|
-
if (runFor(scopeObj[prefix + modifiers(name, event, !isChar)]))
|
|
7698
|
-
|
|
7699
|
-
|
|
7662
|
+
if (runFor(scopeObj[prefix + modifiers(name, event, !isChar)])) {
|
|
7663
|
+
handled = true;
|
|
7664
|
+
}
|
|
7665
|
+
else if (isChar && (event.altKey || event.metaKey || event.ctrlKey) &&
|
|
7700
7666
|
// Ctrl-Alt may be used for AltGr on Windows
|
|
7701
7667
|
!(browser.windows && event.ctrlKey && event.altKey) &&
|
|
7702
7668
|
(baseName = base[event.keyCode]) && baseName != name) {
|
|
7703
|
-
if (runFor(scopeObj[prefix + modifiers(baseName, event, true)]))
|
|
7704
|
-
|
|
7669
|
+
if (runFor(scopeObj[prefix + modifiers(baseName, event, true)])) {
|
|
7670
|
+
handled = true;
|
|
7671
|
+
}
|
|
7705
7672
|
else if (event.shiftKey && (shiftName = shift[event.keyCode]) != name && shiftName != baseName &&
|
|
7706
|
-
runFor(scopeObj[prefix + modifiers(shiftName, event, false)]))
|
|
7707
|
-
|
|
7673
|
+
runFor(scopeObj[prefix + modifiers(shiftName, event, false)])) {
|
|
7674
|
+
handled = true;
|
|
7675
|
+
}
|
|
7708
7676
|
}
|
|
7709
|
-
else if (isChar && event.shiftKey
|
|
7710
|
-
|
|
7711
|
-
|
|
7677
|
+
else if (isChar && event.shiftKey &&
|
|
7678
|
+
runFor(scopeObj[prefix + modifiers(name, event, true)])) {
|
|
7679
|
+
handled = true;
|
|
7712
7680
|
}
|
|
7713
|
-
if (runFor(scopeObj._any))
|
|
7714
|
-
|
|
7681
|
+
if (!handled && runFor(scopeObj._any))
|
|
7682
|
+
handled = true;
|
|
7715
7683
|
}
|
|
7716
|
-
|
|
7684
|
+
if (prevented)
|
|
7685
|
+
handled = true;
|
|
7686
|
+
if (handled && stopPropagation)
|
|
7687
|
+
event.stopPropagation();
|
|
7688
|
+
return handled;
|
|
7717
7689
|
}
|
|
7718
7690
|
|
|
7719
7691
|
/**
|
|
@@ -8500,7 +8472,9 @@ function placeholder(content) {
|
|
|
8500
8472
|
return ViewPlugin.fromClass(class {
|
|
8501
8473
|
constructor(view) {
|
|
8502
8474
|
this.view = view;
|
|
8503
|
-
this.placeholder =
|
|
8475
|
+
this.placeholder = content
|
|
8476
|
+
? Decoration.set([Decoration.widget({ widget: new Placeholder(content), side: 1 }).range(0)])
|
|
8477
|
+
: Decoration.none;
|
|
8504
8478
|
}
|
|
8505
8479
|
get decorations() { return this.view.state.doc.length ? Decoration.none : this.placeholder; }
|
|
8506
8480
|
}, { decorations: v => v.decorations });
|