bsky-richtext-react 1.0.0 → 1.0.2
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 +21 -4835
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +18 -4832
- package/dist/index.js.map +1 -1
- package/package.json +46 -2
package/dist/index.cjs
CHANGED
|
@@ -13,6 +13,8 @@ var api = require('@atproto/api');
|
|
|
13
13
|
var extensionMention = require('@tiptap/extension-mention');
|
|
14
14
|
var tippy = require('tippy.js');
|
|
15
15
|
var core = require('@tiptap/core');
|
|
16
|
+
var state = require('@tiptap/pm/state');
|
|
17
|
+
var view = require('@tiptap/pm/view');
|
|
16
18
|
|
|
17
19
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
18
20
|
|
|
@@ -479,9 +481,9 @@ function createDefaultSuggestionRenderer(options = {}) {
|
|
|
479
481
|
editor: props.editor
|
|
480
482
|
});
|
|
481
483
|
if (!props.clientRect) return;
|
|
482
|
-
const
|
|
484
|
+
const clientRect = props.clientRect;
|
|
483
485
|
popup = tippy__default.default("body", {
|
|
484
|
-
getReferenceClientRect: () =>
|
|
486
|
+
getReferenceClientRect: () => clientRect?.() ?? new DOMRect(),
|
|
485
487
|
appendTo: () => document.body,
|
|
486
488
|
content: renderer.element,
|
|
487
489
|
showOnCreate: true,
|
|
@@ -493,9 +495,9 @@ function createDefaultSuggestionRenderer(options = {}) {
|
|
|
493
495
|
onUpdate(props) {
|
|
494
496
|
renderer?.updateProps(buildProps(props));
|
|
495
497
|
if (!props.clientRect) return;
|
|
496
|
-
const
|
|
498
|
+
const clientRect = props.clientRect;
|
|
497
499
|
popup?.[0]?.setProps({
|
|
498
|
-
getReferenceClientRect: () =>
|
|
500
|
+
getReferenceClientRect: () => clientRect?.() ?? new DOMRect()
|
|
499
501
|
});
|
|
500
502
|
},
|
|
501
503
|
onKeyDown(props) {
|
|
@@ -559,4831 +561,10 @@ function createBskyMentionExtension({
|
|
|
559
561
|
}
|
|
560
562
|
});
|
|
561
563
|
}
|
|
562
|
-
|
|
563
|
-
// node_modules/prosemirror-model/dist/index.js
|
|
564
|
-
function findDiffStart(a, b, pos) {
|
|
565
|
-
for (let i = 0; ; i++) {
|
|
566
|
-
if (i == a.childCount || i == b.childCount)
|
|
567
|
-
return a.childCount == b.childCount ? null : pos;
|
|
568
|
-
let childA = a.child(i), childB = b.child(i);
|
|
569
|
-
if (childA == childB) {
|
|
570
|
-
pos += childA.nodeSize;
|
|
571
|
-
continue;
|
|
572
|
-
}
|
|
573
|
-
if (!childA.sameMarkup(childB))
|
|
574
|
-
return pos;
|
|
575
|
-
if (childA.isText && childA.text != childB.text) {
|
|
576
|
-
for (let j = 0; childA.text[j] == childB.text[j]; j++)
|
|
577
|
-
pos++;
|
|
578
|
-
return pos;
|
|
579
|
-
}
|
|
580
|
-
if (childA.content.size || childB.content.size) {
|
|
581
|
-
let inner = findDiffStart(childA.content, childB.content, pos + 1);
|
|
582
|
-
if (inner != null)
|
|
583
|
-
return inner;
|
|
584
|
-
}
|
|
585
|
-
pos += childA.nodeSize;
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
function findDiffEnd(a, b, posA, posB) {
|
|
589
|
-
for (let iA = a.childCount, iB = b.childCount; ; ) {
|
|
590
|
-
if (iA == 0 || iB == 0)
|
|
591
|
-
return iA == iB ? null : { a: posA, b: posB };
|
|
592
|
-
let childA = a.child(--iA), childB = b.child(--iB), size = childA.nodeSize;
|
|
593
|
-
if (childA == childB) {
|
|
594
|
-
posA -= size;
|
|
595
|
-
posB -= size;
|
|
596
|
-
continue;
|
|
597
|
-
}
|
|
598
|
-
if (!childA.sameMarkup(childB))
|
|
599
|
-
return { a: posA, b: posB };
|
|
600
|
-
if (childA.isText && childA.text != childB.text) {
|
|
601
|
-
let same = 0, minSize = Math.min(childA.text.length, childB.text.length);
|
|
602
|
-
while (same < minSize && childA.text[childA.text.length - same - 1] == childB.text[childB.text.length - same - 1]) {
|
|
603
|
-
same++;
|
|
604
|
-
posA--;
|
|
605
|
-
posB--;
|
|
606
|
-
}
|
|
607
|
-
return { a: posA, b: posB };
|
|
608
|
-
}
|
|
609
|
-
if (childA.content.size || childB.content.size) {
|
|
610
|
-
let inner = findDiffEnd(childA.content, childB.content, posA - 1, posB - 1);
|
|
611
|
-
if (inner)
|
|
612
|
-
return inner;
|
|
613
|
-
}
|
|
614
|
-
posA -= size;
|
|
615
|
-
posB -= size;
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
var Fragment = class _Fragment {
|
|
619
|
-
/**
|
|
620
|
-
@internal
|
|
621
|
-
*/
|
|
622
|
-
constructor(content, size) {
|
|
623
|
-
this.content = content;
|
|
624
|
-
this.size = size || 0;
|
|
625
|
-
if (size == null)
|
|
626
|
-
for (let i = 0; i < content.length; i++)
|
|
627
|
-
this.size += content[i].nodeSize;
|
|
628
|
-
}
|
|
629
|
-
/**
|
|
630
|
-
Invoke a callback for all descendant nodes between the given two
|
|
631
|
-
positions (relative to start of this fragment). Doesn't descend
|
|
632
|
-
into a node when the callback returns `false`.
|
|
633
|
-
*/
|
|
634
|
-
nodesBetween(from, to, f, nodeStart = 0, parent) {
|
|
635
|
-
for (let i = 0, pos = 0; pos < to; i++) {
|
|
636
|
-
let child = this.content[i], end = pos + child.nodeSize;
|
|
637
|
-
if (end > from && f(child, nodeStart + pos, parent || null, i) !== false && child.content.size) {
|
|
638
|
-
let start = pos + 1;
|
|
639
|
-
child.nodesBetween(Math.max(0, from - start), Math.min(child.content.size, to - start), f, nodeStart + start);
|
|
640
|
-
}
|
|
641
|
-
pos = end;
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
/**
|
|
645
|
-
Call the given callback for every descendant node. `pos` will be
|
|
646
|
-
relative to the start of the fragment. The callback may return
|
|
647
|
-
`false` to prevent traversal of a given node's children.
|
|
648
|
-
*/
|
|
649
|
-
descendants(f) {
|
|
650
|
-
this.nodesBetween(0, this.size, f);
|
|
651
|
-
}
|
|
652
|
-
/**
|
|
653
|
-
Extract the text between `from` and `to`. See the same method on
|
|
654
|
-
[`Node`](https://prosemirror.net/docs/ref/#model.Node.textBetween).
|
|
655
|
-
*/
|
|
656
|
-
textBetween(from, to, blockSeparator, leafText) {
|
|
657
|
-
let text = "", first = true;
|
|
658
|
-
this.nodesBetween(from, to, (node, pos) => {
|
|
659
|
-
let nodeText = node.isText ? node.text.slice(Math.max(from, pos) - pos, to - pos) : !node.isLeaf ? "" : leafText ? typeof leafText === "function" ? leafText(node) : leafText : node.type.spec.leafText ? node.type.spec.leafText(node) : "";
|
|
660
|
-
if (node.isBlock && (node.isLeaf && nodeText || node.isTextblock) && blockSeparator) {
|
|
661
|
-
if (first)
|
|
662
|
-
first = false;
|
|
663
|
-
else
|
|
664
|
-
text += blockSeparator;
|
|
665
|
-
}
|
|
666
|
-
text += nodeText;
|
|
667
|
-
}, 0);
|
|
668
|
-
return text;
|
|
669
|
-
}
|
|
670
|
-
/**
|
|
671
|
-
Create a new fragment containing the combined content of this
|
|
672
|
-
fragment and the other.
|
|
673
|
-
*/
|
|
674
|
-
append(other) {
|
|
675
|
-
if (!other.size)
|
|
676
|
-
return this;
|
|
677
|
-
if (!this.size)
|
|
678
|
-
return other;
|
|
679
|
-
let last = this.lastChild, first = other.firstChild, content = this.content.slice(), i = 0;
|
|
680
|
-
if (last.isText && last.sameMarkup(first)) {
|
|
681
|
-
content[content.length - 1] = last.withText(last.text + first.text);
|
|
682
|
-
i = 1;
|
|
683
|
-
}
|
|
684
|
-
for (; i < other.content.length; i++)
|
|
685
|
-
content.push(other.content[i]);
|
|
686
|
-
return new _Fragment(content, this.size + other.size);
|
|
687
|
-
}
|
|
688
|
-
/**
|
|
689
|
-
Cut out the sub-fragment between the two given positions.
|
|
690
|
-
*/
|
|
691
|
-
cut(from, to = this.size) {
|
|
692
|
-
if (from == 0 && to == this.size)
|
|
693
|
-
return this;
|
|
694
|
-
let result = [], size = 0;
|
|
695
|
-
if (to > from)
|
|
696
|
-
for (let i = 0, pos = 0; pos < to; i++) {
|
|
697
|
-
let child = this.content[i], end = pos + child.nodeSize;
|
|
698
|
-
if (end > from) {
|
|
699
|
-
if (pos < from || end > to) {
|
|
700
|
-
if (child.isText)
|
|
701
|
-
child = child.cut(Math.max(0, from - pos), Math.min(child.text.length, to - pos));
|
|
702
|
-
else
|
|
703
|
-
child = child.cut(Math.max(0, from - pos - 1), Math.min(child.content.size, to - pos - 1));
|
|
704
|
-
}
|
|
705
|
-
result.push(child);
|
|
706
|
-
size += child.nodeSize;
|
|
707
|
-
}
|
|
708
|
-
pos = end;
|
|
709
|
-
}
|
|
710
|
-
return new _Fragment(result, size);
|
|
711
|
-
}
|
|
712
|
-
/**
|
|
713
|
-
@internal
|
|
714
|
-
*/
|
|
715
|
-
cutByIndex(from, to) {
|
|
716
|
-
if (from == to)
|
|
717
|
-
return _Fragment.empty;
|
|
718
|
-
if (from == 0 && to == this.content.length)
|
|
719
|
-
return this;
|
|
720
|
-
return new _Fragment(this.content.slice(from, to));
|
|
721
|
-
}
|
|
722
|
-
/**
|
|
723
|
-
Create a new fragment in which the node at the given index is
|
|
724
|
-
replaced by the given node.
|
|
725
|
-
*/
|
|
726
|
-
replaceChild(index, node) {
|
|
727
|
-
let current = this.content[index];
|
|
728
|
-
if (current == node)
|
|
729
|
-
return this;
|
|
730
|
-
let copy2 = this.content.slice();
|
|
731
|
-
let size = this.size + node.nodeSize - current.nodeSize;
|
|
732
|
-
copy2[index] = node;
|
|
733
|
-
return new _Fragment(copy2, size);
|
|
734
|
-
}
|
|
735
|
-
/**
|
|
736
|
-
Create a new fragment by prepending the given node to this
|
|
737
|
-
fragment.
|
|
738
|
-
*/
|
|
739
|
-
addToStart(node) {
|
|
740
|
-
return new _Fragment([node].concat(this.content), this.size + node.nodeSize);
|
|
741
|
-
}
|
|
742
|
-
/**
|
|
743
|
-
Create a new fragment by appending the given node to this
|
|
744
|
-
fragment.
|
|
745
|
-
*/
|
|
746
|
-
addToEnd(node) {
|
|
747
|
-
return new _Fragment(this.content.concat(node), this.size + node.nodeSize);
|
|
748
|
-
}
|
|
749
|
-
/**
|
|
750
|
-
Compare this fragment to another one.
|
|
751
|
-
*/
|
|
752
|
-
eq(other) {
|
|
753
|
-
if (this.content.length != other.content.length)
|
|
754
|
-
return false;
|
|
755
|
-
for (let i = 0; i < this.content.length; i++)
|
|
756
|
-
if (!this.content[i].eq(other.content[i]))
|
|
757
|
-
return false;
|
|
758
|
-
return true;
|
|
759
|
-
}
|
|
760
|
-
/**
|
|
761
|
-
The first child of the fragment, or `null` if it is empty.
|
|
762
|
-
*/
|
|
763
|
-
get firstChild() {
|
|
764
|
-
return this.content.length ? this.content[0] : null;
|
|
765
|
-
}
|
|
766
|
-
/**
|
|
767
|
-
The last child of the fragment, or `null` if it is empty.
|
|
768
|
-
*/
|
|
769
|
-
get lastChild() {
|
|
770
|
-
return this.content.length ? this.content[this.content.length - 1] : null;
|
|
771
|
-
}
|
|
772
|
-
/**
|
|
773
|
-
The number of child nodes in this fragment.
|
|
774
|
-
*/
|
|
775
|
-
get childCount() {
|
|
776
|
-
return this.content.length;
|
|
777
|
-
}
|
|
778
|
-
/**
|
|
779
|
-
Get the child node at the given index. Raise an error when the
|
|
780
|
-
index is out of range.
|
|
781
|
-
*/
|
|
782
|
-
child(index) {
|
|
783
|
-
let found2 = this.content[index];
|
|
784
|
-
if (!found2)
|
|
785
|
-
throw new RangeError("Index " + index + " out of range for " + this);
|
|
786
|
-
return found2;
|
|
787
|
-
}
|
|
788
|
-
/**
|
|
789
|
-
Get the child node at the given index, if it exists.
|
|
790
|
-
*/
|
|
791
|
-
maybeChild(index) {
|
|
792
|
-
return this.content[index] || null;
|
|
793
|
-
}
|
|
794
|
-
/**
|
|
795
|
-
Call `f` for every child node, passing the node, its offset
|
|
796
|
-
into this parent node, and its index.
|
|
797
|
-
*/
|
|
798
|
-
forEach(f) {
|
|
799
|
-
for (let i = 0, p = 0; i < this.content.length; i++) {
|
|
800
|
-
let child = this.content[i];
|
|
801
|
-
f(child, p, i);
|
|
802
|
-
p += child.nodeSize;
|
|
803
|
-
}
|
|
804
|
-
}
|
|
805
|
-
/**
|
|
806
|
-
Find the first position at which this fragment and another
|
|
807
|
-
fragment differ, or `null` if they are the same.
|
|
808
|
-
*/
|
|
809
|
-
findDiffStart(other, pos = 0) {
|
|
810
|
-
return findDiffStart(this, other, pos);
|
|
811
|
-
}
|
|
812
|
-
/**
|
|
813
|
-
Find the first position, searching from the end, at which this
|
|
814
|
-
fragment and the given fragment differ, or `null` if they are
|
|
815
|
-
the same. Since this position will not be the same in both
|
|
816
|
-
nodes, an object with two separate positions is returned.
|
|
817
|
-
*/
|
|
818
|
-
findDiffEnd(other, pos = this.size, otherPos = other.size) {
|
|
819
|
-
return findDiffEnd(this, other, pos, otherPos);
|
|
820
|
-
}
|
|
821
|
-
/**
|
|
822
|
-
Find the index and inner offset corresponding to a given relative
|
|
823
|
-
position in this fragment. The result object will be reused
|
|
824
|
-
(overwritten) the next time the function is called. @internal
|
|
825
|
-
*/
|
|
826
|
-
findIndex(pos) {
|
|
827
|
-
if (pos == 0)
|
|
828
|
-
return retIndex(0, pos);
|
|
829
|
-
if (pos == this.size)
|
|
830
|
-
return retIndex(this.content.length, pos);
|
|
831
|
-
if (pos > this.size || pos < 0)
|
|
832
|
-
throw new RangeError(`Position ${pos} outside of fragment (${this})`);
|
|
833
|
-
for (let i = 0, curPos = 0; ; i++) {
|
|
834
|
-
let cur = this.child(i), end = curPos + cur.nodeSize;
|
|
835
|
-
if (end >= pos) {
|
|
836
|
-
if (end == pos)
|
|
837
|
-
return retIndex(i + 1, end);
|
|
838
|
-
return retIndex(i, curPos);
|
|
839
|
-
}
|
|
840
|
-
curPos = end;
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
|
-
/**
|
|
844
|
-
Return a debugging string that describes this fragment.
|
|
845
|
-
*/
|
|
846
|
-
toString() {
|
|
847
|
-
return "<" + this.toStringInner() + ">";
|
|
848
|
-
}
|
|
849
|
-
/**
|
|
850
|
-
@internal
|
|
851
|
-
*/
|
|
852
|
-
toStringInner() {
|
|
853
|
-
return this.content.join(", ");
|
|
854
|
-
}
|
|
855
|
-
/**
|
|
856
|
-
Create a JSON-serializeable representation of this fragment.
|
|
857
|
-
*/
|
|
858
|
-
toJSON() {
|
|
859
|
-
return this.content.length ? this.content.map((n) => n.toJSON()) : null;
|
|
860
|
-
}
|
|
861
|
-
/**
|
|
862
|
-
Deserialize a fragment from its JSON representation.
|
|
863
|
-
*/
|
|
864
|
-
static fromJSON(schema, value) {
|
|
865
|
-
if (!value)
|
|
866
|
-
return _Fragment.empty;
|
|
867
|
-
if (!Array.isArray(value))
|
|
868
|
-
throw new RangeError("Invalid input for Fragment.fromJSON");
|
|
869
|
-
return new _Fragment(value.map(schema.nodeFromJSON));
|
|
870
|
-
}
|
|
871
|
-
/**
|
|
872
|
-
Build a fragment from an array of nodes. Ensures that adjacent
|
|
873
|
-
text nodes with the same marks are joined together.
|
|
874
|
-
*/
|
|
875
|
-
static fromArray(array) {
|
|
876
|
-
if (!array.length)
|
|
877
|
-
return _Fragment.empty;
|
|
878
|
-
let joined, size = 0;
|
|
879
|
-
for (let i = 0; i < array.length; i++) {
|
|
880
|
-
let node = array[i];
|
|
881
|
-
size += node.nodeSize;
|
|
882
|
-
if (i && node.isText && array[i - 1].sameMarkup(node)) {
|
|
883
|
-
if (!joined)
|
|
884
|
-
joined = array.slice(0, i);
|
|
885
|
-
joined[joined.length - 1] = node.withText(joined[joined.length - 1].text + node.text);
|
|
886
|
-
} else if (joined) {
|
|
887
|
-
joined.push(node);
|
|
888
|
-
}
|
|
889
|
-
}
|
|
890
|
-
return new _Fragment(joined || array, size);
|
|
891
|
-
}
|
|
892
|
-
/**
|
|
893
|
-
Create a fragment from something that can be interpreted as a
|
|
894
|
-
set of nodes. For `null`, it returns the empty fragment. For a
|
|
895
|
-
fragment, the fragment itself. For a node or array of nodes, a
|
|
896
|
-
fragment containing those nodes.
|
|
897
|
-
*/
|
|
898
|
-
static from(nodes) {
|
|
899
|
-
if (!nodes)
|
|
900
|
-
return _Fragment.empty;
|
|
901
|
-
if (nodes instanceof _Fragment)
|
|
902
|
-
return nodes;
|
|
903
|
-
if (Array.isArray(nodes))
|
|
904
|
-
return this.fromArray(nodes);
|
|
905
|
-
if (nodes.attrs)
|
|
906
|
-
return new _Fragment([nodes], nodes.nodeSize);
|
|
907
|
-
throw new RangeError("Can not convert " + nodes + " to a Fragment" + (nodes.nodesBetween ? " (looks like multiple versions of prosemirror-model were loaded)" : ""));
|
|
908
|
-
}
|
|
909
|
-
};
|
|
910
|
-
Fragment.empty = new Fragment([], 0);
|
|
911
|
-
var found = { index: 0, offset: 0 };
|
|
912
|
-
function retIndex(index, offset) {
|
|
913
|
-
found.index = index;
|
|
914
|
-
found.offset = offset;
|
|
915
|
-
return found;
|
|
916
|
-
}
|
|
917
|
-
function compareDeep(a, b) {
|
|
918
|
-
if (a === b)
|
|
919
|
-
return true;
|
|
920
|
-
if (!(a && typeof a == "object") || !(b && typeof b == "object"))
|
|
921
|
-
return false;
|
|
922
|
-
let array = Array.isArray(a);
|
|
923
|
-
if (Array.isArray(b) != array)
|
|
924
|
-
return false;
|
|
925
|
-
if (array) {
|
|
926
|
-
if (a.length != b.length)
|
|
927
|
-
return false;
|
|
928
|
-
for (let i = 0; i < a.length; i++)
|
|
929
|
-
if (!compareDeep(a[i], b[i]))
|
|
930
|
-
return false;
|
|
931
|
-
} else {
|
|
932
|
-
for (let p in a)
|
|
933
|
-
if (!(p in b) || !compareDeep(a[p], b[p]))
|
|
934
|
-
return false;
|
|
935
|
-
for (let p in b)
|
|
936
|
-
if (!(p in a))
|
|
937
|
-
return false;
|
|
938
|
-
}
|
|
939
|
-
return true;
|
|
940
|
-
}
|
|
941
|
-
var Mark = class _Mark {
|
|
942
|
-
/**
|
|
943
|
-
@internal
|
|
944
|
-
*/
|
|
945
|
-
constructor(type, attrs) {
|
|
946
|
-
this.type = type;
|
|
947
|
-
this.attrs = attrs;
|
|
948
|
-
}
|
|
949
|
-
/**
|
|
950
|
-
Given a set of marks, create a new set which contains this one as
|
|
951
|
-
well, in the right position. If this mark is already in the set,
|
|
952
|
-
the set itself is returned. If any marks that are set to be
|
|
953
|
-
[exclusive](https://prosemirror.net/docs/ref/#model.MarkSpec.excludes) with this mark are present,
|
|
954
|
-
those are replaced by this one.
|
|
955
|
-
*/
|
|
956
|
-
addToSet(set) {
|
|
957
|
-
let copy2, placed = false;
|
|
958
|
-
for (let i = 0; i < set.length; i++) {
|
|
959
|
-
let other = set[i];
|
|
960
|
-
if (this.eq(other))
|
|
961
|
-
return set;
|
|
962
|
-
if (this.type.excludes(other.type)) {
|
|
963
|
-
if (!copy2)
|
|
964
|
-
copy2 = set.slice(0, i);
|
|
965
|
-
} else if (other.type.excludes(this.type)) {
|
|
966
|
-
return set;
|
|
967
|
-
} else {
|
|
968
|
-
if (!placed && other.type.rank > this.type.rank) {
|
|
969
|
-
if (!copy2)
|
|
970
|
-
copy2 = set.slice(0, i);
|
|
971
|
-
copy2.push(this);
|
|
972
|
-
placed = true;
|
|
973
|
-
}
|
|
974
|
-
if (copy2)
|
|
975
|
-
copy2.push(other);
|
|
976
|
-
}
|
|
977
|
-
}
|
|
978
|
-
if (!copy2)
|
|
979
|
-
copy2 = set.slice();
|
|
980
|
-
if (!placed)
|
|
981
|
-
copy2.push(this);
|
|
982
|
-
return copy2;
|
|
983
|
-
}
|
|
984
|
-
/**
|
|
985
|
-
Remove this mark from the given set, returning a new set. If this
|
|
986
|
-
mark is not in the set, the set itself is returned.
|
|
987
|
-
*/
|
|
988
|
-
removeFromSet(set) {
|
|
989
|
-
for (let i = 0; i < set.length; i++)
|
|
990
|
-
if (this.eq(set[i]))
|
|
991
|
-
return set.slice(0, i).concat(set.slice(i + 1));
|
|
992
|
-
return set;
|
|
993
|
-
}
|
|
994
|
-
/**
|
|
995
|
-
Test whether this mark is in the given set of marks.
|
|
996
|
-
*/
|
|
997
|
-
isInSet(set) {
|
|
998
|
-
for (let i = 0; i < set.length; i++)
|
|
999
|
-
if (this.eq(set[i]))
|
|
1000
|
-
return true;
|
|
1001
|
-
return false;
|
|
1002
|
-
}
|
|
1003
|
-
/**
|
|
1004
|
-
Test whether this mark has the same type and attributes as
|
|
1005
|
-
another mark.
|
|
1006
|
-
*/
|
|
1007
|
-
eq(other) {
|
|
1008
|
-
return this == other || this.type == other.type && compareDeep(this.attrs, other.attrs);
|
|
1009
|
-
}
|
|
1010
|
-
/**
|
|
1011
|
-
Convert this mark to a JSON-serializeable representation.
|
|
1012
|
-
*/
|
|
1013
|
-
toJSON() {
|
|
1014
|
-
let obj = { type: this.type.name };
|
|
1015
|
-
for (let _ in this.attrs) {
|
|
1016
|
-
obj.attrs = this.attrs;
|
|
1017
|
-
break;
|
|
1018
|
-
}
|
|
1019
|
-
return obj;
|
|
1020
|
-
}
|
|
1021
|
-
/**
|
|
1022
|
-
Deserialize a mark from JSON.
|
|
1023
|
-
*/
|
|
1024
|
-
static fromJSON(schema, json) {
|
|
1025
|
-
if (!json)
|
|
1026
|
-
throw new RangeError("Invalid input for Mark.fromJSON");
|
|
1027
|
-
let type = schema.marks[json.type];
|
|
1028
|
-
if (!type)
|
|
1029
|
-
throw new RangeError(`There is no mark type ${json.type} in this schema`);
|
|
1030
|
-
let mark = type.create(json.attrs);
|
|
1031
|
-
type.checkAttrs(mark.attrs);
|
|
1032
|
-
return mark;
|
|
1033
|
-
}
|
|
1034
|
-
/**
|
|
1035
|
-
Test whether two sets of marks are identical.
|
|
1036
|
-
*/
|
|
1037
|
-
static sameSet(a, b) {
|
|
1038
|
-
if (a == b)
|
|
1039
|
-
return true;
|
|
1040
|
-
if (a.length != b.length)
|
|
1041
|
-
return false;
|
|
1042
|
-
for (let i = 0; i < a.length; i++)
|
|
1043
|
-
if (!a[i].eq(b[i]))
|
|
1044
|
-
return false;
|
|
1045
|
-
return true;
|
|
1046
|
-
}
|
|
1047
|
-
/**
|
|
1048
|
-
Create a properly sorted mark set from null, a single mark, or an
|
|
1049
|
-
unsorted array of marks.
|
|
1050
|
-
*/
|
|
1051
|
-
static setFrom(marks) {
|
|
1052
|
-
if (!marks || Array.isArray(marks) && marks.length == 0)
|
|
1053
|
-
return _Mark.none;
|
|
1054
|
-
if (marks instanceof _Mark)
|
|
1055
|
-
return [marks];
|
|
1056
|
-
let copy2 = marks.slice();
|
|
1057
|
-
copy2.sort((a, b) => a.type.rank - b.type.rank);
|
|
1058
|
-
return copy2;
|
|
1059
|
-
}
|
|
1060
|
-
};
|
|
1061
|
-
Mark.none = [];
|
|
1062
|
-
var ReplaceError = class extends Error {
|
|
1063
|
-
};
|
|
1064
|
-
var Slice = class _Slice {
|
|
1065
|
-
/**
|
|
1066
|
-
Create a slice. When specifying a non-zero open depth, you must
|
|
1067
|
-
make sure that there are nodes of at least that depth at the
|
|
1068
|
-
appropriate side of the fragment—i.e. if the fragment is an
|
|
1069
|
-
empty paragraph node, `openStart` and `openEnd` can't be greater
|
|
1070
|
-
than 1.
|
|
1071
|
-
|
|
1072
|
-
It is not necessary for the content of open nodes to conform to
|
|
1073
|
-
the schema's content constraints, though it should be a valid
|
|
1074
|
-
start/end/middle for such a node, depending on which sides are
|
|
1075
|
-
open.
|
|
1076
|
-
*/
|
|
1077
|
-
constructor(content, openStart, openEnd) {
|
|
1078
|
-
this.content = content;
|
|
1079
|
-
this.openStart = openStart;
|
|
1080
|
-
this.openEnd = openEnd;
|
|
1081
|
-
}
|
|
1082
|
-
/**
|
|
1083
|
-
The size this slice would add when inserted into a document.
|
|
1084
|
-
*/
|
|
1085
|
-
get size() {
|
|
1086
|
-
return this.content.size - this.openStart - this.openEnd;
|
|
1087
|
-
}
|
|
1088
|
-
/**
|
|
1089
|
-
@internal
|
|
1090
|
-
*/
|
|
1091
|
-
insertAt(pos, fragment) {
|
|
1092
|
-
let content = insertInto(this.content, pos + this.openStart, fragment);
|
|
1093
|
-
return content && new _Slice(content, this.openStart, this.openEnd);
|
|
1094
|
-
}
|
|
1095
|
-
/**
|
|
1096
|
-
@internal
|
|
1097
|
-
*/
|
|
1098
|
-
removeBetween(from, to) {
|
|
1099
|
-
return new _Slice(removeRange(this.content, from + this.openStart, to + this.openStart), this.openStart, this.openEnd);
|
|
1100
|
-
}
|
|
1101
|
-
/**
|
|
1102
|
-
Tests whether this slice is equal to another slice.
|
|
1103
|
-
*/
|
|
1104
|
-
eq(other) {
|
|
1105
|
-
return this.content.eq(other.content) && this.openStart == other.openStart && this.openEnd == other.openEnd;
|
|
1106
|
-
}
|
|
1107
|
-
/**
|
|
1108
|
-
@internal
|
|
1109
|
-
*/
|
|
1110
|
-
toString() {
|
|
1111
|
-
return this.content + "(" + this.openStart + "," + this.openEnd + ")";
|
|
1112
|
-
}
|
|
1113
|
-
/**
|
|
1114
|
-
Convert a slice to a JSON-serializable representation.
|
|
1115
|
-
*/
|
|
1116
|
-
toJSON() {
|
|
1117
|
-
if (!this.content.size)
|
|
1118
|
-
return null;
|
|
1119
|
-
let json = { content: this.content.toJSON() };
|
|
1120
|
-
if (this.openStart > 0)
|
|
1121
|
-
json.openStart = this.openStart;
|
|
1122
|
-
if (this.openEnd > 0)
|
|
1123
|
-
json.openEnd = this.openEnd;
|
|
1124
|
-
return json;
|
|
1125
|
-
}
|
|
1126
|
-
/**
|
|
1127
|
-
Deserialize a slice from its JSON representation.
|
|
1128
|
-
*/
|
|
1129
|
-
static fromJSON(schema, json) {
|
|
1130
|
-
if (!json)
|
|
1131
|
-
return _Slice.empty;
|
|
1132
|
-
let openStart = json.openStart || 0, openEnd = json.openEnd || 0;
|
|
1133
|
-
if (typeof openStart != "number" || typeof openEnd != "number")
|
|
1134
|
-
throw new RangeError("Invalid input for Slice.fromJSON");
|
|
1135
|
-
return new _Slice(Fragment.fromJSON(schema, json.content), openStart, openEnd);
|
|
1136
|
-
}
|
|
1137
|
-
/**
|
|
1138
|
-
Create a slice from a fragment by taking the maximum possible
|
|
1139
|
-
open value on both side of the fragment.
|
|
1140
|
-
*/
|
|
1141
|
-
static maxOpen(fragment, openIsolating = true) {
|
|
1142
|
-
let openStart = 0, openEnd = 0;
|
|
1143
|
-
for (let n = fragment.firstChild; n && !n.isLeaf && (openIsolating || !n.type.spec.isolating); n = n.firstChild)
|
|
1144
|
-
openStart++;
|
|
1145
|
-
for (let n = fragment.lastChild; n && !n.isLeaf && (openIsolating || !n.type.spec.isolating); n = n.lastChild)
|
|
1146
|
-
openEnd++;
|
|
1147
|
-
return new _Slice(fragment, openStart, openEnd);
|
|
1148
|
-
}
|
|
1149
|
-
};
|
|
1150
|
-
Slice.empty = new Slice(Fragment.empty, 0, 0);
|
|
1151
|
-
function removeRange(content, from, to) {
|
|
1152
|
-
let { index, offset } = content.findIndex(from), child = content.maybeChild(index);
|
|
1153
|
-
let { index: indexTo, offset: offsetTo } = content.findIndex(to);
|
|
1154
|
-
if (offset == from || child.isText) {
|
|
1155
|
-
if (offsetTo != to && !content.child(indexTo).isText)
|
|
1156
|
-
throw new RangeError("Removing non-flat range");
|
|
1157
|
-
return content.cut(0, from).append(content.cut(to));
|
|
1158
|
-
}
|
|
1159
|
-
if (index != indexTo)
|
|
1160
|
-
throw new RangeError("Removing non-flat range");
|
|
1161
|
-
return content.replaceChild(index, child.copy(removeRange(child.content, from - offset - 1, to - offset - 1)));
|
|
1162
|
-
}
|
|
1163
|
-
function insertInto(content, dist, insert, parent) {
|
|
1164
|
-
let { index, offset } = content.findIndex(dist), child = content.maybeChild(index);
|
|
1165
|
-
if (offset == dist || child.isText) {
|
|
1166
|
-
if (parent && !parent.canReplace(index, index, insert))
|
|
1167
|
-
return null;
|
|
1168
|
-
return content.cut(0, dist).append(insert).append(content.cut(dist));
|
|
1169
|
-
}
|
|
1170
|
-
let inner = insertInto(child.content, dist - offset - 1, insert, child);
|
|
1171
|
-
return inner && content.replaceChild(index, child.copy(inner));
|
|
1172
|
-
}
|
|
1173
|
-
function isTagRule(rule) {
|
|
1174
|
-
return rule.tag != null;
|
|
1175
|
-
}
|
|
1176
|
-
function isStyleRule(rule) {
|
|
1177
|
-
return rule.style != null;
|
|
1178
|
-
}
|
|
1179
|
-
var DOMParser = class _DOMParser {
|
|
1180
|
-
/**
|
|
1181
|
-
Create a parser that targets the given schema, using the given
|
|
1182
|
-
parsing rules.
|
|
1183
|
-
*/
|
|
1184
|
-
constructor(schema, rules) {
|
|
1185
|
-
this.schema = schema;
|
|
1186
|
-
this.rules = rules;
|
|
1187
|
-
this.tags = [];
|
|
1188
|
-
this.styles = [];
|
|
1189
|
-
let matchedStyles = this.matchedStyles = [];
|
|
1190
|
-
rules.forEach((rule) => {
|
|
1191
|
-
if (isTagRule(rule)) {
|
|
1192
|
-
this.tags.push(rule);
|
|
1193
|
-
} else if (isStyleRule(rule)) {
|
|
1194
|
-
let prop = /[^=]*/.exec(rule.style)[0];
|
|
1195
|
-
if (matchedStyles.indexOf(prop) < 0)
|
|
1196
|
-
matchedStyles.push(prop);
|
|
1197
|
-
this.styles.push(rule);
|
|
1198
|
-
}
|
|
1199
|
-
});
|
|
1200
|
-
this.normalizeLists = !this.tags.some((r) => {
|
|
1201
|
-
if (!/^(ul|ol)\b/.test(r.tag) || !r.node)
|
|
1202
|
-
return false;
|
|
1203
|
-
let node = schema.nodes[r.node];
|
|
1204
|
-
return node.contentMatch.matchType(node);
|
|
1205
|
-
});
|
|
1206
|
-
}
|
|
1207
|
-
/**
|
|
1208
|
-
Parse a document from the content of a DOM node.
|
|
1209
|
-
*/
|
|
1210
|
-
parse(dom, options = {}) {
|
|
1211
|
-
let context = new ParseContext(this, options, false);
|
|
1212
|
-
context.addAll(dom, Mark.none, options.from, options.to);
|
|
1213
|
-
return context.finish();
|
|
1214
|
-
}
|
|
1215
|
-
/**
|
|
1216
|
-
Parses the content of the given DOM node, like
|
|
1217
|
-
[`parse`](https://prosemirror.net/docs/ref/#model.DOMParser.parse), and takes the same set of
|
|
1218
|
-
options. But unlike that method, which produces a whole node,
|
|
1219
|
-
this one returns a slice that is open at the sides, meaning that
|
|
1220
|
-
the schema constraints aren't applied to the start of nodes to
|
|
1221
|
-
the left of the input and the end of nodes at the end.
|
|
1222
|
-
*/
|
|
1223
|
-
parseSlice(dom, options = {}) {
|
|
1224
|
-
let context = new ParseContext(this, options, true);
|
|
1225
|
-
context.addAll(dom, Mark.none, options.from, options.to);
|
|
1226
|
-
return Slice.maxOpen(context.finish());
|
|
1227
|
-
}
|
|
1228
|
-
/**
|
|
1229
|
-
@internal
|
|
1230
|
-
*/
|
|
1231
|
-
matchTag(dom, context, after) {
|
|
1232
|
-
for (let i = after ? this.tags.indexOf(after) + 1 : 0; i < this.tags.length; i++) {
|
|
1233
|
-
let rule = this.tags[i];
|
|
1234
|
-
if (matches(dom, rule.tag) && (rule.namespace === void 0 || dom.namespaceURI == rule.namespace) && (!rule.context || context.matchesContext(rule.context))) {
|
|
1235
|
-
if (rule.getAttrs) {
|
|
1236
|
-
let result = rule.getAttrs(dom);
|
|
1237
|
-
if (result === false)
|
|
1238
|
-
continue;
|
|
1239
|
-
rule.attrs = result || void 0;
|
|
1240
|
-
}
|
|
1241
|
-
return rule;
|
|
1242
|
-
}
|
|
1243
|
-
}
|
|
1244
|
-
}
|
|
1245
|
-
/**
|
|
1246
|
-
@internal
|
|
1247
|
-
*/
|
|
1248
|
-
matchStyle(prop, value, context, after) {
|
|
1249
|
-
for (let i = after ? this.styles.indexOf(after) + 1 : 0; i < this.styles.length; i++) {
|
|
1250
|
-
let rule = this.styles[i], style = rule.style;
|
|
1251
|
-
if (style.indexOf(prop) != 0 || rule.context && !context.matchesContext(rule.context) || // Test that the style string either precisely matches the prop,
|
|
1252
|
-
// or has an '=' sign after the prop, followed by the given
|
|
1253
|
-
// value.
|
|
1254
|
-
style.length > prop.length && (style.charCodeAt(prop.length) != 61 || style.slice(prop.length + 1) != value))
|
|
1255
|
-
continue;
|
|
1256
|
-
if (rule.getAttrs) {
|
|
1257
|
-
let result = rule.getAttrs(value);
|
|
1258
|
-
if (result === false)
|
|
1259
|
-
continue;
|
|
1260
|
-
rule.attrs = result || void 0;
|
|
1261
|
-
}
|
|
1262
|
-
return rule;
|
|
1263
|
-
}
|
|
1264
|
-
}
|
|
1265
|
-
/**
|
|
1266
|
-
@internal
|
|
1267
|
-
*/
|
|
1268
|
-
static schemaRules(schema) {
|
|
1269
|
-
let result = [];
|
|
1270
|
-
function insert(rule) {
|
|
1271
|
-
let priority = rule.priority == null ? 50 : rule.priority, i = 0;
|
|
1272
|
-
for (; i < result.length; i++) {
|
|
1273
|
-
let next = result[i], nextPriority = next.priority == null ? 50 : next.priority;
|
|
1274
|
-
if (nextPriority < priority)
|
|
1275
|
-
break;
|
|
1276
|
-
}
|
|
1277
|
-
result.splice(i, 0, rule);
|
|
1278
|
-
}
|
|
1279
|
-
for (let name in schema.marks) {
|
|
1280
|
-
let rules = schema.marks[name].spec.parseDOM;
|
|
1281
|
-
if (rules)
|
|
1282
|
-
rules.forEach((rule) => {
|
|
1283
|
-
insert(rule = copy(rule));
|
|
1284
|
-
if (!(rule.mark || rule.ignore || rule.clearMark))
|
|
1285
|
-
rule.mark = name;
|
|
1286
|
-
});
|
|
1287
|
-
}
|
|
1288
|
-
for (let name in schema.nodes) {
|
|
1289
|
-
let rules = schema.nodes[name].spec.parseDOM;
|
|
1290
|
-
if (rules)
|
|
1291
|
-
rules.forEach((rule) => {
|
|
1292
|
-
insert(rule = copy(rule));
|
|
1293
|
-
if (!(rule.node || rule.ignore || rule.mark))
|
|
1294
|
-
rule.node = name;
|
|
1295
|
-
});
|
|
1296
|
-
}
|
|
1297
|
-
return result;
|
|
1298
|
-
}
|
|
1299
|
-
/**
|
|
1300
|
-
Construct a DOM parser using the parsing rules listed in a
|
|
1301
|
-
schema's [node specs](https://prosemirror.net/docs/ref/#model.NodeSpec.parseDOM), reordered by
|
|
1302
|
-
[priority](https://prosemirror.net/docs/ref/#model.GenericParseRule.priority).
|
|
1303
|
-
*/
|
|
1304
|
-
static fromSchema(schema) {
|
|
1305
|
-
return schema.cached.domParser || (schema.cached.domParser = new _DOMParser(schema, _DOMParser.schemaRules(schema)));
|
|
1306
|
-
}
|
|
1307
|
-
};
|
|
1308
|
-
var blockTags = {
|
|
1309
|
-
address: true,
|
|
1310
|
-
article: true,
|
|
1311
|
-
aside: true,
|
|
1312
|
-
blockquote: true,
|
|
1313
|
-
canvas: true,
|
|
1314
|
-
dd: true,
|
|
1315
|
-
div: true,
|
|
1316
|
-
dl: true,
|
|
1317
|
-
fieldset: true,
|
|
1318
|
-
figcaption: true,
|
|
1319
|
-
figure: true,
|
|
1320
|
-
footer: true,
|
|
1321
|
-
form: true,
|
|
1322
|
-
h1: true,
|
|
1323
|
-
h2: true,
|
|
1324
|
-
h3: true,
|
|
1325
|
-
h4: true,
|
|
1326
|
-
h5: true,
|
|
1327
|
-
h6: true,
|
|
1328
|
-
header: true,
|
|
1329
|
-
hgroup: true,
|
|
1330
|
-
hr: true,
|
|
1331
|
-
li: true,
|
|
1332
|
-
noscript: true,
|
|
1333
|
-
ol: true,
|
|
1334
|
-
output: true,
|
|
1335
|
-
p: true,
|
|
1336
|
-
pre: true,
|
|
1337
|
-
section: true,
|
|
1338
|
-
table: true,
|
|
1339
|
-
tfoot: true,
|
|
1340
|
-
ul: true
|
|
1341
|
-
};
|
|
1342
|
-
var ignoreTags = {
|
|
1343
|
-
head: true,
|
|
1344
|
-
noscript: true,
|
|
1345
|
-
object: true,
|
|
1346
|
-
script: true,
|
|
1347
|
-
style: true,
|
|
1348
|
-
title: true
|
|
1349
|
-
};
|
|
1350
|
-
var listTags = { ol: true, ul: true };
|
|
1351
|
-
var OPT_PRESERVE_WS = 1;
|
|
1352
|
-
var OPT_PRESERVE_WS_FULL = 2;
|
|
1353
|
-
var OPT_OPEN_LEFT = 4;
|
|
1354
|
-
function wsOptionsFor(type, preserveWhitespace, base) {
|
|
1355
|
-
if (preserveWhitespace != null)
|
|
1356
|
-
return (preserveWhitespace ? OPT_PRESERVE_WS : 0) | (preserveWhitespace === "full" ? OPT_PRESERVE_WS_FULL : 0);
|
|
1357
|
-
return type && type.whitespace == "pre" ? OPT_PRESERVE_WS | OPT_PRESERVE_WS_FULL : base & ~OPT_OPEN_LEFT;
|
|
1358
|
-
}
|
|
1359
|
-
var NodeContext = class {
|
|
1360
|
-
constructor(type, attrs, marks, solid, match, options) {
|
|
1361
|
-
this.type = type;
|
|
1362
|
-
this.attrs = attrs;
|
|
1363
|
-
this.marks = marks;
|
|
1364
|
-
this.solid = solid;
|
|
1365
|
-
this.options = options;
|
|
1366
|
-
this.content = [];
|
|
1367
|
-
this.activeMarks = Mark.none;
|
|
1368
|
-
this.match = match || (options & OPT_OPEN_LEFT ? null : type.contentMatch);
|
|
1369
|
-
}
|
|
1370
|
-
findWrapping(node) {
|
|
1371
|
-
if (!this.match) {
|
|
1372
|
-
if (!this.type)
|
|
1373
|
-
return [];
|
|
1374
|
-
let fill = this.type.contentMatch.fillBefore(Fragment.from(node));
|
|
1375
|
-
if (fill) {
|
|
1376
|
-
this.match = this.type.contentMatch.matchFragment(fill);
|
|
1377
|
-
} else {
|
|
1378
|
-
let start = this.type.contentMatch, wrap;
|
|
1379
|
-
if (wrap = start.findWrapping(node.type)) {
|
|
1380
|
-
this.match = start;
|
|
1381
|
-
return wrap;
|
|
1382
|
-
} else {
|
|
1383
|
-
return null;
|
|
1384
|
-
}
|
|
1385
|
-
}
|
|
1386
|
-
}
|
|
1387
|
-
return this.match.findWrapping(node.type);
|
|
1388
|
-
}
|
|
1389
|
-
finish(openEnd) {
|
|
1390
|
-
if (!(this.options & OPT_PRESERVE_WS)) {
|
|
1391
|
-
let last = this.content[this.content.length - 1], m;
|
|
1392
|
-
if (last && last.isText && (m = /[ \t\r\n\u000c]+$/.exec(last.text))) {
|
|
1393
|
-
let text = last;
|
|
1394
|
-
if (last.text.length == m[0].length)
|
|
1395
|
-
this.content.pop();
|
|
1396
|
-
else
|
|
1397
|
-
this.content[this.content.length - 1] = text.withText(text.text.slice(0, text.text.length - m[0].length));
|
|
1398
|
-
}
|
|
1399
|
-
}
|
|
1400
|
-
let content = Fragment.from(this.content);
|
|
1401
|
-
if (!openEnd && this.match)
|
|
1402
|
-
content = content.append(this.match.fillBefore(Fragment.empty, true));
|
|
1403
|
-
return this.type ? this.type.create(this.attrs, content, this.marks) : content;
|
|
1404
|
-
}
|
|
1405
|
-
inlineContext(node) {
|
|
1406
|
-
if (this.type)
|
|
1407
|
-
return this.type.inlineContent;
|
|
1408
|
-
if (this.content.length)
|
|
1409
|
-
return this.content[0].isInline;
|
|
1410
|
-
return node.parentNode && !blockTags.hasOwnProperty(node.parentNode.nodeName.toLowerCase());
|
|
1411
|
-
}
|
|
1412
|
-
};
|
|
1413
|
-
var ParseContext = class {
|
|
1414
|
-
constructor(parser, options, isOpen) {
|
|
1415
|
-
this.parser = parser;
|
|
1416
|
-
this.options = options;
|
|
1417
|
-
this.isOpen = isOpen;
|
|
1418
|
-
this.open = 0;
|
|
1419
|
-
this.localPreserveWS = false;
|
|
1420
|
-
let topNode = options.topNode, topContext;
|
|
1421
|
-
let topOptions = wsOptionsFor(null, options.preserveWhitespace, 0) | (isOpen ? OPT_OPEN_LEFT : 0);
|
|
1422
|
-
if (topNode)
|
|
1423
|
-
topContext = new NodeContext(topNode.type, topNode.attrs, Mark.none, true, options.topMatch || topNode.type.contentMatch, topOptions);
|
|
1424
|
-
else if (isOpen)
|
|
1425
|
-
topContext = new NodeContext(null, null, Mark.none, true, null, topOptions);
|
|
1426
|
-
else
|
|
1427
|
-
topContext = new NodeContext(parser.schema.topNodeType, null, Mark.none, true, null, topOptions);
|
|
1428
|
-
this.nodes = [topContext];
|
|
1429
|
-
this.find = options.findPositions;
|
|
1430
|
-
this.needsBlock = false;
|
|
1431
|
-
}
|
|
1432
|
-
get top() {
|
|
1433
|
-
return this.nodes[this.open];
|
|
1434
|
-
}
|
|
1435
|
-
// Add a DOM node to the content. Text is inserted as text node,
|
|
1436
|
-
// otherwise, the node is passed to `addElement` or, if it has a
|
|
1437
|
-
// `style` attribute, `addElementWithStyles`.
|
|
1438
|
-
addDOM(dom, marks) {
|
|
1439
|
-
if (dom.nodeType == 3)
|
|
1440
|
-
this.addTextNode(dom, marks);
|
|
1441
|
-
else if (dom.nodeType == 1)
|
|
1442
|
-
this.addElement(dom, marks);
|
|
1443
|
-
}
|
|
1444
|
-
addTextNode(dom, marks) {
|
|
1445
|
-
let value = dom.nodeValue;
|
|
1446
|
-
let top = this.top, preserveWS = top.options & OPT_PRESERVE_WS_FULL ? "full" : this.localPreserveWS || (top.options & OPT_PRESERVE_WS) > 0;
|
|
1447
|
-
let { schema } = this.parser;
|
|
1448
|
-
if (preserveWS === "full" || top.inlineContext(dom) || /[^ \t\r\n\u000c]/.test(value)) {
|
|
1449
|
-
if (!preserveWS) {
|
|
1450
|
-
value = value.replace(/[ \t\r\n\u000c]+/g, " ");
|
|
1451
|
-
if (/^[ \t\r\n\u000c]/.test(value) && this.open == this.nodes.length - 1) {
|
|
1452
|
-
let nodeBefore = top.content[top.content.length - 1];
|
|
1453
|
-
let domNodeBefore = dom.previousSibling;
|
|
1454
|
-
if (!nodeBefore || domNodeBefore && domNodeBefore.nodeName == "BR" || nodeBefore.isText && /[ \t\r\n\u000c]$/.test(nodeBefore.text))
|
|
1455
|
-
value = value.slice(1);
|
|
1456
|
-
}
|
|
1457
|
-
} else if (preserveWS === "full") {
|
|
1458
|
-
value = value.replace(/\r\n?/g, "\n");
|
|
1459
|
-
} else if (schema.linebreakReplacement && /[\r\n]/.test(value) && this.top.findWrapping(schema.linebreakReplacement.create())) {
|
|
1460
|
-
let lines = value.split(/\r?\n|\r/);
|
|
1461
|
-
for (let i = 0; i < lines.length; i++) {
|
|
1462
|
-
if (i)
|
|
1463
|
-
this.insertNode(schema.linebreakReplacement.create(), marks, true);
|
|
1464
|
-
if (lines[i])
|
|
1465
|
-
this.insertNode(schema.text(lines[i]), marks, !/\S/.test(lines[i]));
|
|
1466
|
-
}
|
|
1467
|
-
value = "";
|
|
1468
|
-
} else {
|
|
1469
|
-
value = value.replace(/\r?\n|\r/g, " ");
|
|
1470
|
-
}
|
|
1471
|
-
if (value)
|
|
1472
|
-
this.insertNode(schema.text(value), marks, !/\S/.test(value));
|
|
1473
|
-
this.findInText(dom);
|
|
1474
|
-
} else {
|
|
1475
|
-
this.findInside(dom);
|
|
1476
|
-
}
|
|
1477
|
-
}
|
|
1478
|
-
// Try to find a handler for the given tag and use that to parse. If
|
|
1479
|
-
// none is found, the element's content nodes are added directly.
|
|
1480
|
-
addElement(dom, marks, matchAfter) {
|
|
1481
|
-
let outerWS = this.localPreserveWS, top = this.top;
|
|
1482
|
-
if (dom.tagName == "PRE" || /pre/.test(dom.style && dom.style.whiteSpace))
|
|
1483
|
-
this.localPreserveWS = true;
|
|
1484
|
-
let name = dom.nodeName.toLowerCase(), ruleID;
|
|
1485
|
-
if (listTags.hasOwnProperty(name) && this.parser.normalizeLists)
|
|
1486
|
-
normalizeList(dom);
|
|
1487
|
-
let rule = this.options.ruleFromNode && this.options.ruleFromNode(dom) || (ruleID = this.parser.matchTag(dom, this, matchAfter));
|
|
1488
|
-
out: if (rule ? rule.ignore : ignoreTags.hasOwnProperty(name)) {
|
|
1489
|
-
this.findInside(dom);
|
|
1490
|
-
this.ignoreFallback(dom, marks);
|
|
1491
|
-
} else if (!rule || rule.skip || rule.closeParent) {
|
|
1492
|
-
if (rule && rule.closeParent)
|
|
1493
|
-
this.open = Math.max(0, this.open - 1);
|
|
1494
|
-
else if (rule && rule.skip.nodeType)
|
|
1495
|
-
dom = rule.skip;
|
|
1496
|
-
let sync, oldNeedsBlock = this.needsBlock;
|
|
1497
|
-
if (blockTags.hasOwnProperty(name)) {
|
|
1498
|
-
if (top.content.length && top.content[0].isInline && this.open) {
|
|
1499
|
-
this.open--;
|
|
1500
|
-
top = this.top;
|
|
1501
|
-
}
|
|
1502
|
-
sync = true;
|
|
1503
|
-
if (!top.type)
|
|
1504
|
-
this.needsBlock = true;
|
|
1505
|
-
} else if (!dom.firstChild) {
|
|
1506
|
-
this.leafFallback(dom, marks);
|
|
1507
|
-
break out;
|
|
1508
|
-
}
|
|
1509
|
-
let innerMarks = rule && rule.skip ? marks : this.readStyles(dom, marks);
|
|
1510
|
-
if (innerMarks)
|
|
1511
|
-
this.addAll(dom, innerMarks);
|
|
1512
|
-
if (sync)
|
|
1513
|
-
this.sync(top);
|
|
1514
|
-
this.needsBlock = oldNeedsBlock;
|
|
1515
|
-
} else {
|
|
1516
|
-
let innerMarks = this.readStyles(dom, marks);
|
|
1517
|
-
if (innerMarks)
|
|
1518
|
-
this.addElementByRule(dom, rule, innerMarks, rule.consuming === false ? ruleID : void 0);
|
|
1519
|
-
}
|
|
1520
|
-
this.localPreserveWS = outerWS;
|
|
1521
|
-
}
|
|
1522
|
-
// Called for leaf DOM nodes that would otherwise be ignored
|
|
1523
|
-
leafFallback(dom, marks) {
|
|
1524
|
-
if (dom.nodeName == "BR" && this.top.type && this.top.type.inlineContent)
|
|
1525
|
-
this.addTextNode(dom.ownerDocument.createTextNode("\n"), marks);
|
|
1526
|
-
}
|
|
1527
|
-
// Called for ignored nodes
|
|
1528
|
-
ignoreFallback(dom, marks) {
|
|
1529
|
-
if (dom.nodeName == "BR" && (!this.top.type || !this.top.type.inlineContent))
|
|
1530
|
-
this.findPlace(this.parser.schema.text("-"), marks, true);
|
|
1531
|
-
}
|
|
1532
|
-
// Run any style parser associated with the node's styles. Either
|
|
1533
|
-
// return an updated array of marks, or null to indicate some of the
|
|
1534
|
-
// styles had a rule with `ignore` set.
|
|
1535
|
-
readStyles(dom, marks) {
|
|
1536
|
-
let styles = dom.style;
|
|
1537
|
-
if (styles && styles.length)
|
|
1538
|
-
for (let i = 0; i < this.parser.matchedStyles.length; i++) {
|
|
1539
|
-
let name = this.parser.matchedStyles[i], value = styles.getPropertyValue(name);
|
|
1540
|
-
if (value)
|
|
1541
|
-
for (let after = void 0; ; ) {
|
|
1542
|
-
let rule = this.parser.matchStyle(name, value, this, after);
|
|
1543
|
-
if (!rule)
|
|
1544
|
-
break;
|
|
1545
|
-
if (rule.ignore)
|
|
1546
|
-
return null;
|
|
1547
|
-
if (rule.clearMark)
|
|
1548
|
-
marks = marks.filter((m) => !rule.clearMark(m));
|
|
1549
|
-
else
|
|
1550
|
-
marks = marks.concat(this.parser.schema.marks[rule.mark].create(rule.attrs));
|
|
1551
|
-
if (rule.consuming === false)
|
|
1552
|
-
after = rule;
|
|
1553
|
-
else
|
|
1554
|
-
break;
|
|
1555
|
-
}
|
|
1556
|
-
}
|
|
1557
|
-
return marks;
|
|
1558
|
-
}
|
|
1559
|
-
// Look up a handler for the given node. If none are found, return
|
|
1560
|
-
// false. Otherwise, apply it, use its return value to drive the way
|
|
1561
|
-
// the node's content is wrapped, and return true.
|
|
1562
|
-
addElementByRule(dom, rule, marks, continueAfter) {
|
|
1563
|
-
let sync, nodeType;
|
|
1564
|
-
if (rule.node) {
|
|
1565
|
-
nodeType = this.parser.schema.nodes[rule.node];
|
|
1566
|
-
if (!nodeType.isLeaf) {
|
|
1567
|
-
let inner = this.enter(nodeType, rule.attrs || null, marks, rule.preserveWhitespace);
|
|
1568
|
-
if (inner) {
|
|
1569
|
-
sync = true;
|
|
1570
|
-
marks = inner;
|
|
1571
|
-
}
|
|
1572
|
-
} else if (!this.insertNode(nodeType.create(rule.attrs), marks, dom.nodeName == "BR")) {
|
|
1573
|
-
this.leafFallback(dom, marks);
|
|
1574
|
-
}
|
|
1575
|
-
} else {
|
|
1576
|
-
let markType = this.parser.schema.marks[rule.mark];
|
|
1577
|
-
marks = marks.concat(markType.create(rule.attrs));
|
|
1578
|
-
}
|
|
1579
|
-
let startIn = this.top;
|
|
1580
|
-
if (nodeType && nodeType.isLeaf) {
|
|
1581
|
-
this.findInside(dom);
|
|
1582
|
-
} else if (continueAfter) {
|
|
1583
|
-
this.addElement(dom, marks, continueAfter);
|
|
1584
|
-
} else if (rule.getContent) {
|
|
1585
|
-
this.findInside(dom);
|
|
1586
|
-
rule.getContent(dom, this.parser.schema).forEach((node) => this.insertNode(node, marks, false));
|
|
1587
|
-
} else {
|
|
1588
|
-
let contentDOM = dom;
|
|
1589
|
-
if (typeof rule.contentElement == "string")
|
|
1590
|
-
contentDOM = dom.querySelector(rule.contentElement);
|
|
1591
|
-
else if (typeof rule.contentElement == "function")
|
|
1592
|
-
contentDOM = rule.contentElement(dom);
|
|
1593
|
-
else if (rule.contentElement)
|
|
1594
|
-
contentDOM = rule.contentElement;
|
|
1595
|
-
this.findAround(dom, contentDOM, true);
|
|
1596
|
-
this.addAll(contentDOM, marks);
|
|
1597
|
-
this.findAround(dom, contentDOM, false);
|
|
1598
|
-
}
|
|
1599
|
-
if (sync && this.sync(startIn))
|
|
1600
|
-
this.open--;
|
|
1601
|
-
}
|
|
1602
|
-
// Add all child nodes between `startIndex` and `endIndex` (or the
|
|
1603
|
-
// whole node, if not given). If `sync` is passed, use it to
|
|
1604
|
-
// synchronize after every block element.
|
|
1605
|
-
addAll(parent, marks, startIndex, endIndex) {
|
|
1606
|
-
let index = startIndex || 0;
|
|
1607
|
-
for (let dom = startIndex ? parent.childNodes[startIndex] : parent.firstChild, end = endIndex == null ? null : parent.childNodes[endIndex]; dom != end; dom = dom.nextSibling, ++index) {
|
|
1608
|
-
this.findAtPoint(parent, index);
|
|
1609
|
-
this.addDOM(dom, marks);
|
|
1610
|
-
}
|
|
1611
|
-
this.findAtPoint(parent, index);
|
|
1612
|
-
}
|
|
1613
|
-
// Try to find a way to fit the given node type into the current
|
|
1614
|
-
// context. May add intermediate wrappers and/or leave non-solid
|
|
1615
|
-
// nodes that we're in.
|
|
1616
|
-
findPlace(node, marks, cautious) {
|
|
1617
|
-
let route, sync;
|
|
1618
|
-
for (let depth = this.open, penalty = 0; depth >= 0; depth--) {
|
|
1619
|
-
let cx = this.nodes[depth];
|
|
1620
|
-
let found2 = cx.findWrapping(node);
|
|
1621
|
-
if (found2 && (!route || route.length > found2.length + penalty)) {
|
|
1622
|
-
route = found2;
|
|
1623
|
-
sync = cx;
|
|
1624
|
-
if (!found2.length)
|
|
1625
|
-
break;
|
|
1626
|
-
}
|
|
1627
|
-
if (cx.solid) {
|
|
1628
|
-
if (cautious)
|
|
1629
|
-
break;
|
|
1630
|
-
penalty += 2;
|
|
1631
|
-
}
|
|
1632
|
-
}
|
|
1633
|
-
if (!route)
|
|
1634
|
-
return null;
|
|
1635
|
-
this.sync(sync);
|
|
1636
|
-
for (let i = 0; i < route.length; i++)
|
|
1637
|
-
marks = this.enterInner(route[i], null, marks, false);
|
|
1638
|
-
return marks;
|
|
1639
|
-
}
|
|
1640
|
-
// Try to insert the given node, adjusting the context when needed.
|
|
1641
|
-
insertNode(node, marks, cautious) {
|
|
1642
|
-
if (node.isInline && this.needsBlock && !this.top.type) {
|
|
1643
|
-
let block = this.textblockFromContext();
|
|
1644
|
-
if (block)
|
|
1645
|
-
marks = this.enterInner(block, null, marks);
|
|
1646
|
-
}
|
|
1647
|
-
let innerMarks = this.findPlace(node, marks, cautious);
|
|
1648
|
-
if (innerMarks) {
|
|
1649
|
-
this.closeExtra();
|
|
1650
|
-
let top = this.top;
|
|
1651
|
-
if (top.match)
|
|
1652
|
-
top.match = top.match.matchType(node.type);
|
|
1653
|
-
let nodeMarks = Mark.none;
|
|
1654
|
-
for (let m of innerMarks.concat(node.marks))
|
|
1655
|
-
if (top.type ? top.type.allowsMarkType(m.type) : markMayApply(m.type, node.type))
|
|
1656
|
-
nodeMarks = m.addToSet(nodeMarks);
|
|
1657
|
-
top.content.push(node.mark(nodeMarks));
|
|
1658
|
-
return true;
|
|
1659
|
-
}
|
|
1660
|
-
return false;
|
|
1661
|
-
}
|
|
1662
|
-
// Try to start a node of the given type, adjusting the context when
|
|
1663
|
-
// necessary.
|
|
1664
|
-
enter(type, attrs, marks, preserveWS) {
|
|
1665
|
-
let innerMarks = this.findPlace(type.create(attrs), marks, false);
|
|
1666
|
-
if (innerMarks)
|
|
1667
|
-
innerMarks = this.enterInner(type, attrs, marks, true, preserveWS);
|
|
1668
|
-
return innerMarks;
|
|
1669
|
-
}
|
|
1670
|
-
// Open a node of the given type
|
|
1671
|
-
enterInner(type, attrs, marks, solid = false, preserveWS) {
|
|
1672
|
-
this.closeExtra();
|
|
1673
|
-
let top = this.top;
|
|
1674
|
-
top.match = top.match && top.match.matchType(type);
|
|
1675
|
-
let options = wsOptionsFor(type, preserveWS, top.options);
|
|
1676
|
-
if (top.options & OPT_OPEN_LEFT && top.content.length == 0)
|
|
1677
|
-
options |= OPT_OPEN_LEFT;
|
|
1678
|
-
let applyMarks = Mark.none;
|
|
1679
|
-
marks = marks.filter((m) => {
|
|
1680
|
-
if (top.type ? top.type.allowsMarkType(m.type) : markMayApply(m.type, type)) {
|
|
1681
|
-
applyMarks = m.addToSet(applyMarks);
|
|
1682
|
-
return false;
|
|
1683
|
-
}
|
|
1684
|
-
return true;
|
|
1685
|
-
});
|
|
1686
|
-
this.nodes.push(new NodeContext(type, attrs, applyMarks, solid, null, options));
|
|
1687
|
-
this.open++;
|
|
1688
|
-
return marks;
|
|
1689
|
-
}
|
|
1690
|
-
// Make sure all nodes above this.open are finished and added to
|
|
1691
|
-
// their parents
|
|
1692
|
-
closeExtra(openEnd = false) {
|
|
1693
|
-
let i = this.nodes.length - 1;
|
|
1694
|
-
if (i > this.open) {
|
|
1695
|
-
for (; i > this.open; i--)
|
|
1696
|
-
this.nodes[i - 1].content.push(this.nodes[i].finish(openEnd));
|
|
1697
|
-
this.nodes.length = this.open + 1;
|
|
1698
|
-
}
|
|
1699
|
-
}
|
|
1700
|
-
finish() {
|
|
1701
|
-
this.open = 0;
|
|
1702
|
-
this.closeExtra(this.isOpen);
|
|
1703
|
-
return this.nodes[0].finish(!!(this.isOpen || this.options.topOpen));
|
|
1704
|
-
}
|
|
1705
|
-
sync(to) {
|
|
1706
|
-
for (let i = this.open; i >= 0; i--) {
|
|
1707
|
-
if (this.nodes[i] == to) {
|
|
1708
|
-
this.open = i;
|
|
1709
|
-
return true;
|
|
1710
|
-
} else if (this.localPreserveWS) {
|
|
1711
|
-
this.nodes[i].options |= OPT_PRESERVE_WS;
|
|
1712
|
-
}
|
|
1713
|
-
}
|
|
1714
|
-
return false;
|
|
1715
|
-
}
|
|
1716
|
-
get currentPos() {
|
|
1717
|
-
this.closeExtra();
|
|
1718
|
-
let pos = 0;
|
|
1719
|
-
for (let i = this.open; i >= 0; i--) {
|
|
1720
|
-
let content = this.nodes[i].content;
|
|
1721
|
-
for (let j = content.length - 1; j >= 0; j--)
|
|
1722
|
-
pos += content[j].nodeSize;
|
|
1723
|
-
if (i)
|
|
1724
|
-
pos++;
|
|
1725
|
-
}
|
|
1726
|
-
return pos;
|
|
1727
|
-
}
|
|
1728
|
-
findAtPoint(parent, offset) {
|
|
1729
|
-
if (this.find)
|
|
1730
|
-
for (let i = 0; i < this.find.length; i++) {
|
|
1731
|
-
if (this.find[i].node == parent && this.find[i].offset == offset)
|
|
1732
|
-
this.find[i].pos = this.currentPos;
|
|
1733
|
-
}
|
|
1734
|
-
}
|
|
1735
|
-
findInside(parent) {
|
|
1736
|
-
if (this.find)
|
|
1737
|
-
for (let i = 0; i < this.find.length; i++) {
|
|
1738
|
-
if (this.find[i].pos == null && parent.nodeType == 1 && parent.contains(this.find[i].node))
|
|
1739
|
-
this.find[i].pos = this.currentPos;
|
|
1740
|
-
}
|
|
1741
|
-
}
|
|
1742
|
-
findAround(parent, content, before) {
|
|
1743
|
-
if (parent != content && this.find)
|
|
1744
|
-
for (let i = 0; i < this.find.length; i++) {
|
|
1745
|
-
if (this.find[i].pos == null && parent.nodeType == 1 && parent.contains(this.find[i].node)) {
|
|
1746
|
-
let pos = content.compareDocumentPosition(this.find[i].node);
|
|
1747
|
-
if (pos & (before ? 2 : 4))
|
|
1748
|
-
this.find[i].pos = this.currentPos;
|
|
1749
|
-
}
|
|
1750
|
-
}
|
|
1751
|
-
}
|
|
1752
|
-
findInText(textNode) {
|
|
1753
|
-
if (this.find)
|
|
1754
|
-
for (let i = 0; i < this.find.length; i++) {
|
|
1755
|
-
if (this.find[i].node == textNode)
|
|
1756
|
-
this.find[i].pos = this.currentPos - (textNode.nodeValue.length - this.find[i].offset);
|
|
1757
|
-
}
|
|
1758
|
-
}
|
|
1759
|
-
// Determines whether the given context string matches this context.
|
|
1760
|
-
matchesContext(context) {
|
|
1761
|
-
if (context.indexOf("|") > -1)
|
|
1762
|
-
return context.split(/\s*\|\s*/).some(this.matchesContext, this);
|
|
1763
|
-
let parts = context.split("/");
|
|
1764
|
-
let option = this.options.context;
|
|
1765
|
-
let useRoot = !this.isOpen && (!option || option.parent.type == this.nodes[0].type);
|
|
1766
|
-
let minDepth = -(option ? option.depth + 1 : 0) + (useRoot ? 0 : 1);
|
|
1767
|
-
let match = (i, depth) => {
|
|
1768
|
-
for (; i >= 0; i--) {
|
|
1769
|
-
let part = parts[i];
|
|
1770
|
-
if (part == "") {
|
|
1771
|
-
if (i == parts.length - 1 || i == 0)
|
|
1772
|
-
continue;
|
|
1773
|
-
for (; depth >= minDepth; depth--)
|
|
1774
|
-
if (match(i - 1, depth))
|
|
1775
|
-
return true;
|
|
1776
|
-
return false;
|
|
1777
|
-
} else {
|
|
1778
|
-
let next = depth > 0 || depth == 0 && useRoot ? this.nodes[depth].type : option && depth >= minDepth ? option.node(depth - minDepth).type : null;
|
|
1779
|
-
if (!next || next.name != part && !next.isInGroup(part))
|
|
1780
|
-
return false;
|
|
1781
|
-
depth--;
|
|
1782
|
-
}
|
|
1783
|
-
}
|
|
1784
|
-
return true;
|
|
1785
|
-
};
|
|
1786
|
-
return match(parts.length - 1, this.open);
|
|
1787
|
-
}
|
|
1788
|
-
textblockFromContext() {
|
|
1789
|
-
let $context = this.options.context;
|
|
1790
|
-
if ($context)
|
|
1791
|
-
for (let d = $context.depth; d >= 0; d--) {
|
|
1792
|
-
let deflt = $context.node(d).contentMatchAt($context.indexAfter(d)).defaultType;
|
|
1793
|
-
if (deflt && deflt.isTextblock && deflt.defaultAttrs)
|
|
1794
|
-
return deflt;
|
|
1795
|
-
}
|
|
1796
|
-
for (let name in this.parser.schema.nodes) {
|
|
1797
|
-
let type = this.parser.schema.nodes[name];
|
|
1798
|
-
if (type.isTextblock && type.defaultAttrs)
|
|
1799
|
-
return type;
|
|
1800
|
-
}
|
|
1801
|
-
}
|
|
1802
|
-
};
|
|
1803
|
-
function normalizeList(dom) {
|
|
1804
|
-
for (let child = dom.firstChild, prevItem = null; child; child = child.nextSibling) {
|
|
1805
|
-
let name = child.nodeType == 1 ? child.nodeName.toLowerCase() : null;
|
|
1806
|
-
if (name && listTags.hasOwnProperty(name) && prevItem) {
|
|
1807
|
-
prevItem.appendChild(child);
|
|
1808
|
-
child = prevItem;
|
|
1809
|
-
} else if (name == "li") {
|
|
1810
|
-
prevItem = child;
|
|
1811
|
-
} else if (name) {
|
|
1812
|
-
prevItem = null;
|
|
1813
|
-
}
|
|
1814
|
-
}
|
|
1815
|
-
}
|
|
1816
|
-
function matches(dom, selector) {
|
|
1817
|
-
return (dom.matches || dom.msMatchesSelector || dom.webkitMatchesSelector || dom.mozMatchesSelector).call(dom, selector);
|
|
1818
|
-
}
|
|
1819
|
-
function copy(obj) {
|
|
1820
|
-
let copy2 = {};
|
|
1821
|
-
for (let prop in obj)
|
|
1822
|
-
copy2[prop] = obj[prop];
|
|
1823
|
-
return copy2;
|
|
1824
|
-
}
|
|
1825
|
-
function markMayApply(markType, nodeType) {
|
|
1826
|
-
let nodes = nodeType.schema.nodes;
|
|
1827
|
-
for (let name in nodes) {
|
|
1828
|
-
let parent = nodes[name];
|
|
1829
|
-
if (!parent.allowsMarkType(markType))
|
|
1830
|
-
continue;
|
|
1831
|
-
let seen = [], scan = (match) => {
|
|
1832
|
-
seen.push(match);
|
|
1833
|
-
for (let i = 0; i < match.edgeCount; i++) {
|
|
1834
|
-
let { type, next } = match.edge(i);
|
|
1835
|
-
if (type == nodeType)
|
|
1836
|
-
return true;
|
|
1837
|
-
if (seen.indexOf(next) < 0 && scan(next))
|
|
1838
|
-
return true;
|
|
1839
|
-
}
|
|
1840
|
-
};
|
|
1841
|
-
if (scan(parent.contentMatch))
|
|
1842
|
-
return true;
|
|
1843
|
-
}
|
|
1844
|
-
}
|
|
1845
|
-
var DOMSerializer = class _DOMSerializer {
|
|
1846
|
-
/**
|
|
1847
|
-
Create a serializer. `nodes` should map node names to functions
|
|
1848
|
-
that take a node and return a description of the corresponding
|
|
1849
|
-
DOM. `marks` does the same for mark names, but also gets an
|
|
1850
|
-
argument that tells it whether the mark's content is block or
|
|
1851
|
-
inline content (for typical use, it'll always be inline). A mark
|
|
1852
|
-
serializer may be `null` to indicate that marks of that type
|
|
1853
|
-
should not be serialized.
|
|
1854
|
-
*/
|
|
1855
|
-
constructor(nodes, marks) {
|
|
1856
|
-
this.nodes = nodes;
|
|
1857
|
-
this.marks = marks;
|
|
1858
|
-
}
|
|
1859
|
-
/**
|
|
1860
|
-
Serialize the content of this fragment to a DOM fragment. When
|
|
1861
|
-
not in the browser, the `document` option, containing a DOM
|
|
1862
|
-
document, should be passed so that the serializer can create
|
|
1863
|
-
nodes.
|
|
1864
|
-
*/
|
|
1865
|
-
serializeFragment(fragment, options = {}, target) {
|
|
1866
|
-
if (!target)
|
|
1867
|
-
target = doc(options).createDocumentFragment();
|
|
1868
|
-
let top = target, active = [];
|
|
1869
|
-
fragment.forEach((node) => {
|
|
1870
|
-
if (active.length || node.marks.length) {
|
|
1871
|
-
let keep = 0, rendered = 0;
|
|
1872
|
-
while (keep < active.length && rendered < node.marks.length) {
|
|
1873
|
-
let next = node.marks[rendered];
|
|
1874
|
-
if (!this.marks[next.type.name]) {
|
|
1875
|
-
rendered++;
|
|
1876
|
-
continue;
|
|
1877
|
-
}
|
|
1878
|
-
if (!next.eq(active[keep][0]) || next.type.spec.spanning === false)
|
|
1879
|
-
break;
|
|
1880
|
-
keep++;
|
|
1881
|
-
rendered++;
|
|
1882
|
-
}
|
|
1883
|
-
while (keep < active.length)
|
|
1884
|
-
top = active.pop()[1];
|
|
1885
|
-
while (rendered < node.marks.length) {
|
|
1886
|
-
let add = node.marks[rendered++];
|
|
1887
|
-
let markDOM = this.serializeMark(add, node.isInline, options);
|
|
1888
|
-
if (markDOM) {
|
|
1889
|
-
active.push([add, top]);
|
|
1890
|
-
top.appendChild(markDOM.dom);
|
|
1891
|
-
top = markDOM.contentDOM || markDOM.dom;
|
|
1892
|
-
}
|
|
1893
|
-
}
|
|
1894
|
-
}
|
|
1895
|
-
top.appendChild(this.serializeNodeInner(node, options));
|
|
1896
|
-
});
|
|
1897
|
-
return target;
|
|
1898
|
-
}
|
|
1899
|
-
/**
|
|
1900
|
-
@internal
|
|
1901
|
-
*/
|
|
1902
|
-
serializeNodeInner(node, options) {
|
|
1903
|
-
let { dom, contentDOM } = renderSpec(doc(options), this.nodes[node.type.name](node), null, node.attrs);
|
|
1904
|
-
if (contentDOM) {
|
|
1905
|
-
if (node.isLeaf)
|
|
1906
|
-
throw new RangeError("Content hole not allowed in a leaf node spec");
|
|
1907
|
-
this.serializeFragment(node.content, options, contentDOM);
|
|
1908
|
-
}
|
|
1909
|
-
return dom;
|
|
1910
|
-
}
|
|
1911
|
-
/**
|
|
1912
|
-
Serialize this node to a DOM node. This can be useful when you
|
|
1913
|
-
need to serialize a part of a document, as opposed to the whole
|
|
1914
|
-
document. To serialize a whole document, use
|
|
1915
|
-
[`serializeFragment`](https://prosemirror.net/docs/ref/#model.DOMSerializer.serializeFragment) on
|
|
1916
|
-
its [content](https://prosemirror.net/docs/ref/#model.Node.content).
|
|
1917
|
-
*/
|
|
1918
|
-
serializeNode(node, options = {}) {
|
|
1919
|
-
let dom = this.serializeNodeInner(node, options);
|
|
1920
|
-
for (let i = node.marks.length - 1; i >= 0; i--) {
|
|
1921
|
-
let wrap = this.serializeMark(node.marks[i], node.isInline, options);
|
|
1922
|
-
if (wrap) {
|
|
1923
|
-
(wrap.contentDOM || wrap.dom).appendChild(dom);
|
|
1924
|
-
dom = wrap.dom;
|
|
1925
|
-
}
|
|
1926
|
-
}
|
|
1927
|
-
return dom;
|
|
1928
|
-
}
|
|
1929
|
-
/**
|
|
1930
|
-
@internal
|
|
1931
|
-
*/
|
|
1932
|
-
serializeMark(mark, inline, options = {}) {
|
|
1933
|
-
let toDOM = this.marks[mark.type.name];
|
|
1934
|
-
return toDOM && renderSpec(doc(options), toDOM(mark, inline), null, mark.attrs);
|
|
1935
|
-
}
|
|
1936
|
-
static renderSpec(doc3, structure, xmlNS = null, blockArraysIn) {
|
|
1937
|
-
return renderSpec(doc3, structure, xmlNS, blockArraysIn);
|
|
1938
|
-
}
|
|
1939
|
-
/**
|
|
1940
|
-
Build a serializer using the [`toDOM`](https://prosemirror.net/docs/ref/#model.NodeSpec.toDOM)
|
|
1941
|
-
properties in a schema's node and mark specs.
|
|
1942
|
-
*/
|
|
1943
|
-
static fromSchema(schema) {
|
|
1944
|
-
return schema.cached.domSerializer || (schema.cached.domSerializer = new _DOMSerializer(this.nodesFromSchema(schema), this.marksFromSchema(schema)));
|
|
1945
|
-
}
|
|
1946
|
-
/**
|
|
1947
|
-
Gather the serializers in a schema's node specs into an object.
|
|
1948
|
-
This can be useful as a base to build a custom serializer from.
|
|
1949
|
-
*/
|
|
1950
|
-
static nodesFromSchema(schema) {
|
|
1951
|
-
let result = gatherToDOM(schema.nodes);
|
|
1952
|
-
if (!result.text)
|
|
1953
|
-
result.text = (node) => node.text;
|
|
1954
|
-
return result;
|
|
1955
|
-
}
|
|
1956
|
-
/**
|
|
1957
|
-
Gather the serializers in a schema's mark specs into an object.
|
|
1958
|
-
*/
|
|
1959
|
-
static marksFromSchema(schema) {
|
|
1960
|
-
return gatherToDOM(schema.marks);
|
|
1961
|
-
}
|
|
1962
|
-
};
|
|
1963
|
-
function gatherToDOM(obj) {
|
|
1964
|
-
let result = {};
|
|
1965
|
-
for (let name in obj) {
|
|
1966
|
-
let toDOM = obj[name].spec.toDOM;
|
|
1967
|
-
if (toDOM)
|
|
1968
|
-
result[name] = toDOM;
|
|
1969
|
-
}
|
|
1970
|
-
return result;
|
|
1971
|
-
}
|
|
1972
|
-
function doc(options) {
|
|
1973
|
-
return options.document || window.document;
|
|
1974
|
-
}
|
|
1975
|
-
var suspiciousAttributeCache = /* @__PURE__ */ new WeakMap();
|
|
1976
|
-
function suspiciousAttributes(attrs) {
|
|
1977
|
-
let value = suspiciousAttributeCache.get(attrs);
|
|
1978
|
-
if (value === void 0)
|
|
1979
|
-
suspiciousAttributeCache.set(attrs, value = suspiciousAttributesInner(attrs));
|
|
1980
|
-
return value;
|
|
1981
|
-
}
|
|
1982
|
-
function suspiciousAttributesInner(attrs) {
|
|
1983
|
-
let result = null;
|
|
1984
|
-
function scan(value) {
|
|
1985
|
-
if (value && typeof value == "object") {
|
|
1986
|
-
if (Array.isArray(value)) {
|
|
1987
|
-
if (typeof value[0] == "string") {
|
|
1988
|
-
if (!result)
|
|
1989
|
-
result = [];
|
|
1990
|
-
result.push(value);
|
|
1991
|
-
} else {
|
|
1992
|
-
for (let i = 0; i < value.length; i++)
|
|
1993
|
-
scan(value[i]);
|
|
1994
|
-
}
|
|
1995
|
-
} else {
|
|
1996
|
-
for (let prop in value)
|
|
1997
|
-
scan(value[prop]);
|
|
1998
|
-
}
|
|
1999
|
-
}
|
|
2000
|
-
}
|
|
2001
|
-
scan(attrs);
|
|
2002
|
-
return result;
|
|
2003
|
-
}
|
|
2004
|
-
function renderSpec(doc3, structure, xmlNS, blockArraysIn) {
|
|
2005
|
-
if (typeof structure == "string")
|
|
2006
|
-
return { dom: doc3.createTextNode(structure) };
|
|
2007
|
-
if (structure.nodeType != null)
|
|
2008
|
-
return { dom: structure };
|
|
2009
|
-
if (structure.dom && structure.dom.nodeType != null)
|
|
2010
|
-
return structure;
|
|
2011
|
-
let tagName = structure[0], suspicious;
|
|
2012
|
-
if (typeof tagName != "string")
|
|
2013
|
-
throw new RangeError("Invalid array passed to renderSpec");
|
|
2014
|
-
if (blockArraysIn && (suspicious = suspiciousAttributes(blockArraysIn)) && suspicious.indexOf(structure) > -1)
|
|
2015
|
-
throw new RangeError("Using an array from an attribute object as a DOM spec. This may be an attempted cross site scripting attack.");
|
|
2016
|
-
let space = tagName.indexOf(" ");
|
|
2017
|
-
if (space > 0) {
|
|
2018
|
-
xmlNS = tagName.slice(0, space);
|
|
2019
|
-
tagName = tagName.slice(space + 1);
|
|
2020
|
-
}
|
|
2021
|
-
let contentDOM;
|
|
2022
|
-
let dom = xmlNS ? doc3.createElementNS(xmlNS, tagName) : doc3.createElement(tagName);
|
|
2023
|
-
let attrs = structure[1], start = 1;
|
|
2024
|
-
if (attrs && typeof attrs == "object" && attrs.nodeType == null && !Array.isArray(attrs)) {
|
|
2025
|
-
start = 2;
|
|
2026
|
-
for (let name in attrs)
|
|
2027
|
-
if (attrs[name] != null) {
|
|
2028
|
-
let space2 = name.indexOf(" ");
|
|
2029
|
-
if (space2 > 0)
|
|
2030
|
-
dom.setAttributeNS(name.slice(0, space2), name.slice(space2 + 1), attrs[name]);
|
|
2031
|
-
else if (name == "style" && dom.style)
|
|
2032
|
-
dom.style.cssText = attrs[name];
|
|
2033
|
-
else
|
|
2034
|
-
dom.setAttribute(name, attrs[name]);
|
|
2035
|
-
}
|
|
2036
|
-
}
|
|
2037
|
-
for (let i = start; i < structure.length; i++) {
|
|
2038
|
-
let child = structure[i];
|
|
2039
|
-
if (child === 0) {
|
|
2040
|
-
if (i < structure.length - 1 || i > start)
|
|
2041
|
-
throw new RangeError("Content hole must be the only child of its parent node");
|
|
2042
|
-
return { dom, contentDOM: dom };
|
|
2043
|
-
} else {
|
|
2044
|
-
let { dom: inner, contentDOM: innerContent } = renderSpec(doc3, child, xmlNS, blockArraysIn);
|
|
2045
|
-
dom.appendChild(inner);
|
|
2046
|
-
if (innerContent) {
|
|
2047
|
-
if (contentDOM)
|
|
2048
|
-
throw new RangeError("Multiple content holes");
|
|
2049
|
-
contentDOM = innerContent;
|
|
2050
|
-
}
|
|
2051
|
-
}
|
|
2052
|
-
}
|
|
2053
|
-
return { dom, contentDOM };
|
|
2054
|
-
}
|
|
2055
|
-
|
|
2056
|
-
// node_modules/prosemirror-transform/dist/index.js
|
|
2057
|
-
var lower16 = 65535;
|
|
2058
|
-
var factor16 = Math.pow(2, 16);
|
|
2059
|
-
function makeRecover(index, offset) {
|
|
2060
|
-
return index + offset * factor16;
|
|
2061
|
-
}
|
|
2062
|
-
function recoverIndex(value) {
|
|
2063
|
-
return value & lower16;
|
|
2064
|
-
}
|
|
2065
|
-
function recoverOffset(value) {
|
|
2066
|
-
return (value - (value & lower16)) / factor16;
|
|
2067
|
-
}
|
|
2068
|
-
var DEL_BEFORE = 1;
|
|
2069
|
-
var DEL_AFTER = 2;
|
|
2070
|
-
var DEL_ACROSS = 4;
|
|
2071
|
-
var DEL_SIDE = 8;
|
|
2072
|
-
var MapResult = class {
|
|
2073
|
-
/**
|
|
2074
|
-
@internal
|
|
2075
|
-
*/
|
|
2076
|
-
constructor(pos, delInfo, recover) {
|
|
2077
|
-
this.pos = pos;
|
|
2078
|
-
this.delInfo = delInfo;
|
|
2079
|
-
this.recover = recover;
|
|
2080
|
-
}
|
|
2081
|
-
/**
|
|
2082
|
-
Tells you whether the position was deleted, that is, whether the
|
|
2083
|
-
step removed the token on the side queried (via the `assoc`)
|
|
2084
|
-
argument from the document.
|
|
2085
|
-
*/
|
|
2086
|
-
get deleted() {
|
|
2087
|
-
return (this.delInfo & DEL_SIDE) > 0;
|
|
2088
|
-
}
|
|
2089
|
-
/**
|
|
2090
|
-
Tells you whether the token before the mapped position was deleted.
|
|
2091
|
-
*/
|
|
2092
|
-
get deletedBefore() {
|
|
2093
|
-
return (this.delInfo & (DEL_BEFORE | DEL_ACROSS)) > 0;
|
|
2094
|
-
}
|
|
2095
|
-
/**
|
|
2096
|
-
True when the token after the mapped position was deleted.
|
|
2097
|
-
*/
|
|
2098
|
-
get deletedAfter() {
|
|
2099
|
-
return (this.delInfo & (DEL_AFTER | DEL_ACROSS)) > 0;
|
|
2100
|
-
}
|
|
2101
|
-
/**
|
|
2102
|
-
Tells whether any of the steps mapped through deletes across the
|
|
2103
|
-
position (including both the token before and after the
|
|
2104
|
-
position).
|
|
2105
|
-
*/
|
|
2106
|
-
get deletedAcross() {
|
|
2107
|
-
return (this.delInfo & DEL_ACROSS) > 0;
|
|
2108
|
-
}
|
|
2109
|
-
};
|
|
2110
|
-
var StepMap = class _StepMap {
|
|
2111
|
-
/**
|
|
2112
|
-
Create a position map. The modifications to the document are
|
|
2113
|
-
represented as an array of numbers, in which each group of three
|
|
2114
|
-
represents a modified chunk as `[start, oldSize, newSize]`.
|
|
2115
|
-
*/
|
|
2116
|
-
constructor(ranges, inverted = false) {
|
|
2117
|
-
this.ranges = ranges;
|
|
2118
|
-
this.inverted = inverted;
|
|
2119
|
-
if (!ranges.length && _StepMap.empty)
|
|
2120
|
-
return _StepMap.empty;
|
|
2121
|
-
}
|
|
2122
|
-
/**
|
|
2123
|
-
@internal
|
|
2124
|
-
*/
|
|
2125
|
-
recover(value) {
|
|
2126
|
-
let diff = 0, index = recoverIndex(value);
|
|
2127
|
-
if (!this.inverted)
|
|
2128
|
-
for (let i = 0; i < index; i++)
|
|
2129
|
-
diff += this.ranges[i * 3 + 2] - this.ranges[i * 3 + 1];
|
|
2130
|
-
return this.ranges[index * 3] + diff + recoverOffset(value);
|
|
2131
|
-
}
|
|
2132
|
-
mapResult(pos, assoc = 1) {
|
|
2133
|
-
return this._map(pos, assoc, false);
|
|
2134
|
-
}
|
|
2135
|
-
map(pos, assoc = 1) {
|
|
2136
|
-
return this._map(pos, assoc, true);
|
|
2137
|
-
}
|
|
2138
|
-
/**
|
|
2139
|
-
@internal
|
|
2140
|
-
*/
|
|
2141
|
-
_map(pos, assoc, simple) {
|
|
2142
|
-
let diff = 0, oldIndex = this.inverted ? 2 : 1, newIndex = this.inverted ? 1 : 2;
|
|
2143
|
-
for (let i = 0; i < this.ranges.length; i += 3) {
|
|
2144
|
-
let start = this.ranges[i] - (this.inverted ? diff : 0);
|
|
2145
|
-
if (start > pos)
|
|
2146
|
-
break;
|
|
2147
|
-
let oldSize = this.ranges[i + oldIndex], newSize = this.ranges[i + newIndex], end = start + oldSize;
|
|
2148
|
-
if (pos <= end) {
|
|
2149
|
-
let side = !oldSize ? assoc : pos == start ? -1 : pos == end ? 1 : assoc;
|
|
2150
|
-
let result = start + diff + (side < 0 ? 0 : newSize);
|
|
2151
|
-
if (simple)
|
|
2152
|
-
return result;
|
|
2153
|
-
let recover = pos == (assoc < 0 ? start : end) ? null : makeRecover(i / 3, pos - start);
|
|
2154
|
-
let del = pos == start ? DEL_AFTER : pos == end ? DEL_BEFORE : DEL_ACROSS;
|
|
2155
|
-
if (assoc < 0 ? pos != start : pos != end)
|
|
2156
|
-
del |= DEL_SIDE;
|
|
2157
|
-
return new MapResult(result, del, recover);
|
|
2158
|
-
}
|
|
2159
|
-
diff += newSize - oldSize;
|
|
2160
|
-
}
|
|
2161
|
-
return simple ? pos + diff : new MapResult(pos + diff, 0, null);
|
|
2162
|
-
}
|
|
2163
|
-
/**
|
|
2164
|
-
@internal
|
|
2165
|
-
*/
|
|
2166
|
-
touches(pos, recover) {
|
|
2167
|
-
let diff = 0, index = recoverIndex(recover);
|
|
2168
|
-
let oldIndex = this.inverted ? 2 : 1, newIndex = this.inverted ? 1 : 2;
|
|
2169
|
-
for (let i = 0; i < this.ranges.length; i += 3) {
|
|
2170
|
-
let start = this.ranges[i] - (this.inverted ? diff : 0);
|
|
2171
|
-
if (start > pos)
|
|
2172
|
-
break;
|
|
2173
|
-
let oldSize = this.ranges[i + oldIndex], end = start + oldSize;
|
|
2174
|
-
if (pos <= end && i == index * 3)
|
|
2175
|
-
return true;
|
|
2176
|
-
diff += this.ranges[i + newIndex] - oldSize;
|
|
2177
|
-
}
|
|
2178
|
-
return false;
|
|
2179
|
-
}
|
|
2180
|
-
/**
|
|
2181
|
-
Calls the given function on each of the changed ranges included in
|
|
2182
|
-
this map.
|
|
2183
|
-
*/
|
|
2184
|
-
forEach(f) {
|
|
2185
|
-
let oldIndex = this.inverted ? 2 : 1, newIndex = this.inverted ? 1 : 2;
|
|
2186
|
-
for (let i = 0, diff = 0; i < this.ranges.length; i += 3) {
|
|
2187
|
-
let start = this.ranges[i], oldStart = start - (this.inverted ? diff : 0), newStart = start + (this.inverted ? 0 : diff);
|
|
2188
|
-
let oldSize = this.ranges[i + oldIndex], newSize = this.ranges[i + newIndex];
|
|
2189
|
-
f(oldStart, oldStart + oldSize, newStart, newStart + newSize);
|
|
2190
|
-
diff += newSize - oldSize;
|
|
2191
|
-
}
|
|
2192
|
-
}
|
|
2193
|
-
/**
|
|
2194
|
-
Create an inverted version of this map. The result can be used to
|
|
2195
|
-
map positions in the post-step document to the pre-step document.
|
|
2196
|
-
*/
|
|
2197
|
-
invert() {
|
|
2198
|
-
return new _StepMap(this.ranges, !this.inverted);
|
|
2199
|
-
}
|
|
2200
|
-
/**
|
|
2201
|
-
@internal
|
|
2202
|
-
*/
|
|
2203
|
-
toString() {
|
|
2204
|
-
return (this.inverted ? "-" : "") + JSON.stringify(this.ranges);
|
|
2205
|
-
}
|
|
2206
|
-
/**
|
|
2207
|
-
Create a map that moves all positions by offset `n` (which may be
|
|
2208
|
-
negative). This can be useful when applying steps meant for a
|
|
2209
|
-
sub-document to a larger document, or vice-versa.
|
|
2210
|
-
*/
|
|
2211
|
-
static offset(n) {
|
|
2212
|
-
return n == 0 ? _StepMap.empty : new _StepMap(n < 0 ? [0, -n, 0] : [0, 0, n]);
|
|
2213
|
-
}
|
|
2214
|
-
};
|
|
2215
|
-
StepMap.empty = new StepMap([]);
|
|
2216
|
-
var stepsByID = /* @__PURE__ */ Object.create(null);
|
|
2217
|
-
var Step = class {
|
|
2218
|
-
/**
|
|
2219
|
-
Get the step map that represents the changes made by this step,
|
|
2220
|
-
and which can be used to transform between positions in the old
|
|
2221
|
-
and the new document.
|
|
2222
|
-
*/
|
|
2223
|
-
getMap() {
|
|
2224
|
-
return StepMap.empty;
|
|
2225
|
-
}
|
|
2226
|
-
/**
|
|
2227
|
-
Try to merge this step with another one, to be applied directly
|
|
2228
|
-
after it. Returns the merged step when possible, null if the
|
|
2229
|
-
steps can't be merged.
|
|
2230
|
-
*/
|
|
2231
|
-
merge(other) {
|
|
2232
|
-
return null;
|
|
2233
|
-
}
|
|
2234
|
-
/**
|
|
2235
|
-
Deserialize a step from its JSON representation. Will call
|
|
2236
|
-
through to the step class' own implementation of this method.
|
|
2237
|
-
*/
|
|
2238
|
-
static fromJSON(schema, json) {
|
|
2239
|
-
if (!json || !json.stepType)
|
|
2240
|
-
throw new RangeError("Invalid input for Step.fromJSON");
|
|
2241
|
-
let type = stepsByID[json.stepType];
|
|
2242
|
-
if (!type)
|
|
2243
|
-
throw new RangeError(`No step type ${json.stepType} defined`);
|
|
2244
|
-
return type.fromJSON(schema, json);
|
|
2245
|
-
}
|
|
2246
|
-
/**
|
|
2247
|
-
To be able to serialize steps to JSON, each step needs a string
|
|
2248
|
-
ID to attach to its JSON representation. Use this method to
|
|
2249
|
-
register an ID for your step classes. Try to pick something
|
|
2250
|
-
that's unlikely to clash with steps from other modules.
|
|
2251
|
-
*/
|
|
2252
|
-
static jsonID(id, stepClass) {
|
|
2253
|
-
if (id in stepsByID)
|
|
2254
|
-
throw new RangeError("Duplicate use of step JSON ID " + id);
|
|
2255
|
-
stepsByID[id] = stepClass;
|
|
2256
|
-
stepClass.prototype.jsonID = id;
|
|
2257
|
-
return stepClass;
|
|
2258
|
-
}
|
|
2259
|
-
};
|
|
2260
|
-
var StepResult = class _StepResult {
|
|
2261
|
-
/**
|
|
2262
|
-
@internal
|
|
2263
|
-
*/
|
|
2264
|
-
constructor(doc3, failed) {
|
|
2265
|
-
this.doc = doc3;
|
|
2266
|
-
this.failed = failed;
|
|
2267
|
-
}
|
|
2268
|
-
/**
|
|
2269
|
-
Create a successful step result.
|
|
2270
|
-
*/
|
|
2271
|
-
static ok(doc3) {
|
|
2272
|
-
return new _StepResult(doc3, null);
|
|
2273
|
-
}
|
|
2274
|
-
/**
|
|
2275
|
-
Create a failed step result.
|
|
2276
|
-
*/
|
|
2277
|
-
static fail(message) {
|
|
2278
|
-
return new _StepResult(null, message);
|
|
2279
|
-
}
|
|
2280
|
-
/**
|
|
2281
|
-
Call [`Node.replace`](https://prosemirror.net/docs/ref/#model.Node.replace) with the given
|
|
2282
|
-
arguments. Create a successful result if it succeeds, and a
|
|
2283
|
-
failed one if it throws a `ReplaceError`.
|
|
2284
|
-
*/
|
|
2285
|
-
static fromReplace(doc3, from, to, slice) {
|
|
2286
|
-
try {
|
|
2287
|
-
return _StepResult.ok(doc3.replace(from, to, slice));
|
|
2288
|
-
} catch (e) {
|
|
2289
|
-
if (e instanceof ReplaceError)
|
|
2290
|
-
return _StepResult.fail(e.message);
|
|
2291
|
-
throw e;
|
|
2292
|
-
}
|
|
2293
|
-
}
|
|
2294
|
-
};
|
|
2295
|
-
function mapFragment(fragment, f, parent) {
|
|
2296
|
-
let mapped = [];
|
|
2297
|
-
for (let i = 0; i < fragment.childCount; i++) {
|
|
2298
|
-
let child = fragment.child(i);
|
|
2299
|
-
if (child.content.size)
|
|
2300
|
-
child = child.copy(mapFragment(child.content, f, child));
|
|
2301
|
-
if (child.isInline)
|
|
2302
|
-
child = f(child, parent, i);
|
|
2303
|
-
mapped.push(child);
|
|
2304
|
-
}
|
|
2305
|
-
return Fragment.fromArray(mapped);
|
|
2306
|
-
}
|
|
2307
|
-
var AddMarkStep = class _AddMarkStep extends Step {
|
|
2308
|
-
/**
|
|
2309
|
-
Create a mark step.
|
|
2310
|
-
*/
|
|
2311
|
-
constructor(from, to, mark) {
|
|
2312
|
-
super();
|
|
2313
|
-
this.from = from;
|
|
2314
|
-
this.to = to;
|
|
2315
|
-
this.mark = mark;
|
|
2316
|
-
}
|
|
2317
|
-
apply(doc3) {
|
|
2318
|
-
let oldSlice = doc3.slice(this.from, this.to), $from = doc3.resolve(this.from);
|
|
2319
|
-
let parent = $from.node($from.sharedDepth(this.to));
|
|
2320
|
-
let slice = new Slice(mapFragment(oldSlice.content, (node, parent2) => {
|
|
2321
|
-
if (!node.isAtom || !parent2.type.allowsMarkType(this.mark.type))
|
|
2322
|
-
return node;
|
|
2323
|
-
return node.mark(this.mark.addToSet(node.marks));
|
|
2324
|
-
}, parent), oldSlice.openStart, oldSlice.openEnd);
|
|
2325
|
-
return StepResult.fromReplace(doc3, this.from, this.to, slice);
|
|
2326
|
-
}
|
|
2327
|
-
invert() {
|
|
2328
|
-
return new RemoveMarkStep(this.from, this.to, this.mark);
|
|
2329
|
-
}
|
|
2330
|
-
map(mapping) {
|
|
2331
|
-
let from = mapping.mapResult(this.from, 1), to = mapping.mapResult(this.to, -1);
|
|
2332
|
-
if (from.deleted && to.deleted || from.pos >= to.pos)
|
|
2333
|
-
return null;
|
|
2334
|
-
return new _AddMarkStep(from.pos, to.pos, this.mark);
|
|
2335
|
-
}
|
|
2336
|
-
merge(other) {
|
|
2337
|
-
if (other instanceof _AddMarkStep && other.mark.eq(this.mark) && this.from <= other.to && this.to >= other.from)
|
|
2338
|
-
return new _AddMarkStep(Math.min(this.from, other.from), Math.max(this.to, other.to), this.mark);
|
|
2339
|
-
return null;
|
|
2340
|
-
}
|
|
2341
|
-
toJSON() {
|
|
2342
|
-
return {
|
|
2343
|
-
stepType: "addMark",
|
|
2344
|
-
mark: this.mark.toJSON(),
|
|
2345
|
-
from: this.from,
|
|
2346
|
-
to: this.to
|
|
2347
|
-
};
|
|
2348
|
-
}
|
|
2349
|
-
/**
|
|
2350
|
-
@internal
|
|
2351
|
-
*/
|
|
2352
|
-
static fromJSON(schema, json) {
|
|
2353
|
-
if (typeof json.from != "number" || typeof json.to != "number")
|
|
2354
|
-
throw new RangeError("Invalid input for AddMarkStep.fromJSON");
|
|
2355
|
-
return new _AddMarkStep(json.from, json.to, schema.markFromJSON(json.mark));
|
|
2356
|
-
}
|
|
2357
|
-
};
|
|
2358
|
-
Step.jsonID("addMark", AddMarkStep);
|
|
2359
|
-
var RemoveMarkStep = class _RemoveMarkStep extends Step {
|
|
2360
|
-
/**
|
|
2361
|
-
Create a mark-removing step.
|
|
2362
|
-
*/
|
|
2363
|
-
constructor(from, to, mark) {
|
|
2364
|
-
super();
|
|
2365
|
-
this.from = from;
|
|
2366
|
-
this.to = to;
|
|
2367
|
-
this.mark = mark;
|
|
2368
|
-
}
|
|
2369
|
-
apply(doc3) {
|
|
2370
|
-
let oldSlice = doc3.slice(this.from, this.to);
|
|
2371
|
-
let slice = new Slice(mapFragment(oldSlice.content, (node) => {
|
|
2372
|
-
return node.mark(this.mark.removeFromSet(node.marks));
|
|
2373
|
-
}, doc3), oldSlice.openStart, oldSlice.openEnd);
|
|
2374
|
-
return StepResult.fromReplace(doc3, this.from, this.to, slice);
|
|
2375
|
-
}
|
|
2376
|
-
invert() {
|
|
2377
|
-
return new AddMarkStep(this.from, this.to, this.mark);
|
|
2378
|
-
}
|
|
2379
|
-
map(mapping) {
|
|
2380
|
-
let from = mapping.mapResult(this.from, 1), to = mapping.mapResult(this.to, -1);
|
|
2381
|
-
if (from.deleted && to.deleted || from.pos >= to.pos)
|
|
2382
|
-
return null;
|
|
2383
|
-
return new _RemoveMarkStep(from.pos, to.pos, this.mark);
|
|
2384
|
-
}
|
|
2385
|
-
merge(other) {
|
|
2386
|
-
if (other instanceof _RemoveMarkStep && other.mark.eq(this.mark) && this.from <= other.to && this.to >= other.from)
|
|
2387
|
-
return new _RemoveMarkStep(Math.min(this.from, other.from), Math.max(this.to, other.to), this.mark);
|
|
2388
|
-
return null;
|
|
2389
|
-
}
|
|
2390
|
-
toJSON() {
|
|
2391
|
-
return {
|
|
2392
|
-
stepType: "removeMark",
|
|
2393
|
-
mark: this.mark.toJSON(),
|
|
2394
|
-
from: this.from,
|
|
2395
|
-
to: this.to
|
|
2396
|
-
};
|
|
2397
|
-
}
|
|
2398
|
-
/**
|
|
2399
|
-
@internal
|
|
2400
|
-
*/
|
|
2401
|
-
static fromJSON(schema, json) {
|
|
2402
|
-
if (typeof json.from != "number" || typeof json.to != "number")
|
|
2403
|
-
throw new RangeError("Invalid input for RemoveMarkStep.fromJSON");
|
|
2404
|
-
return new _RemoveMarkStep(json.from, json.to, schema.markFromJSON(json.mark));
|
|
2405
|
-
}
|
|
2406
|
-
};
|
|
2407
|
-
Step.jsonID("removeMark", RemoveMarkStep);
|
|
2408
|
-
var AddNodeMarkStep = class _AddNodeMarkStep extends Step {
|
|
2409
|
-
/**
|
|
2410
|
-
Create a node mark step.
|
|
2411
|
-
*/
|
|
2412
|
-
constructor(pos, mark) {
|
|
2413
|
-
super();
|
|
2414
|
-
this.pos = pos;
|
|
2415
|
-
this.mark = mark;
|
|
2416
|
-
}
|
|
2417
|
-
apply(doc3) {
|
|
2418
|
-
let node = doc3.nodeAt(this.pos);
|
|
2419
|
-
if (!node)
|
|
2420
|
-
return StepResult.fail("No node at mark step's position");
|
|
2421
|
-
let updated = node.type.create(node.attrs, null, this.mark.addToSet(node.marks));
|
|
2422
|
-
return StepResult.fromReplace(doc3, this.pos, this.pos + 1, new Slice(Fragment.from(updated), 0, node.isLeaf ? 0 : 1));
|
|
2423
|
-
}
|
|
2424
|
-
invert(doc3) {
|
|
2425
|
-
let node = doc3.nodeAt(this.pos);
|
|
2426
|
-
if (node) {
|
|
2427
|
-
let newSet = this.mark.addToSet(node.marks);
|
|
2428
|
-
if (newSet.length == node.marks.length) {
|
|
2429
|
-
for (let i = 0; i < node.marks.length; i++)
|
|
2430
|
-
if (!node.marks[i].isInSet(newSet))
|
|
2431
|
-
return new _AddNodeMarkStep(this.pos, node.marks[i]);
|
|
2432
|
-
return new _AddNodeMarkStep(this.pos, this.mark);
|
|
2433
|
-
}
|
|
2434
|
-
}
|
|
2435
|
-
return new RemoveNodeMarkStep(this.pos, this.mark);
|
|
2436
|
-
}
|
|
2437
|
-
map(mapping) {
|
|
2438
|
-
let pos = mapping.mapResult(this.pos, 1);
|
|
2439
|
-
return pos.deletedAfter ? null : new _AddNodeMarkStep(pos.pos, this.mark);
|
|
2440
|
-
}
|
|
2441
|
-
toJSON() {
|
|
2442
|
-
return { stepType: "addNodeMark", pos: this.pos, mark: this.mark.toJSON() };
|
|
2443
|
-
}
|
|
2444
|
-
/**
|
|
2445
|
-
@internal
|
|
2446
|
-
*/
|
|
2447
|
-
static fromJSON(schema, json) {
|
|
2448
|
-
if (typeof json.pos != "number")
|
|
2449
|
-
throw new RangeError("Invalid input for AddNodeMarkStep.fromJSON");
|
|
2450
|
-
return new _AddNodeMarkStep(json.pos, schema.markFromJSON(json.mark));
|
|
2451
|
-
}
|
|
2452
|
-
};
|
|
2453
|
-
Step.jsonID("addNodeMark", AddNodeMarkStep);
|
|
2454
|
-
var RemoveNodeMarkStep = class _RemoveNodeMarkStep extends Step {
|
|
2455
|
-
/**
|
|
2456
|
-
Create a mark-removing step.
|
|
2457
|
-
*/
|
|
2458
|
-
constructor(pos, mark) {
|
|
2459
|
-
super();
|
|
2460
|
-
this.pos = pos;
|
|
2461
|
-
this.mark = mark;
|
|
2462
|
-
}
|
|
2463
|
-
apply(doc3) {
|
|
2464
|
-
let node = doc3.nodeAt(this.pos);
|
|
2465
|
-
if (!node)
|
|
2466
|
-
return StepResult.fail("No node at mark step's position");
|
|
2467
|
-
let updated = node.type.create(node.attrs, null, this.mark.removeFromSet(node.marks));
|
|
2468
|
-
return StepResult.fromReplace(doc3, this.pos, this.pos + 1, new Slice(Fragment.from(updated), 0, node.isLeaf ? 0 : 1));
|
|
2469
|
-
}
|
|
2470
|
-
invert(doc3) {
|
|
2471
|
-
let node = doc3.nodeAt(this.pos);
|
|
2472
|
-
if (!node || !this.mark.isInSet(node.marks))
|
|
2473
|
-
return this;
|
|
2474
|
-
return new AddNodeMarkStep(this.pos, this.mark);
|
|
2475
|
-
}
|
|
2476
|
-
map(mapping) {
|
|
2477
|
-
let pos = mapping.mapResult(this.pos, 1);
|
|
2478
|
-
return pos.deletedAfter ? null : new _RemoveNodeMarkStep(pos.pos, this.mark);
|
|
2479
|
-
}
|
|
2480
|
-
toJSON() {
|
|
2481
|
-
return { stepType: "removeNodeMark", pos: this.pos, mark: this.mark.toJSON() };
|
|
2482
|
-
}
|
|
2483
|
-
/**
|
|
2484
|
-
@internal
|
|
2485
|
-
*/
|
|
2486
|
-
static fromJSON(schema, json) {
|
|
2487
|
-
if (typeof json.pos != "number")
|
|
2488
|
-
throw new RangeError("Invalid input for RemoveNodeMarkStep.fromJSON");
|
|
2489
|
-
return new _RemoveNodeMarkStep(json.pos, schema.markFromJSON(json.mark));
|
|
2490
|
-
}
|
|
2491
|
-
};
|
|
2492
|
-
Step.jsonID("removeNodeMark", RemoveNodeMarkStep);
|
|
2493
|
-
var ReplaceStep = class _ReplaceStep extends Step {
|
|
2494
|
-
/**
|
|
2495
|
-
The given `slice` should fit the 'gap' between `from` and
|
|
2496
|
-
`to`—the depths must line up, and the surrounding nodes must be
|
|
2497
|
-
able to be joined with the open sides of the slice. When
|
|
2498
|
-
`structure` is true, the step will fail if the content between
|
|
2499
|
-
from and to is not just a sequence of closing and then opening
|
|
2500
|
-
tokens (this is to guard against rebased replace steps
|
|
2501
|
-
overwriting something they weren't supposed to).
|
|
2502
|
-
*/
|
|
2503
|
-
constructor(from, to, slice, structure = false) {
|
|
2504
|
-
super();
|
|
2505
|
-
this.from = from;
|
|
2506
|
-
this.to = to;
|
|
2507
|
-
this.slice = slice;
|
|
2508
|
-
this.structure = structure;
|
|
2509
|
-
}
|
|
2510
|
-
apply(doc3) {
|
|
2511
|
-
if (this.structure && contentBetween(doc3, this.from, this.to))
|
|
2512
|
-
return StepResult.fail("Structure replace would overwrite content");
|
|
2513
|
-
return StepResult.fromReplace(doc3, this.from, this.to, this.slice);
|
|
2514
|
-
}
|
|
2515
|
-
getMap() {
|
|
2516
|
-
return new StepMap([this.from, this.to - this.from, this.slice.size]);
|
|
2517
|
-
}
|
|
2518
|
-
invert(doc3) {
|
|
2519
|
-
return new _ReplaceStep(this.from, this.from + this.slice.size, doc3.slice(this.from, this.to));
|
|
2520
|
-
}
|
|
2521
|
-
map(mapping) {
|
|
2522
|
-
let from = mapping.mapResult(this.from, 1), to = mapping.mapResult(this.to, -1);
|
|
2523
|
-
if (from.deletedAcross && to.deletedAcross)
|
|
2524
|
-
return null;
|
|
2525
|
-
return new _ReplaceStep(from.pos, Math.max(from.pos, to.pos), this.slice, this.structure);
|
|
2526
|
-
}
|
|
2527
|
-
merge(other) {
|
|
2528
|
-
if (!(other instanceof _ReplaceStep) || other.structure || this.structure)
|
|
2529
|
-
return null;
|
|
2530
|
-
if (this.from + this.slice.size == other.from && !this.slice.openEnd && !other.slice.openStart) {
|
|
2531
|
-
let slice = this.slice.size + other.slice.size == 0 ? Slice.empty : new Slice(this.slice.content.append(other.slice.content), this.slice.openStart, other.slice.openEnd);
|
|
2532
|
-
return new _ReplaceStep(this.from, this.to + (other.to - other.from), slice, this.structure);
|
|
2533
|
-
} else if (other.to == this.from && !this.slice.openStart && !other.slice.openEnd) {
|
|
2534
|
-
let slice = this.slice.size + other.slice.size == 0 ? Slice.empty : new Slice(other.slice.content.append(this.slice.content), other.slice.openStart, this.slice.openEnd);
|
|
2535
|
-
return new _ReplaceStep(other.from, this.to, slice, this.structure);
|
|
2536
|
-
} else {
|
|
2537
|
-
return null;
|
|
2538
|
-
}
|
|
2539
|
-
}
|
|
2540
|
-
toJSON() {
|
|
2541
|
-
let json = { stepType: "replace", from: this.from, to: this.to };
|
|
2542
|
-
if (this.slice.size)
|
|
2543
|
-
json.slice = this.slice.toJSON();
|
|
2544
|
-
if (this.structure)
|
|
2545
|
-
json.structure = true;
|
|
2546
|
-
return json;
|
|
2547
|
-
}
|
|
2548
|
-
/**
|
|
2549
|
-
@internal
|
|
2550
|
-
*/
|
|
2551
|
-
static fromJSON(schema, json) {
|
|
2552
|
-
if (typeof json.from != "number" || typeof json.to != "number")
|
|
2553
|
-
throw new RangeError("Invalid input for ReplaceStep.fromJSON");
|
|
2554
|
-
return new _ReplaceStep(json.from, json.to, Slice.fromJSON(schema, json.slice), !!json.structure);
|
|
2555
|
-
}
|
|
2556
|
-
};
|
|
2557
|
-
Step.jsonID("replace", ReplaceStep);
|
|
2558
|
-
var ReplaceAroundStep = class _ReplaceAroundStep extends Step {
|
|
2559
|
-
/**
|
|
2560
|
-
Create a replace-around step with the given range and gap.
|
|
2561
|
-
`insert` should be the point in the slice into which the content
|
|
2562
|
-
of the gap should be moved. `structure` has the same meaning as
|
|
2563
|
-
it has in the [`ReplaceStep`](https://prosemirror.net/docs/ref/#transform.ReplaceStep) class.
|
|
2564
|
-
*/
|
|
2565
|
-
constructor(from, to, gapFrom, gapTo, slice, insert, structure = false) {
|
|
2566
|
-
super();
|
|
2567
|
-
this.from = from;
|
|
2568
|
-
this.to = to;
|
|
2569
|
-
this.gapFrom = gapFrom;
|
|
2570
|
-
this.gapTo = gapTo;
|
|
2571
|
-
this.slice = slice;
|
|
2572
|
-
this.insert = insert;
|
|
2573
|
-
this.structure = structure;
|
|
2574
|
-
}
|
|
2575
|
-
apply(doc3) {
|
|
2576
|
-
if (this.structure && (contentBetween(doc3, this.from, this.gapFrom) || contentBetween(doc3, this.gapTo, this.to)))
|
|
2577
|
-
return StepResult.fail("Structure gap-replace would overwrite content");
|
|
2578
|
-
let gap = doc3.slice(this.gapFrom, this.gapTo);
|
|
2579
|
-
if (gap.openStart || gap.openEnd)
|
|
2580
|
-
return StepResult.fail("Gap is not a flat range");
|
|
2581
|
-
let inserted = this.slice.insertAt(this.insert, gap.content);
|
|
2582
|
-
if (!inserted)
|
|
2583
|
-
return StepResult.fail("Content does not fit in gap");
|
|
2584
|
-
return StepResult.fromReplace(doc3, this.from, this.to, inserted);
|
|
2585
|
-
}
|
|
2586
|
-
getMap() {
|
|
2587
|
-
return new StepMap([
|
|
2588
|
-
this.from,
|
|
2589
|
-
this.gapFrom - this.from,
|
|
2590
|
-
this.insert,
|
|
2591
|
-
this.gapTo,
|
|
2592
|
-
this.to - this.gapTo,
|
|
2593
|
-
this.slice.size - this.insert
|
|
2594
|
-
]);
|
|
2595
|
-
}
|
|
2596
|
-
invert(doc3) {
|
|
2597
|
-
let gap = this.gapTo - this.gapFrom;
|
|
2598
|
-
return new _ReplaceAroundStep(this.from, this.from + this.slice.size + gap, this.from + this.insert, this.from + this.insert + gap, doc3.slice(this.from, this.to).removeBetween(this.gapFrom - this.from, this.gapTo - this.from), this.gapFrom - this.from, this.structure);
|
|
2599
|
-
}
|
|
2600
|
-
map(mapping) {
|
|
2601
|
-
let from = mapping.mapResult(this.from, 1), to = mapping.mapResult(this.to, -1);
|
|
2602
|
-
let gapFrom = this.from == this.gapFrom ? from.pos : mapping.map(this.gapFrom, -1);
|
|
2603
|
-
let gapTo = this.to == this.gapTo ? to.pos : mapping.map(this.gapTo, 1);
|
|
2604
|
-
if (from.deletedAcross && to.deletedAcross || gapFrom < from.pos || gapTo > to.pos)
|
|
2605
|
-
return null;
|
|
2606
|
-
return new _ReplaceAroundStep(from.pos, to.pos, gapFrom, gapTo, this.slice, this.insert, this.structure);
|
|
2607
|
-
}
|
|
2608
|
-
toJSON() {
|
|
2609
|
-
let json = {
|
|
2610
|
-
stepType: "replaceAround",
|
|
2611
|
-
from: this.from,
|
|
2612
|
-
to: this.to,
|
|
2613
|
-
gapFrom: this.gapFrom,
|
|
2614
|
-
gapTo: this.gapTo,
|
|
2615
|
-
insert: this.insert
|
|
2616
|
-
};
|
|
2617
|
-
if (this.slice.size)
|
|
2618
|
-
json.slice = this.slice.toJSON();
|
|
2619
|
-
if (this.structure)
|
|
2620
|
-
json.structure = true;
|
|
2621
|
-
return json;
|
|
2622
|
-
}
|
|
2623
|
-
/**
|
|
2624
|
-
@internal
|
|
2625
|
-
*/
|
|
2626
|
-
static fromJSON(schema, json) {
|
|
2627
|
-
if (typeof json.from != "number" || typeof json.to != "number" || typeof json.gapFrom != "number" || typeof json.gapTo != "number" || typeof json.insert != "number")
|
|
2628
|
-
throw new RangeError("Invalid input for ReplaceAroundStep.fromJSON");
|
|
2629
|
-
return new _ReplaceAroundStep(json.from, json.to, json.gapFrom, json.gapTo, Slice.fromJSON(schema, json.slice), json.insert, !!json.structure);
|
|
2630
|
-
}
|
|
2631
|
-
};
|
|
2632
|
-
Step.jsonID("replaceAround", ReplaceAroundStep);
|
|
2633
|
-
function contentBetween(doc3, from, to) {
|
|
2634
|
-
let $from = doc3.resolve(from), dist = to - from, depth = $from.depth;
|
|
2635
|
-
while (dist > 0 && depth > 0 && $from.indexAfter(depth) == $from.node(depth).childCount) {
|
|
2636
|
-
depth--;
|
|
2637
|
-
dist--;
|
|
2638
|
-
}
|
|
2639
|
-
if (dist > 0) {
|
|
2640
|
-
let next = $from.node(depth).maybeChild($from.indexAfter(depth));
|
|
2641
|
-
while (dist > 0) {
|
|
2642
|
-
if (!next || next.isLeaf)
|
|
2643
|
-
return true;
|
|
2644
|
-
next = next.firstChild;
|
|
2645
|
-
dist--;
|
|
2646
|
-
}
|
|
2647
|
-
}
|
|
2648
|
-
return false;
|
|
2649
|
-
}
|
|
2650
|
-
function dropPoint(doc3, pos, slice) {
|
|
2651
|
-
let $pos = doc3.resolve(pos);
|
|
2652
|
-
if (!slice.content.size)
|
|
2653
|
-
return pos;
|
|
2654
|
-
let content = slice.content;
|
|
2655
|
-
for (let i = 0; i < slice.openStart; i++)
|
|
2656
|
-
content = content.firstChild.content;
|
|
2657
|
-
for (let pass = 1; pass <= (slice.openStart == 0 && slice.size ? 2 : 1); pass++) {
|
|
2658
|
-
for (let d = $pos.depth; d >= 0; d--) {
|
|
2659
|
-
let bias = d == $pos.depth ? 0 : $pos.pos <= ($pos.start(d + 1) + $pos.end(d + 1)) / 2 ? -1 : 1;
|
|
2660
|
-
let insertPos = $pos.index(d) + (bias > 0 ? 1 : 0);
|
|
2661
|
-
let parent = $pos.node(d), fits = false;
|
|
2662
|
-
if (pass == 1) {
|
|
2663
|
-
fits = parent.canReplace(insertPos, insertPos, content);
|
|
2664
|
-
} else {
|
|
2665
|
-
let wrapping = parent.contentMatchAt(insertPos).findWrapping(content.firstChild.type);
|
|
2666
|
-
fits = wrapping && parent.canReplaceWith(insertPos, insertPos, wrapping[0]);
|
|
2667
|
-
}
|
|
2668
|
-
if (fits)
|
|
2669
|
-
return bias == 0 ? $pos.pos : bias < 0 ? $pos.before(d + 1) : $pos.after(d + 1);
|
|
2670
|
-
}
|
|
2671
|
-
}
|
|
2672
|
-
return null;
|
|
2673
|
-
}
|
|
2674
|
-
var AttrStep = class _AttrStep extends Step {
|
|
2675
|
-
/**
|
|
2676
|
-
Construct an attribute step.
|
|
2677
|
-
*/
|
|
2678
|
-
constructor(pos, attr, value) {
|
|
2679
|
-
super();
|
|
2680
|
-
this.pos = pos;
|
|
2681
|
-
this.attr = attr;
|
|
2682
|
-
this.value = value;
|
|
2683
|
-
}
|
|
2684
|
-
apply(doc3) {
|
|
2685
|
-
let node = doc3.nodeAt(this.pos);
|
|
2686
|
-
if (!node)
|
|
2687
|
-
return StepResult.fail("No node at attribute step's position");
|
|
2688
|
-
let attrs = /* @__PURE__ */ Object.create(null);
|
|
2689
|
-
for (let name in node.attrs)
|
|
2690
|
-
attrs[name] = node.attrs[name];
|
|
2691
|
-
attrs[this.attr] = this.value;
|
|
2692
|
-
let updated = node.type.create(attrs, null, node.marks);
|
|
2693
|
-
return StepResult.fromReplace(doc3, this.pos, this.pos + 1, new Slice(Fragment.from(updated), 0, node.isLeaf ? 0 : 1));
|
|
2694
|
-
}
|
|
2695
|
-
getMap() {
|
|
2696
|
-
return StepMap.empty;
|
|
2697
|
-
}
|
|
2698
|
-
invert(doc3) {
|
|
2699
|
-
return new _AttrStep(this.pos, this.attr, doc3.nodeAt(this.pos).attrs[this.attr]);
|
|
2700
|
-
}
|
|
2701
|
-
map(mapping) {
|
|
2702
|
-
let pos = mapping.mapResult(this.pos, 1);
|
|
2703
|
-
return pos.deletedAfter ? null : new _AttrStep(pos.pos, this.attr, this.value);
|
|
2704
|
-
}
|
|
2705
|
-
toJSON() {
|
|
2706
|
-
return { stepType: "attr", pos: this.pos, attr: this.attr, value: this.value };
|
|
2707
|
-
}
|
|
2708
|
-
static fromJSON(schema, json) {
|
|
2709
|
-
if (typeof json.pos != "number" || typeof json.attr != "string")
|
|
2710
|
-
throw new RangeError("Invalid input for AttrStep.fromJSON");
|
|
2711
|
-
return new _AttrStep(json.pos, json.attr, json.value);
|
|
2712
|
-
}
|
|
2713
|
-
};
|
|
2714
|
-
Step.jsonID("attr", AttrStep);
|
|
2715
|
-
var DocAttrStep = class _DocAttrStep extends Step {
|
|
2716
|
-
/**
|
|
2717
|
-
Construct an attribute step.
|
|
2718
|
-
*/
|
|
2719
|
-
constructor(attr, value) {
|
|
2720
|
-
super();
|
|
2721
|
-
this.attr = attr;
|
|
2722
|
-
this.value = value;
|
|
2723
|
-
}
|
|
2724
|
-
apply(doc3) {
|
|
2725
|
-
let attrs = /* @__PURE__ */ Object.create(null);
|
|
2726
|
-
for (let name in doc3.attrs)
|
|
2727
|
-
attrs[name] = doc3.attrs[name];
|
|
2728
|
-
attrs[this.attr] = this.value;
|
|
2729
|
-
let updated = doc3.type.create(attrs, doc3.content, doc3.marks);
|
|
2730
|
-
return StepResult.ok(updated);
|
|
2731
|
-
}
|
|
2732
|
-
getMap() {
|
|
2733
|
-
return StepMap.empty;
|
|
2734
|
-
}
|
|
2735
|
-
invert(doc3) {
|
|
2736
|
-
return new _DocAttrStep(this.attr, doc3.attrs[this.attr]);
|
|
2737
|
-
}
|
|
2738
|
-
map(mapping) {
|
|
2739
|
-
return this;
|
|
2740
|
-
}
|
|
2741
|
-
toJSON() {
|
|
2742
|
-
return { stepType: "docAttr", attr: this.attr, value: this.value };
|
|
2743
|
-
}
|
|
2744
|
-
static fromJSON(schema, json) {
|
|
2745
|
-
if (typeof json.attr != "string")
|
|
2746
|
-
throw new RangeError("Invalid input for DocAttrStep.fromJSON");
|
|
2747
|
-
return new _DocAttrStep(json.attr, json.value);
|
|
2748
|
-
}
|
|
2749
|
-
};
|
|
2750
|
-
Step.jsonID("docAttr", DocAttrStep);
|
|
2751
|
-
var TransformError = class extends Error {
|
|
2752
|
-
};
|
|
2753
|
-
TransformError = function TransformError2(message) {
|
|
2754
|
-
let err = Error.call(this, message);
|
|
2755
|
-
err.__proto__ = TransformError2.prototype;
|
|
2756
|
-
return err;
|
|
2757
|
-
};
|
|
2758
|
-
TransformError.prototype = Object.create(Error.prototype);
|
|
2759
|
-
TransformError.prototype.constructor = TransformError;
|
|
2760
|
-
TransformError.prototype.name = "TransformError";
|
|
2761
|
-
|
|
2762
|
-
// node_modules/prosemirror-state/dist/index.js
|
|
2763
|
-
var classesById = /* @__PURE__ */ Object.create(null);
|
|
2764
|
-
var Selection = class {
|
|
2765
|
-
/**
|
|
2766
|
-
Initialize a selection with the head and anchor and ranges. If no
|
|
2767
|
-
ranges are given, constructs a single range across `$anchor` and
|
|
2768
|
-
`$head`.
|
|
2769
|
-
*/
|
|
2770
|
-
constructor($anchor, $head, ranges) {
|
|
2771
|
-
this.$anchor = $anchor;
|
|
2772
|
-
this.$head = $head;
|
|
2773
|
-
this.ranges = ranges || [new SelectionRange($anchor.min($head), $anchor.max($head))];
|
|
2774
|
-
}
|
|
2775
|
-
/**
|
|
2776
|
-
The selection's anchor, as an unresolved position.
|
|
2777
|
-
*/
|
|
2778
|
-
get anchor() {
|
|
2779
|
-
return this.$anchor.pos;
|
|
2780
|
-
}
|
|
2781
|
-
/**
|
|
2782
|
-
The selection's head.
|
|
2783
|
-
*/
|
|
2784
|
-
get head() {
|
|
2785
|
-
return this.$head.pos;
|
|
2786
|
-
}
|
|
2787
|
-
/**
|
|
2788
|
-
The lower bound of the selection's main range.
|
|
2789
|
-
*/
|
|
2790
|
-
get from() {
|
|
2791
|
-
return this.$from.pos;
|
|
2792
|
-
}
|
|
2793
|
-
/**
|
|
2794
|
-
The upper bound of the selection's main range.
|
|
2795
|
-
*/
|
|
2796
|
-
get to() {
|
|
2797
|
-
return this.$to.pos;
|
|
2798
|
-
}
|
|
2799
|
-
/**
|
|
2800
|
-
The resolved lower bound of the selection's main range.
|
|
2801
|
-
*/
|
|
2802
|
-
get $from() {
|
|
2803
|
-
return this.ranges[0].$from;
|
|
2804
|
-
}
|
|
2805
|
-
/**
|
|
2806
|
-
The resolved upper bound of the selection's main range.
|
|
2807
|
-
*/
|
|
2808
|
-
get $to() {
|
|
2809
|
-
return this.ranges[0].$to;
|
|
2810
|
-
}
|
|
2811
|
-
/**
|
|
2812
|
-
Indicates whether the selection contains any content.
|
|
2813
|
-
*/
|
|
2814
|
-
get empty() {
|
|
2815
|
-
let ranges = this.ranges;
|
|
2816
|
-
for (let i = 0; i < ranges.length; i++)
|
|
2817
|
-
if (ranges[i].$from.pos != ranges[i].$to.pos)
|
|
2818
|
-
return false;
|
|
2819
|
-
return true;
|
|
2820
|
-
}
|
|
2821
|
-
/**
|
|
2822
|
-
Get the content of this selection as a slice.
|
|
2823
|
-
*/
|
|
2824
|
-
content() {
|
|
2825
|
-
return this.$from.doc.slice(this.from, this.to, true);
|
|
2826
|
-
}
|
|
2827
|
-
/**
|
|
2828
|
-
Replace the selection with a slice or, if no slice is given,
|
|
2829
|
-
delete the selection. Will append to the given transaction.
|
|
2830
|
-
*/
|
|
2831
|
-
replace(tr, content = Slice.empty) {
|
|
2832
|
-
let lastNode = content.content.lastChild, lastParent = null;
|
|
2833
|
-
for (let i = 0; i < content.openEnd; i++) {
|
|
2834
|
-
lastParent = lastNode;
|
|
2835
|
-
lastNode = lastNode.lastChild;
|
|
2836
|
-
}
|
|
2837
|
-
let mapFrom = tr.steps.length, ranges = this.ranges;
|
|
2838
|
-
for (let i = 0; i < ranges.length; i++) {
|
|
2839
|
-
let { $from, $to } = ranges[i], mapping = tr.mapping.slice(mapFrom);
|
|
2840
|
-
tr.replaceRange(mapping.map($from.pos), mapping.map($to.pos), i ? Slice.empty : content);
|
|
2841
|
-
if (i == 0)
|
|
2842
|
-
selectionToInsertionEnd(tr, mapFrom, (lastNode ? lastNode.isInline : lastParent && lastParent.isTextblock) ? -1 : 1);
|
|
2843
|
-
}
|
|
2844
|
-
}
|
|
2845
|
-
/**
|
|
2846
|
-
Replace the selection with the given node, appending the changes
|
|
2847
|
-
to the given transaction.
|
|
2848
|
-
*/
|
|
2849
|
-
replaceWith(tr, node) {
|
|
2850
|
-
let mapFrom = tr.steps.length, ranges = this.ranges;
|
|
2851
|
-
for (let i = 0; i < ranges.length; i++) {
|
|
2852
|
-
let { $from, $to } = ranges[i], mapping = tr.mapping.slice(mapFrom);
|
|
2853
|
-
let from = mapping.map($from.pos), to = mapping.map($to.pos);
|
|
2854
|
-
if (i) {
|
|
2855
|
-
tr.deleteRange(from, to);
|
|
2856
|
-
} else {
|
|
2857
|
-
tr.replaceRangeWith(from, to, node);
|
|
2858
|
-
selectionToInsertionEnd(tr, mapFrom, node.isInline ? -1 : 1);
|
|
2859
|
-
}
|
|
2860
|
-
}
|
|
2861
|
-
}
|
|
2862
|
-
/**
|
|
2863
|
-
Find a valid cursor or leaf node selection starting at the given
|
|
2864
|
-
position and searching back if `dir` is negative, and forward if
|
|
2865
|
-
positive. When `textOnly` is true, only consider cursor
|
|
2866
|
-
selections. Will return null when no valid selection position is
|
|
2867
|
-
found.
|
|
2868
|
-
*/
|
|
2869
|
-
static findFrom($pos, dir, textOnly = false) {
|
|
2870
|
-
let inner = $pos.parent.inlineContent ? new TextSelection($pos) : findSelectionIn($pos.node(0), $pos.parent, $pos.pos, $pos.index(), dir, textOnly);
|
|
2871
|
-
if (inner)
|
|
2872
|
-
return inner;
|
|
2873
|
-
for (let depth = $pos.depth - 1; depth >= 0; depth--) {
|
|
2874
|
-
let found2 = dir < 0 ? findSelectionIn($pos.node(0), $pos.node(depth), $pos.before(depth + 1), $pos.index(depth), dir, textOnly) : findSelectionIn($pos.node(0), $pos.node(depth), $pos.after(depth + 1), $pos.index(depth) + 1, dir, textOnly);
|
|
2875
|
-
if (found2)
|
|
2876
|
-
return found2;
|
|
2877
|
-
}
|
|
2878
|
-
return null;
|
|
2879
|
-
}
|
|
2880
|
-
/**
|
|
2881
|
-
Find a valid cursor or leaf node selection near the given
|
|
2882
|
-
position. Searches forward first by default, but if `bias` is
|
|
2883
|
-
negative, it will search backwards first.
|
|
2884
|
-
*/
|
|
2885
|
-
static near($pos, bias = 1) {
|
|
2886
|
-
return this.findFrom($pos, bias) || this.findFrom($pos, -bias) || new AllSelection($pos.node(0));
|
|
2887
|
-
}
|
|
2888
|
-
/**
|
|
2889
|
-
Find the cursor or leaf node selection closest to the start of
|
|
2890
|
-
the given document. Will return an
|
|
2891
|
-
[`AllSelection`](https://prosemirror.net/docs/ref/#state.AllSelection) if no valid position
|
|
2892
|
-
exists.
|
|
2893
|
-
*/
|
|
2894
|
-
static atStart(doc3) {
|
|
2895
|
-
return findSelectionIn(doc3, doc3, 0, 0, 1) || new AllSelection(doc3);
|
|
2896
|
-
}
|
|
2897
|
-
/**
|
|
2898
|
-
Find the cursor or leaf node selection closest to the end of the
|
|
2899
|
-
given document.
|
|
2900
|
-
*/
|
|
2901
|
-
static atEnd(doc3) {
|
|
2902
|
-
return findSelectionIn(doc3, doc3, doc3.content.size, doc3.childCount, -1) || new AllSelection(doc3);
|
|
2903
|
-
}
|
|
2904
|
-
/**
|
|
2905
|
-
Deserialize the JSON representation of a selection. Must be
|
|
2906
|
-
implemented for custom classes (as a static class method).
|
|
2907
|
-
*/
|
|
2908
|
-
static fromJSON(doc3, json) {
|
|
2909
|
-
if (!json || !json.type)
|
|
2910
|
-
throw new RangeError("Invalid input for Selection.fromJSON");
|
|
2911
|
-
let cls = classesById[json.type];
|
|
2912
|
-
if (!cls)
|
|
2913
|
-
throw new RangeError(`No selection type ${json.type} defined`);
|
|
2914
|
-
return cls.fromJSON(doc3, json);
|
|
2915
|
-
}
|
|
2916
|
-
/**
|
|
2917
|
-
To be able to deserialize selections from JSON, custom selection
|
|
2918
|
-
classes must register themselves with an ID string, so that they
|
|
2919
|
-
can be disambiguated. Try to pick something that's unlikely to
|
|
2920
|
-
clash with classes from other modules.
|
|
2921
|
-
*/
|
|
2922
|
-
static jsonID(id, selectionClass) {
|
|
2923
|
-
if (id in classesById)
|
|
2924
|
-
throw new RangeError("Duplicate use of selection JSON ID " + id);
|
|
2925
|
-
classesById[id] = selectionClass;
|
|
2926
|
-
selectionClass.prototype.jsonID = id;
|
|
2927
|
-
return selectionClass;
|
|
2928
|
-
}
|
|
2929
|
-
/**
|
|
2930
|
-
Get a [bookmark](https://prosemirror.net/docs/ref/#state.SelectionBookmark) for this selection,
|
|
2931
|
-
which is a value that can be mapped without having access to a
|
|
2932
|
-
current document, and later resolved to a real selection for a
|
|
2933
|
-
given document again. (This is used mostly by the history to
|
|
2934
|
-
track and restore old selections.) The default implementation of
|
|
2935
|
-
this method just converts the selection to a text selection and
|
|
2936
|
-
returns the bookmark for that.
|
|
2937
|
-
*/
|
|
2938
|
-
getBookmark() {
|
|
2939
|
-
return TextSelection.between(this.$anchor, this.$head).getBookmark();
|
|
2940
|
-
}
|
|
2941
|
-
};
|
|
2942
|
-
Selection.prototype.visible = true;
|
|
2943
|
-
var SelectionRange = class {
|
|
2944
|
-
/**
|
|
2945
|
-
Create a range.
|
|
2946
|
-
*/
|
|
2947
|
-
constructor($from, $to) {
|
|
2948
|
-
this.$from = $from;
|
|
2949
|
-
this.$to = $to;
|
|
2950
|
-
}
|
|
2951
|
-
};
|
|
2952
|
-
var warnedAboutTextSelection = false;
|
|
2953
|
-
function checkTextSelection($pos) {
|
|
2954
|
-
if (!warnedAboutTextSelection && !$pos.parent.inlineContent) {
|
|
2955
|
-
warnedAboutTextSelection = true;
|
|
2956
|
-
console["warn"]("TextSelection endpoint not pointing into a node with inline content (" + $pos.parent.type.name + ")");
|
|
2957
|
-
}
|
|
2958
|
-
}
|
|
2959
|
-
var TextSelection = class _TextSelection extends Selection {
|
|
2960
|
-
/**
|
|
2961
|
-
Construct a text selection between the given points.
|
|
2962
|
-
*/
|
|
2963
|
-
constructor($anchor, $head = $anchor) {
|
|
2964
|
-
checkTextSelection($anchor);
|
|
2965
|
-
checkTextSelection($head);
|
|
2966
|
-
super($anchor, $head);
|
|
2967
|
-
}
|
|
2968
|
-
/**
|
|
2969
|
-
Returns a resolved position if this is a cursor selection (an
|
|
2970
|
-
empty text selection), and null otherwise.
|
|
2971
|
-
*/
|
|
2972
|
-
get $cursor() {
|
|
2973
|
-
return this.$anchor.pos == this.$head.pos ? this.$head : null;
|
|
2974
|
-
}
|
|
2975
|
-
map(doc3, mapping) {
|
|
2976
|
-
let $head = doc3.resolve(mapping.map(this.head));
|
|
2977
|
-
if (!$head.parent.inlineContent)
|
|
2978
|
-
return Selection.near($head);
|
|
2979
|
-
let $anchor = doc3.resolve(mapping.map(this.anchor));
|
|
2980
|
-
return new _TextSelection($anchor.parent.inlineContent ? $anchor : $head, $head);
|
|
2981
|
-
}
|
|
2982
|
-
replace(tr, content = Slice.empty) {
|
|
2983
|
-
super.replace(tr, content);
|
|
2984
|
-
if (content == Slice.empty) {
|
|
2985
|
-
let marks = this.$from.marksAcross(this.$to);
|
|
2986
|
-
if (marks)
|
|
2987
|
-
tr.ensureMarks(marks);
|
|
2988
|
-
}
|
|
2989
|
-
}
|
|
2990
|
-
eq(other) {
|
|
2991
|
-
return other instanceof _TextSelection && other.anchor == this.anchor && other.head == this.head;
|
|
2992
|
-
}
|
|
2993
|
-
getBookmark() {
|
|
2994
|
-
return new TextBookmark(this.anchor, this.head);
|
|
2995
|
-
}
|
|
2996
|
-
toJSON() {
|
|
2997
|
-
return { type: "text", anchor: this.anchor, head: this.head };
|
|
2998
|
-
}
|
|
2999
|
-
/**
|
|
3000
|
-
@internal
|
|
3001
|
-
*/
|
|
3002
|
-
static fromJSON(doc3, json) {
|
|
3003
|
-
if (typeof json.anchor != "number" || typeof json.head != "number")
|
|
3004
|
-
throw new RangeError("Invalid input for TextSelection.fromJSON");
|
|
3005
|
-
return new _TextSelection(doc3.resolve(json.anchor), doc3.resolve(json.head));
|
|
3006
|
-
}
|
|
3007
|
-
/**
|
|
3008
|
-
Create a text selection from non-resolved positions.
|
|
3009
|
-
*/
|
|
3010
|
-
static create(doc3, anchor, head = anchor) {
|
|
3011
|
-
let $anchor = doc3.resolve(anchor);
|
|
3012
|
-
return new this($anchor, head == anchor ? $anchor : doc3.resolve(head));
|
|
3013
|
-
}
|
|
3014
|
-
/**
|
|
3015
|
-
Return a text selection that spans the given positions or, if
|
|
3016
|
-
they aren't text positions, find a text selection near them.
|
|
3017
|
-
`bias` determines whether the method searches forward (default)
|
|
3018
|
-
or backwards (negative number) first. Will fall back to calling
|
|
3019
|
-
[`Selection.near`](https://prosemirror.net/docs/ref/#state.Selection^near) when the document
|
|
3020
|
-
doesn't contain a valid text position.
|
|
3021
|
-
*/
|
|
3022
|
-
static between($anchor, $head, bias) {
|
|
3023
|
-
let dPos = $anchor.pos - $head.pos;
|
|
3024
|
-
if (!bias || dPos)
|
|
3025
|
-
bias = dPos >= 0 ? 1 : -1;
|
|
3026
|
-
if (!$head.parent.inlineContent) {
|
|
3027
|
-
let found2 = Selection.findFrom($head, bias, true) || Selection.findFrom($head, -bias, true);
|
|
3028
|
-
if (found2)
|
|
3029
|
-
$head = found2.$head;
|
|
3030
|
-
else
|
|
3031
|
-
return Selection.near($head, bias);
|
|
3032
|
-
}
|
|
3033
|
-
if (!$anchor.parent.inlineContent) {
|
|
3034
|
-
if (dPos == 0) {
|
|
3035
|
-
$anchor = $head;
|
|
3036
|
-
} else {
|
|
3037
|
-
$anchor = (Selection.findFrom($anchor, -bias, true) || Selection.findFrom($anchor, bias, true)).$anchor;
|
|
3038
|
-
if ($anchor.pos < $head.pos != dPos < 0)
|
|
3039
|
-
$anchor = $head;
|
|
3040
|
-
}
|
|
3041
|
-
}
|
|
3042
|
-
return new _TextSelection($anchor, $head);
|
|
3043
|
-
}
|
|
3044
|
-
};
|
|
3045
|
-
Selection.jsonID("text", TextSelection);
|
|
3046
|
-
var TextBookmark = class _TextBookmark {
|
|
3047
|
-
constructor(anchor, head) {
|
|
3048
|
-
this.anchor = anchor;
|
|
3049
|
-
this.head = head;
|
|
3050
|
-
}
|
|
3051
|
-
map(mapping) {
|
|
3052
|
-
return new _TextBookmark(mapping.map(this.anchor), mapping.map(this.head));
|
|
3053
|
-
}
|
|
3054
|
-
resolve(doc3) {
|
|
3055
|
-
return TextSelection.between(doc3.resolve(this.anchor), doc3.resolve(this.head));
|
|
3056
|
-
}
|
|
3057
|
-
};
|
|
3058
|
-
var NodeSelection = class _NodeSelection extends Selection {
|
|
3059
|
-
/**
|
|
3060
|
-
Create a node selection. Does not verify the validity of its
|
|
3061
|
-
argument.
|
|
3062
|
-
*/
|
|
3063
|
-
constructor($pos) {
|
|
3064
|
-
let node = $pos.nodeAfter;
|
|
3065
|
-
let $end = $pos.node(0).resolve($pos.pos + node.nodeSize);
|
|
3066
|
-
super($pos, $end);
|
|
3067
|
-
this.node = node;
|
|
3068
|
-
}
|
|
3069
|
-
map(doc3, mapping) {
|
|
3070
|
-
let { deleted, pos } = mapping.mapResult(this.anchor);
|
|
3071
|
-
let $pos = doc3.resolve(pos);
|
|
3072
|
-
if (deleted)
|
|
3073
|
-
return Selection.near($pos);
|
|
3074
|
-
return new _NodeSelection($pos);
|
|
3075
|
-
}
|
|
3076
|
-
content() {
|
|
3077
|
-
return new Slice(Fragment.from(this.node), 0, 0);
|
|
3078
|
-
}
|
|
3079
|
-
eq(other) {
|
|
3080
|
-
return other instanceof _NodeSelection && other.anchor == this.anchor;
|
|
3081
|
-
}
|
|
3082
|
-
toJSON() {
|
|
3083
|
-
return { type: "node", anchor: this.anchor };
|
|
3084
|
-
}
|
|
3085
|
-
getBookmark() {
|
|
3086
|
-
return new NodeBookmark(this.anchor);
|
|
3087
|
-
}
|
|
3088
|
-
/**
|
|
3089
|
-
@internal
|
|
3090
|
-
*/
|
|
3091
|
-
static fromJSON(doc3, json) {
|
|
3092
|
-
if (typeof json.anchor != "number")
|
|
3093
|
-
throw new RangeError("Invalid input for NodeSelection.fromJSON");
|
|
3094
|
-
return new _NodeSelection(doc3.resolve(json.anchor));
|
|
3095
|
-
}
|
|
3096
|
-
/**
|
|
3097
|
-
Create a node selection from non-resolved positions.
|
|
3098
|
-
*/
|
|
3099
|
-
static create(doc3, from) {
|
|
3100
|
-
return new _NodeSelection(doc3.resolve(from));
|
|
3101
|
-
}
|
|
3102
|
-
/**
|
|
3103
|
-
Determines whether the given node may be selected as a node
|
|
3104
|
-
selection.
|
|
3105
|
-
*/
|
|
3106
|
-
static isSelectable(node) {
|
|
3107
|
-
return !node.isText && node.type.spec.selectable !== false;
|
|
3108
|
-
}
|
|
3109
|
-
};
|
|
3110
|
-
NodeSelection.prototype.visible = false;
|
|
3111
|
-
Selection.jsonID("node", NodeSelection);
|
|
3112
|
-
var NodeBookmark = class _NodeBookmark {
|
|
3113
|
-
constructor(anchor) {
|
|
3114
|
-
this.anchor = anchor;
|
|
3115
|
-
}
|
|
3116
|
-
map(mapping) {
|
|
3117
|
-
let { deleted, pos } = mapping.mapResult(this.anchor);
|
|
3118
|
-
return deleted ? new TextBookmark(pos, pos) : new _NodeBookmark(pos);
|
|
3119
|
-
}
|
|
3120
|
-
resolve(doc3) {
|
|
3121
|
-
let $pos = doc3.resolve(this.anchor), node = $pos.nodeAfter;
|
|
3122
|
-
if (node && NodeSelection.isSelectable(node))
|
|
3123
|
-
return new NodeSelection($pos);
|
|
3124
|
-
return Selection.near($pos);
|
|
3125
|
-
}
|
|
3126
|
-
};
|
|
3127
|
-
var AllSelection = class _AllSelection extends Selection {
|
|
3128
|
-
/**
|
|
3129
|
-
Create an all-selection over the given document.
|
|
3130
|
-
*/
|
|
3131
|
-
constructor(doc3) {
|
|
3132
|
-
super(doc3.resolve(0), doc3.resolve(doc3.content.size));
|
|
3133
|
-
}
|
|
3134
|
-
replace(tr, content = Slice.empty) {
|
|
3135
|
-
if (content == Slice.empty) {
|
|
3136
|
-
tr.delete(0, tr.doc.content.size);
|
|
3137
|
-
let sel = Selection.atStart(tr.doc);
|
|
3138
|
-
if (!sel.eq(tr.selection))
|
|
3139
|
-
tr.setSelection(sel);
|
|
3140
|
-
} else {
|
|
3141
|
-
super.replace(tr, content);
|
|
3142
|
-
}
|
|
3143
|
-
}
|
|
3144
|
-
toJSON() {
|
|
3145
|
-
return { type: "all" };
|
|
3146
|
-
}
|
|
3147
|
-
/**
|
|
3148
|
-
@internal
|
|
3149
|
-
*/
|
|
3150
|
-
static fromJSON(doc3) {
|
|
3151
|
-
return new _AllSelection(doc3);
|
|
3152
|
-
}
|
|
3153
|
-
map(doc3) {
|
|
3154
|
-
return new _AllSelection(doc3);
|
|
3155
|
-
}
|
|
3156
|
-
eq(other) {
|
|
3157
|
-
return other instanceof _AllSelection;
|
|
3158
|
-
}
|
|
3159
|
-
getBookmark() {
|
|
3160
|
-
return AllBookmark;
|
|
3161
|
-
}
|
|
3162
|
-
};
|
|
3163
|
-
Selection.jsonID("all", AllSelection);
|
|
3164
|
-
var AllBookmark = {
|
|
3165
|
-
map() {
|
|
3166
|
-
return this;
|
|
3167
|
-
},
|
|
3168
|
-
resolve(doc3) {
|
|
3169
|
-
return new AllSelection(doc3);
|
|
3170
|
-
}
|
|
3171
|
-
};
|
|
3172
|
-
function findSelectionIn(doc3, node, pos, index, dir, text = false) {
|
|
3173
|
-
if (node.inlineContent)
|
|
3174
|
-
return TextSelection.create(doc3, pos);
|
|
3175
|
-
for (let i = index - (dir > 0 ? 0 : 1); dir > 0 ? i < node.childCount : i >= 0; i += dir) {
|
|
3176
|
-
let child = node.child(i);
|
|
3177
|
-
if (!child.isAtom) {
|
|
3178
|
-
let inner = findSelectionIn(doc3, child, pos + dir, dir < 0 ? child.childCount : 0, dir, text);
|
|
3179
|
-
if (inner)
|
|
3180
|
-
return inner;
|
|
3181
|
-
} else if (!text && NodeSelection.isSelectable(child)) {
|
|
3182
|
-
return NodeSelection.create(doc3, pos - (dir < 0 ? child.nodeSize : 0));
|
|
3183
|
-
}
|
|
3184
|
-
pos += child.nodeSize * dir;
|
|
3185
|
-
}
|
|
3186
|
-
return null;
|
|
3187
|
-
}
|
|
3188
|
-
function selectionToInsertionEnd(tr, startLen, bias) {
|
|
3189
|
-
let last = tr.steps.length - 1;
|
|
3190
|
-
if (last < startLen)
|
|
3191
|
-
return;
|
|
3192
|
-
let step = tr.steps[last];
|
|
3193
|
-
if (!(step instanceof ReplaceStep || step instanceof ReplaceAroundStep))
|
|
3194
|
-
return;
|
|
3195
|
-
let map = tr.mapping.maps[last], end;
|
|
3196
|
-
map.forEach((_from, _to, _newFrom, newTo) => {
|
|
3197
|
-
if (end == null)
|
|
3198
|
-
end = newTo;
|
|
3199
|
-
});
|
|
3200
|
-
tr.setSelection(Selection.near(tr.doc.resolve(end), bias));
|
|
3201
|
-
}
|
|
3202
|
-
function bind(f, self) {
|
|
3203
|
-
return !self || !f ? f : f.bind(self);
|
|
3204
|
-
}
|
|
3205
|
-
var FieldDesc = class {
|
|
3206
|
-
constructor(name, desc, self) {
|
|
3207
|
-
this.name = name;
|
|
3208
|
-
this.init = bind(desc.init, self);
|
|
3209
|
-
this.apply = bind(desc.apply, self);
|
|
3210
|
-
}
|
|
3211
|
-
};
|
|
3212
|
-
[
|
|
3213
|
-
new FieldDesc("doc", {
|
|
3214
|
-
init(config) {
|
|
3215
|
-
return config.doc || config.schema.topNodeType.createAndFill();
|
|
3216
|
-
},
|
|
3217
|
-
apply(tr) {
|
|
3218
|
-
return tr.doc;
|
|
3219
|
-
}
|
|
3220
|
-
}),
|
|
3221
|
-
new FieldDesc("selection", {
|
|
3222
|
-
init(config, instance) {
|
|
3223
|
-
return config.selection || Selection.atStart(instance.doc);
|
|
3224
|
-
},
|
|
3225
|
-
apply(tr) {
|
|
3226
|
-
return tr.selection;
|
|
3227
|
-
}
|
|
3228
|
-
}),
|
|
3229
|
-
new FieldDesc("storedMarks", {
|
|
3230
|
-
init(config) {
|
|
3231
|
-
return config.storedMarks || null;
|
|
3232
|
-
},
|
|
3233
|
-
apply(tr, _marks, _old, state) {
|
|
3234
|
-
return state.selection.$cursor ? tr.storedMarks : null;
|
|
3235
|
-
}
|
|
3236
|
-
}),
|
|
3237
|
-
new FieldDesc("scrollToSelection", {
|
|
3238
|
-
init() {
|
|
3239
|
-
return 0;
|
|
3240
|
-
},
|
|
3241
|
-
apply(tr, prev) {
|
|
3242
|
-
return tr.scrolledIntoView ? prev + 1 : prev;
|
|
3243
|
-
}
|
|
3244
|
-
})
|
|
3245
|
-
];
|
|
3246
|
-
function bindProps(obj, self, target) {
|
|
3247
|
-
for (let prop in obj) {
|
|
3248
|
-
let val = obj[prop];
|
|
3249
|
-
if (val instanceof Function)
|
|
3250
|
-
val = val.bind(self);
|
|
3251
|
-
else if (prop == "handleDOMEvents")
|
|
3252
|
-
val = bindProps(val, self, {});
|
|
3253
|
-
target[prop] = val;
|
|
3254
|
-
}
|
|
3255
|
-
return target;
|
|
3256
|
-
}
|
|
3257
|
-
var Plugin = class {
|
|
3258
|
-
/**
|
|
3259
|
-
Create a plugin.
|
|
3260
|
-
*/
|
|
3261
|
-
constructor(spec) {
|
|
3262
|
-
this.spec = spec;
|
|
3263
|
-
this.props = {};
|
|
3264
|
-
if (spec.props)
|
|
3265
|
-
bindProps(spec.props, this, this.props);
|
|
3266
|
-
this.key = spec.key ? spec.key.key : createKey("plugin");
|
|
3267
|
-
}
|
|
3268
|
-
/**
|
|
3269
|
-
Extract the plugin's state field from an editor state.
|
|
3270
|
-
*/
|
|
3271
|
-
getState(state) {
|
|
3272
|
-
return state[this.key];
|
|
3273
|
-
}
|
|
3274
|
-
};
|
|
3275
|
-
var keys = /* @__PURE__ */ Object.create(null);
|
|
3276
|
-
function createKey(name) {
|
|
3277
|
-
if (name in keys)
|
|
3278
|
-
return name + "$" + ++keys[name];
|
|
3279
|
-
keys[name] = 0;
|
|
3280
|
-
return name + "$";
|
|
3281
|
-
}
|
|
3282
|
-
var PluginKey = class {
|
|
3283
|
-
/**
|
|
3284
|
-
Create a plugin key.
|
|
3285
|
-
*/
|
|
3286
|
-
constructor(name = "key") {
|
|
3287
|
-
this.key = createKey(name);
|
|
3288
|
-
}
|
|
3289
|
-
/**
|
|
3290
|
-
Get the active plugin with this key, if any, from an editor
|
|
3291
|
-
state.
|
|
3292
|
-
*/
|
|
3293
|
-
get(state) {
|
|
3294
|
-
return state.config.pluginsByKey[this.key];
|
|
3295
|
-
}
|
|
3296
|
-
/**
|
|
3297
|
-
Get the plugin's state from an editor state.
|
|
3298
|
-
*/
|
|
3299
|
-
getState(state) {
|
|
3300
|
-
return state[this.key];
|
|
3301
|
-
}
|
|
3302
|
-
};
|
|
3303
|
-
|
|
3304
|
-
// node_modules/prosemirror-view/dist/index.js
|
|
3305
|
-
var domIndex = function(node) {
|
|
3306
|
-
for (var index = 0; ; index++) {
|
|
3307
|
-
node = node.previousSibling;
|
|
3308
|
-
if (!node)
|
|
3309
|
-
return index;
|
|
3310
|
-
}
|
|
3311
|
-
};
|
|
3312
|
-
var isEquivalentPosition = function(node, off, targetNode, targetOff) {
|
|
3313
|
-
return targetNode && (scanFor(node, off, targetNode, targetOff, -1) || scanFor(node, off, targetNode, targetOff, 1));
|
|
3314
|
-
};
|
|
3315
|
-
var atomElements = /^(img|br|input|textarea|hr)$/i;
|
|
3316
|
-
function scanFor(node, off, targetNode, targetOff, dir) {
|
|
3317
|
-
var _a;
|
|
3318
|
-
for (; ; ) {
|
|
3319
|
-
if (node == targetNode && off == targetOff)
|
|
3320
|
-
return true;
|
|
3321
|
-
if (off == (dir < 0 ? 0 : nodeSize(node))) {
|
|
3322
|
-
let parent = node.parentNode;
|
|
3323
|
-
if (!parent || parent.nodeType != 1 || hasBlockDesc(node) || atomElements.test(node.nodeName) || node.contentEditable == "false")
|
|
3324
|
-
return false;
|
|
3325
|
-
off = domIndex(node) + (dir < 0 ? 0 : 1);
|
|
3326
|
-
node = parent;
|
|
3327
|
-
} else if (node.nodeType == 1) {
|
|
3328
|
-
let child = node.childNodes[off + (dir < 0 ? -1 : 0)];
|
|
3329
|
-
if (child.nodeType == 1 && child.contentEditable == "false") {
|
|
3330
|
-
if ((_a = child.pmViewDesc) === null || _a === void 0 ? void 0 : _a.ignoreForSelection)
|
|
3331
|
-
off += dir;
|
|
3332
|
-
else
|
|
3333
|
-
return false;
|
|
3334
|
-
} else {
|
|
3335
|
-
node = child;
|
|
3336
|
-
off = dir < 0 ? nodeSize(node) : 0;
|
|
3337
|
-
}
|
|
3338
|
-
} else {
|
|
3339
|
-
return false;
|
|
3340
|
-
}
|
|
3341
|
-
}
|
|
3342
|
-
}
|
|
3343
|
-
function nodeSize(node) {
|
|
3344
|
-
return node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length;
|
|
3345
|
-
}
|
|
3346
|
-
function isOnEdge(node, offset, parent) {
|
|
3347
|
-
for (let atStart = offset == 0, atEnd = offset == nodeSize(node); atStart || atEnd; ) {
|
|
3348
|
-
if (node == parent)
|
|
3349
|
-
return true;
|
|
3350
|
-
let index = domIndex(node);
|
|
3351
|
-
node = node.parentNode;
|
|
3352
|
-
if (!node)
|
|
3353
|
-
return false;
|
|
3354
|
-
atStart = atStart && index == 0;
|
|
3355
|
-
atEnd = atEnd && index == nodeSize(node);
|
|
3356
|
-
}
|
|
3357
|
-
}
|
|
3358
|
-
function hasBlockDesc(dom) {
|
|
3359
|
-
let desc;
|
|
3360
|
-
for (let cur = dom; cur; cur = cur.parentNode)
|
|
3361
|
-
if (desc = cur.pmViewDesc)
|
|
3362
|
-
break;
|
|
3363
|
-
return desc && desc.node && desc.node.isBlock && (desc.dom == dom || desc.contentDOM == dom);
|
|
3364
|
-
}
|
|
3365
|
-
var selectionCollapsed = function(domSel) {
|
|
3366
|
-
return domSel.focusNode && isEquivalentPosition(domSel.focusNode, domSel.focusOffset, domSel.anchorNode, domSel.anchorOffset);
|
|
3367
|
-
};
|
|
3368
|
-
function keyEvent(keyCode, key) {
|
|
3369
|
-
let event = document.createEvent("Event");
|
|
3370
|
-
event.initEvent("keydown", true, true);
|
|
3371
|
-
event.keyCode = keyCode;
|
|
3372
|
-
event.key = event.code = key;
|
|
3373
|
-
return event;
|
|
3374
|
-
}
|
|
3375
|
-
var nav = typeof navigator != "undefined" ? navigator : null;
|
|
3376
|
-
var doc2 = typeof document != "undefined" ? document : null;
|
|
3377
|
-
var agent = nav && nav.userAgent || "";
|
|
3378
|
-
var ie_edge = /Edge\/(\d+)/.exec(agent);
|
|
3379
|
-
var ie_upto10 = /MSIE \d/.exec(agent);
|
|
3380
|
-
var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(agent);
|
|
3381
|
-
var ie = !!(ie_upto10 || ie_11up || ie_edge);
|
|
3382
|
-
var ie_version = ie_upto10 ? document.documentMode : ie_11up ? +ie_11up[1] : ie_edge ? +ie_edge[1] : 0;
|
|
3383
|
-
var gecko = !ie && /gecko\/(\d+)/i.test(agent);
|
|
3384
|
-
gecko && +(/Firefox\/(\d+)/.exec(agent) || [0, 0])[1];
|
|
3385
|
-
var _chrome = !ie && /Chrome\/(\d+)/.exec(agent);
|
|
3386
|
-
var chrome = !!_chrome;
|
|
3387
|
-
var chrome_version = _chrome ? +_chrome[1] : 0;
|
|
3388
|
-
var safari = !ie && !!nav && /Apple Computer/.test(nav.vendor);
|
|
3389
|
-
var ios = safari && (/Mobile\/\w+/.test(agent) || !!nav && nav.maxTouchPoints > 2);
|
|
3390
|
-
var mac = ios || (nav ? /Mac/.test(nav.platform) : false);
|
|
3391
|
-
var windows = nav ? /Win/.test(nav.platform) : false;
|
|
3392
|
-
var android = /Android \d/.test(agent);
|
|
3393
|
-
var webkit = !!doc2 && "webkitFontSmoothing" in doc2.documentElement.style;
|
|
3394
|
-
var webkit_version = webkit ? +(/\bAppleWebKit\/(\d+)/.exec(navigator.userAgent) || [0, 0])[1] : 0;
|
|
3395
|
-
function selectionFromDOM(view, origin = null) {
|
|
3396
|
-
let domSel = view.domSelectionRange(), doc3 = view.state.doc;
|
|
3397
|
-
if (!domSel.focusNode)
|
|
3398
|
-
return null;
|
|
3399
|
-
let nearestDesc = view.docView.nearestDesc(domSel.focusNode), inWidget = nearestDesc && nearestDesc.size == 0;
|
|
3400
|
-
let head = view.docView.posFromDOM(domSel.focusNode, domSel.focusOffset, 1);
|
|
3401
|
-
if (head < 0)
|
|
3402
|
-
return null;
|
|
3403
|
-
let $head = doc3.resolve(head), anchor, selection;
|
|
3404
|
-
if (selectionCollapsed(domSel)) {
|
|
3405
|
-
anchor = head;
|
|
3406
|
-
while (nearestDesc && !nearestDesc.node)
|
|
3407
|
-
nearestDesc = nearestDesc.parent;
|
|
3408
|
-
let nearestDescNode = nearestDesc.node;
|
|
3409
|
-
if (nearestDesc && nearestDescNode.isAtom && NodeSelection.isSelectable(nearestDescNode) && nearestDesc.parent && !(nearestDescNode.isInline && isOnEdge(domSel.focusNode, domSel.focusOffset, nearestDesc.dom))) {
|
|
3410
|
-
let pos = nearestDesc.posBefore;
|
|
3411
|
-
selection = new NodeSelection(head == pos ? $head : doc3.resolve(pos));
|
|
3412
|
-
}
|
|
3413
|
-
} else {
|
|
3414
|
-
if (domSel instanceof view.dom.ownerDocument.defaultView.Selection && domSel.rangeCount > 1) {
|
|
3415
|
-
let min = head, max = head;
|
|
3416
|
-
for (let i = 0; i < domSel.rangeCount; i++) {
|
|
3417
|
-
let range = domSel.getRangeAt(i);
|
|
3418
|
-
min = Math.min(min, view.docView.posFromDOM(range.startContainer, range.startOffset, 1));
|
|
3419
|
-
max = Math.max(max, view.docView.posFromDOM(range.endContainer, range.endOffset, -1));
|
|
3420
|
-
}
|
|
3421
|
-
if (min < 0)
|
|
3422
|
-
return null;
|
|
3423
|
-
[anchor, head] = max == view.state.selection.anchor ? [max, min] : [min, max];
|
|
3424
|
-
$head = doc3.resolve(head);
|
|
3425
|
-
} else {
|
|
3426
|
-
anchor = view.docView.posFromDOM(domSel.anchorNode, domSel.anchorOffset, 1);
|
|
3427
|
-
}
|
|
3428
|
-
if (anchor < 0)
|
|
3429
|
-
return null;
|
|
3430
|
-
}
|
|
3431
|
-
let $anchor = doc3.resolve(anchor);
|
|
3432
|
-
if (!selection) {
|
|
3433
|
-
let bias = origin == "pointer" || view.state.selection.head < $head.pos && !inWidget ? 1 : -1;
|
|
3434
|
-
selection = selectionBetween(view, $anchor, $head, bias);
|
|
3435
|
-
}
|
|
3436
|
-
return selection;
|
|
3437
|
-
}
|
|
3438
|
-
function editorOwnsSelection(view) {
|
|
3439
|
-
return view.editable ? view.hasFocus() : hasSelection(view) && document.activeElement && document.activeElement.contains(view.dom);
|
|
3440
|
-
}
|
|
3441
|
-
function selectionToDOM(view, force = false) {
|
|
3442
|
-
let sel = view.state.selection;
|
|
3443
|
-
syncNodeSelection(view, sel);
|
|
3444
|
-
if (!editorOwnsSelection(view))
|
|
3445
|
-
return;
|
|
3446
|
-
if (!force && view.input.mouseDown && view.input.mouseDown.allowDefault && chrome) {
|
|
3447
|
-
let domSel = view.domSelectionRange(), curSel = view.domObserver.currentSelection;
|
|
3448
|
-
if (domSel.anchorNode && curSel.anchorNode && isEquivalentPosition(domSel.anchorNode, domSel.anchorOffset, curSel.anchorNode, curSel.anchorOffset)) {
|
|
3449
|
-
view.input.mouseDown.delayedSelectionSync = true;
|
|
3450
|
-
view.domObserver.setCurSelection();
|
|
3451
|
-
return;
|
|
3452
|
-
}
|
|
3453
|
-
}
|
|
3454
|
-
view.domObserver.disconnectSelection();
|
|
3455
|
-
if (view.cursorWrapper) {
|
|
3456
|
-
selectCursorWrapper(view);
|
|
3457
|
-
} else {
|
|
3458
|
-
let { anchor, head } = sel, resetEditableFrom, resetEditableTo;
|
|
3459
|
-
if (brokenSelectBetweenUneditable && !(sel instanceof TextSelection)) {
|
|
3460
|
-
if (!sel.$from.parent.inlineContent)
|
|
3461
|
-
resetEditableFrom = temporarilyEditableNear(view, sel.from);
|
|
3462
|
-
if (!sel.empty && !sel.$from.parent.inlineContent)
|
|
3463
|
-
resetEditableTo = temporarilyEditableNear(view, sel.to);
|
|
3464
|
-
}
|
|
3465
|
-
view.docView.setSelection(anchor, head, view, force);
|
|
3466
|
-
if (brokenSelectBetweenUneditable) {
|
|
3467
|
-
if (resetEditableFrom)
|
|
3468
|
-
resetEditable(resetEditableFrom);
|
|
3469
|
-
if (resetEditableTo)
|
|
3470
|
-
resetEditable(resetEditableTo);
|
|
3471
|
-
}
|
|
3472
|
-
if (sel.visible) {
|
|
3473
|
-
view.dom.classList.remove("ProseMirror-hideselection");
|
|
3474
|
-
} else {
|
|
3475
|
-
view.dom.classList.add("ProseMirror-hideselection");
|
|
3476
|
-
if ("onselectionchange" in document)
|
|
3477
|
-
removeClassOnSelectionChange(view);
|
|
3478
|
-
}
|
|
3479
|
-
}
|
|
3480
|
-
view.domObserver.setCurSelection();
|
|
3481
|
-
view.domObserver.connectSelection();
|
|
3482
|
-
}
|
|
3483
|
-
var brokenSelectBetweenUneditable = safari || chrome && chrome_version < 63;
|
|
3484
|
-
function temporarilyEditableNear(view, pos) {
|
|
3485
|
-
let { node, offset } = view.docView.domFromPos(pos, 0);
|
|
3486
|
-
let after = offset < node.childNodes.length ? node.childNodes[offset] : null;
|
|
3487
|
-
let before = offset ? node.childNodes[offset - 1] : null;
|
|
3488
|
-
if (safari && after && after.contentEditable == "false")
|
|
3489
|
-
return setEditable(after);
|
|
3490
|
-
if ((!after || after.contentEditable == "false") && (!before || before.contentEditable == "false")) {
|
|
3491
|
-
if (after)
|
|
3492
|
-
return setEditable(after);
|
|
3493
|
-
else if (before)
|
|
3494
|
-
return setEditable(before);
|
|
3495
|
-
}
|
|
3496
|
-
}
|
|
3497
|
-
function setEditable(element) {
|
|
3498
|
-
element.contentEditable = "true";
|
|
3499
|
-
if (safari && element.draggable) {
|
|
3500
|
-
element.draggable = false;
|
|
3501
|
-
element.wasDraggable = true;
|
|
3502
|
-
}
|
|
3503
|
-
return element;
|
|
3504
|
-
}
|
|
3505
|
-
function resetEditable(element) {
|
|
3506
|
-
element.contentEditable = "false";
|
|
3507
|
-
if (element.wasDraggable) {
|
|
3508
|
-
element.draggable = true;
|
|
3509
|
-
element.wasDraggable = null;
|
|
3510
|
-
}
|
|
3511
|
-
}
|
|
3512
|
-
function removeClassOnSelectionChange(view) {
|
|
3513
|
-
let doc3 = view.dom.ownerDocument;
|
|
3514
|
-
doc3.removeEventListener("selectionchange", view.input.hideSelectionGuard);
|
|
3515
|
-
let domSel = view.domSelectionRange();
|
|
3516
|
-
let node = domSel.anchorNode, offset = domSel.anchorOffset;
|
|
3517
|
-
doc3.addEventListener("selectionchange", view.input.hideSelectionGuard = () => {
|
|
3518
|
-
if (domSel.anchorNode != node || domSel.anchorOffset != offset) {
|
|
3519
|
-
doc3.removeEventListener("selectionchange", view.input.hideSelectionGuard);
|
|
3520
|
-
setTimeout(() => {
|
|
3521
|
-
if (!editorOwnsSelection(view) || view.state.selection.visible)
|
|
3522
|
-
view.dom.classList.remove("ProseMirror-hideselection");
|
|
3523
|
-
}, 20);
|
|
3524
|
-
}
|
|
3525
|
-
});
|
|
3526
|
-
}
|
|
3527
|
-
function selectCursorWrapper(view) {
|
|
3528
|
-
let domSel = view.domSelection();
|
|
3529
|
-
if (!domSel)
|
|
3530
|
-
return;
|
|
3531
|
-
let node = view.cursorWrapper.dom, img = node.nodeName == "IMG";
|
|
3532
|
-
if (img)
|
|
3533
|
-
domSel.collapse(node.parentNode, domIndex(node) + 1);
|
|
3534
|
-
else
|
|
3535
|
-
domSel.collapse(node, 0);
|
|
3536
|
-
if (!img && !view.state.selection.visible && ie && ie_version <= 11) {
|
|
3537
|
-
node.disabled = true;
|
|
3538
|
-
node.disabled = false;
|
|
3539
|
-
}
|
|
3540
|
-
}
|
|
3541
|
-
function syncNodeSelection(view, sel) {
|
|
3542
|
-
if (sel instanceof NodeSelection) {
|
|
3543
|
-
let desc = view.docView.descAt(sel.from);
|
|
3544
|
-
if (desc != view.lastSelectedViewDesc) {
|
|
3545
|
-
clearNodeSelection(view);
|
|
3546
|
-
if (desc)
|
|
3547
|
-
desc.selectNode();
|
|
3548
|
-
view.lastSelectedViewDesc = desc;
|
|
3549
|
-
}
|
|
3550
|
-
} else {
|
|
3551
|
-
clearNodeSelection(view);
|
|
3552
|
-
}
|
|
3553
|
-
}
|
|
3554
|
-
function clearNodeSelection(view) {
|
|
3555
|
-
if (view.lastSelectedViewDesc) {
|
|
3556
|
-
if (view.lastSelectedViewDesc.parent)
|
|
3557
|
-
view.lastSelectedViewDesc.deselectNode();
|
|
3558
|
-
view.lastSelectedViewDesc = void 0;
|
|
3559
|
-
}
|
|
3560
|
-
}
|
|
3561
|
-
function selectionBetween(view, $anchor, $head, bias) {
|
|
3562
|
-
return view.someProp("createSelectionBetween", (f) => f(view, $anchor, $head)) || TextSelection.between($anchor, $head, bias);
|
|
3563
|
-
}
|
|
3564
|
-
function hasSelection(view) {
|
|
3565
|
-
let sel = view.domSelectionRange();
|
|
3566
|
-
if (!sel.anchorNode)
|
|
3567
|
-
return false;
|
|
3568
|
-
try {
|
|
3569
|
-
return view.dom.contains(sel.anchorNode.nodeType == 3 ? sel.anchorNode.parentNode : sel.anchorNode) && (view.editable || view.dom.contains(sel.focusNode.nodeType == 3 ? sel.focusNode.parentNode : sel.focusNode));
|
|
3570
|
-
} catch (_) {
|
|
3571
|
-
return false;
|
|
3572
|
-
}
|
|
3573
|
-
}
|
|
3574
|
-
function moveSelectionBlock(state, dir) {
|
|
3575
|
-
let { $anchor, $head } = state.selection;
|
|
3576
|
-
let $side = dir > 0 ? $anchor.max($head) : $anchor.min($head);
|
|
3577
|
-
let $start = !$side.parent.inlineContent ? $side : $side.depth ? state.doc.resolve(dir > 0 ? $side.after() : $side.before()) : null;
|
|
3578
|
-
return $start && Selection.findFrom($start, dir);
|
|
3579
|
-
}
|
|
3580
|
-
function apply(view, sel) {
|
|
3581
|
-
view.dispatch(view.state.tr.setSelection(sel).scrollIntoView());
|
|
3582
|
-
return true;
|
|
3583
|
-
}
|
|
3584
|
-
function selectHorizontally(view, dir, mods) {
|
|
3585
|
-
let sel = view.state.selection;
|
|
3586
|
-
if (sel instanceof TextSelection) {
|
|
3587
|
-
if (mods.indexOf("s") > -1) {
|
|
3588
|
-
let { $head } = sel, node = $head.textOffset ? null : dir < 0 ? $head.nodeBefore : $head.nodeAfter;
|
|
3589
|
-
if (!node || node.isText || !node.isLeaf)
|
|
3590
|
-
return false;
|
|
3591
|
-
let $newHead = view.state.doc.resolve($head.pos + node.nodeSize * (dir < 0 ? -1 : 1));
|
|
3592
|
-
return apply(view, new TextSelection(sel.$anchor, $newHead));
|
|
3593
|
-
} else if (!sel.empty) {
|
|
3594
|
-
return false;
|
|
3595
|
-
} else if (view.endOfTextblock(dir > 0 ? "forward" : "backward")) {
|
|
3596
|
-
let next = moveSelectionBlock(view.state, dir);
|
|
3597
|
-
if (next && next instanceof NodeSelection)
|
|
3598
|
-
return apply(view, next);
|
|
3599
|
-
return false;
|
|
3600
|
-
} else if (!(mac && mods.indexOf("m") > -1)) {
|
|
3601
|
-
let $head = sel.$head, node = $head.textOffset ? null : dir < 0 ? $head.nodeBefore : $head.nodeAfter, desc;
|
|
3602
|
-
if (!node || node.isText)
|
|
3603
|
-
return false;
|
|
3604
|
-
let nodePos = dir < 0 ? $head.pos - node.nodeSize : $head.pos;
|
|
3605
|
-
if (!(node.isAtom || (desc = view.docView.descAt(nodePos)) && !desc.contentDOM))
|
|
3606
|
-
return false;
|
|
3607
|
-
if (NodeSelection.isSelectable(node)) {
|
|
3608
|
-
return apply(view, new NodeSelection(dir < 0 ? view.state.doc.resolve($head.pos - node.nodeSize) : $head));
|
|
3609
|
-
} else if (webkit) {
|
|
3610
|
-
return apply(view, new TextSelection(view.state.doc.resolve(dir < 0 ? nodePos : nodePos + node.nodeSize)));
|
|
3611
|
-
} else {
|
|
3612
|
-
return false;
|
|
3613
|
-
}
|
|
3614
|
-
}
|
|
3615
|
-
} else if (sel instanceof NodeSelection && sel.node.isInline) {
|
|
3616
|
-
return apply(view, new TextSelection(dir > 0 ? sel.$to : sel.$from));
|
|
3617
|
-
} else {
|
|
3618
|
-
let next = moveSelectionBlock(view.state, dir);
|
|
3619
|
-
if (next)
|
|
3620
|
-
return apply(view, next);
|
|
3621
|
-
return false;
|
|
3622
|
-
}
|
|
3623
|
-
}
|
|
3624
|
-
function nodeLen(node) {
|
|
3625
|
-
return node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length;
|
|
3626
|
-
}
|
|
3627
|
-
function isIgnorable(dom, dir) {
|
|
3628
|
-
let desc = dom.pmViewDesc;
|
|
3629
|
-
return desc && desc.size == 0 && (dir < 0 || dom.nextSibling || dom.nodeName != "BR");
|
|
3630
|
-
}
|
|
3631
|
-
function skipIgnoredNodes(view, dir) {
|
|
3632
|
-
return dir < 0 ? skipIgnoredNodesBefore(view) : skipIgnoredNodesAfter(view);
|
|
3633
|
-
}
|
|
3634
|
-
function skipIgnoredNodesBefore(view) {
|
|
3635
|
-
let sel = view.domSelectionRange();
|
|
3636
|
-
let node = sel.focusNode, offset = sel.focusOffset;
|
|
3637
|
-
if (!node)
|
|
3638
|
-
return;
|
|
3639
|
-
let moveNode, moveOffset, force = false;
|
|
3640
|
-
if (gecko && node.nodeType == 1 && offset < nodeLen(node) && isIgnorable(node.childNodes[offset], -1))
|
|
3641
|
-
force = true;
|
|
3642
|
-
for (; ; ) {
|
|
3643
|
-
if (offset > 0) {
|
|
3644
|
-
if (node.nodeType != 1) {
|
|
3645
|
-
break;
|
|
3646
|
-
} else {
|
|
3647
|
-
let before = node.childNodes[offset - 1];
|
|
3648
|
-
if (isIgnorable(before, -1)) {
|
|
3649
|
-
moveNode = node;
|
|
3650
|
-
moveOffset = --offset;
|
|
3651
|
-
} else if (before.nodeType == 3) {
|
|
3652
|
-
node = before;
|
|
3653
|
-
offset = node.nodeValue.length;
|
|
3654
|
-
} else
|
|
3655
|
-
break;
|
|
3656
|
-
}
|
|
3657
|
-
} else if (isBlockNode(node)) {
|
|
3658
|
-
break;
|
|
3659
|
-
} else {
|
|
3660
|
-
let prev = node.previousSibling;
|
|
3661
|
-
while (prev && isIgnorable(prev, -1)) {
|
|
3662
|
-
moveNode = node.parentNode;
|
|
3663
|
-
moveOffset = domIndex(prev);
|
|
3664
|
-
prev = prev.previousSibling;
|
|
3665
|
-
}
|
|
3666
|
-
if (!prev) {
|
|
3667
|
-
node = node.parentNode;
|
|
3668
|
-
if (node == view.dom)
|
|
3669
|
-
break;
|
|
3670
|
-
offset = 0;
|
|
3671
|
-
} else {
|
|
3672
|
-
node = prev;
|
|
3673
|
-
offset = nodeLen(node);
|
|
3674
|
-
}
|
|
3675
|
-
}
|
|
3676
|
-
}
|
|
3677
|
-
if (force)
|
|
3678
|
-
setSelFocus(view, node, offset);
|
|
3679
|
-
else if (moveNode)
|
|
3680
|
-
setSelFocus(view, moveNode, moveOffset);
|
|
3681
|
-
}
|
|
3682
|
-
function skipIgnoredNodesAfter(view) {
|
|
3683
|
-
let sel = view.domSelectionRange();
|
|
3684
|
-
let node = sel.focusNode, offset = sel.focusOffset;
|
|
3685
|
-
if (!node)
|
|
3686
|
-
return;
|
|
3687
|
-
let len = nodeLen(node);
|
|
3688
|
-
let moveNode, moveOffset;
|
|
3689
|
-
for (; ; ) {
|
|
3690
|
-
if (offset < len) {
|
|
3691
|
-
if (node.nodeType != 1)
|
|
3692
|
-
break;
|
|
3693
|
-
let after = node.childNodes[offset];
|
|
3694
|
-
if (isIgnorable(after, 1)) {
|
|
3695
|
-
moveNode = node;
|
|
3696
|
-
moveOffset = ++offset;
|
|
3697
|
-
} else
|
|
3698
|
-
break;
|
|
3699
|
-
} else if (isBlockNode(node)) {
|
|
3700
|
-
break;
|
|
3701
|
-
} else {
|
|
3702
|
-
let next = node.nextSibling;
|
|
3703
|
-
while (next && isIgnorable(next, 1)) {
|
|
3704
|
-
moveNode = next.parentNode;
|
|
3705
|
-
moveOffset = domIndex(next) + 1;
|
|
3706
|
-
next = next.nextSibling;
|
|
3707
|
-
}
|
|
3708
|
-
if (!next) {
|
|
3709
|
-
node = node.parentNode;
|
|
3710
|
-
if (node == view.dom)
|
|
3711
|
-
break;
|
|
3712
|
-
offset = len = 0;
|
|
3713
|
-
} else {
|
|
3714
|
-
node = next;
|
|
3715
|
-
offset = 0;
|
|
3716
|
-
len = nodeLen(node);
|
|
3717
|
-
}
|
|
3718
|
-
}
|
|
3719
|
-
}
|
|
3720
|
-
if (moveNode)
|
|
3721
|
-
setSelFocus(view, moveNode, moveOffset);
|
|
3722
|
-
}
|
|
3723
|
-
function isBlockNode(dom) {
|
|
3724
|
-
let desc = dom.pmViewDesc;
|
|
3725
|
-
return desc && desc.node && desc.node.isBlock;
|
|
3726
|
-
}
|
|
3727
|
-
function textNodeAfter(node, offset) {
|
|
3728
|
-
while (node && offset == node.childNodes.length && !hasBlockDesc(node)) {
|
|
3729
|
-
offset = domIndex(node) + 1;
|
|
3730
|
-
node = node.parentNode;
|
|
3731
|
-
}
|
|
3732
|
-
while (node && offset < node.childNodes.length) {
|
|
3733
|
-
let next = node.childNodes[offset];
|
|
3734
|
-
if (next.nodeType == 3)
|
|
3735
|
-
return next;
|
|
3736
|
-
if (next.nodeType == 1 && next.contentEditable == "false")
|
|
3737
|
-
break;
|
|
3738
|
-
node = next;
|
|
3739
|
-
offset = 0;
|
|
3740
|
-
}
|
|
3741
|
-
}
|
|
3742
|
-
function textNodeBefore(node, offset) {
|
|
3743
|
-
while (node && !offset && !hasBlockDesc(node)) {
|
|
3744
|
-
offset = domIndex(node);
|
|
3745
|
-
node = node.parentNode;
|
|
3746
|
-
}
|
|
3747
|
-
while (node && offset) {
|
|
3748
|
-
let next = node.childNodes[offset - 1];
|
|
3749
|
-
if (next.nodeType == 3)
|
|
3750
|
-
return next;
|
|
3751
|
-
if (next.nodeType == 1 && next.contentEditable == "false")
|
|
3752
|
-
break;
|
|
3753
|
-
node = next;
|
|
3754
|
-
offset = node.childNodes.length;
|
|
3755
|
-
}
|
|
3756
|
-
}
|
|
3757
|
-
function setSelFocus(view, node, offset) {
|
|
3758
|
-
if (node.nodeType != 3) {
|
|
3759
|
-
let before, after;
|
|
3760
|
-
if (after = textNodeAfter(node, offset)) {
|
|
3761
|
-
node = after;
|
|
3762
|
-
offset = 0;
|
|
3763
|
-
} else if (before = textNodeBefore(node, offset)) {
|
|
3764
|
-
node = before;
|
|
3765
|
-
offset = before.nodeValue.length;
|
|
3766
|
-
}
|
|
3767
|
-
}
|
|
3768
|
-
let sel = view.domSelection();
|
|
3769
|
-
if (!sel)
|
|
3770
|
-
return;
|
|
3771
|
-
if (selectionCollapsed(sel)) {
|
|
3772
|
-
let range = document.createRange();
|
|
3773
|
-
range.setEnd(node, offset);
|
|
3774
|
-
range.setStart(node, offset);
|
|
3775
|
-
sel.removeAllRanges();
|
|
3776
|
-
sel.addRange(range);
|
|
3777
|
-
} else if (sel.extend) {
|
|
3778
|
-
sel.extend(node, offset);
|
|
3779
|
-
}
|
|
3780
|
-
view.domObserver.setCurSelection();
|
|
3781
|
-
let { state } = view;
|
|
3782
|
-
setTimeout(() => {
|
|
3783
|
-
if (view.state == state)
|
|
3784
|
-
selectionToDOM(view);
|
|
3785
|
-
}, 50);
|
|
3786
|
-
}
|
|
3787
|
-
function findDirection(view, pos) {
|
|
3788
|
-
let $pos = view.state.doc.resolve(pos);
|
|
3789
|
-
if (!(chrome || windows) && $pos.parent.inlineContent) {
|
|
3790
|
-
let coords = view.coordsAtPos(pos);
|
|
3791
|
-
if (pos > $pos.start()) {
|
|
3792
|
-
let before = view.coordsAtPos(pos - 1);
|
|
3793
|
-
let mid = (before.top + before.bottom) / 2;
|
|
3794
|
-
if (mid > coords.top && mid < coords.bottom && Math.abs(before.left - coords.left) > 1)
|
|
3795
|
-
return before.left < coords.left ? "ltr" : "rtl";
|
|
3796
|
-
}
|
|
3797
|
-
if (pos < $pos.end()) {
|
|
3798
|
-
let after = view.coordsAtPos(pos + 1);
|
|
3799
|
-
let mid = (after.top + after.bottom) / 2;
|
|
3800
|
-
if (mid > coords.top && mid < coords.bottom && Math.abs(after.left - coords.left) > 1)
|
|
3801
|
-
return after.left > coords.left ? "ltr" : "rtl";
|
|
3802
|
-
}
|
|
3803
|
-
}
|
|
3804
|
-
let computed = getComputedStyle(view.dom).direction;
|
|
3805
|
-
return computed == "rtl" ? "rtl" : "ltr";
|
|
3806
|
-
}
|
|
3807
|
-
function selectVertically(view, dir, mods) {
|
|
3808
|
-
let sel = view.state.selection;
|
|
3809
|
-
if (sel instanceof TextSelection && !sel.empty || mods.indexOf("s") > -1)
|
|
3810
|
-
return false;
|
|
3811
|
-
if (mac && mods.indexOf("m") > -1)
|
|
3812
|
-
return false;
|
|
3813
|
-
let { $from, $to } = sel;
|
|
3814
|
-
if (!$from.parent.inlineContent || view.endOfTextblock(dir < 0 ? "up" : "down")) {
|
|
3815
|
-
let next = moveSelectionBlock(view.state, dir);
|
|
3816
|
-
if (next && next instanceof NodeSelection)
|
|
3817
|
-
return apply(view, next);
|
|
3818
|
-
}
|
|
3819
|
-
if (!$from.parent.inlineContent) {
|
|
3820
|
-
let side = dir < 0 ? $from : $to;
|
|
3821
|
-
let beyond = sel instanceof AllSelection ? Selection.near(side, dir) : Selection.findFrom(side, dir);
|
|
3822
|
-
return beyond ? apply(view, beyond) : false;
|
|
3823
|
-
}
|
|
3824
|
-
return false;
|
|
3825
|
-
}
|
|
3826
|
-
function stopNativeHorizontalDelete(view, dir) {
|
|
3827
|
-
if (!(view.state.selection instanceof TextSelection))
|
|
3828
|
-
return true;
|
|
3829
|
-
let { $head, $anchor, empty: empty2 } = view.state.selection;
|
|
3830
|
-
if (!$head.sameParent($anchor))
|
|
3831
|
-
return true;
|
|
3832
|
-
if (!empty2)
|
|
3833
|
-
return false;
|
|
3834
|
-
if (view.endOfTextblock(dir > 0 ? "forward" : "backward"))
|
|
3835
|
-
return true;
|
|
3836
|
-
let nextNode = !$head.textOffset && (dir < 0 ? $head.nodeBefore : $head.nodeAfter);
|
|
3837
|
-
if (nextNode && !nextNode.isText) {
|
|
3838
|
-
let tr = view.state.tr;
|
|
3839
|
-
if (dir < 0)
|
|
3840
|
-
tr.delete($head.pos - nextNode.nodeSize, $head.pos);
|
|
3841
|
-
else
|
|
3842
|
-
tr.delete($head.pos, $head.pos + nextNode.nodeSize);
|
|
3843
|
-
view.dispatch(tr);
|
|
3844
|
-
return true;
|
|
3845
|
-
}
|
|
3846
|
-
return false;
|
|
3847
|
-
}
|
|
3848
|
-
function switchEditable(view, node, state) {
|
|
3849
|
-
view.domObserver.stop();
|
|
3850
|
-
node.contentEditable = state;
|
|
3851
|
-
view.domObserver.start();
|
|
3852
|
-
}
|
|
3853
|
-
function safariDownArrowBug(view) {
|
|
3854
|
-
if (!safari || view.state.selection.$head.parentOffset > 0)
|
|
3855
|
-
return false;
|
|
3856
|
-
let { focusNode, focusOffset } = view.domSelectionRange();
|
|
3857
|
-
if (focusNode && focusNode.nodeType == 1 && focusOffset == 0 && focusNode.firstChild && focusNode.firstChild.contentEditable == "false") {
|
|
3858
|
-
let child = focusNode.firstChild;
|
|
3859
|
-
switchEditable(view, child, "true");
|
|
3860
|
-
setTimeout(() => switchEditable(view, child, "false"), 20);
|
|
3861
|
-
}
|
|
3862
|
-
return false;
|
|
3863
|
-
}
|
|
3864
|
-
function getMods(event) {
|
|
3865
|
-
let result = "";
|
|
3866
|
-
if (event.ctrlKey)
|
|
3867
|
-
result += "c";
|
|
3868
|
-
if (event.metaKey)
|
|
3869
|
-
result += "m";
|
|
3870
|
-
if (event.altKey)
|
|
3871
|
-
result += "a";
|
|
3872
|
-
if (event.shiftKey)
|
|
3873
|
-
result += "s";
|
|
3874
|
-
return result;
|
|
3875
|
-
}
|
|
3876
|
-
function captureKeyDown(view, event) {
|
|
3877
|
-
let code = event.keyCode, mods = getMods(event);
|
|
3878
|
-
if (code == 8 || mac && code == 72 && mods == "c") {
|
|
3879
|
-
return stopNativeHorizontalDelete(view, -1) || skipIgnoredNodes(view, -1);
|
|
3880
|
-
} else if (code == 46 && !event.shiftKey || mac && code == 68 && mods == "c") {
|
|
3881
|
-
return stopNativeHorizontalDelete(view, 1) || skipIgnoredNodes(view, 1);
|
|
3882
|
-
} else if (code == 13 || code == 27) {
|
|
3883
|
-
return true;
|
|
3884
|
-
} else if (code == 37 || mac && code == 66 && mods == "c") {
|
|
3885
|
-
let dir = code == 37 ? findDirection(view, view.state.selection.from) == "ltr" ? -1 : 1 : -1;
|
|
3886
|
-
return selectHorizontally(view, dir, mods) || skipIgnoredNodes(view, dir);
|
|
3887
|
-
} else if (code == 39 || mac && code == 70 && mods == "c") {
|
|
3888
|
-
let dir = code == 39 ? findDirection(view, view.state.selection.from) == "ltr" ? 1 : -1 : 1;
|
|
3889
|
-
return selectHorizontally(view, dir, mods) || skipIgnoredNodes(view, dir);
|
|
3890
|
-
} else if (code == 38 || mac && code == 80 && mods == "c") {
|
|
3891
|
-
return selectVertically(view, -1, mods) || skipIgnoredNodes(view, -1);
|
|
3892
|
-
} else if (code == 40 || mac && code == 78 && mods == "c") {
|
|
3893
|
-
return safariDownArrowBug(view) || selectVertically(view, 1, mods) || skipIgnoredNodes(view, 1);
|
|
3894
|
-
} else if (mods == (mac ? "m" : "c") && (code == 66 || code == 73 || code == 89 || code == 90)) {
|
|
3895
|
-
return true;
|
|
3896
|
-
}
|
|
3897
|
-
return false;
|
|
3898
|
-
}
|
|
3899
|
-
function serializeForClipboard(view, slice) {
|
|
3900
|
-
view.someProp("transformCopied", (f) => {
|
|
3901
|
-
slice = f(slice, view);
|
|
3902
|
-
});
|
|
3903
|
-
let context = [], { content, openStart, openEnd } = slice;
|
|
3904
|
-
while (openStart > 1 && openEnd > 1 && content.childCount == 1 && content.firstChild.childCount == 1) {
|
|
3905
|
-
openStart--;
|
|
3906
|
-
openEnd--;
|
|
3907
|
-
let node = content.firstChild;
|
|
3908
|
-
context.push(node.type.name, node.attrs != node.type.defaultAttrs ? node.attrs : null);
|
|
3909
|
-
content = node.content;
|
|
3910
|
-
}
|
|
3911
|
-
let serializer = view.someProp("clipboardSerializer") || DOMSerializer.fromSchema(view.state.schema);
|
|
3912
|
-
let doc3 = detachedDoc(), wrap = doc3.createElement("div");
|
|
3913
|
-
wrap.appendChild(serializer.serializeFragment(content, { document: doc3 }));
|
|
3914
|
-
let firstChild = wrap.firstChild, needsWrap, wrappers = 0;
|
|
3915
|
-
while (firstChild && firstChild.nodeType == 1 && (needsWrap = wrapMap[firstChild.nodeName.toLowerCase()])) {
|
|
3916
|
-
for (let i = needsWrap.length - 1; i >= 0; i--) {
|
|
3917
|
-
let wrapper = doc3.createElement(needsWrap[i]);
|
|
3918
|
-
while (wrap.firstChild)
|
|
3919
|
-
wrapper.appendChild(wrap.firstChild);
|
|
3920
|
-
wrap.appendChild(wrapper);
|
|
3921
|
-
wrappers++;
|
|
3922
|
-
}
|
|
3923
|
-
firstChild = wrap.firstChild;
|
|
3924
|
-
}
|
|
3925
|
-
if (firstChild && firstChild.nodeType == 1)
|
|
3926
|
-
firstChild.setAttribute("data-pm-slice", `${openStart} ${openEnd}${wrappers ? ` -${wrappers}` : ""} ${JSON.stringify(context)}`);
|
|
3927
|
-
let text = view.someProp("clipboardTextSerializer", (f) => f(slice, view)) || slice.content.textBetween(0, slice.content.size, "\n\n");
|
|
3928
|
-
return { dom: wrap, text, slice };
|
|
3929
|
-
}
|
|
3930
|
-
function parseFromClipboard(view, text, html, plainText, $context) {
|
|
3931
|
-
let inCode = $context.parent.type.spec.code;
|
|
3932
|
-
let dom, slice;
|
|
3933
|
-
if (!html && !text)
|
|
3934
|
-
return null;
|
|
3935
|
-
let asText = !!text && (plainText || inCode || !html);
|
|
3936
|
-
if (asText) {
|
|
3937
|
-
view.someProp("transformPastedText", (f) => {
|
|
3938
|
-
text = f(text, inCode || plainText, view);
|
|
3939
|
-
});
|
|
3940
|
-
if (inCode) {
|
|
3941
|
-
slice = new Slice(Fragment.from(view.state.schema.text(text.replace(/\r\n?/g, "\n"))), 0, 0);
|
|
3942
|
-
view.someProp("transformPasted", (f) => {
|
|
3943
|
-
slice = f(slice, view, true);
|
|
3944
|
-
});
|
|
3945
|
-
return slice;
|
|
3946
|
-
}
|
|
3947
|
-
let parsed = view.someProp("clipboardTextParser", (f) => f(text, $context, plainText, view));
|
|
3948
|
-
if (parsed) {
|
|
3949
|
-
slice = parsed;
|
|
3950
|
-
} else {
|
|
3951
|
-
let marks = $context.marks();
|
|
3952
|
-
let { schema } = view.state, serializer = DOMSerializer.fromSchema(schema);
|
|
3953
|
-
dom = document.createElement("div");
|
|
3954
|
-
text.split(/(?:\r\n?|\n)+/).forEach((block) => {
|
|
3955
|
-
let p = dom.appendChild(document.createElement("p"));
|
|
3956
|
-
if (block)
|
|
3957
|
-
p.appendChild(serializer.serializeNode(schema.text(block, marks)));
|
|
3958
|
-
});
|
|
3959
|
-
}
|
|
3960
|
-
} else {
|
|
3961
|
-
view.someProp("transformPastedHTML", (f) => {
|
|
3962
|
-
html = f(html, view);
|
|
3963
|
-
});
|
|
3964
|
-
dom = readHTML(html);
|
|
3965
|
-
if (webkit)
|
|
3966
|
-
restoreReplacedSpaces(dom);
|
|
3967
|
-
}
|
|
3968
|
-
let contextNode = dom && dom.querySelector("[data-pm-slice]");
|
|
3969
|
-
let sliceData = contextNode && /^(\d+) (\d+)(?: -(\d+))? (.*)/.exec(contextNode.getAttribute("data-pm-slice") || "");
|
|
3970
|
-
if (sliceData && sliceData[3])
|
|
3971
|
-
for (let i = +sliceData[3]; i > 0; i--) {
|
|
3972
|
-
let child = dom.firstChild;
|
|
3973
|
-
while (child && child.nodeType != 1)
|
|
3974
|
-
child = child.nextSibling;
|
|
3975
|
-
if (!child)
|
|
3976
|
-
break;
|
|
3977
|
-
dom = child;
|
|
3978
|
-
}
|
|
3979
|
-
if (!slice) {
|
|
3980
|
-
let parser = view.someProp("clipboardParser") || view.someProp("domParser") || DOMParser.fromSchema(view.state.schema);
|
|
3981
|
-
slice = parser.parseSlice(dom, {
|
|
3982
|
-
preserveWhitespace: !!(asText || sliceData),
|
|
3983
|
-
context: $context,
|
|
3984
|
-
ruleFromNode(dom2) {
|
|
3985
|
-
if (dom2.nodeName == "BR" && !dom2.nextSibling && dom2.parentNode && !inlineParents.test(dom2.parentNode.nodeName))
|
|
3986
|
-
return { ignore: true };
|
|
3987
|
-
return null;
|
|
3988
|
-
}
|
|
3989
|
-
});
|
|
3990
|
-
}
|
|
3991
|
-
if (sliceData) {
|
|
3992
|
-
slice = addContext(closeSlice(slice, +sliceData[1], +sliceData[2]), sliceData[4]);
|
|
3993
|
-
} else {
|
|
3994
|
-
slice = Slice.maxOpen(normalizeSiblings(slice.content, $context), true);
|
|
3995
|
-
if (slice.openStart || slice.openEnd) {
|
|
3996
|
-
let openStart = 0, openEnd = 0;
|
|
3997
|
-
for (let node = slice.content.firstChild; openStart < slice.openStart && !node.type.spec.isolating; openStart++, node = node.firstChild) {
|
|
3998
|
-
}
|
|
3999
|
-
for (let node = slice.content.lastChild; openEnd < slice.openEnd && !node.type.spec.isolating; openEnd++, node = node.lastChild) {
|
|
4000
|
-
}
|
|
4001
|
-
slice = closeSlice(slice, openStart, openEnd);
|
|
4002
|
-
}
|
|
4003
|
-
}
|
|
4004
|
-
view.someProp("transformPasted", (f) => {
|
|
4005
|
-
slice = f(slice, view, asText);
|
|
4006
|
-
});
|
|
4007
|
-
return slice;
|
|
4008
|
-
}
|
|
4009
|
-
var inlineParents = /^(a|abbr|acronym|b|cite|code|del|em|i|ins|kbd|label|output|q|ruby|s|samp|span|strong|sub|sup|time|u|tt|var)$/i;
|
|
4010
|
-
function normalizeSiblings(fragment, $context) {
|
|
4011
|
-
if (fragment.childCount < 2)
|
|
4012
|
-
return fragment;
|
|
4013
|
-
for (let d = $context.depth; d >= 0; d--) {
|
|
4014
|
-
let parent = $context.node(d);
|
|
4015
|
-
let match = parent.contentMatchAt($context.index(d));
|
|
4016
|
-
let lastWrap, result = [];
|
|
4017
|
-
fragment.forEach((node) => {
|
|
4018
|
-
if (!result)
|
|
4019
|
-
return;
|
|
4020
|
-
let wrap = match.findWrapping(node.type), inLast;
|
|
4021
|
-
if (!wrap)
|
|
4022
|
-
return result = null;
|
|
4023
|
-
if (inLast = result.length && lastWrap.length && addToSibling(wrap, lastWrap, node, result[result.length - 1], 0)) {
|
|
4024
|
-
result[result.length - 1] = inLast;
|
|
4025
|
-
} else {
|
|
4026
|
-
if (result.length)
|
|
4027
|
-
result[result.length - 1] = closeRight(result[result.length - 1], lastWrap.length);
|
|
4028
|
-
let wrapped = withWrappers(node, wrap);
|
|
4029
|
-
result.push(wrapped);
|
|
4030
|
-
match = match.matchType(wrapped.type);
|
|
4031
|
-
lastWrap = wrap;
|
|
4032
|
-
}
|
|
4033
|
-
});
|
|
4034
|
-
if (result)
|
|
4035
|
-
return Fragment.from(result);
|
|
4036
|
-
}
|
|
4037
|
-
return fragment;
|
|
4038
|
-
}
|
|
4039
|
-
function withWrappers(node, wrap, from = 0) {
|
|
4040
|
-
for (let i = wrap.length - 1; i >= from; i--)
|
|
4041
|
-
node = wrap[i].create(null, Fragment.from(node));
|
|
4042
|
-
return node;
|
|
4043
|
-
}
|
|
4044
|
-
function addToSibling(wrap, lastWrap, node, sibling, depth) {
|
|
4045
|
-
if (depth < wrap.length && depth < lastWrap.length && wrap[depth] == lastWrap[depth]) {
|
|
4046
|
-
let inner = addToSibling(wrap, lastWrap, node, sibling.lastChild, depth + 1);
|
|
4047
|
-
if (inner)
|
|
4048
|
-
return sibling.copy(sibling.content.replaceChild(sibling.childCount - 1, inner));
|
|
4049
|
-
let match = sibling.contentMatchAt(sibling.childCount);
|
|
4050
|
-
if (match.matchType(depth == wrap.length - 1 ? node.type : wrap[depth + 1]))
|
|
4051
|
-
return sibling.copy(sibling.content.append(Fragment.from(withWrappers(node, wrap, depth + 1))));
|
|
4052
|
-
}
|
|
4053
|
-
}
|
|
4054
|
-
function closeRight(node, depth) {
|
|
4055
|
-
if (depth == 0)
|
|
4056
|
-
return node;
|
|
4057
|
-
let fragment = node.content.replaceChild(node.childCount - 1, closeRight(node.lastChild, depth - 1));
|
|
4058
|
-
let fill = node.contentMatchAt(node.childCount).fillBefore(Fragment.empty, true);
|
|
4059
|
-
return node.copy(fragment.append(fill));
|
|
4060
|
-
}
|
|
4061
|
-
function closeRange(fragment, side, from, to, depth, openEnd) {
|
|
4062
|
-
let node = side < 0 ? fragment.firstChild : fragment.lastChild, inner = node.content;
|
|
4063
|
-
if (fragment.childCount > 1)
|
|
4064
|
-
openEnd = 0;
|
|
4065
|
-
if (depth < to - 1)
|
|
4066
|
-
inner = closeRange(inner, side, from, to, depth + 1, openEnd);
|
|
4067
|
-
if (depth >= from)
|
|
4068
|
-
inner = side < 0 ? node.contentMatchAt(0).fillBefore(inner, openEnd <= depth).append(inner) : inner.append(node.contentMatchAt(node.childCount).fillBefore(Fragment.empty, true));
|
|
4069
|
-
return fragment.replaceChild(side < 0 ? 0 : fragment.childCount - 1, node.copy(inner));
|
|
4070
|
-
}
|
|
4071
|
-
function closeSlice(slice, openStart, openEnd) {
|
|
4072
|
-
if (openStart < slice.openStart)
|
|
4073
|
-
slice = new Slice(closeRange(slice.content, -1, openStart, slice.openStart, 0, slice.openEnd), openStart, slice.openEnd);
|
|
4074
|
-
if (openEnd < slice.openEnd)
|
|
4075
|
-
slice = new Slice(closeRange(slice.content, 1, openEnd, slice.openEnd, 0, 0), slice.openStart, openEnd);
|
|
4076
|
-
return slice;
|
|
4077
|
-
}
|
|
4078
|
-
var wrapMap = {
|
|
4079
|
-
thead: ["table"],
|
|
4080
|
-
tbody: ["table"],
|
|
4081
|
-
tfoot: ["table"],
|
|
4082
|
-
caption: ["table"],
|
|
4083
|
-
colgroup: ["table"],
|
|
4084
|
-
col: ["table", "colgroup"],
|
|
4085
|
-
tr: ["table", "tbody"],
|
|
4086
|
-
td: ["table", "tbody", "tr"],
|
|
4087
|
-
th: ["table", "tbody", "tr"]
|
|
4088
|
-
};
|
|
4089
|
-
var _detachedDoc = null;
|
|
4090
|
-
function detachedDoc() {
|
|
4091
|
-
return _detachedDoc || (_detachedDoc = document.implementation.createHTMLDocument("title"));
|
|
4092
|
-
}
|
|
4093
|
-
var _policy = null;
|
|
4094
|
-
function maybeWrapTrusted(html) {
|
|
4095
|
-
let trustedTypes = window.trustedTypes;
|
|
4096
|
-
if (!trustedTypes)
|
|
4097
|
-
return html;
|
|
4098
|
-
if (!_policy)
|
|
4099
|
-
_policy = trustedTypes.defaultPolicy || trustedTypes.createPolicy("ProseMirrorClipboard", { createHTML: (s) => s });
|
|
4100
|
-
return _policy.createHTML(html);
|
|
4101
|
-
}
|
|
4102
|
-
function readHTML(html) {
|
|
4103
|
-
let metas = /^(\s*<meta [^>]*>)*/.exec(html);
|
|
4104
|
-
if (metas)
|
|
4105
|
-
html = html.slice(metas[0].length);
|
|
4106
|
-
let elt = detachedDoc().createElement("div");
|
|
4107
|
-
let firstTag = /<([a-z][^>\s]+)/i.exec(html), wrap;
|
|
4108
|
-
if (wrap = firstTag && wrapMap[firstTag[1].toLowerCase()])
|
|
4109
|
-
html = wrap.map((n) => "<" + n + ">").join("") + html + wrap.map((n) => "</" + n + ">").reverse().join("");
|
|
4110
|
-
elt.innerHTML = maybeWrapTrusted(html);
|
|
4111
|
-
if (wrap)
|
|
4112
|
-
for (let i = 0; i < wrap.length; i++)
|
|
4113
|
-
elt = elt.querySelector(wrap[i]) || elt;
|
|
4114
|
-
return elt;
|
|
4115
|
-
}
|
|
4116
|
-
function restoreReplacedSpaces(dom) {
|
|
4117
|
-
let nodes = dom.querySelectorAll(chrome ? "span:not([class]):not([style])" : "span.Apple-converted-space");
|
|
4118
|
-
for (let i = 0; i < nodes.length; i++) {
|
|
4119
|
-
let node = nodes[i];
|
|
4120
|
-
if (node.childNodes.length == 1 && node.textContent == "\xA0" && node.parentNode)
|
|
4121
|
-
node.parentNode.replaceChild(dom.ownerDocument.createTextNode(" "), node);
|
|
4122
|
-
}
|
|
4123
|
-
}
|
|
4124
|
-
function addContext(slice, context) {
|
|
4125
|
-
if (!slice.size)
|
|
4126
|
-
return slice;
|
|
4127
|
-
let schema = slice.content.firstChild.type.schema, array;
|
|
4128
|
-
try {
|
|
4129
|
-
array = JSON.parse(context);
|
|
4130
|
-
} catch (e) {
|
|
4131
|
-
return slice;
|
|
4132
|
-
}
|
|
4133
|
-
let { content, openStart, openEnd } = slice;
|
|
4134
|
-
for (let i = array.length - 2; i >= 0; i -= 2) {
|
|
4135
|
-
let type = schema.nodes[array[i]];
|
|
4136
|
-
if (!type || type.hasRequiredAttrs())
|
|
4137
|
-
break;
|
|
4138
|
-
content = Fragment.from(type.create(array[i + 1], content));
|
|
4139
|
-
openStart++;
|
|
4140
|
-
openEnd++;
|
|
4141
|
-
}
|
|
4142
|
-
return new Slice(content, openStart, openEnd);
|
|
4143
|
-
}
|
|
4144
|
-
var handlers = {};
|
|
4145
|
-
var editHandlers = {};
|
|
4146
|
-
function setSelectionOrigin(view, origin) {
|
|
4147
|
-
view.input.lastSelectionOrigin = origin;
|
|
4148
|
-
view.input.lastSelectionTime = Date.now();
|
|
4149
|
-
}
|
|
4150
|
-
editHandlers.keydown = (view, _event) => {
|
|
4151
|
-
let event = _event;
|
|
4152
|
-
view.input.shiftKey = event.keyCode == 16 || event.shiftKey;
|
|
4153
|
-
if (inOrNearComposition(view, event))
|
|
4154
|
-
return;
|
|
4155
|
-
view.input.lastKeyCode = event.keyCode;
|
|
4156
|
-
view.input.lastKeyCodeTime = Date.now();
|
|
4157
|
-
if (android && chrome && event.keyCode == 13)
|
|
4158
|
-
return;
|
|
4159
|
-
if (event.keyCode != 229)
|
|
4160
|
-
view.domObserver.forceFlush();
|
|
4161
|
-
if (ios && event.keyCode == 13 && !event.ctrlKey && !event.altKey && !event.metaKey) {
|
|
4162
|
-
let now = Date.now();
|
|
4163
|
-
view.input.lastIOSEnter = now;
|
|
4164
|
-
view.input.lastIOSEnterFallbackTimeout = setTimeout(() => {
|
|
4165
|
-
if (view.input.lastIOSEnter == now) {
|
|
4166
|
-
view.someProp("handleKeyDown", (f) => f(view, keyEvent(13, "Enter")));
|
|
4167
|
-
view.input.lastIOSEnter = 0;
|
|
4168
|
-
}
|
|
4169
|
-
}, 200);
|
|
4170
|
-
} else if (view.someProp("handleKeyDown", (f) => f(view, event)) || captureKeyDown(view, event)) {
|
|
4171
|
-
event.preventDefault();
|
|
4172
|
-
} else {
|
|
4173
|
-
setSelectionOrigin(view, "key");
|
|
4174
|
-
}
|
|
4175
|
-
};
|
|
4176
|
-
editHandlers.keyup = (view, event) => {
|
|
4177
|
-
if (event.keyCode == 16)
|
|
4178
|
-
view.input.shiftKey = false;
|
|
4179
|
-
};
|
|
4180
|
-
editHandlers.keypress = (view, _event) => {
|
|
4181
|
-
let event = _event;
|
|
4182
|
-
if (inOrNearComposition(view, event) || !event.charCode || event.ctrlKey && !event.altKey || mac && event.metaKey)
|
|
4183
|
-
return;
|
|
4184
|
-
if (view.someProp("handleKeyPress", (f) => f(view, event))) {
|
|
4185
|
-
event.preventDefault();
|
|
4186
|
-
return;
|
|
4187
|
-
}
|
|
4188
|
-
let sel = view.state.selection;
|
|
4189
|
-
if (!(sel instanceof TextSelection) || !sel.$from.sameParent(sel.$to)) {
|
|
4190
|
-
let text = String.fromCharCode(event.charCode);
|
|
4191
|
-
let deflt = () => view.state.tr.insertText(text).scrollIntoView();
|
|
4192
|
-
if (!/[\r\n]/.test(text) && !view.someProp("handleTextInput", (f) => f(view, sel.$from.pos, sel.$to.pos, text, deflt)))
|
|
4193
|
-
view.dispatch(deflt());
|
|
4194
|
-
event.preventDefault();
|
|
4195
|
-
}
|
|
4196
|
-
};
|
|
4197
|
-
function eventCoords(event) {
|
|
4198
|
-
return { left: event.clientX, top: event.clientY };
|
|
4199
|
-
}
|
|
4200
|
-
function isNear(event, click) {
|
|
4201
|
-
let dx = click.x - event.clientX, dy = click.y - event.clientY;
|
|
4202
|
-
return dx * dx + dy * dy < 100;
|
|
4203
|
-
}
|
|
4204
|
-
function runHandlerOnContext(view, propName, pos, inside, event) {
|
|
4205
|
-
if (inside == -1)
|
|
4206
|
-
return false;
|
|
4207
|
-
let $pos = view.state.doc.resolve(inside);
|
|
4208
|
-
for (let i = $pos.depth + 1; i > 0; i--) {
|
|
4209
|
-
if (view.someProp(propName, (f) => i > $pos.depth ? f(view, pos, $pos.nodeAfter, $pos.before(i), event, true) : f(view, pos, $pos.node(i), $pos.before(i), event, false)))
|
|
4210
|
-
return true;
|
|
4211
|
-
}
|
|
4212
|
-
return false;
|
|
4213
|
-
}
|
|
4214
|
-
function updateSelection(view, selection, origin) {
|
|
4215
|
-
if (!view.focused)
|
|
4216
|
-
view.focus();
|
|
4217
|
-
if (view.state.selection.eq(selection))
|
|
4218
|
-
return;
|
|
4219
|
-
let tr = view.state.tr.setSelection(selection);
|
|
4220
|
-
tr.setMeta("pointer", true);
|
|
4221
|
-
view.dispatch(tr);
|
|
4222
|
-
}
|
|
4223
|
-
function selectClickedLeaf(view, inside) {
|
|
4224
|
-
if (inside == -1)
|
|
4225
|
-
return false;
|
|
4226
|
-
let $pos = view.state.doc.resolve(inside), node = $pos.nodeAfter;
|
|
4227
|
-
if (node && node.isAtom && NodeSelection.isSelectable(node)) {
|
|
4228
|
-
updateSelection(view, new NodeSelection($pos));
|
|
4229
|
-
return true;
|
|
4230
|
-
}
|
|
4231
|
-
return false;
|
|
4232
|
-
}
|
|
4233
|
-
function selectClickedNode(view, inside) {
|
|
4234
|
-
if (inside == -1)
|
|
4235
|
-
return false;
|
|
4236
|
-
let sel = view.state.selection, selectedNode, selectAt;
|
|
4237
|
-
if (sel instanceof NodeSelection)
|
|
4238
|
-
selectedNode = sel.node;
|
|
4239
|
-
let $pos = view.state.doc.resolve(inside);
|
|
4240
|
-
for (let i = $pos.depth + 1; i > 0; i--) {
|
|
4241
|
-
let node = i > $pos.depth ? $pos.nodeAfter : $pos.node(i);
|
|
4242
|
-
if (NodeSelection.isSelectable(node)) {
|
|
4243
|
-
if (selectedNode && sel.$from.depth > 0 && i >= sel.$from.depth && $pos.before(sel.$from.depth + 1) == sel.$from.pos)
|
|
4244
|
-
selectAt = $pos.before(sel.$from.depth);
|
|
4245
|
-
else
|
|
4246
|
-
selectAt = $pos.before(i);
|
|
4247
|
-
break;
|
|
4248
|
-
}
|
|
4249
|
-
}
|
|
4250
|
-
if (selectAt != null) {
|
|
4251
|
-
updateSelection(view, NodeSelection.create(view.state.doc, selectAt));
|
|
4252
|
-
return true;
|
|
4253
|
-
} else {
|
|
4254
|
-
return false;
|
|
4255
|
-
}
|
|
4256
|
-
}
|
|
4257
|
-
function handleSingleClick(view, pos, inside, event, selectNode) {
|
|
4258
|
-
return runHandlerOnContext(view, "handleClickOn", pos, inside, event) || view.someProp("handleClick", (f) => f(view, pos, event)) || (selectNode ? selectClickedNode(view, inside) : selectClickedLeaf(view, inside));
|
|
4259
|
-
}
|
|
4260
|
-
function handleDoubleClick(view, pos, inside, event) {
|
|
4261
|
-
return runHandlerOnContext(view, "handleDoubleClickOn", pos, inside, event) || view.someProp("handleDoubleClick", (f) => f(view, pos, event));
|
|
4262
|
-
}
|
|
4263
|
-
function handleTripleClick(view, pos, inside, event) {
|
|
4264
|
-
return runHandlerOnContext(view, "handleTripleClickOn", pos, inside, event) || view.someProp("handleTripleClick", (f) => f(view, pos, event)) || defaultTripleClick(view, inside, event);
|
|
4265
|
-
}
|
|
4266
|
-
function defaultTripleClick(view, inside, event) {
|
|
4267
|
-
if (event.button != 0)
|
|
4268
|
-
return false;
|
|
4269
|
-
let doc3 = view.state.doc;
|
|
4270
|
-
if (inside == -1) {
|
|
4271
|
-
if (doc3.inlineContent) {
|
|
4272
|
-
updateSelection(view, TextSelection.create(doc3, 0, doc3.content.size));
|
|
4273
|
-
return true;
|
|
4274
|
-
}
|
|
4275
|
-
return false;
|
|
4276
|
-
}
|
|
4277
|
-
let $pos = doc3.resolve(inside);
|
|
4278
|
-
for (let i = $pos.depth + 1; i > 0; i--) {
|
|
4279
|
-
let node = i > $pos.depth ? $pos.nodeAfter : $pos.node(i);
|
|
4280
|
-
let nodePos = $pos.before(i);
|
|
4281
|
-
if (node.inlineContent)
|
|
4282
|
-
updateSelection(view, TextSelection.create(doc3, nodePos + 1, nodePos + 1 + node.content.size));
|
|
4283
|
-
else if (NodeSelection.isSelectable(node))
|
|
4284
|
-
updateSelection(view, NodeSelection.create(doc3, nodePos));
|
|
4285
|
-
else
|
|
4286
|
-
continue;
|
|
4287
|
-
return true;
|
|
4288
|
-
}
|
|
4289
|
-
}
|
|
4290
|
-
function forceDOMFlush(view) {
|
|
4291
|
-
return endComposition(view);
|
|
4292
|
-
}
|
|
4293
|
-
var selectNodeModifier = mac ? "metaKey" : "ctrlKey";
|
|
4294
|
-
handlers.mousedown = (view, _event) => {
|
|
4295
|
-
let event = _event;
|
|
4296
|
-
view.input.shiftKey = event.shiftKey;
|
|
4297
|
-
let flushed = forceDOMFlush(view);
|
|
4298
|
-
let now = Date.now(), type = "singleClick";
|
|
4299
|
-
if (now - view.input.lastClick.time < 500 && isNear(event, view.input.lastClick) && !event[selectNodeModifier] && view.input.lastClick.button == event.button) {
|
|
4300
|
-
if (view.input.lastClick.type == "singleClick")
|
|
4301
|
-
type = "doubleClick";
|
|
4302
|
-
else if (view.input.lastClick.type == "doubleClick")
|
|
4303
|
-
type = "tripleClick";
|
|
4304
|
-
}
|
|
4305
|
-
view.input.lastClick = { time: now, x: event.clientX, y: event.clientY, type, button: event.button };
|
|
4306
|
-
let pos = view.posAtCoords(eventCoords(event));
|
|
4307
|
-
if (!pos)
|
|
4308
|
-
return;
|
|
4309
|
-
if (type == "singleClick") {
|
|
4310
|
-
if (view.input.mouseDown)
|
|
4311
|
-
view.input.mouseDown.done();
|
|
4312
|
-
view.input.mouseDown = new MouseDown(view, pos, event, !!flushed);
|
|
4313
|
-
} else if ((type == "doubleClick" ? handleDoubleClick : handleTripleClick)(view, pos.pos, pos.inside, event)) {
|
|
4314
|
-
event.preventDefault();
|
|
4315
|
-
} else {
|
|
4316
|
-
setSelectionOrigin(view, "pointer");
|
|
4317
|
-
}
|
|
4318
|
-
};
|
|
4319
|
-
var MouseDown = class {
|
|
4320
|
-
constructor(view, pos, event, flushed) {
|
|
4321
|
-
this.view = view;
|
|
4322
|
-
this.pos = pos;
|
|
4323
|
-
this.event = event;
|
|
4324
|
-
this.flushed = flushed;
|
|
4325
|
-
this.delayedSelectionSync = false;
|
|
4326
|
-
this.mightDrag = null;
|
|
4327
|
-
this.startDoc = view.state.doc;
|
|
4328
|
-
this.selectNode = !!event[selectNodeModifier];
|
|
4329
|
-
this.allowDefault = event.shiftKey;
|
|
4330
|
-
let targetNode, targetPos;
|
|
4331
|
-
if (pos.inside > -1) {
|
|
4332
|
-
targetNode = view.state.doc.nodeAt(pos.inside);
|
|
4333
|
-
targetPos = pos.inside;
|
|
4334
|
-
} else {
|
|
4335
|
-
let $pos = view.state.doc.resolve(pos.pos);
|
|
4336
|
-
targetNode = $pos.parent;
|
|
4337
|
-
targetPos = $pos.depth ? $pos.before() : 0;
|
|
4338
|
-
}
|
|
4339
|
-
const target = flushed ? null : event.target;
|
|
4340
|
-
const targetDesc = target ? view.docView.nearestDesc(target, true) : null;
|
|
4341
|
-
this.target = targetDesc && targetDesc.nodeDOM.nodeType == 1 ? targetDesc.nodeDOM : null;
|
|
4342
|
-
let { selection } = view.state;
|
|
4343
|
-
if (event.button == 0 && targetNode.type.spec.draggable && targetNode.type.spec.selectable !== false || selection instanceof NodeSelection && selection.from <= targetPos && selection.to > targetPos)
|
|
4344
|
-
this.mightDrag = {
|
|
4345
|
-
node: targetNode,
|
|
4346
|
-
pos: targetPos,
|
|
4347
|
-
addAttr: !!(this.target && !this.target.draggable),
|
|
4348
|
-
setUneditable: !!(this.target && gecko && !this.target.hasAttribute("contentEditable"))
|
|
4349
|
-
};
|
|
4350
|
-
if (this.target && this.mightDrag && (this.mightDrag.addAttr || this.mightDrag.setUneditable)) {
|
|
4351
|
-
this.view.domObserver.stop();
|
|
4352
|
-
if (this.mightDrag.addAttr)
|
|
4353
|
-
this.target.draggable = true;
|
|
4354
|
-
if (this.mightDrag.setUneditable)
|
|
4355
|
-
setTimeout(() => {
|
|
4356
|
-
if (this.view.input.mouseDown == this)
|
|
4357
|
-
this.target.setAttribute("contentEditable", "false");
|
|
4358
|
-
}, 20);
|
|
4359
|
-
this.view.domObserver.start();
|
|
4360
|
-
}
|
|
4361
|
-
view.root.addEventListener("mouseup", this.up = this.up.bind(this));
|
|
4362
|
-
view.root.addEventListener("mousemove", this.move = this.move.bind(this));
|
|
4363
|
-
setSelectionOrigin(view, "pointer");
|
|
4364
|
-
}
|
|
4365
|
-
done() {
|
|
4366
|
-
this.view.root.removeEventListener("mouseup", this.up);
|
|
4367
|
-
this.view.root.removeEventListener("mousemove", this.move);
|
|
4368
|
-
if (this.mightDrag && this.target) {
|
|
4369
|
-
this.view.domObserver.stop();
|
|
4370
|
-
if (this.mightDrag.addAttr)
|
|
4371
|
-
this.target.removeAttribute("draggable");
|
|
4372
|
-
if (this.mightDrag.setUneditable)
|
|
4373
|
-
this.target.removeAttribute("contentEditable");
|
|
4374
|
-
this.view.domObserver.start();
|
|
4375
|
-
}
|
|
4376
|
-
if (this.delayedSelectionSync)
|
|
4377
|
-
setTimeout(() => selectionToDOM(this.view));
|
|
4378
|
-
this.view.input.mouseDown = null;
|
|
4379
|
-
}
|
|
4380
|
-
up(event) {
|
|
4381
|
-
this.done();
|
|
4382
|
-
if (!this.view.dom.contains(event.target))
|
|
4383
|
-
return;
|
|
4384
|
-
let pos = this.pos;
|
|
4385
|
-
if (this.view.state.doc != this.startDoc)
|
|
4386
|
-
pos = this.view.posAtCoords(eventCoords(event));
|
|
4387
|
-
this.updateAllowDefault(event);
|
|
4388
|
-
if (this.allowDefault || !pos) {
|
|
4389
|
-
setSelectionOrigin(this.view, "pointer");
|
|
4390
|
-
} else if (handleSingleClick(this.view, pos.pos, pos.inside, event, this.selectNode)) {
|
|
4391
|
-
event.preventDefault();
|
|
4392
|
-
} else if (event.button == 0 && (this.flushed || // Safari ignores clicks on draggable elements
|
|
4393
|
-
safari && this.mightDrag && !this.mightDrag.node.isAtom || // Chrome will sometimes treat a node selection as a
|
|
4394
|
-
// cursor, but still report that the node is selected
|
|
4395
|
-
// when asked through getSelection. You'll then get a
|
|
4396
|
-
// situation where clicking at the point where that
|
|
4397
|
-
// (hidden) cursor is doesn't change the selection, and
|
|
4398
|
-
// thus doesn't get a reaction from ProseMirror. This
|
|
4399
|
-
// works around that.
|
|
4400
|
-
chrome && !this.view.state.selection.visible && Math.min(Math.abs(pos.pos - this.view.state.selection.from), Math.abs(pos.pos - this.view.state.selection.to)) <= 2)) {
|
|
4401
|
-
updateSelection(this.view, Selection.near(this.view.state.doc.resolve(pos.pos)));
|
|
4402
|
-
event.preventDefault();
|
|
4403
|
-
} else {
|
|
4404
|
-
setSelectionOrigin(this.view, "pointer");
|
|
4405
|
-
}
|
|
4406
|
-
}
|
|
4407
|
-
move(event) {
|
|
4408
|
-
this.updateAllowDefault(event);
|
|
4409
|
-
setSelectionOrigin(this.view, "pointer");
|
|
4410
|
-
if (event.buttons == 0)
|
|
4411
|
-
this.done();
|
|
4412
|
-
}
|
|
4413
|
-
updateAllowDefault(event) {
|
|
4414
|
-
if (!this.allowDefault && (Math.abs(this.event.x - event.clientX) > 4 || Math.abs(this.event.y - event.clientY) > 4))
|
|
4415
|
-
this.allowDefault = true;
|
|
4416
|
-
}
|
|
4417
|
-
};
|
|
4418
|
-
handlers.touchstart = (view) => {
|
|
4419
|
-
view.input.lastTouch = Date.now();
|
|
4420
|
-
forceDOMFlush(view);
|
|
4421
|
-
setSelectionOrigin(view, "pointer");
|
|
4422
|
-
};
|
|
4423
|
-
handlers.touchmove = (view) => {
|
|
4424
|
-
view.input.lastTouch = Date.now();
|
|
4425
|
-
setSelectionOrigin(view, "pointer");
|
|
4426
|
-
};
|
|
4427
|
-
handlers.contextmenu = (view) => forceDOMFlush(view);
|
|
4428
|
-
function inOrNearComposition(view, event) {
|
|
4429
|
-
if (view.composing)
|
|
4430
|
-
return true;
|
|
4431
|
-
if (safari && Math.abs(event.timeStamp - view.input.compositionEndedAt) < 500) {
|
|
4432
|
-
view.input.compositionEndedAt = -2e8;
|
|
4433
|
-
return true;
|
|
4434
|
-
}
|
|
4435
|
-
return false;
|
|
4436
|
-
}
|
|
4437
|
-
var timeoutComposition = android ? 5e3 : -1;
|
|
4438
|
-
editHandlers.compositionstart = editHandlers.compositionupdate = (view) => {
|
|
4439
|
-
if (!view.composing) {
|
|
4440
|
-
view.domObserver.flush();
|
|
4441
|
-
let { state } = view, $pos = state.selection.$to;
|
|
4442
|
-
if (state.selection instanceof TextSelection && (state.storedMarks || !$pos.textOffset && $pos.parentOffset && $pos.nodeBefore.marks.some((m) => m.type.spec.inclusive === false) || chrome && windows && selectionBeforeUneditable(view))) {
|
|
4443
|
-
view.markCursor = view.state.storedMarks || $pos.marks();
|
|
4444
|
-
endComposition(view, true);
|
|
4445
|
-
view.markCursor = null;
|
|
4446
|
-
} else {
|
|
4447
|
-
endComposition(view, !state.selection.empty);
|
|
4448
|
-
if (gecko && state.selection.empty && $pos.parentOffset && !$pos.textOffset && $pos.nodeBefore.marks.length) {
|
|
4449
|
-
let sel = view.domSelectionRange();
|
|
4450
|
-
for (let node = sel.focusNode, offset = sel.focusOffset; node && node.nodeType == 1 && offset != 0; ) {
|
|
4451
|
-
let before = offset < 0 ? node.lastChild : node.childNodes[offset - 1];
|
|
4452
|
-
if (!before)
|
|
4453
|
-
break;
|
|
4454
|
-
if (before.nodeType == 3) {
|
|
4455
|
-
let sel2 = view.domSelection();
|
|
4456
|
-
if (sel2)
|
|
4457
|
-
sel2.collapse(before, before.nodeValue.length);
|
|
4458
|
-
break;
|
|
4459
|
-
} else {
|
|
4460
|
-
node = before;
|
|
4461
|
-
offset = -1;
|
|
4462
|
-
}
|
|
4463
|
-
}
|
|
4464
|
-
}
|
|
4465
|
-
}
|
|
4466
|
-
view.input.composing = true;
|
|
4467
|
-
}
|
|
4468
|
-
scheduleComposeEnd(view, timeoutComposition);
|
|
4469
|
-
};
|
|
4470
|
-
function selectionBeforeUneditable(view) {
|
|
4471
|
-
let { focusNode, focusOffset } = view.domSelectionRange();
|
|
4472
|
-
if (!focusNode || focusNode.nodeType != 1 || focusOffset >= focusNode.childNodes.length)
|
|
4473
|
-
return false;
|
|
4474
|
-
let next = focusNode.childNodes[focusOffset];
|
|
4475
|
-
return next.nodeType == 1 && next.contentEditable == "false";
|
|
4476
|
-
}
|
|
4477
|
-
editHandlers.compositionend = (view, event) => {
|
|
4478
|
-
if (view.composing) {
|
|
4479
|
-
view.input.composing = false;
|
|
4480
|
-
view.input.compositionEndedAt = event.timeStamp;
|
|
4481
|
-
view.input.compositionPendingChanges = view.domObserver.pendingRecords().length ? view.input.compositionID : 0;
|
|
4482
|
-
view.input.compositionNode = null;
|
|
4483
|
-
if (view.input.badSafariComposition)
|
|
4484
|
-
view.domObserver.forceFlush();
|
|
4485
|
-
else if (view.input.compositionPendingChanges)
|
|
4486
|
-
Promise.resolve().then(() => view.domObserver.flush());
|
|
4487
|
-
view.input.compositionID++;
|
|
4488
|
-
scheduleComposeEnd(view, 20);
|
|
4489
|
-
}
|
|
4490
|
-
};
|
|
4491
|
-
function scheduleComposeEnd(view, delay) {
|
|
4492
|
-
clearTimeout(view.input.composingTimeout);
|
|
4493
|
-
if (delay > -1)
|
|
4494
|
-
view.input.composingTimeout = setTimeout(() => endComposition(view), delay);
|
|
4495
|
-
}
|
|
4496
|
-
function clearComposition(view) {
|
|
4497
|
-
if (view.composing) {
|
|
4498
|
-
view.input.composing = false;
|
|
4499
|
-
view.input.compositionEndedAt = timestampFromCustomEvent();
|
|
4500
|
-
}
|
|
4501
|
-
while (view.input.compositionNodes.length > 0)
|
|
4502
|
-
view.input.compositionNodes.pop().markParentsDirty();
|
|
4503
|
-
}
|
|
4504
|
-
function timestampFromCustomEvent() {
|
|
4505
|
-
let event = document.createEvent("Event");
|
|
4506
|
-
event.initEvent("event", true, true);
|
|
4507
|
-
return event.timeStamp;
|
|
4508
|
-
}
|
|
4509
|
-
function endComposition(view, restarting = false) {
|
|
4510
|
-
if (android && view.domObserver.flushingSoon >= 0)
|
|
4511
|
-
return;
|
|
4512
|
-
view.domObserver.forceFlush();
|
|
4513
|
-
clearComposition(view);
|
|
4514
|
-
if (restarting || view.docView && view.docView.dirty) {
|
|
4515
|
-
let sel = selectionFromDOM(view), cur = view.state.selection;
|
|
4516
|
-
if (sel && !sel.eq(cur))
|
|
4517
|
-
view.dispatch(view.state.tr.setSelection(sel));
|
|
4518
|
-
else if ((view.markCursor || restarting) && !cur.$from.node(cur.$from.sharedDepth(cur.to)).inlineContent)
|
|
4519
|
-
view.dispatch(view.state.tr.deleteSelection());
|
|
4520
|
-
else
|
|
4521
|
-
view.updateState(view.state);
|
|
4522
|
-
return true;
|
|
4523
|
-
}
|
|
4524
|
-
return false;
|
|
4525
|
-
}
|
|
4526
|
-
function captureCopy(view, dom) {
|
|
4527
|
-
if (!view.dom.parentNode)
|
|
4528
|
-
return;
|
|
4529
|
-
let wrap = view.dom.parentNode.appendChild(document.createElement("div"));
|
|
4530
|
-
wrap.appendChild(dom);
|
|
4531
|
-
wrap.style.cssText = "position: fixed; left: -10000px; top: 10px";
|
|
4532
|
-
let sel = getSelection(), range = document.createRange();
|
|
4533
|
-
range.selectNodeContents(dom);
|
|
4534
|
-
view.dom.blur();
|
|
4535
|
-
sel.removeAllRanges();
|
|
4536
|
-
sel.addRange(range);
|
|
4537
|
-
setTimeout(() => {
|
|
4538
|
-
if (wrap.parentNode)
|
|
4539
|
-
wrap.parentNode.removeChild(wrap);
|
|
4540
|
-
view.focus();
|
|
4541
|
-
}, 50);
|
|
4542
|
-
}
|
|
4543
|
-
var brokenClipboardAPI = ie && ie_version < 15 || ios && webkit_version < 604;
|
|
4544
|
-
handlers.copy = editHandlers.cut = (view, _event) => {
|
|
4545
|
-
let event = _event;
|
|
4546
|
-
let sel = view.state.selection, cut = event.type == "cut";
|
|
4547
|
-
if (sel.empty)
|
|
4548
|
-
return;
|
|
4549
|
-
let data = brokenClipboardAPI ? null : event.clipboardData;
|
|
4550
|
-
let slice = sel.content(), { dom, text } = serializeForClipboard(view, slice);
|
|
4551
|
-
if (data) {
|
|
4552
|
-
event.preventDefault();
|
|
4553
|
-
data.clearData();
|
|
4554
|
-
data.setData("text/html", dom.innerHTML);
|
|
4555
|
-
data.setData("text/plain", text);
|
|
4556
|
-
} else {
|
|
4557
|
-
captureCopy(view, dom);
|
|
4558
|
-
}
|
|
4559
|
-
if (cut)
|
|
4560
|
-
view.dispatch(view.state.tr.deleteSelection().scrollIntoView().setMeta("uiEvent", "cut"));
|
|
4561
|
-
};
|
|
4562
|
-
function sliceSingleNode(slice) {
|
|
4563
|
-
return slice.openStart == 0 && slice.openEnd == 0 && slice.content.childCount == 1 ? slice.content.firstChild : null;
|
|
4564
|
-
}
|
|
4565
|
-
function capturePaste(view, event) {
|
|
4566
|
-
if (!view.dom.parentNode)
|
|
4567
|
-
return;
|
|
4568
|
-
let plainText = view.input.shiftKey || view.state.selection.$from.parent.type.spec.code;
|
|
4569
|
-
let target = view.dom.parentNode.appendChild(document.createElement(plainText ? "textarea" : "div"));
|
|
4570
|
-
if (!plainText)
|
|
4571
|
-
target.contentEditable = "true";
|
|
4572
|
-
target.style.cssText = "position: fixed; left: -10000px; top: 10px";
|
|
4573
|
-
target.focus();
|
|
4574
|
-
let plain = view.input.shiftKey && view.input.lastKeyCode != 45;
|
|
4575
|
-
setTimeout(() => {
|
|
4576
|
-
view.focus();
|
|
4577
|
-
if (target.parentNode)
|
|
4578
|
-
target.parentNode.removeChild(target);
|
|
4579
|
-
if (plainText)
|
|
4580
|
-
doPaste(view, target.value, null, plain, event);
|
|
4581
|
-
else
|
|
4582
|
-
doPaste(view, target.textContent, target.innerHTML, plain, event);
|
|
4583
|
-
}, 50);
|
|
4584
|
-
}
|
|
4585
|
-
function doPaste(view, text, html, preferPlain, event) {
|
|
4586
|
-
let slice = parseFromClipboard(view, text, html, preferPlain, view.state.selection.$from);
|
|
4587
|
-
if (view.someProp("handlePaste", (f) => f(view, event, slice || Slice.empty)))
|
|
4588
|
-
return true;
|
|
4589
|
-
if (!slice)
|
|
4590
|
-
return false;
|
|
4591
|
-
let singleNode = sliceSingleNode(slice);
|
|
4592
|
-
let tr = singleNode ? view.state.tr.replaceSelectionWith(singleNode, preferPlain) : view.state.tr.replaceSelection(slice);
|
|
4593
|
-
view.dispatch(tr.scrollIntoView().setMeta("paste", true).setMeta("uiEvent", "paste"));
|
|
4594
|
-
return true;
|
|
4595
|
-
}
|
|
4596
|
-
function getText(clipboardData) {
|
|
4597
|
-
let text = clipboardData.getData("text/plain") || clipboardData.getData("Text");
|
|
4598
|
-
if (text)
|
|
4599
|
-
return text;
|
|
4600
|
-
let uris = clipboardData.getData("text/uri-list");
|
|
4601
|
-
return uris ? uris.replace(/\r?\n/g, " ") : "";
|
|
4602
|
-
}
|
|
4603
|
-
editHandlers.paste = (view, _event) => {
|
|
4604
|
-
let event = _event;
|
|
4605
|
-
if (view.composing && !android)
|
|
4606
|
-
return;
|
|
4607
|
-
let data = brokenClipboardAPI ? null : event.clipboardData;
|
|
4608
|
-
let plain = view.input.shiftKey && view.input.lastKeyCode != 45;
|
|
4609
|
-
if (data && doPaste(view, getText(data), data.getData("text/html"), plain, event))
|
|
4610
|
-
event.preventDefault();
|
|
4611
|
-
else
|
|
4612
|
-
capturePaste(view, event);
|
|
4613
|
-
};
|
|
4614
|
-
var Dragging = class {
|
|
4615
|
-
constructor(slice, move, node) {
|
|
4616
|
-
this.slice = slice;
|
|
4617
|
-
this.move = move;
|
|
4618
|
-
this.node = node;
|
|
4619
|
-
}
|
|
4620
|
-
};
|
|
4621
|
-
var dragCopyModifier = mac ? "altKey" : "ctrlKey";
|
|
4622
|
-
function dragMoves(view, event) {
|
|
4623
|
-
let moves = view.someProp("dragCopies", (test) => !test(event));
|
|
4624
|
-
return moves != null ? moves : !event[dragCopyModifier];
|
|
4625
|
-
}
|
|
4626
|
-
handlers.dragstart = (view, _event) => {
|
|
4627
|
-
let event = _event;
|
|
4628
|
-
let mouseDown = view.input.mouseDown;
|
|
4629
|
-
if (mouseDown)
|
|
4630
|
-
mouseDown.done();
|
|
4631
|
-
if (!event.dataTransfer)
|
|
4632
|
-
return;
|
|
4633
|
-
let sel = view.state.selection;
|
|
4634
|
-
let pos = sel.empty ? null : view.posAtCoords(eventCoords(event));
|
|
4635
|
-
let node;
|
|
4636
|
-
if (pos && pos.pos >= sel.from && pos.pos <= (sel instanceof NodeSelection ? sel.to - 1 : sel.to)) ;
|
|
4637
|
-
else if (mouseDown && mouseDown.mightDrag) {
|
|
4638
|
-
node = NodeSelection.create(view.state.doc, mouseDown.mightDrag.pos);
|
|
4639
|
-
} else if (event.target && event.target.nodeType == 1) {
|
|
4640
|
-
let desc = view.docView.nearestDesc(event.target, true);
|
|
4641
|
-
if (desc && desc.node.type.spec.draggable && desc != view.docView)
|
|
4642
|
-
node = NodeSelection.create(view.state.doc, desc.posBefore);
|
|
4643
|
-
}
|
|
4644
|
-
let draggedSlice = (node || view.state.selection).content();
|
|
4645
|
-
let { dom, text, slice } = serializeForClipboard(view, draggedSlice);
|
|
4646
|
-
if (!event.dataTransfer.files.length || !chrome || chrome_version > 120)
|
|
4647
|
-
event.dataTransfer.clearData();
|
|
4648
|
-
event.dataTransfer.setData(brokenClipboardAPI ? "Text" : "text/html", dom.innerHTML);
|
|
4649
|
-
event.dataTransfer.effectAllowed = "copyMove";
|
|
4650
|
-
if (!brokenClipboardAPI)
|
|
4651
|
-
event.dataTransfer.setData("text/plain", text);
|
|
4652
|
-
view.dragging = new Dragging(slice, dragMoves(view, event), node);
|
|
4653
|
-
};
|
|
4654
|
-
handlers.dragend = (view) => {
|
|
4655
|
-
let dragging = view.dragging;
|
|
4656
|
-
window.setTimeout(() => {
|
|
4657
|
-
if (view.dragging == dragging)
|
|
4658
|
-
view.dragging = null;
|
|
4659
|
-
}, 50);
|
|
4660
|
-
};
|
|
4661
|
-
editHandlers.dragover = editHandlers.dragenter = (_, e) => e.preventDefault();
|
|
4662
|
-
editHandlers.drop = (view, event) => {
|
|
4663
|
-
try {
|
|
4664
|
-
handleDrop(view, event, view.dragging);
|
|
4665
|
-
} finally {
|
|
4666
|
-
view.dragging = null;
|
|
4667
|
-
}
|
|
4668
|
-
};
|
|
4669
|
-
function handleDrop(view, event, dragging) {
|
|
4670
|
-
if (!event.dataTransfer)
|
|
4671
|
-
return;
|
|
4672
|
-
let eventPos = view.posAtCoords(eventCoords(event));
|
|
4673
|
-
if (!eventPos)
|
|
4674
|
-
return;
|
|
4675
|
-
let $mouse = view.state.doc.resolve(eventPos.pos);
|
|
4676
|
-
let slice = dragging && dragging.slice;
|
|
4677
|
-
if (slice) {
|
|
4678
|
-
view.someProp("transformPasted", (f) => {
|
|
4679
|
-
slice = f(slice, view, false);
|
|
4680
|
-
});
|
|
4681
|
-
} else {
|
|
4682
|
-
slice = parseFromClipboard(view, getText(event.dataTransfer), brokenClipboardAPI ? null : event.dataTransfer.getData("text/html"), false, $mouse);
|
|
4683
|
-
}
|
|
4684
|
-
let move = !!(dragging && dragMoves(view, event));
|
|
4685
|
-
if (view.someProp("handleDrop", (f) => f(view, event, slice || Slice.empty, move))) {
|
|
4686
|
-
event.preventDefault();
|
|
4687
|
-
return;
|
|
4688
|
-
}
|
|
4689
|
-
if (!slice)
|
|
4690
|
-
return;
|
|
4691
|
-
event.preventDefault();
|
|
4692
|
-
let insertPos = slice ? dropPoint(view.state.doc, $mouse.pos, slice) : $mouse.pos;
|
|
4693
|
-
if (insertPos == null)
|
|
4694
|
-
insertPos = $mouse.pos;
|
|
4695
|
-
let tr = view.state.tr;
|
|
4696
|
-
if (move) {
|
|
4697
|
-
let { node } = dragging;
|
|
4698
|
-
if (node)
|
|
4699
|
-
node.replace(tr);
|
|
4700
|
-
else
|
|
4701
|
-
tr.deleteSelection();
|
|
4702
|
-
}
|
|
4703
|
-
let pos = tr.mapping.map(insertPos);
|
|
4704
|
-
let isNode = slice.openStart == 0 && slice.openEnd == 0 && slice.content.childCount == 1;
|
|
4705
|
-
let beforeInsert = tr.doc;
|
|
4706
|
-
if (isNode)
|
|
4707
|
-
tr.replaceRangeWith(pos, pos, slice.content.firstChild);
|
|
4708
|
-
else
|
|
4709
|
-
tr.replaceRange(pos, pos, slice);
|
|
4710
|
-
if (tr.doc.eq(beforeInsert))
|
|
4711
|
-
return;
|
|
4712
|
-
let $pos = tr.doc.resolve(pos);
|
|
4713
|
-
if (isNode && NodeSelection.isSelectable(slice.content.firstChild) && $pos.nodeAfter && $pos.nodeAfter.sameMarkup(slice.content.firstChild)) {
|
|
4714
|
-
tr.setSelection(new NodeSelection($pos));
|
|
4715
|
-
} else {
|
|
4716
|
-
let end = tr.mapping.map(insertPos);
|
|
4717
|
-
tr.mapping.maps[tr.mapping.maps.length - 1].forEach((_from, _to, _newFrom, newTo) => end = newTo);
|
|
4718
|
-
tr.setSelection(selectionBetween(view, $pos, tr.doc.resolve(end)));
|
|
4719
|
-
}
|
|
4720
|
-
view.focus();
|
|
4721
|
-
view.dispatch(tr.setMeta("uiEvent", "drop"));
|
|
4722
|
-
}
|
|
4723
|
-
handlers.focus = (view) => {
|
|
4724
|
-
view.input.lastFocus = Date.now();
|
|
4725
|
-
if (!view.focused) {
|
|
4726
|
-
view.domObserver.stop();
|
|
4727
|
-
view.dom.classList.add("ProseMirror-focused");
|
|
4728
|
-
view.domObserver.start();
|
|
4729
|
-
view.focused = true;
|
|
4730
|
-
setTimeout(() => {
|
|
4731
|
-
if (view.docView && view.hasFocus() && !view.domObserver.currentSelection.eq(view.domSelectionRange()))
|
|
4732
|
-
selectionToDOM(view);
|
|
4733
|
-
}, 20);
|
|
4734
|
-
}
|
|
4735
|
-
};
|
|
4736
|
-
handlers.blur = (view, _event) => {
|
|
4737
|
-
let event = _event;
|
|
4738
|
-
if (view.focused) {
|
|
4739
|
-
view.domObserver.stop();
|
|
4740
|
-
view.dom.classList.remove("ProseMirror-focused");
|
|
4741
|
-
view.domObserver.start();
|
|
4742
|
-
if (event.relatedTarget && view.dom.contains(event.relatedTarget))
|
|
4743
|
-
view.domObserver.currentSelection.clear();
|
|
4744
|
-
view.focused = false;
|
|
4745
|
-
}
|
|
4746
|
-
};
|
|
4747
|
-
handlers.beforeinput = (view, _event) => {
|
|
4748
|
-
let event = _event;
|
|
4749
|
-
if (chrome && android && event.inputType == "deleteContentBackward") {
|
|
4750
|
-
view.domObserver.flushSoon();
|
|
4751
|
-
let { domChangeCount } = view.input;
|
|
4752
|
-
setTimeout(() => {
|
|
4753
|
-
if (view.input.domChangeCount != domChangeCount)
|
|
4754
|
-
return;
|
|
4755
|
-
view.dom.blur();
|
|
4756
|
-
view.focus();
|
|
4757
|
-
if (view.someProp("handleKeyDown", (f) => f(view, keyEvent(8, "Backspace"))))
|
|
4758
|
-
return;
|
|
4759
|
-
let { $cursor } = view.state.selection;
|
|
4760
|
-
if ($cursor && $cursor.pos > 0)
|
|
4761
|
-
view.dispatch(view.state.tr.delete($cursor.pos - 1, $cursor.pos).scrollIntoView());
|
|
4762
|
-
}, 50);
|
|
4763
|
-
}
|
|
4764
|
-
};
|
|
4765
|
-
for (let prop in editHandlers)
|
|
4766
|
-
handlers[prop] = editHandlers[prop];
|
|
4767
|
-
function compareObjs(a, b) {
|
|
4768
|
-
if (a == b)
|
|
4769
|
-
return true;
|
|
4770
|
-
for (let p in a)
|
|
4771
|
-
if (a[p] !== b[p])
|
|
4772
|
-
return false;
|
|
4773
|
-
for (let p in b)
|
|
4774
|
-
if (!(p in a))
|
|
4775
|
-
return false;
|
|
4776
|
-
return true;
|
|
4777
|
-
}
|
|
4778
|
-
var WidgetType = class _WidgetType {
|
|
4779
|
-
constructor(toDOM, spec) {
|
|
4780
|
-
this.toDOM = toDOM;
|
|
4781
|
-
this.spec = spec || noSpec;
|
|
4782
|
-
this.side = this.spec.side || 0;
|
|
4783
|
-
}
|
|
4784
|
-
map(mapping, span, offset, oldOffset) {
|
|
4785
|
-
let { pos, deleted } = mapping.mapResult(span.from + oldOffset, this.side < 0 ? -1 : 1);
|
|
4786
|
-
return deleted ? null : new Decoration(pos - offset, pos - offset, this);
|
|
4787
|
-
}
|
|
4788
|
-
valid() {
|
|
4789
|
-
return true;
|
|
4790
|
-
}
|
|
4791
|
-
eq(other) {
|
|
4792
|
-
return this == other || other instanceof _WidgetType && (this.spec.key && this.spec.key == other.spec.key || this.toDOM == other.toDOM && compareObjs(this.spec, other.spec));
|
|
4793
|
-
}
|
|
4794
|
-
destroy(node) {
|
|
4795
|
-
if (this.spec.destroy)
|
|
4796
|
-
this.spec.destroy(node);
|
|
4797
|
-
}
|
|
4798
|
-
};
|
|
4799
|
-
var InlineType = class _InlineType {
|
|
4800
|
-
constructor(attrs, spec) {
|
|
4801
|
-
this.attrs = attrs;
|
|
4802
|
-
this.spec = spec || noSpec;
|
|
4803
|
-
}
|
|
4804
|
-
map(mapping, span, offset, oldOffset) {
|
|
4805
|
-
let from = mapping.map(span.from + oldOffset, this.spec.inclusiveStart ? -1 : 1) - offset;
|
|
4806
|
-
let to = mapping.map(span.to + oldOffset, this.spec.inclusiveEnd ? 1 : -1) - offset;
|
|
4807
|
-
return from >= to ? null : new Decoration(from, to, this);
|
|
4808
|
-
}
|
|
4809
|
-
valid(_, span) {
|
|
4810
|
-
return span.from < span.to;
|
|
4811
|
-
}
|
|
4812
|
-
eq(other) {
|
|
4813
|
-
return this == other || other instanceof _InlineType && compareObjs(this.attrs, other.attrs) && compareObjs(this.spec, other.spec);
|
|
4814
|
-
}
|
|
4815
|
-
static is(span) {
|
|
4816
|
-
return span.type instanceof _InlineType;
|
|
4817
|
-
}
|
|
4818
|
-
destroy() {
|
|
4819
|
-
}
|
|
4820
|
-
};
|
|
4821
|
-
var NodeType = class _NodeType {
|
|
4822
|
-
constructor(attrs, spec) {
|
|
4823
|
-
this.attrs = attrs;
|
|
4824
|
-
this.spec = spec || noSpec;
|
|
4825
|
-
}
|
|
4826
|
-
map(mapping, span, offset, oldOffset) {
|
|
4827
|
-
let from = mapping.mapResult(span.from + oldOffset, 1);
|
|
4828
|
-
if (from.deleted)
|
|
4829
|
-
return null;
|
|
4830
|
-
let to = mapping.mapResult(span.to + oldOffset, -1);
|
|
4831
|
-
if (to.deleted || to.pos <= from.pos)
|
|
4832
|
-
return null;
|
|
4833
|
-
return new Decoration(from.pos - offset, to.pos - offset, this);
|
|
4834
|
-
}
|
|
4835
|
-
valid(node, span) {
|
|
4836
|
-
let { index, offset } = node.content.findIndex(span.from), child;
|
|
4837
|
-
return offset == span.from && !(child = node.child(index)).isText && offset + child.nodeSize == span.to;
|
|
4838
|
-
}
|
|
4839
|
-
eq(other) {
|
|
4840
|
-
return this == other || other instanceof _NodeType && compareObjs(this.attrs, other.attrs) && compareObjs(this.spec, other.spec);
|
|
4841
|
-
}
|
|
4842
|
-
destroy() {
|
|
4843
|
-
}
|
|
4844
|
-
};
|
|
4845
|
-
var Decoration = class _Decoration {
|
|
4846
|
-
/**
|
|
4847
|
-
@internal
|
|
4848
|
-
*/
|
|
4849
|
-
constructor(from, to, type) {
|
|
4850
|
-
this.from = from;
|
|
4851
|
-
this.to = to;
|
|
4852
|
-
this.type = type;
|
|
4853
|
-
}
|
|
4854
|
-
/**
|
|
4855
|
-
@internal
|
|
4856
|
-
*/
|
|
4857
|
-
copy(from, to) {
|
|
4858
|
-
return new _Decoration(from, to, this.type);
|
|
4859
|
-
}
|
|
4860
|
-
/**
|
|
4861
|
-
@internal
|
|
4862
|
-
*/
|
|
4863
|
-
eq(other, offset = 0) {
|
|
4864
|
-
return this.type.eq(other.type) && this.from + offset == other.from && this.to + offset == other.to;
|
|
4865
|
-
}
|
|
4866
|
-
/**
|
|
4867
|
-
@internal
|
|
4868
|
-
*/
|
|
4869
|
-
map(mapping, offset, oldOffset) {
|
|
4870
|
-
return this.type.map(mapping, this, offset, oldOffset);
|
|
4871
|
-
}
|
|
4872
|
-
/**
|
|
4873
|
-
Creates a widget decoration, which is a DOM node that's shown in
|
|
4874
|
-
the document at the given position. It is recommended that you
|
|
4875
|
-
delay rendering the widget by passing a function that will be
|
|
4876
|
-
called when the widget is actually drawn in a view, but you can
|
|
4877
|
-
also directly pass a DOM node. `getPos` can be used to find the
|
|
4878
|
-
widget's current document position.
|
|
4879
|
-
*/
|
|
4880
|
-
static widget(pos, toDOM, spec) {
|
|
4881
|
-
return new _Decoration(pos, pos, new WidgetType(toDOM, spec));
|
|
4882
|
-
}
|
|
4883
|
-
/**
|
|
4884
|
-
Creates an inline decoration, which adds the given attributes to
|
|
4885
|
-
each inline node between `from` and `to`.
|
|
4886
|
-
*/
|
|
4887
|
-
static inline(from, to, attrs, spec) {
|
|
4888
|
-
return new _Decoration(from, to, new InlineType(attrs, spec));
|
|
4889
|
-
}
|
|
4890
|
-
/**
|
|
4891
|
-
Creates a node decoration. `from` and `to` should point precisely
|
|
4892
|
-
before and after a node in the document. That node, and only that
|
|
4893
|
-
node, will receive the given attributes.
|
|
4894
|
-
*/
|
|
4895
|
-
static node(from, to, attrs, spec) {
|
|
4896
|
-
return new _Decoration(from, to, new NodeType(attrs, spec));
|
|
4897
|
-
}
|
|
4898
|
-
/**
|
|
4899
|
-
The spec provided when creating this decoration. Can be useful
|
|
4900
|
-
if you've stored extra information in that object.
|
|
4901
|
-
*/
|
|
4902
|
-
get spec() {
|
|
4903
|
-
return this.type.spec;
|
|
4904
|
-
}
|
|
4905
|
-
/**
|
|
4906
|
-
@internal
|
|
4907
|
-
*/
|
|
4908
|
-
get inline() {
|
|
4909
|
-
return this.type instanceof InlineType;
|
|
4910
|
-
}
|
|
4911
|
-
/**
|
|
4912
|
-
@internal
|
|
4913
|
-
*/
|
|
4914
|
-
get widget() {
|
|
4915
|
-
return this.type instanceof WidgetType;
|
|
4916
|
-
}
|
|
4917
|
-
};
|
|
4918
|
-
var none = [];
|
|
4919
|
-
var noSpec = {};
|
|
4920
|
-
var DecorationSet = class _DecorationSet {
|
|
4921
|
-
/**
|
|
4922
|
-
@internal
|
|
4923
|
-
*/
|
|
4924
|
-
constructor(local, children) {
|
|
4925
|
-
this.local = local.length ? local : none;
|
|
4926
|
-
this.children = children.length ? children : none;
|
|
4927
|
-
}
|
|
4928
|
-
/**
|
|
4929
|
-
Create a set of decorations, using the structure of the given
|
|
4930
|
-
document. This will consume (modify) the `decorations` array, so
|
|
4931
|
-
you must make a copy if you want need to preserve that.
|
|
4932
|
-
*/
|
|
4933
|
-
static create(doc3, decorations) {
|
|
4934
|
-
return decorations.length ? buildTree(decorations, doc3, 0, noSpec) : empty;
|
|
4935
|
-
}
|
|
4936
|
-
/**
|
|
4937
|
-
Find all decorations in this set which touch the given range
|
|
4938
|
-
(including decorations that start or end directly at the
|
|
4939
|
-
boundaries) and match the given predicate on their spec. When
|
|
4940
|
-
`start` and `end` are omitted, all decorations in the set are
|
|
4941
|
-
considered. When `predicate` isn't given, all decorations are
|
|
4942
|
-
assumed to match.
|
|
4943
|
-
*/
|
|
4944
|
-
find(start, end, predicate) {
|
|
4945
|
-
let result = [];
|
|
4946
|
-
this.findInner(start == null ? 0 : start, end == null ? 1e9 : end, result, 0, predicate);
|
|
4947
|
-
return result;
|
|
4948
|
-
}
|
|
4949
|
-
findInner(start, end, result, offset, predicate) {
|
|
4950
|
-
for (let i = 0; i < this.local.length; i++) {
|
|
4951
|
-
let span = this.local[i];
|
|
4952
|
-
if (span.from <= end && span.to >= start && (!predicate || predicate(span.spec)))
|
|
4953
|
-
result.push(span.copy(span.from + offset, span.to + offset));
|
|
4954
|
-
}
|
|
4955
|
-
for (let i = 0; i < this.children.length; i += 3) {
|
|
4956
|
-
if (this.children[i] < end && this.children[i + 1] > start) {
|
|
4957
|
-
let childOff = this.children[i] + 1;
|
|
4958
|
-
this.children[i + 2].findInner(start - childOff, end - childOff, result, offset + childOff, predicate);
|
|
4959
|
-
}
|
|
4960
|
-
}
|
|
4961
|
-
}
|
|
4962
|
-
/**
|
|
4963
|
-
Map the set of decorations in response to a change in the
|
|
4964
|
-
document.
|
|
4965
|
-
*/
|
|
4966
|
-
map(mapping, doc3, options) {
|
|
4967
|
-
if (this == empty || mapping.maps.length == 0)
|
|
4968
|
-
return this;
|
|
4969
|
-
return this.mapInner(mapping, doc3, 0, 0, options || noSpec);
|
|
4970
|
-
}
|
|
4971
|
-
/**
|
|
4972
|
-
@internal
|
|
4973
|
-
*/
|
|
4974
|
-
mapInner(mapping, node, offset, oldOffset, options) {
|
|
4975
|
-
let newLocal;
|
|
4976
|
-
for (let i = 0; i < this.local.length; i++) {
|
|
4977
|
-
let mapped = this.local[i].map(mapping, offset, oldOffset);
|
|
4978
|
-
if (mapped && mapped.type.valid(node, mapped))
|
|
4979
|
-
(newLocal || (newLocal = [])).push(mapped);
|
|
4980
|
-
else if (options.onRemove)
|
|
4981
|
-
options.onRemove(this.local[i].spec);
|
|
4982
|
-
}
|
|
4983
|
-
if (this.children.length)
|
|
4984
|
-
return mapChildren(this.children, newLocal || [], mapping, node, offset, oldOffset, options);
|
|
4985
|
-
else
|
|
4986
|
-
return newLocal ? new _DecorationSet(newLocal.sort(byPos), none) : empty;
|
|
4987
|
-
}
|
|
4988
|
-
/**
|
|
4989
|
-
Add the given array of decorations to the ones in the set,
|
|
4990
|
-
producing a new set. Consumes the `decorations` array. Needs
|
|
4991
|
-
access to the current document to create the appropriate tree
|
|
4992
|
-
structure.
|
|
4993
|
-
*/
|
|
4994
|
-
add(doc3, decorations) {
|
|
4995
|
-
if (!decorations.length)
|
|
4996
|
-
return this;
|
|
4997
|
-
if (this == empty)
|
|
4998
|
-
return _DecorationSet.create(doc3, decorations);
|
|
4999
|
-
return this.addInner(doc3, decorations, 0);
|
|
5000
|
-
}
|
|
5001
|
-
addInner(doc3, decorations, offset) {
|
|
5002
|
-
let children, childIndex = 0;
|
|
5003
|
-
doc3.forEach((childNode, childOffset) => {
|
|
5004
|
-
let baseOffset = childOffset + offset, found2;
|
|
5005
|
-
if (!(found2 = takeSpansForNode(decorations, childNode, baseOffset)))
|
|
5006
|
-
return;
|
|
5007
|
-
if (!children)
|
|
5008
|
-
children = this.children.slice();
|
|
5009
|
-
while (childIndex < children.length && children[childIndex] < childOffset)
|
|
5010
|
-
childIndex += 3;
|
|
5011
|
-
if (children[childIndex] == childOffset)
|
|
5012
|
-
children[childIndex + 2] = children[childIndex + 2].addInner(childNode, found2, baseOffset + 1);
|
|
5013
|
-
else
|
|
5014
|
-
children.splice(childIndex, 0, childOffset, childOffset + childNode.nodeSize, buildTree(found2, childNode, baseOffset + 1, noSpec));
|
|
5015
|
-
childIndex += 3;
|
|
5016
|
-
});
|
|
5017
|
-
let local = moveSpans(childIndex ? withoutNulls(decorations) : decorations, -offset);
|
|
5018
|
-
for (let i = 0; i < local.length; i++)
|
|
5019
|
-
if (!local[i].type.valid(doc3, local[i]))
|
|
5020
|
-
local.splice(i--, 1);
|
|
5021
|
-
return new _DecorationSet(local.length ? this.local.concat(local).sort(byPos) : this.local, children || this.children);
|
|
5022
|
-
}
|
|
5023
|
-
/**
|
|
5024
|
-
Create a new set that contains the decorations in this set, minus
|
|
5025
|
-
the ones in the given array.
|
|
5026
|
-
*/
|
|
5027
|
-
remove(decorations) {
|
|
5028
|
-
if (decorations.length == 0 || this == empty)
|
|
5029
|
-
return this;
|
|
5030
|
-
return this.removeInner(decorations, 0);
|
|
5031
|
-
}
|
|
5032
|
-
removeInner(decorations, offset) {
|
|
5033
|
-
let children = this.children, local = this.local;
|
|
5034
|
-
for (let i = 0; i < children.length; i += 3) {
|
|
5035
|
-
let found2;
|
|
5036
|
-
let from = children[i] + offset, to = children[i + 1] + offset;
|
|
5037
|
-
for (let j = 0, span; j < decorations.length; j++)
|
|
5038
|
-
if (span = decorations[j]) {
|
|
5039
|
-
if (span.from > from && span.to < to) {
|
|
5040
|
-
decorations[j] = null;
|
|
5041
|
-
(found2 || (found2 = [])).push(span);
|
|
5042
|
-
}
|
|
5043
|
-
}
|
|
5044
|
-
if (!found2)
|
|
5045
|
-
continue;
|
|
5046
|
-
if (children == this.children)
|
|
5047
|
-
children = this.children.slice();
|
|
5048
|
-
let removed = children[i + 2].removeInner(found2, from + 1);
|
|
5049
|
-
if (removed != empty) {
|
|
5050
|
-
children[i + 2] = removed;
|
|
5051
|
-
} else {
|
|
5052
|
-
children.splice(i, 3);
|
|
5053
|
-
i -= 3;
|
|
5054
|
-
}
|
|
5055
|
-
}
|
|
5056
|
-
if (local.length) {
|
|
5057
|
-
for (let i = 0, span; i < decorations.length; i++)
|
|
5058
|
-
if (span = decorations[i]) {
|
|
5059
|
-
for (let j = 0; j < local.length; j++)
|
|
5060
|
-
if (local[j].eq(span, offset)) {
|
|
5061
|
-
if (local == this.local)
|
|
5062
|
-
local = this.local.slice();
|
|
5063
|
-
local.splice(j--, 1);
|
|
5064
|
-
}
|
|
5065
|
-
}
|
|
5066
|
-
}
|
|
5067
|
-
if (children == this.children && local == this.local)
|
|
5068
|
-
return this;
|
|
5069
|
-
return local.length || children.length ? new _DecorationSet(local, children) : empty;
|
|
5070
|
-
}
|
|
5071
|
-
forChild(offset, node) {
|
|
5072
|
-
if (this == empty)
|
|
5073
|
-
return this;
|
|
5074
|
-
if (node.isLeaf)
|
|
5075
|
-
return _DecorationSet.empty;
|
|
5076
|
-
let child, local;
|
|
5077
|
-
for (let i = 0; i < this.children.length; i += 3)
|
|
5078
|
-
if (this.children[i] >= offset) {
|
|
5079
|
-
if (this.children[i] == offset)
|
|
5080
|
-
child = this.children[i + 2];
|
|
5081
|
-
break;
|
|
5082
|
-
}
|
|
5083
|
-
let start = offset + 1, end = start + node.content.size;
|
|
5084
|
-
for (let i = 0; i < this.local.length; i++) {
|
|
5085
|
-
let dec = this.local[i];
|
|
5086
|
-
if (dec.from < end && dec.to > start && dec.type instanceof InlineType) {
|
|
5087
|
-
let from = Math.max(start, dec.from) - start, to = Math.min(end, dec.to) - start;
|
|
5088
|
-
if (from < to)
|
|
5089
|
-
(local || (local = [])).push(dec.copy(from, to));
|
|
5090
|
-
}
|
|
5091
|
-
}
|
|
5092
|
-
if (local) {
|
|
5093
|
-
let localSet = new _DecorationSet(local.sort(byPos), none);
|
|
5094
|
-
return child ? new DecorationGroup([localSet, child]) : localSet;
|
|
5095
|
-
}
|
|
5096
|
-
return child || empty;
|
|
5097
|
-
}
|
|
5098
|
-
/**
|
|
5099
|
-
@internal
|
|
5100
|
-
*/
|
|
5101
|
-
eq(other) {
|
|
5102
|
-
if (this == other)
|
|
5103
|
-
return true;
|
|
5104
|
-
if (!(other instanceof _DecorationSet) || this.local.length != other.local.length || this.children.length != other.children.length)
|
|
5105
|
-
return false;
|
|
5106
|
-
for (let i = 0; i < this.local.length; i++)
|
|
5107
|
-
if (!this.local[i].eq(other.local[i]))
|
|
5108
|
-
return false;
|
|
5109
|
-
for (let i = 0; i < this.children.length; i += 3)
|
|
5110
|
-
if (this.children[i] != other.children[i] || this.children[i + 1] != other.children[i + 1] || !this.children[i + 2].eq(other.children[i + 2]))
|
|
5111
|
-
return false;
|
|
5112
|
-
return true;
|
|
5113
|
-
}
|
|
5114
|
-
/**
|
|
5115
|
-
@internal
|
|
5116
|
-
*/
|
|
5117
|
-
locals(node) {
|
|
5118
|
-
return removeOverlap(this.localsInner(node));
|
|
5119
|
-
}
|
|
5120
|
-
/**
|
|
5121
|
-
@internal
|
|
5122
|
-
*/
|
|
5123
|
-
localsInner(node) {
|
|
5124
|
-
if (this == empty)
|
|
5125
|
-
return none;
|
|
5126
|
-
if (node.inlineContent || !this.local.some(InlineType.is))
|
|
5127
|
-
return this.local;
|
|
5128
|
-
let result = [];
|
|
5129
|
-
for (let i = 0; i < this.local.length; i++) {
|
|
5130
|
-
if (!(this.local[i].type instanceof InlineType))
|
|
5131
|
-
result.push(this.local[i]);
|
|
5132
|
-
}
|
|
5133
|
-
return result;
|
|
5134
|
-
}
|
|
5135
|
-
forEachSet(f) {
|
|
5136
|
-
f(this);
|
|
5137
|
-
}
|
|
5138
|
-
};
|
|
5139
|
-
DecorationSet.empty = new DecorationSet([], []);
|
|
5140
|
-
DecorationSet.removeOverlap = removeOverlap;
|
|
5141
|
-
var empty = DecorationSet.empty;
|
|
5142
|
-
var DecorationGroup = class _DecorationGroup {
|
|
5143
|
-
constructor(members) {
|
|
5144
|
-
this.members = members;
|
|
5145
|
-
}
|
|
5146
|
-
map(mapping, doc3) {
|
|
5147
|
-
const mappedDecos = this.members.map((member) => member.map(mapping, doc3, noSpec));
|
|
5148
|
-
return _DecorationGroup.from(mappedDecos);
|
|
5149
|
-
}
|
|
5150
|
-
forChild(offset, child) {
|
|
5151
|
-
if (child.isLeaf)
|
|
5152
|
-
return DecorationSet.empty;
|
|
5153
|
-
let found2 = [];
|
|
5154
|
-
for (let i = 0; i < this.members.length; i++) {
|
|
5155
|
-
let result = this.members[i].forChild(offset, child);
|
|
5156
|
-
if (result == empty)
|
|
5157
|
-
continue;
|
|
5158
|
-
if (result instanceof _DecorationGroup)
|
|
5159
|
-
found2 = found2.concat(result.members);
|
|
5160
|
-
else
|
|
5161
|
-
found2.push(result);
|
|
5162
|
-
}
|
|
5163
|
-
return _DecorationGroup.from(found2);
|
|
5164
|
-
}
|
|
5165
|
-
eq(other) {
|
|
5166
|
-
if (!(other instanceof _DecorationGroup) || other.members.length != this.members.length)
|
|
5167
|
-
return false;
|
|
5168
|
-
for (let i = 0; i < this.members.length; i++)
|
|
5169
|
-
if (!this.members[i].eq(other.members[i]))
|
|
5170
|
-
return false;
|
|
5171
|
-
return true;
|
|
5172
|
-
}
|
|
5173
|
-
locals(node) {
|
|
5174
|
-
let result, sorted = true;
|
|
5175
|
-
for (let i = 0; i < this.members.length; i++) {
|
|
5176
|
-
let locals = this.members[i].localsInner(node);
|
|
5177
|
-
if (!locals.length)
|
|
5178
|
-
continue;
|
|
5179
|
-
if (!result) {
|
|
5180
|
-
result = locals;
|
|
5181
|
-
} else {
|
|
5182
|
-
if (sorted) {
|
|
5183
|
-
result = result.slice();
|
|
5184
|
-
sorted = false;
|
|
5185
|
-
}
|
|
5186
|
-
for (let j = 0; j < locals.length; j++)
|
|
5187
|
-
result.push(locals[j]);
|
|
5188
|
-
}
|
|
5189
|
-
}
|
|
5190
|
-
return result ? removeOverlap(sorted ? result : result.sort(byPos)) : none;
|
|
5191
|
-
}
|
|
5192
|
-
// Create a group for the given array of decoration sets, or return
|
|
5193
|
-
// a single set when possible.
|
|
5194
|
-
static from(members) {
|
|
5195
|
-
switch (members.length) {
|
|
5196
|
-
case 0:
|
|
5197
|
-
return empty;
|
|
5198
|
-
case 1:
|
|
5199
|
-
return members[0];
|
|
5200
|
-
default:
|
|
5201
|
-
return new _DecorationGroup(members.every((m) => m instanceof DecorationSet) ? members : members.reduce((r, m) => r.concat(m instanceof DecorationSet ? m : m.members), []));
|
|
5202
|
-
}
|
|
5203
|
-
}
|
|
5204
|
-
forEachSet(f) {
|
|
5205
|
-
for (let i = 0; i < this.members.length; i++)
|
|
5206
|
-
this.members[i].forEachSet(f);
|
|
5207
|
-
}
|
|
5208
|
-
};
|
|
5209
|
-
function mapChildren(oldChildren, newLocal, mapping, node, offset, oldOffset, options) {
|
|
5210
|
-
let children = oldChildren.slice();
|
|
5211
|
-
for (let i = 0, baseOffset = oldOffset; i < mapping.maps.length; i++) {
|
|
5212
|
-
let moved = 0;
|
|
5213
|
-
mapping.maps[i].forEach((oldStart, oldEnd, newStart, newEnd) => {
|
|
5214
|
-
let dSize = newEnd - newStart - (oldEnd - oldStart);
|
|
5215
|
-
for (let i2 = 0; i2 < children.length; i2 += 3) {
|
|
5216
|
-
let end = children[i2 + 1];
|
|
5217
|
-
if (end < 0 || oldStart > end + baseOffset - moved)
|
|
5218
|
-
continue;
|
|
5219
|
-
let start = children[i2] + baseOffset - moved;
|
|
5220
|
-
if (oldEnd >= start) {
|
|
5221
|
-
children[i2 + 1] = oldStart <= start ? -2 : -1;
|
|
5222
|
-
} else if (oldStart >= baseOffset && dSize) {
|
|
5223
|
-
children[i2] += dSize;
|
|
5224
|
-
children[i2 + 1] += dSize;
|
|
5225
|
-
}
|
|
5226
|
-
}
|
|
5227
|
-
moved += dSize;
|
|
5228
|
-
});
|
|
5229
|
-
baseOffset = mapping.maps[i].map(baseOffset, -1);
|
|
5230
|
-
}
|
|
5231
|
-
let mustRebuild = false;
|
|
5232
|
-
for (let i = 0; i < children.length; i += 3)
|
|
5233
|
-
if (children[i + 1] < 0) {
|
|
5234
|
-
if (children[i + 1] == -2) {
|
|
5235
|
-
mustRebuild = true;
|
|
5236
|
-
children[i + 1] = -1;
|
|
5237
|
-
continue;
|
|
5238
|
-
}
|
|
5239
|
-
let from = mapping.map(oldChildren[i] + oldOffset), fromLocal = from - offset;
|
|
5240
|
-
if (fromLocal < 0 || fromLocal >= node.content.size) {
|
|
5241
|
-
mustRebuild = true;
|
|
5242
|
-
continue;
|
|
5243
|
-
}
|
|
5244
|
-
let to = mapping.map(oldChildren[i + 1] + oldOffset, -1), toLocal = to - offset;
|
|
5245
|
-
let { index, offset: childOffset } = node.content.findIndex(fromLocal);
|
|
5246
|
-
let childNode = node.maybeChild(index);
|
|
5247
|
-
if (childNode && childOffset == fromLocal && childOffset + childNode.nodeSize == toLocal) {
|
|
5248
|
-
let mapped = children[i + 2].mapInner(mapping, childNode, from + 1, oldChildren[i] + oldOffset + 1, options);
|
|
5249
|
-
if (mapped != empty) {
|
|
5250
|
-
children[i] = fromLocal;
|
|
5251
|
-
children[i + 1] = toLocal;
|
|
5252
|
-
children[i + 2] = mapped;
|
|
5253
|
-
} else {
|
|
5254
|
-
children[i + 1] = -2;
|
|
5255
|
-
mustRebuild = true;
|
|
5256
|
-
}
|
|
5257
|
-
} else {
|
|
5258
|
-
mustRebuild = true;
|
|
5259
|
-
}
|
|
5260
|
-
}
|
|
5261
|
-
if (mustRebuild) {
|
|
5262
|
-
let decorations = mapAndGatherRemainingDecorations(children, oldChildren, newLocal, mapping, offset, oldOffset, options);
|
|
5263
|
-
let built = buildTree(decorations, node, 0, options);
|
|
5264
|
-
newLocal = built.local;
|
|
5265
|
-
for (let i = 0; i < children.length; i += 3)
|
|
5266
|
-
if (children[i + 1] < 0) {
|
|
5267
|
-
children.splice(i, 3);
|
|
5268
|
-
i -= 3;
|
|
5269
|
-
}
|
|
5270
|
-
for (let i = 0, j = 0; i < built.children.length; i += 3) {
|
|
5271
|
-
let from = built.children[i];
|
|
5272
|
-
while (j < children.length && children[j] < from)
|
|
5273
|
-
j += 3;
|
|
5274
|
-
children.splice(j, 0, built.children[i], built.children[i + 1], built.children[i + 2]);
|
|
5275
|
-
}
|
|
5276
|
-
}
|
|
5277
|
-
return new DecorationSet(newLocal.sort(byPos), children);
|
|
5278
|
-
}
|
|
5279
|
-
function moveSpans(spans, offset) {
|
|
5280
|
-
if (!offset || !spans.length)
|
|
5281
|
-
return spans;
|
|
5282
|
-
let result = [];
|
|
5283
|
-
for (let i = 0; i < spans.length; i++) {
|
|
5284
|
-
let span = spans[i];
|
|
5285
|
-
result.push(new Decoration(span.from + offset, span.to + offset, span.type));
|
|
5286
|
-
}
|
|
5287
|
-
return result;
|
|
5288
|
-
}
|
|
5289
|
-
function mapAndGatherRemainingDecorations(children, oldChildren, decorations, mapping, offset, oldOffset, options) {
|
|
5290
|
-
function gather(set, oldOffset2) {
|
|
5291
|
-
for (let i = 0; i < set.local.length; i++) {
|
|
5292
|
-
let mapped = set.local[i].map(mapping, offset, oldOffset2);
|
|
5293
|
-
if (mapped)
|
|
5294
|
-
decorations.push(mapped);
|
|
5295
|
-
else if (options.onRemove)
|
|
5296
|
-
options.onRemove(set.local[i].spec);
|
|
5297
|
-
}
|
|
5298
|
-
for (let i = 0; i < set.children.length; i += 3)
|
|
5299
|
-
gather(set.children[i + 2], set.children[i] + oldOffset2 + 1);
|
|
5300
|
-
}
|
|
5301
|
-
for (let i = 0; i < children.length; i += 3)
|
|
5302
|
-
if (children[i + 1] == -1)
|
|
5303
|
-
gather(children[i + 2], oldChildren[i] + oldOffset + 1);
|
|
5304
|
-
return decorations;
|
|
5305
|
-
}
|
|
5306
|
-
function takeSpansForNode(spans, node, offset) {
|
|
5307
|
-
if (node.isLeaf)
|
|
5308
|
-
return null;
|
|
5309
|
-
let end = offset + node.nodeSize, found2 = null;
|
|
5310
|
-
for (let i = 0, span; i < spans.length; i++) {
|
|
5311
|
-
if ((span = spans[i]) && span.from > offset && span.to < end) {
|
|
5312
|
-
(found2 || (found2 = [])).push(span);
|
|
5313
|
-
spans[i] = null;
|
|
5314
|
-
}
|
|
5315
|
-
}
|
|
5316
|
-
return found2;
|
|
5317
|
-
}
|
|
5318
|
-
function withoutNulls(array) {
|
|
5319
|
-
let result = [];
|
|
5320
|
-
for (let i = 0; i < array.length; i++)
|
|
5321
|
-
if (array[i] != null)
|
|
5322
|
-
result.push(array[i]);
|
|
5323
|
-
return result;
|
|
5324
|
-
}
|
|
5325
|
-
function buildTree(spans, node, offset, options) {
|
|
5326
|
-
let children = [], hasNulls = false;
|
|
5327
|
-
node.forEach((childNode, localStart) => {
|
|
5328
|
-
let found2 = takeSpansForNode(spans, childNode, localStart + offset);
|
|
5329
|
-
if (found2) {
|
|
5330
|
-
hasNulls = true;
|
|
5331
|
-
let subtree = buildTree(found2, childNode, offset + localStart + 1, options);
|
|
5332
|
-
if (subtree != empty)
|
|
5333
|
-
children.push(localStart, localStart + childNode.nodeSize, subtree);
|
|
5334
|
-
}
|
|
5335
|
-
});
|
|
5336
|
-
let locals = moveSpans(hasNulls ? withoutNulls(spans) : spans, -offset).sort(byPos);
|
|
5337
|
-
for (let i = 0; i < locals.length; i++)
|
|
5338
|
-
if (!locals[i].type.valid(node, locals[i])) {
|
|
5339
|
-
if (options.onRemove)
|
|
5340
|
-
options.onRemove(locals[i].spec);
|
|
5341
|
-
locals.splice(i--, 1);
|
|
5342
|
-
}
|
|
5343
|
-
return locals.length || children.length ? new DecorationSet(locals, children) : empty;
|
|
5344
|
-
}
|
|
5345
|
-
function byPos(a, b) {
|
|
5346
|
-
return a.from - b.from || a.to - b.to;
|
|
5347
|
-
}
|
|
5348
|
-
function removeOverlap(spans) {
|
|
5349
|
-
let working = spans;
|
|
5350
|
-
for (let i = 0; i < working.length - 1; i++) {
|
|
5351
|
-
let span = working[i];
|
|
5352
|
-
if (span.from != span.to)
|
|
5353
|
-
for (let j = i + 1; j < working.length; j++) {
|
|
5354
|
-
let next = working[j];
|
|
5355
|
-
if (next.from == span.from) {
|
|
5356
|
-
if (next.to != span.to) {
|
|
5357
|
-
if (working == spans)
|
|
5358
|
-
working = spans.slice();
|
|
5359
|
-
working[j] = next.copy(next.from, span.to);
|
|
5360
|
-
insertAhead(working, j + 1, next.copy(span.to, next.to));
|
|
5361
|
-
}
|
|
5362
|
-
continue;
|
|
5363
|
-
} else {
|
|
5364
|
-
if (next.from < span.to) {
|
|
5365
|
-
if (working == spans)
|
|
5366
|
-
working = spans.slice();
|
|
5367
|
-
working[i] = span.copy(span.from, next.from);
|
|
5368
|
-
insertAhead(working, j, span.copy(next.from, span.to));
|
|
5369
|
-
}
|
|
5370
|
-
break;
|
|
5371
|
-
}
|
|
5372
|
-
}
|
|
5373
|
-
}
|
|
5374
|
-
return working;
|
|
5375
|
-
}
|
|
5376
|
-
function insertAhead(array, i, deco) {
|
|
5377
|
-
while (i < array.length && byPos(deco, array[i]) > 0)
|
|
5378
|
-
i++;
|
|
5379
|
-
array.splice(i, 0, deco);
|
|
5380
|
-
}
|
|
5381
|
-
|
|
5382
|
-
// src/components/RichTextEditor/extensions/BskyLinkDecorator.ts
|
|
5383
564
|
var URL_REGEX = /https?:\/\/[^\s<>"{}|\\^`[\]]+/g;
|
|
5384
|
-
function getDecorations(
|
|
565
|
+
function getDecorations(doc, linkClass) {
|
|
5385
566
|
const decorations = [];
|
|
5386
|
-
|
|
567
|
+
doc.descendants((node, pos) => {
|
|
5387
568
|
if (!node.isText || !node.text) return;
|
|
5388
569
|
const text = node.text;
|
|
5389
570
|
URL_REGEX.lastIndex = 0;
|
|
@@ -5401,21 +582,21 @@ function getDecorations(doc3, linkClass) {
|
|
|
5401
582
|
to--;
|
|
5402
583
|
}
|
|
5403
584
|
decorations.push(
|
|
5404
|
-
Decoration.inline(from, to, {
|
|
585
|
+
view.Decoration.inline(from, to, {
|
|
5405
586
|
class: linkClass,
|
|
5406
587
|
"data-autolink": ""
|
|
5407
588
|
})
|
|
5408
589
|
);
|
|
5409
590
|
}
|
|
5410
591
|
});
|
|
5411
|
-
return DecorationSet.create(
|
|
592
|
+
return view.DecorationSet.create(doc, decorations);
|
|
5412
593
|
}
|
|
5413
594
|
function createLinkDecoratorPlugin(linkClass) {
|
|
5414
|
-
const key = new PluginKey("bsky-link-decorator");
|
|
5415
|
-
return new Plugin({
|
|
595
|
+
const key = new state.PluginKey("bsky-link-decorator");
|
|
596
|
+
return new state.Plugin({
|
|
5416
597
|
key,
|
|
5417
598
|
state: {
|
|
5418
|
-
init: (_, { doc
|
|
599
|
+
init: (_, { doc }) => getDecorations(doc, linkClass),
|
|
5419
600
|
apply: (transaction, decorationSet) => {
|
|
5420
601
|
if (transaction.docChanged) {
|
|
5421
602
|
return getDecorations(transaction.doc, linkClass);
|
|
@@ -5451,9 +632,7 @@ function toInitialHTML(value) {
|
|
|
5451
632
|
return `<p>${escapeHTML(text)}</p>`;
|
|
5452
633
|
}
|
|
5453
634
|
const atpFacets = facets;
|
|
5454
|
-
const rt = new api.RichText(
|
|
5455
|
-
atpFacets ? { text, facets: atpFacets } : { text }
|
|
5456
|
-
);
|
|
635
|
+
const rt = new api.RichText(atpFacets ? { text, facets: atpFacets } : { text });
|
|
5457
636
|
let html = "";
|
|
5458
637
|
for (const segment of rt.segments()) {
|
|
5459
638
|
if (segment.mention) {
|
|
@@ -5572,6 +751,13 @@ function RichTextEditor({
|
|
|
5572
751
|
extensions,
|
|
5573
752
|
editable,
|
|
5574
753
|
content: toInitialHTML(initialValue),
|
|
754
|
+
/**
|
|
755
|
+
* Disable immediate rendering to prevent SSR/hydration issues in Next.js,
|
|
756
|
+
* Remix, and other server-rendering frameworks. The editor defers rendering
|
|
757
|
+
* until after the component mounts on the client.
|
|
758
|
+
* @see https://github.com/ueberdosis/tiptap/issues/5856
|
|
759
|
+
*/
|
|
760
|
+
immediatelyRender: false,
|
|
5575
761
|
/**
|
|
5576
762
|
* Clipboard text serialisation: use '\n' as the block separator so
|
|
5577
763
|
* multi-paragraph content is copied as plain newline-delimited text.
|