prosemirror-view 1.20.0 → 1.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/dist/index.es.js +69 -43
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +69 -43
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/browser.js +1 -1
- package/src/clipboard.js +16 -6
- package/src/decoration.js +2 -2
- package/src/domcoords.js +11 -8
- package/src/index.js +3 -0
- package/src/viewdesc.js +31 -22
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,37 @@
|
|
|
1
|
+
## 1.21.0 (2021-10-29)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Fix issue where recent Mobile Safari versions weren't treated as Mac platforms.
|
|
6
|
+
|
|
7
|
+
### New features
|
|
8
|
+
|
|
9
|
+
Multiple `style` properties provided through the `attributes` prop are now merged. Adjust mac detection for recent changes to navigator.platform on iOS
|
|
10
|
+
|
|
11
|
+
## 1.20.3 (2021-10-13)
|
|
12
|
+
|
|
13
|
+
### Bug fixes
|
|
14
|
+
|
|
15
|
+
Stop removing leading/trailing whitespace from pasted plain text.
|
|
16
|
+
|
|
17
|
+
Fix an issue that could cause invalid content to be produced when pasting HTML with isolating nodes in it.
|
|
18
|
+
|
|
19
|
+
## 1.20.2 (2021-10-07)
|
|
20
|
+
|
|
21
|
+
### Bug fixes
|
|
22
|
+
|
|
23
|
+
Fix a crash when pasting whitespace-only content as text.
|
|
24
|
+
|
|
25
|
+
## 1.20.1 (2021-09-09)
|
|
26
|
+
|
|
27
|
+
### Bug fixes
|
|
28
|
+
|
|
29
|
+
The library accidentally allowed node decorations on text nodes. It no longer does.
|
|
30
|
+
|
|
31
|
+
Fix an issue on Chrome and Safari where coordinates for positions between uneditable nodes and the end of a textblock would return zero-height rectangles.
|
|
32
|
+
|
|
33
|
+
Fix a bug where vertical `endOfTextblock` queries could inappropriately return true when a small line height is used.
|
|
34
|
+
|
|
1
35
|
## 1.20.0 (2021-09-03)
|
|
2
36
|
|
|
3
37
|
### New features
|
package/dist/index.es.js
CHANGED
|
@@ -9,7 +9,6 @@ if (typeof navigator != "undefined" && typeof document != "undefined") {
|
|
|
9
9
|
var ie_upto10 = /MSIE \d/.test(navigator.userAgent);
|
|
10
10
|
var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(navigator.userAgent);
|
|
11
11
|
|
|
12
|
-
result.mac = /Mac/.test(navigator.platform);
|
|
13
12
|
var ie = result.ie = !!(ie_upto10 || ie_11up || ie_edge);
|
|
14
13
|
result.ie_version = ie_upto10 ? document.documentMode || 6 : ie_11up ? +ie_11up[1] : ie_edge ? +ie_edge[1] : null;
|
|
15
14
|
result.gecko = !ie && /gecko\/(\d+)/i.test(navigator.userAgent);
|
|
@@ -20,6 +19,7 @@ if (typeof navigator != "undefined" && typeof document != "undefined") {
|
|
|
20
19
|
// Is true for both iOS and iPadOS for convenience
|
|
21
20
|
result.safari = !ie && /Apple Computer/.test(navigator.vendor);
|
|
22
21
|
result.ios = result.safari && (/Mobile\/\w+/.test(navigator.userAgent) || navigator.maxTouchPoints > 2);
|
|
22
|
+
result.mac = result.ios || /Mac/.test(navigator.platform);
|
|
23
23
|
result.android = /Android \d/.test(navigator.userAgent);
|
|
24
24
|
result.webkit = "webkitFontSmoothing" in document.documentElement.style;
|
|
25
25
|
result.webkit_version = result.webkit && +(/\bAppleWebKit\/(\d+)/.exec(navigator.userAgent) || [0, 0])[1];
|
|
@@ -357,19 +357,19 @@ function elementFromPoint(element, coords, box) {
|
|
|
357
357
|
function posAtCoords(view, coords) {
|
|
358
358
|
var assign, assign$1;
|
|
359
359
|
|
|
360
|
-
var
|
|
361
|
-
if (
|
|
360
|
+
var doc = view.dom.ownerDocument, node, offset;
|
|
361
|
+
if (doc.caretPositionFromPoint) {
|
|
362
362
|
try { // Firefox throws for this call in hard-to-predict circumstances (#994)
|
|
363
|
-
var pos$1 =
|
|
363
|
+
var pos$1 = doc.caretPositionFromPoint(coords.left, coords.top);
|
|
364
364
|
if (pos$1) { ((assign = pos$1, node = assign.offsetNode, offset = assign.offset)); }
|
|
365
365
|
} catch (_) {}
|
|
366
366
|
}
|
|
367
|
-
if (!node &&
|
|
368
|
-
var range =
|
|
367
|
+
if (!node && doc.caretRangeFromPoint) {
|
|
368
|
+
var range = doc.caretRangeFromPoint(coords.left, coords.top);
|
|
369
369
|
if (range) { ((assign$1 = range, node = assign$1.startContainer, offset = assign$1.startOffset)); }
|
|
370
370
|
}
|
|
371
371
|
|
|
372
|
-
var elt = root.elementFromPoint(coords.left, coords.top + 1), pos;
|
|
372
|
+
var elt = (view.root.elementFromPoint ? view.root : doc).elementFromPoint(coords.left, coords.top + 1), pos;
|
|
373
373
|
if (!elt || !view.dom.contains(elt.nodeType != 1 ? elt.parentNode : elt)) {
|
|
374
374
|
var box = view.dom.getBoundingClientRect();
|
|
375
375
|
if (!inRect(coords, box)) { return null }
|
|
@@ -480,7 +480,8 @@ function coordsAtPos(view, pos, side) {
|
|
|
480
480
|
}
|
|
481
481
|
if (offset < nodeSize(node)) {
|
|
482
482
|
var after$1 = node.childNodes[offset];
|
|
483
|
-
|
|
483
|
+
while (after$1.pmViewDesc && after$1.pmViewDesc.ignoreForCoords) { after$1 = after$1.nextSibling; }
|
|
484
|
+
var target$1 = !after$1 ? null : after$1.nodeType == 3 ? textRange(after$1, 0, (supportEmptyRange ? 0 : 1))
|
|
484
485
|
: after$1.nodeType == 1 ? after$1 : null;
|
|
485
486
|
if (target$1) { return flattenV(singleRect(target$1, -1), true) }
|
|
486
487
|
}
|
|
@@ -535,7 +536,9 @@ function endOfTextblockVertical(view, state, dir) {
|
|
|
535
536
|
else { continue }
|
|
536
537
|
for (var i = 0; i < boxes.length; i++) {
|
|
537
538
|
var box = boxes[i];
|
|
538
|
-
if (box.bottom > box.top
|
|
539
|
+
if (box.bottom > box.top + 1 &&
|
|
540
|
+
(dir == "up" ? coords.top - box.top > (box.bottom - coords.top) * 2
|
|
541
|
+
: box.bottom - coords.bottom > (coords.bottom - box.top) * 2))
|
|
539
542
|
{ return false }
|
|
540
543
|
}
|
|
541
544
|
}
|
|
@@ -687,7 +690,7 @@ var ViewDesc = function ViewDesc(parent, children, dom, contentDOM) {
|
|
|
687
690
|
this.dirty = NOT_DIRTY;
|
|
688
691
|
};
|
|
689
692
|
|
|
690
|
-
var prototypeAccessors = {
|
|
693
|
+
var prototypeAccessors = { size: { configurable: true },border: { configurable: true },posBefore: { configurable: true },posAtStart: { configurable: true },posAfter: { configurable: true },posAtEnd: { configurable: true },contentLost: { configurable: true },domAtom: { configurable: true },ignoreForCoords: { configurable: true } };
|
|
691
694
|
|
|
692
695
|
// Used to check whether a given description corresponds to a
|
|
693
696
|
// widget/mark/node.
|
|
@@ -696,8 +699,6 @@ ViewDesc.prototype.matchesMark = function matchesMark () { return false };
|
|
|
696
699
|
ViewDesc.prototype.matchesNode = function matchesNode () { return false };
|
|
697
700
|
ViewDesc.prototype.matchesHack = function matchesHack (_nodeName) { return false };
|
|
698
701
|
|
|
699
|
-
prototypeAccessors.beforePosition.get = function () { return false };
|
|
700
|
-
|
|
701
702
|
// : () → ?ParseRule
|
|
702
703
|
// When parsing in-editor content (in domchange.js), we allow
|
|
703
704
|
// descriptions to determine the parse rules that should be used to
|
|
@@ -846,23 +847,34 @@ ViewDesc.prototype.descAt = function descAt (pos) {
|
|
|
846
847
|
// : (number, number) → {node: dom.Node, offset: number}
|
|
847
848
|
ViewDesc.prototype.domFromPos = function domFromPos (pos, side) {
|
|
848
849
|
if (!this.contentDOM) { return {node: this.dom, offset: 0} }
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
850
|
+
// First find the position in the child array
|
|
851
|
+
var i = 0, offset = 0;
|
|
852
|
+
for (var curPos = 0; i < this.children.length; i++) {
|
|
853
|
+
var child = this.children[i], end = curPos + child.size;
|
|
854
|
+
if (end > pos || child instanceof TrailingHackViewDesc) { offset = pos - curPos; break }
|
|
855
|
+
curPos = end;
|
|
856
|
+
}
|
|
857
|
+
// If this points into the middle of a child, call through
|
|
858
|
+
if (offset) { return this.children[i].domFromPos(offset - this.children[i].border, side) }
|
|
859
|
+
// Go back if there were any zero-length widgets with side >= 0 before this point
|
|
860
|
+
for (var prev = (void 0); i && !(prev = this.children[i - 1]).size && prev instanceof WidgetViewDesc && prev.widget.type.side >= 0; i--) {}
|
|
861
|
+
// Scan towards the first useable node
|
|
862
|
+
if (side <= 0) {
|
|
863
|
+
var prev$1, enter = true;
|
|
864
|
+
for (;; i--, enter = false) {
|
|
865
|
+
prev$1 = i ? this.children[i - 1] : null;
|
|
866
|
+
if (!prev$1 || prev$1.dom.parentNode == this.contentDOM) { break }
|
|
867
|
+
}
|
|
868
|
+
if (prev$1 && side && enter && !prev$1.border && !prev$1.domAtom) { return prev$1.domFromPos(prev$1.size, side) }
|
|
869
|
+
return {node: this.contentDOM, offset: prev$1 ? domIndex(prev$1.dom) + 1 : 0}
|
|
870
|
+
} else {
|
|
871
|
+
var next, enter$1 = true;
|
|
872
|
+
for (;; i++, enter$1 = false) {
|
|
873
|
+
next = i < this.children.length ? this.children[i] : null;
|
|
874
|
+
if (!next || next.dom.parentNode == this.contentDOM) { break }
|
|
875
|
+
}
|
|
876
|
+
if (next && enter$1 && !next.border && !next.domAtom) { return next.domFromPos(0, side) }
|
|
877
|
+
return {node: this.contentDOM, offset: next ? domIndex(next.dom) : this.contentDOM.childNodes.length}
|
|
866
878
|
}
|
|
867
879
|
};
|
|
868
880
|
|
|
@@ -1057,6 +1069,8 @@ ViewDesc.prototype.markParentsDirty = function markParentsDirty () {
|
|
|
1057
1069
|
|
|
1058
1070
|
prototypeAccessors.domAtom.get = function () { return false };
|
|
1059
1071
|
|
|
1072
|
+
prototypeAccessors.ignoreForCoords.get = function () { return false };
|
|
1073
|
+
|
|
1060
1074
|
Object.defineProperties( ViewDesc.prototype, prototypeAccessors );
|
|
1061
1075
|
|
|
1062
1076
|
// Reused array to avoid allocating fresh arrays for things that will
|
|
@@ -1090,11 +1104,7 @@ var WidgetViewDesc = /*@__PURE__*/(function (ViewDesc) {
|
|
|
1090
1104
|
WidgetViewDesc.prototype = Object.create( ViewDesc && ViewDesc.prototype );
|
|
1091
1105
|
WidgetViewDesc.prototype.constructor = WidgetViewDesc;
|
|
1092
1106
|
|
|
1093
|
-
var prototypeAccessors$1 = {
|
|
1094
|
-
|
|
1095
|
-
prototypeAccessors$1.beforePosition.get = function () {
|
|
1096
|
-
return this.widget.type.side < 0
|
|
1097
|
-
};
|
|
1107
|
+
var prototypeAccessors$1 = { domAtom: { configurable: true } };
|
|
1098
1108
|
|
|
1099
1109
|
WidgetViewDesc.prototype.matchesWidget = function matchesWidget (widget) {
|
|
1100
1110
|
return this.dirty == NOT_DIRTY && widget.type.eq(this.widget.type)
|
|
@@ -1520,11 +1530,12 @@ var TrailingHackViewDesc = /*@__PURE__*/(function (ViewDesc) {
|
|
|
1520
1530
|
TrailingHackViewDesc.prototype = Object.create( ViewDesc && ViewDesc.prototype );
|
|
1521
1531
|
TrailingHackViewDesc.prototype.constructor = TrailingHackViewDesc;
|
|
1522
1532
|
|
|
1523
|
-
var prototypeAccessors$5 = { domAtom: { configurable: true } };
|
|
1533
|
+
var prototypeAccessors$5 = { domAtom: { configurable: true },ignoreForCoords: { configurable: true } };
|
|
1524
1534
|
|
|
1525
1535
|
TrailingHackViewDesc.prototype.parseRule = function parseRule () { return {ignore: true} };
|
|
1526
1536
|
TrailingHackViewDesc.prototype.matchesHack = function matchesHack (nodeName) { return this.dirty == NOT_DIRTY && this.dom.nodeName == nodeName };
|
|
1527
1537
|
prototypeAccessors$5.domAtom.get = function () { return true };
|
|
1538
|
+
prototypeAccessors$5.ignoreForCoords.get = function () { return this.dom.nodeName == "IMG" };
|
|
1528
1539
|
|
|
1529
1540
|
Object.defineProperties( TrailingHackViewDesc.prototype, prototypeAccessors$5 );
|
|
1530
1541
|
|
|
@@ -1903,6 +1914,7 @@ ViewTreeUpdater.prototype.addHackNode = function addHackNode (nodeName) {
|
|
|
1903
1914
|
} else {
|
|
1904
1915
|
var dom = document.createElement(nodeName);
|
|
1905
1916
|
if (nodeName == "IMG") { dom.className = "ProseMirror-separator"; }
|
|
1917
|
+
if (nodeName == "BR") { dom.className = "ProseMirror-trailingBreak"; }
|
|
1906
1918
|
this.top.children.splice(this.index++, 0, new TrailingHackViewDesc(this.top, nothing, dom, null));
|
|
1907
1919
|
this.changed = true;
|
|
1908
1920
|
}
|
|
@@ -2929,7 +2941,7 @@ function parseFromClipboard(view, text, html, plainText, $context) {
|
|
|
2929
2941
|
var asText = text && (plainText || inCode || !html);
|
|
2930
2942
|
if (asText) {
|
|
2931
2943
|
view.someProp("transformPastedText", function (f) { text = f(text, inCode || plainText); });
|
|
2932
|
-
if (inCode) { return new Slice(Fragment.from(view.state.schema.text(text.replace(/\r\n?/g, "\n"))), 0, 0) }
|
|
2944
|
+
if (inCode) { return text ? new Slice(Fragment.from(view.state.schema.text(text.replace(/\r\n?/g, "\n"))), 0, 0) : Slice.empty }
|
|
2933
2945
|
var parsed = view.someProp("clipboardTextParser", function (f) { return f(text, $context, plainText); });
|
|
2934
2946
|
if (parsed) {
|
|
2935
2947
|
slice = parsed;
|
|
@@ -2939,8 +2951,9 @@ function parseFromClipboard(view, text, html, plainText, $context) {
|
|
|
2939
2951
|
var schema = ref.schema;
|
|
2940
2952
|
var serializer = DOMSerializer.fromSchema(schema);
|
|
2941
2953
|
dom = document.createElement("div");
|
|
2942
|
-
text.
|
|
2943
|
-
dom.appendChild(document.createElement("p"))
|
|
2954
|
+
text.split(/(?:\r\n?|\n)+/).forEach(function (block) {
|
|
2955
|
+
var p = dom.appendChild(document.createElement("p"));
|
|
2956
|
+
if (block) { p.appendChild(serializer.serializeNode(schema.text(block, marks))); }
|
|
2944
2957
|
});
|
|
2945
2958
|
}
|
|
2946
2959
|
} else {
|
|
@@ -2955,10 +2968,19 @@ function parseFromClipboard(view, text, html, plainText, $context) {
|
|
|
2955
2968
|
var parser = view.someProp("clipboardParser") || view.someProp("domParser") || DOMParser.fromSchema(view.state.schema);
|
|
2956
2969
|
slice = parser.parseSlice(dom, {preserveWhitespace: !!(asText || sliceData), context: $context});
|
|
2957
2970
|
}
|
|
2958
|
-
if (sliceData)
|
|
2959
|
-
|
|
2960
|
-
else // HTML wasn't created by ProseMirror. Make sure top-level siblings are coherent
|
|
2961
|
-
|
|
2971
|
+
if (sliceData) {
|
|
2972
|
+
slice = addContext(closeSlice(slice, +sliceData[1], +sliceData[2]), sliceData[3]);
|
|
2973
|
+
} else { // HTML wasn't created by ProseMirror. Make sure top-level siblings are coherent
|
|
2974
|
+
slice = Slice.maxOpen(normalizeSiblings(slice.content, $context), true);
|
|
2975
|
+
if (slice.openStart || slice.openEnd) {
|
|
2976
|
+
var openStart = 0, openEnd = 0;
|
|
2977
|
+
for (var node = slice.content.firstChild; openStart < slice.openStart && !node.type.spec.isolating;
|
|
2978
|
+
openStart++, node = node.firstChild) {}
|
|
2979
|
+
for (var node$1 = slice.content.lastChild; openEnd < slice.openEnd && !node$1.type.spec.isolating;
|
|
2980
|
+
openEnd++, node$1 = node$1.lastChild) {}
|
|
2981
|
+
slice = closeSlice(slice, openStart, openEnd);
|
|
2982
|
+
}
|
|
2983
|
+
}
|
|
2962
2984
|
|
|
2963
2985
|
view.someProp("transformPasted", function (f) { slice = f(slice); });
|
|
2964
2986
|
return slice
|
|
@@ -4137,7 +4159,8 @@ NodeType.prototype.valid = function valid (node, span) {
|
|
|
4137
4159
|
var ref = node.content.findIndex(span.from);
|
|
4138
4160
|
var index = ref.index;
|
|
4139
4161
|
var offset = ref.offset;
|
|
4140
|
-
|
|
4162
|
+
var child;
|
|
4163
|
+
return offset == span.from && !(child = node.child(index)).isText && offset + child.nodeSize == span.to
|
|
4141
4164
|
};
|
|
4142
4165
|
|
|
4143
4166
|
NodeType.prototype.eq = function eq (other) {
|
|
@@ -5162,6 +5185,9 @@ function computeDocDeco(view) {
|
|
|
5162
5185
|
if (value) { for (var attr in value) {
|
|
5163
5186
|
if (attr == "class")
|
|
5164
5187
|
{ attrs.class += " " + value[attr]; }
|
|
5188
|
+
if (attr == "style") {
|
|
5189
|
+
attrs.style = (attrs.style ? attrs.style + ";" : "") + value[attr];
|
|
5190
|
+
}
|
|
5165
5191
|
else if (!attrs[attr] && attr != "contenteditable" && attr != "nodeName")
|
|
5166
5192
|
{ attrs[attr] = String(value[attr]); }
|
|
5167
5193
|
} }
|