prosekit 0.0.0-next-20230627094841
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/LICENSE +21 -0
- package/README.md +13 -0
- package/dist/basic/style.css +133 -0
- package/dist/chunk-23S3SZFA.js +46 -0
- package/dist/chunk-2MVHS73Q.js +709 -0
- package/dist/chunk-4GDRVRDP.js +0 -0
- package/dist/chunk-5PFF57NB.js +1546 -0
- package/dist/chunk-6A2XHVFY.js +46 -0
- package/dist/chunk-7OYIOTDD.js +16472 -0
- package/dist/chunk-ARJTWYPA.js +1321 -0
- package/dist/chunk-CDGN4JUS.js +1546 -0
- package/dist/chunk-CG5B6PMC.js +973 -0
- package/dist/chunk-DDN3TFRH.js +185 -0
- package/dist/chunk-EQV3CWHZ.js +2213 -0
- package/dist/chunk-ERNIDFFW.js +1711 -0
- package/dist/chunk-FAVXZAF7.js +3279 -0
- package/dist/chunk-HSPTUO6P.js +53 -0
- package/dist/chunk-JMNJUDT7.js +165 -0
- package/dist/chunk-LXCCO2LO.js +52 -0
- package/dist/chunk-MIPON3OH.js +922 -0
- package/dist/chunk-NAWSCY5F.js +166 -0
- package/dist/chunk-S64NFSV2.js +236 -0
- package/dist/chunk-S65R2BUY.js +15 -0
- package/dist/chunk-T2V5UU6H.js +204 -0
- package/dist/chunk-TWIMWRRZ.js +57 -0
- package/dist/chunk-US2P3K6I.js +185 -0
- package/dist/chunk-UTNVEPBA.js +950 -0
- package/dist/chunk-UWHQRU5N.js +4883 -0
- package/dist/chunk-VIKPJJET.js +662 -0
- package/dist/chunk-WAMZOD5I.js +67 -0
- package/dist/chunk-YUY5I2TY.js +236 -0
- package/dist/core/style.css +54 -0
- package/dist/extension-list/style.css +78 -0
- package/dist/pm/view/style/prosemirror.css +52 -0
- package/dist/prosekit-basic.js +2 -0
- package/dist/prosekit-core.js +2 -0
- package/dist/prosekit-extension-blockquote.js +2 -0
- package/dist/prosekit-extension-bold.js +2 -0
- package/dist/prosekit-extension-code-block.js +2 -0
- package/dist/prosekit-extension-code.js +2 -0
- package/dist/prosekit-extension-heading.js +2 -0
- package/dist/prosekit-extension-horizontal-rule.js +2 -0
- package/dist/prosekit-extension-italic.js +2 -0
- package/dist/prosekit-extension-list.js +2 -0
- package/dist/prosekit-extension-suggestion.js +2 -0
- package/dist/prosekit-lit-elements-menu-item.js +2 -0
- package/dist/prosekit-lit-elements-menu.js +2 -0
- package/dist/prosekit-lit-elements-popover.js +2 -0
- package/dist/prosekit-lit.js +2 -0
- package/dist/prosekit-pm-commands.js +2 -0
- package/dist/prosekit-pm-inputrules.js +2 -0
- package/dist/prosekit-pm-keymap.js +2 -0
- package/dist/prosekit-pm-model.js +2 -0
- package/dist/prosekit-pm-state.js +2 -0
- package/dist/prosekit-pm-transform.js +2 -0
- package/dist/prosekit-pm-view.js +2 -0
- package/dist/prosekit-pm.js +2 -0
- package/dist/prosekit-react-components-menu-item.js +2 -0
- package/dist/prosekit-react-components-menu.js +2 -0
- package/dist/prosekit-react-components-popover-suggestion.js +2 -0
- package/dist/prosekit-react-components-popover.js +2 -0
- package/dist/prosekit-react.js +2 -0
- package/dist/prosekit-vue-components-menu-item.js +2 -0
- package/dist/prosekit-vue-components-menu.js +2 -0
- package/dist/prosekit-vue-components-popover-suggestion.js +2 -0
- package/dist/prosekit-vue-components-popover.js +2 -0
- package/dist/prosekit-vue.js +2 -0
- package/dist/prosekit.js +0 -0
- package/package.json +262 -0
- package/src/index.ts +1 -0
|
@@ -0,0 +1,4883 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AllSelection,
|
|
3
|
+
NodeSelection,
|
|
4
|
+
Selection,
|
|
5
|
+
TextSelection
|
|
6
|
+
} from "./chunk-UTNVEPBA.js";
|
|
7
|
+
import {
|
|
8
|
+
dropPoint
|
|
9
|
+
} from "./chunk-ERNIDFFW.js";
|
|
10
|
+
import {
|
|
11
|
+
DOMParser,
|
|
12
|
+
DOMSerializer,
|
|
13
|
+
Fragment,
|
|
14
|
+
Mark,
|
|
15
|
+
Slice
|
|
16
|
+
} from "./chunk-FAVXZAF7.js";
|
|
17
|
+
|
|
18
|
+
// ../../node_modules/.pnpm/prosemirror-view@1.31.5/node_modules/prosemirror-view/dist/index.js
|
|
19
|
+
var domIndex = function(node) {
|
|
20
|
+
for (var index = 0; ; index++) {
|
|
21
|
+
node = node.previousSibling;
|
|
22
|
+
if (!node)
|
|
23
|
+
return index;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
var parentNode = function(node) {
|
|
27
|
+
let parent = node.assignedSlot || node.parentNode;
|
|
28
|
+
return parent && parent.nodeType == 11 ? parent.host : parent;
|
|
29
|
+
};
|
|
30
|
+
var reusedRange = null;
|
|
31
|
+
var textRange = function(node, from, to) {
|
|
32
|
+
let range = reusedRange || (reusedRange = document.createRange());
|
|
33
|
+
range.setEnd(node, to == null ? node.nodeValue.length : to);
|
|
34
|
+
range.setStart(node, from || 0);
|
|
35
|
+
return range;
|
|
36
|
+
};
|
|
37
|
+
var isEquivalentPosition = function(node, off, targetNode, targetOff) {
|
|
38
|
+
return targetNode && (scanFor(node, off, targetNode, targetOff, -1) || scanFor(node, off, targetNode, targetOff, 1));
|
|
39
|
+
};
|
|
40
|
+
var atomElements = /^(img|br|input|textarea|hr)$/i;
|
|
41
|
+
function scanFor(node, off, targetNode, targetOff, dir) {
|
|
42
|
+
for (; ; ) {
|
|
43
|
+
if (node == targetNode && off == targetOff)
|
|
44
|
+
return true;
|
|
45
|
+
if (off == (dir < 0 ? 0 : nodeSize(node))) {
|
|
46
|
+
let parent = node.parentNode;
|
|
47
|
+
if (!parent || parent.nodeType != 1 || hasBlockDesc(node) || atomElements.test(node.nodeName) || node.contentEditable == "false")
|
|
48
|
+
return false;
|
|
49
|
+
off = domIndex(node) + (dir < 0 ? 0 : 1);
|
|
50
|
+
node = parent;
|
|
51
|
+
} else if (node.nodeType == 1) {
|
|
52
|
+
node = node.childNodes[off + (dir < 0 ? -1 : 0)];
|
|
53
|
+
if (node.contentEditable == "false")
|
|
54
|
+
return false;
|
|
55
|
+
off = dir < 0 ? nodeSize(node) : 0;
|
|
56
|
+
} else {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function nodeSize(node) {
|
|
62
|
+
return node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length;
|
|
63
|
+
}
|
|
64
|
+
function isOnEdge(node, offset, parent) {
|
|
65
|
+
for (let atStart = offset == 0, atEnd = offset == nodeSize(node); atStart || atEnd; ) {
|
|
66
|
+
if (node == parent)
|
|
67
|
+
return true;
|
|
68
|
+
let index = domIndex(node);
|
|
69
|
+
node = node.parentNode;
|
|
70
|
+
if (!node)
|
|
71
|
+
return false;
|
|
72
|
+
atStart = atStart && index == 0;
|
|
73
|
+
atEnd = atEnd && index == nodeSize(node);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
function hasBlockDesc(dom) {
|
|
77
|
+
let desc;
|
|
78
|
+
for (let cur = dom; cur; cur = cur.parentNode)
|
|
79
|
+
if (desc = cur.pmViewDesc)
|
|
80
|
+
break;
|
|
81
|
+
return desc && desc.node && desc.node.isBlock && (desc.dom == dom || desc.contentDOM == dom);
|
|
82
|
+
}
|
|
83
|
+
var selectionCollapsed = function(domSel) {
|
|
84
|
+
return domSel.focusNode && isEquivalentPosition(domSel.focusNode, domSel.focusOffset, domSel.anchorNode, domSel.anchorOffset);
|
|
85
|
+
};
|
|
86
|
+
function keyEvent(keyCode, key) {
|
|
87
|
+
let event = document.createEvent("Event");
|
|
88
|
+
event.initEvent("keydown", true, true);
|
|
89
|
+
event.keyCode = keyCode;
|
|
90
|
+
event.key = event.code = key;
|
|
91
|
+
return event;
|
|
92
|
+
}
|
|
93
|
+
function deepActiveElement(doc2) {
|
|
94
|
+
let elt = doc2.activeElement;
|
|
95
|
+
while (elt && elt.shadowRoot)
|
|
96
|
+
elt = elt.shadowRoot.activeElement;
|
|
97
|
+
return elt;
|
|
98
|
+
}
|
|
99
|
+
function caretFromPoint(doc2, x, y) {
|
|
100
|
+
if (doc2.caretPositionFromPoint) {
|
|
101
|
+
try {
|
|
102
|
+
let pos = doc2.caretPositionFromPoint(x, y);
|
|
103
|
+
if (pos)
|
|
104
|
+
return { node: pos.offsetNode, offset: pos.offset };
|
|
105
|
+
} catch (_) {
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
if (doc2.caretRangeFromPoint) {
|
|
109
|
+
let range = doc2.caretRangeFromPoint(x, y);
|
|
110
|
+
if (range)
|
|
111
|
+
return { node: range.startContainer, offset: range.startOffset };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
var nav = typeof navigator != "undefined" ? navigator : null;
|
|
115
|
+
var doc = typeof document != "undefined" ? document : null;
|
|
116
|
+
var agent = nav && nav.userAgent || "";
|
|
117
|
+
var ie_edge = /Edge\/(\d+)/.exec(agent);
|
|
118
|
+
var ie_upto10 = /MSIE \d/.exec(agent);
|
|
119
|
+
var ie_11up = /Trident\/(?:[7-9]|\d{2,})\..*rv:(\d+)/.exec(agent);
|
|
120
|
+
var ie = !!(ie_upto10 || ie_11up || ie_edge);
|
|
121
|
+
var ie_version = ie_upto10 ? document.documentMode : ie_11up ? +ie_11up[1] : ie_edge ? +ie_edge[1] : 0;
|
|
122
|
+
var gecko = !ie && /gecko\/(\d+)/i.test(agent);
|
|
123
|
+
gecko && +(/Firefox\/(\d+)/.exec(agent) || [0, 0])[1];
|
|
124
|
+
var _chrome = !ie && /Chrome\/(\d+)/.exec(agent);
|
|
125
|
+
var chrome = !!_chrome;
|
|
126
|
+
var chrome_version = _chrome ? +_chrome[1] : 0;
|
|
127
|
+
var safari = !ie && !!nav && /Apple Computer/.test(nav.vendor);
|
|
128
|
+
var ios = safari && (/Mobile\/\w+/.test(agent) || !!nav && nav.maxTouchPoints > 2);
|
|
129
|
+
var mac = ios || (nav ? /Mac/.test(nav.platform) : false);
|
|
130
|
+
var windows = nav ? /Win/.test(nav.platform) : false;
|
|
131
|
+
var android = /Android \d/.test(agent);
|
|
132
|
+
var webkit = !!doc && "webkitFontSmoothing" in doc.documentElement.style;
|
|
133
|
+
var webkit_version = webkit ? +(/\bAppleWebKit\/(\d+)/.exec(navigator.userAgent) || [0, 0])[1] : 0;
|
|
134
|
+
function windowRect(doc2) {
|
|
135
|
+
return {
|
|
136
|
+
left: 0,
|
|
137
|
+
right: doc2.documentElement.clientWidth,
|
|
138
|
+
top: 0,
|
|
139
|
+
bottom: doc2.documentElement.clientHeight
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function getSide(value, side) {
|
|
143
|
+
return typeof value == "number" ? value : value[side];
|
|
144
|
+
}
|
|
145
|
+
function clientRect(node) {
|
|
146
|
+
let rect = node.getBoundingClientRect();
|
|
147
|
+
let scaleX = rect.width / node.offsetWidth || 1;
|
|
148
|
+
let scaleY = rect.height / node.offsetHeight || 1;
|
|
149
|
+
return {
|
|
150
|
+
left: rect.left,
|
|
151
|
+
right: rect.left + node.clientWidth * scaleX,
|
|
152
|
+
top: rect.top,
|
|
153
|
+
bottom: rect.top + node.clientHeight * scaleY
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
function scrollRectIntoView(view, rect, startDOM) {
|
|
157
|
+
let scrollThreshold = view.someProp("scrollThreshold") || 0, scrollMargin = view.someProp("scrollMargin") || 5;
|
|
158
|
+
let doc2 = view.dom.ownerDocument;
|
|
159
|
+
for (let parent = startDOM || view.dom; ; parent = parentNode(parent)) {
|
|
160
|
+
if (!parent)
|
|
161
|
+
break;
|
|
162
|
+
if (parent.nodeType != 1)
|
|
163
|
+
continue;
|
|
164
|
+
let elt = parent;
|
|
165
|
+
let atTop = elt == doc2.body;
|
|
166
|
+
let bounding = atTop ? windowRect(doc2) : clientRect(elt);
|
|
167
|
+
let moveX = 0, moveY = 0;
|
|
168
|
+
if (rect.top < bounding.top + getSide(scrollThreshold, "top"))
|
|
169
|
+
moveY = -(bounding.top - rect.top + getSide(scrollMargin, "top"));
|
|
170
|
+
else if (rect.bottom > bounding.bottom - getSide(scrollThreshold, "bottom"))
|
|
171
|
+
moveY = rect.bottom - bounding.bottom + getSide(scrollMargin, "bottom");
|
|
172
|
+
if (rect.left < bounding.left + getSide(scrollThreshold, "left"))
|
|
173
|
+
moveX = -(bounding.left - rect.left + getSide(scrollMargin, "left"));
|
|
174
|
+
else if (rect.right > bounding.right - getSide(scrollThreshold, "right"))
|
|
175
|
+
moveX = rect.right - bounding.right + getSide(scrollMargin, "right");
|
|
176
|
+
if (moveX || moveY) {
|
|
177
|
+
if (atTop) {
|
|
178
|
+
doc2.defaultView.scrollBy(moveX, moveY);
|
|
179
|
+
} else {
|
|
180
|
+
let startX = elt.scrollLeft, startY = elt.scrollTop;
|
|
181
|
+
if (moveY)
|
|
182
|
+
elt.scrollTop += moveY;
|
|
183
|
+
if (moveX)
|
|
184
|
+
elt.scrollLeft += moveX;
|
|
185
|
+
let dX = elt.scrollLeft - startX, dY = elt.scrollTop - startY;
|
|
186
|
+
rect = { left: rect.left - dX, top: rect.top - dY, right: rect.right - dX, bottom: rect.bottom - dY };
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
if (atTop)
|
|
190
|
+
break;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
function storeScrollPos(view) {
|
|
194
|
+
let rect = view.dom.getBoundingClientRect(), startY = Math.max(0, rect.top);
|
|
195
|
+
let refDOM, refTop;
|
|
196
|
+
for (let x = (rect.left + rect.right) / 2, y = startY + 1; y < Math.min(innerHeight, rect.bottom); y += 5) {
|
|
197
|
+
let dom = view.root.elementFromPoint(x, y);
|
|
198
|
+
if (!dom || dom == view.dom || !view.dom.contains(dom))
|
|
199
|
+
continue;
|
|
200
|
+
let localRect = dom.getBoundingClientRect();
|
|
201
|
+
if (localRect.top >= startY - 20) {
|
|
202
|
+
refDOM = dom;
|
|
203
|
+
refTop = localRect.top;
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return { refDOM, refTop, stack: scrollStack(view.dom) };
|
|
208
|
+
}
|
|
209
|
+
function scrollStack(dom) {
|
|
210
|
+
let stack = [], doc2 = dom.ownerDocument;
|
|
211
|
+
for (let cur = dom; cur; cur = parentNode(cur)) {
|
|
212
|
+
stack.push({ dom: cur, top: cur.scrollTop, left: cur.scrollLeft });
|
|
213
|
+
if (dom == doc2)
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
return stack;
|
|
217
|
+
}
|
|
218
|
+
function resetScrollPos({ refDOM, refTop, stack }) {
|
|
219
|
+
let newRefTop = refDOM ? refDOM.getBoundingClientRect().top : 0;
|
|
220
|
+
restoreScrollStack(stack, newRefTop == 0 ? 0 : newRefTop - refTop);
|
|
221
|
+
}
|
|
222
|
+
function restoreScrollStack(stack, dTop) {
|
|
223
|
+
for (let i = 0; i < stack.length; i++) {
|
|
224
|
+
let { dom, top, left } = stack[i];
|
|
225
|
+
if (dom.scrollTop != top + dTop)
|
|
226
|
+
dom.scrollTop = top + dTop;
|
|
227
|
+
if (dom.scrollLeft != left)
|
|
228
|
+
dom.scrollLeft = left;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
var preventScrollSupported = null;
|
|
232
|
+
function focusPreventScroll(dom) {
|
|
233
|
+
if (dom.setActive)
|
|
234
|
+
return dom.setActive();
|
|
235
|
+
if (preventScrollSupported)
|
|
236
|
+
return dom.focus(preventScrollSupported);
|
|
237
|
+
let stored = scrollStack(dom);
|
|
238
|
+
dom.focus(preventScrollSupported == null ? {
|
|
239
|
+
get preventScroll() {
|
|
240
|
+
preventScrollSupported = { preventScroll: true };
|
|
241
|
+
return true;
|
|
242
|
+
}
|
|
243
|
+
} : void 0);
|
|
244
|
+
if (!preventScrollSupported) {
|
|
245
|
+
preventScrollSupported = false;
|
|
246
|
+
restoreScrollStack(stored, 0);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
function findOffsetInNode(node, coords) {
|
|
250
|
+
let closest, dxClosest = 2e8, coordsClosest, offset = 0;
|
|
251
|
+
let rowBot = coords.top, rowTop = coords.top;
|
|
252
|
+
let firstBelow, coordsBelow;
|
|
253
|
+
for (let child = node.firstChild, childIndex = 0; child; child = child.nextSibling, childIndex++) {
|
|
254
|
+
let rects;
|
|
255
|
+
if (child.nodeType == 1)
|
|
256
|
+
rects = child.getClientRects();
|
|
257
|
+
else if (child.nodeType == 3)
|
|
258
|
+
rects = textRange(child).getClientRects();
|
|
259
|
+
else
|
|
260
|
+
continue;
|
|
261
|
+
for (let i = 0; i < rects.length; i++) {
|
|
262
|
+
let rect = rects[i];
|
|
263
|
+
if (rect.top <= rowBot && rect.bottom >= rowTop) {
|
|
264
|
+
rowBot = Math.max(rect.bottom, rowBot);
|
|
265
|
+
rowTop = Math.min(rect.top, rowTop);
|
|
266
|
+
let dx = rect.left > coords.left ? rect.left - coords.left : rect.right < coords.left ? coords.left - rect.right : 0;
|
|
267
|
+
if (dx < dxClosest) {
|
|
268
|
+
closest = child;
|
|
269
|
+
dxClosest = dx;
|
|
270
|
+
coordsClosest = dx && closest.nodeType == 3 ? {
|
|
271
|
+
left: rect.right < coords.left ? rect.right : rect.left,
|
|
272
|
+
top: coords.top
|
|
273
|
+
} : coords;
|
|
274
|
+
if (child.nodeType == 1 && dx)
|
|
275
|
+
offset = childIndex + (coords.left >= (rect.left + rect.right) / 2 ? 1 : 0);
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
} else if (rect.top > coords.top && !firstBelow && rect.left <= coords.left && rect.right >= coords.left) {
|
|
279
|
+
firstBelow = child;
|
|
280
|
+
coordsBelow = { left: Math.max(rect.left, Math.min(rect.right, coords.left)), top: rect.top };
|
|
281
|
+
}
|
|
282
|
+
if (!closest && (coords.left >= rect.right && coords.top >= rect.top || coords.left >= rect.left && coords.top >= rect.bottom))
|
|
283
|
+
offset = childIndex + 1;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
if (!closest && firstBelow) {
|
|
287
|
+
closest = firstBelow;
|
|
288
|
+
coordsClosest = coordsBelow;
|
|
289
|
+
dxClosest = 0;
|
|
290
|
+
}
|
|
291
|
+
if (closest && closest.nodeType == 3)
|
|
292
|
+
return findOffsetInText(closest, coordsClosest);
|
|
293
|
+
if (!closest || dxClosest && closest.nodeType == 1)
|
|
294
|
+
return { node, offset };
|
|
295
|
+
return findOffsetInNode(closest, coordsClosest);
|
|
296
|
+
}
|
|
297
|
+
function findOffsetInText(node, coords) {
|
|
298
|
+
let len = node.nodeValue.length;
|
|
299
|
+
let range = document.createRange();
|
|
300
|
+
for (let i = 0; i < len; i++) {
|
|
301
|
+
range.setEnd(node, i + 1);
|
|
302
|
+
range.setStart(node, i);
|
|
303
|
+
let rect = singleRect(range, 1);
|
|
304
|
+
if (rect.top == rect.bottom)
|
|
305
|
+
continue;
|
|
306
|
+
if (inRect(coords, rect))
|
|
307
|
+
return { node, offset: i + (coords.left >= (rect.left + rect.right) / 2 ? 1 : 0) };
|
|
308
|
+
}
|
|
309
|
+
return { node, offset: 0 };
|
|
310
|
+
}
|
|
311
|
+
function inRect(coords, rect) {
|
|
312
|
+
return coords.left >= rect.left - 1 && coords.left <= rect.right + 1 && coords.top >= rect.top - 1 && coords.top <= rect.bottom + 1;
|
|
313
|
+
}
|
|
314
|
+
function targetKludge(dom, coords) {
|
|
315
|
+
let parent = dom.parentNode;
|
|
316
|
+
if (parent && /^li$/i.test(parent.nodeName) && coords.left < dom.getBoundingClientRect().left)
|
|
317
|
+
return parent;
|
|
318
|
+
return dom;
|
|
319
|
+
}
|
|
320
|
+
function posFromElement(view, elt, coords) {
|
|
321
|
+
let { node, offset } = findOffsetInNode(elt, coords), bias = -1;
|
|
322
|
+
if (node.nodeType == 1 && !node.firstChild) {
|
|
323
|
+
let rect = node.getBoundingClientRect();
|
|
324
|
+
bias = rect.left != rect.right && coords.left > (rect.left + rect.right) / 2 ? 1 : -1;
|
|
325
|
+
}
|
|
326
|
+
return view.docView.posFromDOM(node, offset, bias);
|
|
327
|
+
}
|
|
328
|
+
function posFromCaret(view, node, offset, coords) {
|
|
329
|
+
let outsideBlock = -1;
|
|
330
|
+
for (let cur = node, sawBlock = false; ; ) {
|
|
331
|
+
if (cur == view.dom)
|
|
332
|
+
break;
|
|
333
|
+
let desc = view.docView.nearestDesc(cur, true);
|
|
334
|
+
if (!desc)
|
|
335
|
+
return null;
|
|
336
|
+
if (desc.dom.nodeType == 1 && (desc.node.isBlock && desc.parent && !sawBlock || !desc.contentDOM)) {
|
|
337
|
+
let rect = desc.dom.getBoundingClientRect();
|
|
338
|
+
if (desc.node.isBlock && desc.parent && !sawBlock) {
|
|
339
|
+
sawBlock = true;
|
|
340
|
+
if (rect.left > coords.left || rect.top > coords.top)
|
|
341
|
+
outsideBlock = desc.posBefore;
|
|
342
|
+
else if (rect.right < coords.left || rect.bottom < coords.top)
|
|
343
|
+
outsideBlock = desc.posAfter;
|
|
344
|
+
}
|
|
345
|
+
if (!desc.contentDOM && outsideBlock < 0) {
|
|
346
|
+
let before = desc.node.isBlock ? coords.top < (rect.top + rect.bottom) / 2 : coords.left < (rect.left + rect.right) / 2;
|
|
347
|
+
return before ? desc.posBefore : desc.posAfter;
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
cur = desc.dom.parentNode;
|
|
351
|
+
}
|
|
352
|
+
return outsideBlock > -1 ? outsideBlock : view.docView.posFromDOM(node, offset, -1);
|
|
353
|
+
}
|
|
354
|
+
function elementFromPoint(element, coords, box) {
|
|
355
|
+
let len = element.childNodes.length;
|
|
356
|
+
if (len && box.top < box.bottom) {
|
|
357
|
+
for (let startI = Math.max(0, Math.min(len - 1, Math.floor(len * (coords.top - box.top) / (box.bottom - box.top)) - 2)), i = startI; ; ) {
|
|
358
|
+
let child = element.childNodes[i];
|
|
359
|
+
if (child.nodeType == 1) {
|
|
360
|
+
let rects = child.getClientRects();
|
|
361
|
+
for (let j = 0; j < rects.length; j++) {
|
|
362
|
+
let rect = rects[j];
|
|
363
|
+
if (inRect(coords, rect))
|
|
364
|
+
return elementFromPoint(child, coords, rect);
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
if ((i = (i + 1) % len) == startI)
|
|
368
|
+
break;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
return element;
|
|
372
|
+
}
|
|
373
|
+
function posAtCoords(view, coords) {
|
|
374
|
+
let doc2 = view.dom.ownerDocument, node, offset = 0;
|
|
375
|
+
let caret = caretFromPoint(doc2, coords.left, coords.top);
|
|
376
|
+
if (caret)
|
|
377
|
+
({ node, offset } = caret);
|
|
378
|
+
let elt = (view.root.elementFromPoint ? view.root : doc2).elementFromPoint(coords.left, coords.top);
|
|
379
|
+
let pos;
|
|
380
|
+
if (!elt || !view.dom.contains(elt.nodeType != 1 ? elt.parentNode : elt)) {
|
|
381
|
+
let box = view.dom.getBoundingClientRect();
|
|
382
|
+
if (!inRect(coords, box))
|
|
383
|
+
return null;
|
|
384
|
+
elt = elementFromPoint(view.dom, coords, box);
|
|
385
|
+
if (!elt)
|
|
386
|
+
return null;
|
|
387
|
+
}
|
|
388
|
+
if (safari) {
|
|
389
|
+
for (let p = elt; node && p; p = parentNode(p))
|
|
390
|
+
if (p.draggable)
|
|
391
|
+
node = void 0;
|
|
392
|
+
}
|
|
393
|
+
elt = targetKludge(elt, coords);
|
|
394
|
+
if (node) {
|
|
395
|
+
if (gecko && node.nodeType == 1) {
|
|
396
|
+
offset = Math.min(offset, node.childNodes.length);
|
|
397
|
+
if (offset < node.childNodes.length) {
|
|
398
|
+
let next = node.childNodes[offset], box;
|
|
399
|
+
if (next.nodeName == "IMG" && (box = next.getBoundingClientRect()).right <= coords.left && box.bottom > coords.top)
|
|
400
|
+
offset++;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
if (node == view.dom && offset == node.childNodes.length - 1 && node.lastChild.nodeType == 1 && coords.top > node.lastChild.getBoundingClientRect().bottom)
|
|
404
|
+
pos = view.state.doc.content.size;
|
|
405
|
+
else if (offset == 0 || node.nodeType != 1 || node.childNodes[offset - 1].nodeName != "BR")
|
|
406
|
+
pos = posFromCaret(view, node, offset, coords);
|
|
407
|
+
}
|
|
408
|
+
if (pos == null)
|
|
409
|
+
pos = posFromElement(view, elt, coords);
|
|
410
|
+
let desc = view.docView.nearestDesc(elt, true);
|
|
411
|
+
return { pos, inside: desc ? desc.posAtStart - desc.border : -1 };
|
|
412
|
+
}
|
|
413
|
+
function nonZero(rect) {
|
|
414
|
+
return rect.top < rect.bottom || rect.left < rect.right;
|
|
415
|
+
}
|
|
416
|
+
function singleRect(target, bias) {
|
|
417
|
+
let rects = target.getClientRects();
|
|
418
|
+
if (rects.length) {
|
|
419
|
+
let first = rects[bias < 0 ? 0 : rects.length - 1];
|
|
420
|
+
if (nonZero(first))
|
|
421
|
+
return first;
|
|
422
|
+
}
|
|
423
|
+
return Array.prototype.find.call(rects, nonZero) || target.getBoundingClientRect();
|
|
424
|
+
}
|
|
425
|
+
var BIDI = /[\u0590-\u05f4\u0600-\u06ff\u0700-\u08ac]/;
|
|
426
|
+
function coordsAtPos(view, pos, side) {
|
|
427
|
+
let { node, offset, atom } = view.docView.domFromPos(pos, side < 0 ? -1 : 1);
|
|
428
|
+
let supportEmptyRange = webkit || gecko;
|
|
429
|
+
if (node.nodeType == 3) {
|
|
430
|
+
if (supportEmptyRange && (BIDI.test(node.nodeValue) || (side < 0 ? !offset : offset == node.nodeValue.length))) {
|
|
431
|
+
let rect = singleRect(textRange(node, offset, offset), side);
|
|
432
|
+
if (gecko && offset && /\s/.test(node.nodeValue[offset - 1]) && offset < node.nodeValue.length) {
|
|
433
|
+
let rectBefore = singleRect(textRange(node, offset - 1, offset - 1), -1);
|
|
434
|
+
if (rectBefore.top == rect.top) {
|
|
435
|
+
let rectAfter = singleRect(textRange(node, offset, offset + 1), -1);
|
|
436
|
+
if (rectAfter.top != rect.top)
|
|
437
|
+
return flattenV(rectAfter, rectAfter.left < rectBefore.left);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
return rect;
|
|
441
|
+
} else {
|
|
442
|
+
let from = offset, to = offset, takeSide = side < 0 ? 1 : -1;
|
|
443
|
+
if (side < 0 && !offset) {
|
|
444
|
+
to++;
|
|
445
|
+
takeSide = -1;
|
|
446
|
+
} else if (side >= 0 && offset == node.nodeValue.length) {
|
|
447
|
+
from--;
|
|
448
|
+
takeSide = 1;
|
|
449
|
+
} else if (side < 0) {
|
|
450
|
+
from--;
|
|
451
|
+
} else {
|
|
452
|
+
to++;
|
|
453
|
+
}
|
|
454
|
+
return flattenV(singleRect(textRange(node, from, to), takeSide), takeSide < 0);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
let $dom = view.state.doc.resolve(pos - (atom || 0));
|
|
458
|
+
if (!$dom.parent.inlineContent) {
|
|
459
|
+
if (atom == null && offset && (side < 0 || offset == nodeSize(node))) {
|
|
460
|
+
let before = node.childNodes[offset - 1];
|
|
461
|
+
if (before.nodeType == 1)
|
|
462
|
+
return flattenH(before.getBoundingClientRect(), false);
|
|
463
|
+
}
|
|
464
|
+
if (atom == null && offset < nodeSize(node)) {
|
|
465
|
+
let after = node.childNodes[offset];
|
|
466
|
+
if (after.nodeType == 1)
|
|
467
|
+
return flattenH(after.getBoundingClientRect(), true);
|
|
468
|
+
}
|
|
469
|
+
return flattenH(node.getBoundingClientRect(), side >= 0);
|
|
470
|
+
}
|
|
471
|
+
if (atom == null && offset && (side < 0 || offset == nodeSize(node))) {
|
|
472
|
+
let before = node.childNodes[offset - 1];
|
|
473
|
+
let target = before.nodeType == 3 ? textRange(before, nodeSize(before) - (supportEmptyRange ? 0 : 1)) : before.nodeType == 1 && (before.nodeName != "BR" || !before.nextSibling) ? before : null;
|
|
474
|
+
if (target)
|
|
475
|
+
return flattenV(singleRect(target, 1), false);
|
|
476
|
+
}
|
|
477
|
+
if (atom == null && offset < nodeSize(node)) {
|
|
478
|
+
let after = node.childNodes[offset];
|
|
479
|
+
while (after.pmViewDesc && after.pmViewDesc.ignoreForCoords)
|
|
480
|
+
after = after.nextSibling;
|
|
481
|
+
let target = !after ? null : after.nodeType == 3 ? textRange(after, 0, supportEmptyRange ? 0 : 1) : after.nodeType == 1 ? after : null;
|
|
482
|
+
if (target)
|
|
483
|
+
return flattenV(singleRect(target, -1), true);
|
|
484
|
+
}
|
|
485
|
+
return flattenV(singleRect(node.nodeType == 3 ? textRange(node) : node, -side), side >= 0);
|
|
486
|
+
}
|
|
487
|
+
function flattenV(rect, left) {
|
|
488
|
+
if (rect.width == 0)
|
|
489
|
+
return rect;
|
|
490
|
+
let x = left ? rect.left : rect.right;
|
|
491
|
+
return { top: rect.top, bottom: rect.bottom, left: x, right: x };
|
|
492
|
+
}
|
|
493
|
+
function flattenH(rect, top) {
|
|
494
|
+
if (rect.height == 0)
|
|
495
|
+
return rect;
|
|
496
|
+
let y = top ? rect.top : rect.bottom;
|
|
497
|
+
return { top: y, bottom: y, left: rect.left, right: rect.right };
|
|
498
|
+
}
|
|
499
|
+
function withFlushedState(view, state, f) {
|
|
500
|
+
let viewState = view.state, active = view.root.activeElement;
|
|
501
|
+
if (viewState != state)
|
|
502
|
+
view.updateState(state);
|
|
503
|
+
if (active != view.dom)
|
|
504
|
+
view.focus();
|
|
505
|
+
try {
|
|
506
|
+
return f();
|
|
507
|
+
} finally {
|
|
508
|
+
if (viewState != state)
|
|
509
|
+
view.updateState(viewState);
|
|
510
|
+
if (active != view.dom && active)
|
|
511
|
+
active.focus();
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
function endOfTextblockVertical(view, state, dir) {
|
|
515
|
+
let sel = state.selection;
|
|
516
|
+
let $pos = dir == "up" ? sel.$from : sel.$to;
|
|
517
|
+
return withFlushedState(view, state, () => {
|
|
518
|
+
let { node: dom } = view.docView.domFromPos($pos.pos, dir == "up" ? -1 : 1);
|
|
519
|
+
for (; ; ) {
|
|
520
|
+
let nearest = view.docView.nearestDesc(dom, true);
|
|
521
|
+
if (!nearest)
|
|
522
|
+
break;
|
|
523
|
+
if (nearest.node.isBlock) {
|
|
524
|
+
dom = nearest.contentDOM || nearest.dom;
|
|
525
|
+
break;
|
|
526
|
+
}
|
|
527
|
+
dom = nearest.dom.parentNode;
|
|
528
|
+
}
|
|
529
|
+
let coords = coordsAtPos(view, $pos.pos, 1);
|
|
530
|
+
for (let child = dom.firstChild; child; child = child.nextSibling) {
|
|
531
|
+
let boxes;
|
|
532
|
+
if (child.nodeType == 1)
|
|
533
|
+
boxes = child.getClientRects();
|
|
534
|
+
else if (child.nodeType == 3)
|
|
535
|
+
boxes = textRange(child, 0, child.nodeValue.length).getClientRects();
|
|
536
|
+
else
|
|
537
|
+
continue;
|
|
538
|
+
for (let i = 0; i < boxes.length; i++) {
|
|
539
|
+
let box = boxes[i];
|
|
540
|
+
if (box.bottom > box.top + 1 && (dir == "up" ? coords.top - box.top > (box.bottom - coords.top) * 2 : box.bottom - coords.bottom > (coords.bottom - box.top) * 2))
|
|
541
|
+
return false;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
return true;
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
var maybeRTL = /[\u0590-\u08ac]/;
|
|
548
|
+
function endOfTextblockHorizontal(view, state, dir) {
|
|
549
|
+
let { $head } = state.selection;
|
|
550
|
+
if (!$head.parent.isTextblock)
|
|
551
|
+
return false;
|
|
552
|
+
let offset = $head.parentOffset, atStart = !offset, atEnd = offset == $head.parent.content.size;
|
|
553
|
+
let sel = view.domSelection();
|
|
554
|
+
if (!maybeRTL.test($head.parent.textContent) || !sel.modify)
|
|
555
|
+
return dir == "left" || dir == "backward" ? atStart : atEnd;
|
|
556
|
+
return withFlushedState(view, state, () => {
|
|
557
|
+
let { focusNode: oldNode, focusOffset: oldOff, anchorNode, anchorOffset } = view.domSelectionRange();
|
|
558
|
+
let oldBidiLevel = sel.caretBidiLevel;
|
|
559
|
+
sel.modify("move", dir, "character");
|
|
560
|
+
let parentDOM = $head.depth ? view.docView.domAfterPos($head.before()) : view.dom;
|
|
561
|
+
let { focusNode: newNode, focusOffset: newOff } = view.domSelectionRange();
|
|
562
|
+
let result = newNode && !parentDOM.contains(newNode.nodeType == 1 ? newNode : newNode.parentNode) || oldNode == newNode && oldOff == newOff;
|
|
563
|
+
try {
|
|
564
|
+
sel.collapse(anchorNode, anchorOffset);
|
|
565
|
+
if (oldNode && (oldNode != anchorNode || oldOff != anchorOffset) && sel.extend)
|
|
566
|
+
sel.extend(oldNode, oldOff);
|
|
567
|
+
} catch (_) {
|
|
568
|
+
}
|
|
569
|
+
if (oldBidiLevel != null)
|
|
570
|
+
sel.caretBidiLevel = oldBidiLevel;
|
|
571
|
+
return result;
|
|
572
|
+
});
|
|
573
|
+
}
|
|
574
|
+
var cachedState = null;
|
|
575
|
+
var cachedDir = null;
|
|
576
|
+
var cachedResult = false;
|
|
577
|
+
function endOfTextblock(view, state, dir) {
|
|
578
|
+
if (cachedState == state && cachedDir == dir)
|
|
579
|
+
return cachedResult;
|
|
580
|
+
cachedState = state;
|
|
581
|
+
cachedDir = dir;
|
|
582
|
+
return cachedResult = dir == "up" || dir == "down" ? endOfTextblockVertical(view, state, dir) : endOfTextblockHorizontal(view, state, dir);
|
|
583
|
+
}
|
|
584
|
+
var NOT_DIRTY = 0;
|
|
585
|
+
var CHILD_DIRTY = 1;
|
|
586
|
+
var CONTENT_DIRTY = 2;
|
|
587
|
+
var NODE_DIRTY = 3;
|
|
588
|
+
var ViewDesc = class {
|
|
589
|
+
constructor(parent, children, dom, contentDOM) {
|
|
590
|
+
this.parent = parent;
|
|
591
|
+
this.children = children;
|
|
592
|
+
this.dom = dom;
|
|
593
|
+
this.contentDOM = contentDOM;
|
|
594
|
+
this.dirty = NOT_DIRTY;
|
|
595
|
+
dom.pmViewDesc = this;
|
|
596
|
+
}
|
|
597
|
+
// Used to check whether a given description corresponds to a
|
|
598
|
+
// widget/mark/node.
|
|
599
|
+
matchesWidget(widget) {
|
|
600
|
+
return false;
|
|
601
|
+
}
|
|
602
|
+
matchesMark(mark) {
|
|
603
|
+
return false;
|
|
604
|
+
}
|
|
605
|
+
matchesNode(node, outerDeco, innerDeco) {
|
|
606
|
+
return false;
|
|
607
|
+
}
|
|
608
|
+
matchesHack(nodeName) {
|
|
609
|
+
return false;
|
|
610
|
+
}
|
|
611
|
+
// When parsing in-editor content (in domchange.js), we allow
|
|
612
|
+
// descriptions to determine the parse rules that should be used to
|
|
613
|
+
// parse them.
|
|
614
|
+
parseRule() {
|
|
615
|
+
return null;
|
|
616
|
+
}
|
|
617
|
+
// Used by the editor's event handler to ignore events that come
|
|
618
|
+
// from certain descs.
|
|
619
|
+
stopEvent(event) {
|
|
620
|
+
return false;
|
|
621
|
+
}
|
|
622
|
+
// The size of the content represented by this desc.
|
|
623
|
+
get size() {
|
|
624
|
+
let size = 0;
|
|
625
|
+
for (let i = 0; i < this.children.length; i++)
|
|
626
|
+
size += this.children[i].size;
|
|
627
|
+
return size;
|
|
628
|
+
}
|
|
629
|
+
// For block nodes, this represents the space taken up by their
|
|
630
|
+
// start/end tokens.
|
|
631
|
+
get border() {
|
|
632
|
+
return 0;
|
|
633
|
+
}
|
|
634
|
+
destroy() {
|
|
635
|
+
this.parent = void 0;
|
|
636
|
+
if (this.dom.pmViewDesc == this)
|
|
637
|
+
this.dom.pmViewDesc = void 0;
|
|
638
|
+
for (let i = 0; i < this.children.length; i++)
|
|
639
|
+
this.children[i].destroy();
|
|
640
|
+
}
|
|
641
|
+
posBeforeChild(child) {
|
|
642
|
+
for (let i = 0, pos = this.posAtStart; ; i++) {
|
|
643
|
+
let cur = this.children[i];
|
|
644
|
+
if (cur == child)
|
|
645
|
+
return pos;
|
|
646
|
+
pos += cur.size;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
get posBefore() {
|
|
650
|
+
return this.parent.posBeforeChild(this);
|
|
651
|
+
}
|
|
652
|
+
get posAtStart() {
|
|
653
|
+
return this.parent ? this.parent.posBeforeChild(this) + this.border : 0;
|
|
654
|
+
}
|
|
655
|
+
get posAfter() {
|
|
656
|
+
return this.posBefore + this.size;
|
|
657
|
+
}
|
|
658
|
+
get posAtEnd() {
|
|
659
|
+
return this.posAtStart + this.size - 2 * this.border;
|
|
660
|
+
}
|
|
661
|
+
localPosFromDOM(dom, offset, bias) {
|
|
662
|
+
if (this.contentDOM && this.contentDOM.contains(dom.nodeType == 1 ? dom : dom.parentNode)) {
|
|
663
|
+
if (bias < 0) {
|
|
664
|
+
let domBefore, desc;
|
|
665
|
+
if (dom == this.contentDOM) {
|
|
666
|
+
domBefore = dom.childNodes[offset - 1];
|
|
667
|
+
} else {
|
|
668
|
+
while (dom.parentNode != this.contentDOM)
|
|
669
|
+
dom = dom.parentNode;
|
|
670
|
+
domBefore = dom.previousSibling;
|
|
671
|
+
}
|
|
672
|
+
while (domBefore && !((desc = domBefore.pmViewDesc) && desc.parent == this))
|
|
673
|
+
domBefore = domBefore.previousSibling;
|
|
674
|
+
return domBefore ? this.posBeforeChild(desc) + desc.size : this.posAtStart;
|
|
675
|
+
} else {
|
|
676
|
+
let domAfter, desc;
|
|
677
|
+
if (dom == this.contentDOM) {
|
|
678
|
+
domAfter = dom.childNodes[offset];
|
|
679
|
+
} else {
|
|
680
|
+
while (dom.parentNode != this.contentDOM)
|
|
681
|
+
dom = dom.parentNode;
|
|
682
|
+
domAfter = dom.nextSibling;
|
|
683
|
+
}
|
|
684
|
+
while (domAfter && !((desc = domAfter.pmViewDesc) && desc.parent == this))
|
|
685
|
+
domAfter = domAfter.nextSibling;
|
|
686
|
+
return domAfter ? this.posBeforeChild(desc) : this.posAtEnd;
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
let atEnd;
|
|
690
|
+
if (dom == this.dom && this.contentDOM) {
|
|
691
|
+
atEnd = offset > domIndex(this.contentDOM);
|
|
692
|
+
} else if (this.contentDOM && this.contentDOM != this.dom && this.dom.contains(this.contentDOM)) {
|
|
693
|
+
atEnd = dom.compareDocumentPosition(this.contentDOM) & 2;
|
|
694
|
+
} else if (this.dom.firstChild) {
|
|
695
|
+
if (offset == 0)
|
|
696
|
+
for (let search = dom; ; search = search.parentNode) {
|
|
697
|
+
if (search == this.dom) {
|
|
698
|
+
atEnd = false;
|
|
699
|
+
break;
|
|
700
|
+
}
|
|
701
|
+
if (search.previousSibling)
|
|
702
|
+
break;
|
|
703
|
+
}
|
|
704
|
+
if (atEnd == null && offset == dom.childNodes.length)
|
|
705
|
+
for (let search = dom; ; search = search.parentNode) {
|
|
706
|
+
if (search == this.dom) {
|
|
707
|
+
atEnd = true;
|
|
708
|
+
break;
|
|
709
|
+
}
|
|
710
|
+
if (search.nextSibling)
|
|
711
|
+
break;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
return (atEnd == null ? bias > 0 : atEnd) ? this.posAtEnd : this.posAtStart;
|
|
715
|
+
}
|
|
716
|
+
nearestDesc(dom, onlyNodes = false) {
|
|
717
|
+
for (let first = true, cur = dom; cur; cur = cur.parentNode) {
|
|
718
|
+
let desc = this.getDesc(cur), nodeDOM;
|
|
719
|
+
if (desc && (!onlyNodes || desc.node)) {
|
|
720
|
+
if (first && (nodeDOM = desc.nodeDOM) && !(nodeDOM.nodeType == 1 ? nodeDOM.contains(dom.nodeType == 1 ? dom : dom.parentNode) : nodeDOM == dom))
|
|
721
|
+
first = false;
|
|
722
|
+
else
|
|
723
|
+
return desc;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
getDesc(dom) {
|
|
728
|
+
let desc = dom.pmViewDesc;
|
|
729
|
+
for (let cur = desc; cur; cur = cur.parent)
|
|
730
|
+
if (cur == this)
|
|
731
|
+
return desc;
|
|
732
|
+
}
|
|
733
|
+
posFromDOM(dom, offset, bias) {
|
|
734
|
+
for (let scan = dom; scan; scan = scan.parentNode) {
|
|
735
|
+
let desc = this.getDesc(scan);
|
|
736
|
+
if (desc)
|
|
737
|
+
return desc.localPosFromDOM(dom, offset, bias);
|
|
738
|
+
}
|
|
739
|
+
return -1;
|
|
740
|
+
}
|
|
741
|
+
// Find the desc for the node after the given pos, if any. (When a
|
|
742
|
+
// parent node overrode rendering, there might not be one.)
|
|
743
|
+
descAt(pos) {
|
|
744
|
+
for (let i = 0, offset = 0; i < this.children.length; i++) {
|
|
745
|
+
let child = this.children[i], end = offset + child.size;
|
|
746
|
+
if (offset == pos && end != offset) {
|
|
747
|
+
while (!child.border && child.children.length)
|
|
748
|
+
child = child.children[0];
|
|
749
|
+
return child;
|
|
750
|
+
}
|
|
751
|
+
if (pos < end)
|
|
752
|
+
return child.descAt(pos - offset - child.border);
|
|
753
|
+
offset = end;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
domFromPos(pos, side) {
|
|
757
|
+
if (!this.contentDOM)
|
|
758
|
+
return { node: this.dom, offset: 0, atom: pos + 1 };
|
|
759
|
+
let i = 0, offset = 0;
|
|
760
|
+
for (let curPos = 0; i < this.children.length; i++) {
|
|
761
|
+
let child = this.children[i], end = curPos + child.size;
|
|
762
|
+
if (end > pos || child instanceof TrailingHackViewDesc) {
|
|
763
|
+
offset = pos - curPos;
|
|
764
|
+
break;
|
|
765
|
+
}
|
|
766
|
+
curPos = end;
|
|
767
|
+
}
|
|
768
|
+
if (offset)
|
|
769
|
+
return this.children[i].domFromPos(offset - this.children[i].border, side);
|
|
770
|
+
for (let prev; i && !(prev = this.children[i - 1]).size && prev instanceof WidgetViewDesc && prev.side >= 0; i--) {
|
|
771
|
+
}
|
|
772
|
+
if (side <= 0) {
|
|
773
|
+
let prev, enter = true;
|
|
774
|
+
for (; ; i--, enter = false) {
|
|
775
|
+
prev = i ? this.children[i - 1] : null;
|
|
776
|
+
if (!prev || prev.dom.parentNode == this.contentDOM)
|
|
777
|
+
break;
|
|
778
|
+
}
|
|
779
|
+
if (prev && side && enter && !prev.border && !prev.domAtom)
|
|
780
|
+
return prev.domFromPos(prev.size, side);
|
|
781
|
+
return { node: this.contentDOM, offset: prev ? domIndex(prev.dom) + 1 : 0 };
|
|
782
|
+
} else {
|
|
783
|
+
let next, enter = true;
|
|
784
|
+
for (; ; i++, enter = false) {
|
|
785
|
+
next = i < this.children.length ? this.children[i] : null;
|
|
786
|
+
if (!next || next.dom.parentNode == this.contentDOM)
|
|
787
|
+
break;
|
|
788
|
+
}
|
|
789
|
+
if (next && enter && !next.border && !next.domAtom)
|
|
790
|
+
return next.domFromPos(0, side);
|
|
791
|
+
return { node: this.contentDOM, offset: next ? domIndex(next.dom) : this.contentDOM.childNodes.length };
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
// Used to find a DOM range in a single parent for a given changed
|
|
795
|
+
// range.
|
|
796
|
+
parseRange(from, to, base = 0) {
|
|
797
|
+
if (this.children.length == 0)
|
|
798
|
+
return { node: this.contentDOM, from, to, fromOffset: 0, toOffset: this.contentDOM.childNodes.length };
|
|
799
|
+
let fromOffset = -1, toOffset = -1;
|
|
800
|
+
for (let offset = base, i = 0; ; i++) {
|
|
801
|
+
let child = this.children[i], end = offset + child.size;
|
|
802
|
+
if (fromOffset == -1 && from <= end) {
|
|
803
|
+
let childBase = offset + child.border;
|
|
804
|
+
if (from >= childBase && to <= end - child.border && child.node && child.contentDOM && this.contentDOM.contains(child.contentDOM))
|
|
805
|
+
return child.parseRange(from, to, childBase);
|
|
806
|
+
from = offset;
|
|
807
|
+
for (let j = i; j > 0; j--) {
|
|
808
|
+
let prev = this.children[j - 1];
|
|
809
|
+
if (prev.size && prev.dom.parentNode == this.contentDOM && !prev.emptyChildAt(1)) {
|
|
810
|
+
fromOffset = domIndex(prev.dom) + 1;
|
|
811
|
+
break;
|
|
812
|
+
}
|
|
813
|
+
from -= prev.size;
|
|
814
|
+
}
|
|
815
|
+
if (fromOffset == -1)
|
|
816
|
+
fromOffset = 0;
|
|
817
|
+
}
|
|
818
|
+
if (fromOffset > -1 && (end > to || i == this.children.length - 1)) {
|
|
819
|
+
to = end;
|
|
820
|
+
for (let j = i + 1; j < this.children.length; j++) {
|
|
821
|
+
let next = this.children[j];
|
|
822
|
+
if (next.size && next.dom.parentNode == this.contentDOM && !next.emptyChildAt(-1)) {
|
|
823
|
+
toOffset = domIndex(next.dom);
|
|
824
|
+
break;
|
|
825
|
+
}
|
|
826
|
+
to += next.size;
|
|
827
|
+
}
|
|
828
|
+
if (toOffset == -1)
|
|
829
|
+
toOffset = this.contentDOM.childNodes.length;
|
|
830
|
+
break;
|
|
831
|
+
}
|
|
832
|
+
offset = end;
|
|
833
|
+
}
|
|
834
|
+
return { node: this.contentDOM, from, to, fromOffset, toOffset };
|
|
835
|
+
}
|
|
836
|
+
emptyChildAt(side) {
|
|
837
|
+
if (this.border || !this.contentDOM || !this.children.length)
|
|
838
|
+
return false;
|
|
839
|
+
let child = this.children[side < 0 ? 0 : this.children.length - 1];
|
|
840
|
+
return child.size == 0 || child.emptyChildAt(side);
|
|
841
|
+
}
|
|
842
|
+
domAfterPos(pos) {
|
|
843
|
+
let { node, offset } = this.domFromPos(pos, 0);
|
|
844
|
+
if (node.nodeType != 1 || offset == node.childNodes.length)
|
|
845
|
+
throw new RangeError("No node after pos " + pos);
|
|
846
|
+
return node.childNodes[offset];
|
|
847
|
+
}
|
|
848
|
+
// View descs are responsible for setting any selection that falls
|
|
849
|
+
// entirely inside of them, so that custom implementations can do
|
|
850
|
+
// custom things with the selection. Note that this falls apart when
|
|
851
|
+
// a selection starts in such a node and ends in another, in which
|
|
852
|
+
// case we just use whatever domFromPos produces as a best effort.
|
|
853
|
+
setSelection(anchor, head, root, force = false) {
|
|
854
|
+
let from = Math.min(anchor, head), to = Math.max(anchor, head);
|
|
855
|
+
for (let i = 0, offset = 0; i < this.children.length; i++) {
|
|
856
|
+
let child = this.children[i], end = offset + child.size;
|
|
857
|
+
if (from > offset && to < end)
|
|
858
|
+
return child.setSelection(anchor - offset - child.border, head - offset - child.border, root, force);
|
|
859
|
+
offset = end;
|
|
860
|
+
}
|
|
861
|
+
let anchorDOM = this.domFromPos(anchor, anchor ? -1 : 1);
|
|
862
|
+
let headDOM = head == anchor ? anchorDOM : this.domFromPos(head, head ? -1 : 1);
|
|
863
|
+
let domSel = root.getSelection();
|
|
864
|
+
let brKludge = false;
|
|
865
|
+
if ((gecko || safari) && anchor == head) {
|
|
866
|
+
let { node, offset } = anchorDOM;
|
|
867
|
+
if (node.nodeType == 3) {
|
|
868
|
+
brKludge = !!(offset && node.nodeValue[offset - 1] == "\n");
|
|
869
|
+
if (brKludge && offset == node.nodeValue.length) {
|
|
870
|
+
for (let scan = node, after; scan; scan = scan.parentNode) {
|
|
871
|
+
if (after = scan.nextSibling) {
|
|
872
|
+
if (after.nodeName == "BR")
|
|
873
|
+
anchorDOM = headDOM = { node: after.parentNode, offset: domIndex(after) + 1 };
|
|
874
|
+
break;
|
|
875
|
+
}
|
|
876
|
+
let desc = scan.pmViewDesc;
|
|
877
|
+
if (desc && desc.node && desc.node.isBlock)
|
|
878
|
+
break;
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
} else {
|
|
882
|
+
let prev = node.childNodes[offset - 1];
|
|
883
|
+
brKludge = prev && (prev.nodeName == "BR" || prev.contentEditable == "false");
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
if (gecko && domSel.focusNode && domSel.focusNode != headDOM.node && domSel.focusNode.nodeType == 1) {
|
|
887
|
+
let after = domSel.focusNode.childNodes[domSel.focusOffset];
|
|
888
|
+
if (after && after.contentEditable == "false")
|
|
889
|
+
force = true;
|
|
890
|
+
}
|
|
891
|
+
if (!(force || brKludge && safari) && isEquivalentPosition(anchorDOM.node, anchorDOM.offset, domSel.anchorNode, domSel.anchorOffset) && isEquivalentPosition(headDOM.node, headDOM.offset, domSel.focusNode, domSel.focusOffset))
|
|
892
|
+
return;
|
|
893
|
+
let domSelExtended = false;
|
|
894
|
+
if ((domSel.extend || anchor == head) && !brKludge) {
|
|
895
|
+
domSel.collapse(anchorDOM.node, anchorDOM.offset);
|
|
896
|
+
try {
|
|
897
|
+
if (anchor != head)
|
|
898
|
+
domSel.extend(headDOM.node, headDOM.offset);
|
|
899
|
+
domSelExtended = true;
|
|
900
|
+
} catch (_) {
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
if (!domSelExtended) {
|
|
904
|
+
if (anchor > head) {
|
|
905
|
+
let tmp = anchorDOM;
|
|
906
|
+
anchorDOM = headDOM;
|
|
907
|
+
headDOM = tmp;
|
|
908
|
+
}
|
|
909
|
+
let range = document.createRange();
|
|
910
|
+
range.setEnd(headDOM.node, headDOM.offset);
|
|
911
|
+
range.setStart(anchorDOM.node, anchorDOM.offset);
|
|
912
|
+
domSel.removeAllRanges();
|
|
913
|
+
domSel.addRange(range);
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
ignoreMutation(mutation) {
|
|
917
|
+
return !this.contentDOM && mutation.type != "selection";
|
|
918
|
+
}
|
|
919
|
+
get contentLost() {
|
|
920
|
+
return this.contentDOM && this.contentDOM != this.dom && !this.dom.contains(this.contentDOM);
|
|
921
|
+
}
|
|
922
|
+
// Remove a subtree of the element tree that has been touched
|
|
923
|
+
// by a DOM change, so that the next update will redraw it.
|
|
924
|
+
markDirty(from, to) {
|
|
925
|
+
for (let offset = 0, i = 0; i < this.children.length; i++) {
|
|
926
|
+
let child = this.children[i], end = offset + child.size;
|
|
927
|
+
if (offset == end ? from <= end && to >= offset : from < end && to > offset) {
|
|
928
|
+
let startInside = offset + child.border, endInside = end - child.border;
|
|
929
|
+
if (from >= startInside && to <= endInside) {
|
|
930
|
+
this.dirty = from == offset || to == end ? CONTENT_DIRTY : CHILD_DIRTY;
|
|
931
|
+
if (from == startInside && to == endInside && (child.contentLost || child.dom.parentNode != this.contentDOM))
|
|
932
|
+
child.dirty = NODE_DIRTY;
|
|
933
|
+
else
|
|
934
|
+
child.markDirty(from - startInside, to - startInside);
|
|
935
|
+
return;
|
|
936
|
+
} else {
|
|
937
|
+
child.dirty = child.dom == child.contentDOM && child.dom.parentNode == this.contentDOM && !child.children.length ? CONTENT_DIRTY : NODE_DIRTY;
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
offset = end;
|
|
941
|
+
}
|
|
942
|
+
this.dirty = CONTENT_DIRTY;
|
|
943
|
+
}
|
|
944
|
+
markParentsDirty() {
|
|
945
|
+
let level = 1;
|
|
946
|
+
for (let node = this.parent; node; node = node.parent, level++) {
|
|
947
|
+
let dirty = level == 1 ? CONTENT_DIRTY : CHILD_DIRTY;
|
|
948
|
+
if (node.dirty < dirty)
|
|
949
|
+
node.dirty = dirty;
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
get domAtom() {
|
|
953
|
+
return false;
|
|
954
|
+
}
|
|
955
|
+
get ignoreForCoords() {
|
|
956
|
+
return false;
|
|
957
|
+
}
|
|
958
|
+
};
|
|
959
|
+
var WidgetViewDesc = class extends ViewDesc {
|
|
960
|
+
constructor(parent, widget, view, pos) {
|
|
961
|
+
let self, dom = widget.type.toDOM;
|
|
962
|
+
if (typeof dom == "function")
|
|
963
|
+
dom = dom(view, () => {
|
|
964
|
+
if (!self)
|
|
965
|
+
return pos;
|
|
966
|
+
if (self.parent)
|
|
967
|
+
return self.parent.posBeforeChild(self);
|
|
968
|
+
});
|
|
969
|
+
if (!widget.type.spec.raw) {
|
|
970
|
+
if (dom.nodeType != 1) {
|
|
971
|
+
let wrap = document.createElement("span");
|
|
972
|
+
wrap.appendChild(dom);
|
|
973
|
+
dom = wrap;
|
|
974
|
+
}
|
|
975
|
+
dom.contentEditable = "false";
|
|
976
|
+
dom.classList.add("ProseMirror-widget");
|
|
977
|
+
}
|
|
978
|
+
super(parent, [], dom, null);
|
|
979
|
+
this.widget = widget;
|
|
980
|
+
this.widget = widget;
|
|
981
|
+
self = this;
|
|
982
|
+
}
|
|
983
|
+
matchesWidget(widget) {
|
|
984
|
+
return this.dirty == NOT_DIRTY && widget.type.eq(this.widget.type);
|
|
985
|
+
}
|
|
986
|
+
parseRule() {
|
|
987
|
+
return { ignore: true };
|
|
988
|
+
}
|
|
989
|
+
stopEvent(event) {
|
|
990
|
+
let stop = this.widget.spec.stopEvent;
|
|
991
|
+
return stop ? stop(event) : false;
|
|
992
|
+
}
|
|
993
|
+
ignoreMutation(mutation) {
|
|
994
|
+
return mutation.type != "selection" || this.widget.spec.ignoreSelection;
|
|
995
|
+
}
|
|
996
|
+
destroy() {
|
|
997
|
+
this.widget.type.destroy(this.dom);
|
|
998
|
+
super.destroy();
|
|
999
|
+
}
|
|
1000
|
+
get domAtom() {
|
|
1001
|
+
return true;
|
|
1002
|
+
}
|
|
1003
|
+
get side() {
|
|
1004
|
+
return this.widget.type.side;
|
|
1005
|
+
}
|
|
1006
|
+
};
|
|
1007
|
+
var CompositionViewDesc = class extends ViewDesc {
|
|
1008
|
+
constructor(parent, dom, textDOM, text) {
|
|
1009
|
+
super(parent, [], dom, null);
|
|
1010
|
+
this.textDOM = textDOM;
|
|
1011
|
+
this.text = text;
|
|
1012
|
+
}
|
|
1013
|
+
get size() {
|
|
1014
|
+
return this.text.length;
|
|
1015
|
+
}
|
|
1016
|
+
localPosFromDOM(dom, offset) {
|
|
1017
|
+
if (dom != this.textDOM)
|
|
1018
|
+
return this.posAtStart + (offset ? this.size : 0);
|
|
1019
|
+
return this.posAtStart + offset;
|
|
1020
|
+
}
|
|
1021
|
+
domFromPos(pos) {
|
|
1022
|
+
return { node: this.textDOM, offset: pos };
|
|
1023
|
+
}
|
|
1024
|
+
ignoreMutation(mut) {
|
|
1025
|
+
return mut.type === "characterData" && mut.target.nodeValue == mut.oldValue;
|
|
1026
|
+
}
|
|
1027
|
+
};
|
|
1028
|
+
var MarkViewDesc = class _MarkViewDesc extends ViewDesc {
|
|
1029
|
+
constructor(parent, mark, dom, contentDOM) {
|
|
1030
|
+
super(parent, [], dom, contentDOM);
|
|
1031
|
+
this.mark = mark;
|
|
1032
|
+
}
|
|
1033
|
+
static create(parent, mark, inline, view) {
|
|
1034
|
+
let custom = view.nodeViews[mark.type.name];
|
|
1035
|
+
let spec = custom && custom(mark, view, inline);
|
|
1036
|
+
if (!spec || !spec.dom)
|
|
1037
|
+
spec = DOMSerializer.renderSpec(document, mark.type.spec.toDOM(mark, inline));
|
|
1038
|
+
return new _MarkViewDesc(parent, mark, spec.dom, spec.contentDOM || spec.dom);
|
|
1039
|
+
}
|
|
1040
|
+
parseRule() {
|
|
1041
|
+
if (this.dirty & NODE_DIRTY || this.mark.type.spec.reparseInView)
|
|
1042
|
+
return null;
|
|
1043
|
+
return { mark: this.mark.type.name, attrs: this.mark.attrs, contentElement: this.contentDOM || void 0 };
|
|
1044
|
+
}
|
|
1045
|
+
matchesMark(mark) {
|
|
1046
|
+
return this.dirty != NODE_DIRTY && this.mark.eq(mark);
|
|
1047
|
+
}
|
|
1048
|
+
markDirty(from, to) {
|
|
1049
|
+
super.markDirty(from, to);
|
|
1050
|
+
if (this.dirty != NOT_DIRTY) {
|
|
1051
|
+
let parent = this.parent;
|
|
1052
|
+
while (!parent.node)
|
|
1053
|
+
parent = parent.parent;
|
|
1054
|
+
if (parent.dirty < this.dirty)
|
|
1055
|
+
parent.dirty = this.dirty;
|
|
1056
|
+
this.dirty = NOT_DIRTY;
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
slice(from, to, view) {
|
|
1060
|
+
let copy = _MarkViewDesc.create(this.parent, this.mark, true, view);
|
|
1061
|
+
let nodes = this.children, size = this.size;
|
|
1062
|
+
if (to < size)
|
|
1063
|
+
nodes = replaceNodes(nodes, to, size, view);
|
|
1064
|
+
if (from > 0)
|
|
1065
|
+
nodes = replaceNodes(nodes, 0, from, view);
|
|
1066
|
+
for (let i = 0; i < nodes.length; i++)
|
|
1067
|
+
nodes[i].parent = copy;
|
|
1068
|
+
copy.children = nodes;
|
|
1069
|
+
return copy;
|
|
1070
|
+
}
|
|
1071
|
+
};
|
|
1072
|
+
var NodeViewDesc = class _NodeViewDesc extends ViewDesc {
|
|
1073
|
+
constructor(parent, node, outerDeco, innerDeco, dom, contentDOM, nodeDOM, view, pos) {
|
|
1074
|
+
super(parent, [], dom, contentDOM);
|
|
1075
|
+
this.node = node;
|
|
1076
|
+
this.outerDeco = outerDeco;
|
|
1077
|
+
this.innerDeco = innerDeco;
|
|
1078
|
+
this.nodeDOM = nodeDOM;
|
|
1079
|
+
}
|
|
1080
|
+
// By default, a node is rendered using the `toDOM` method from the
|
|
1081
|
+
// node type spec. But client code can use the `nodeViews` spec to
|
|
1082
|
+
// supply a custom node view, which can influence various aspects of
|
|
1083
|
+
// the way the node works.
|
|
1084
|
+
//
|
|
1085
|
+
// (Using subclassing for this was intentionally decided against,
|
|
1086
|
+
// since it'd require exposing a whole slew of finicky
|
|
1087
|
+
// implementation details to the user code that they probably will
|
|
1088
|
+
// never need.)
|
|
1089
|
+
static create(parent, node, outerDeco, innerDeco, view, pos) {
|
|
1090
|
+
let custom = view.nodeViews[node.type.name], descObj;
|
|
1091
|
+
let spec = custom && custom(node, view, () => {
|
|
1092
|
+
if (!descObj)
|
|
1093
|
+
return pos;
|
|
1094
|
+
if (descObj.parent)
|
|
1095
|
+
return descObj.parent.posBeforeChild(descObj);
|
|
1096
|
+
}, outerDeco, innerDeco);
|
|
1097
|
+
let dom = spec && spec.dom, contentDOM = spec && spec.contentDOM;
|
|
1098
|
+
if (node.isText) {
|
|
1099
|
+
if (!dom)
|
|
1100
|
+
dom = document.createTextNode(node.text);
|
|
1101
|
+
else if (dom.nodeType != 3)
|
|
1102
|
+
throw new RangeError("Text must be rendered as a DOM text node");
|
|
1103
|
+
} else if (!dom) {
|
|
1104
|
+
({ dom, contentDOM } = DOMSerializer.renderSpec(document, node.type.spec.toDOM(node)));
|
|
1105
|
+
}
|
|
1106
|
+
if (!contentDOM && !node.isText && dom.nodeName != "BR") {
|
|
1107
|
+
if (!dom.hasAttribute("contenteditable"))
|
|
1108
|
+
dom.contentEditable = "false";
|
|
1109
|
+
if (node.type.spec.draggable)
|
|
1110
|
+
dom.draggable = true;
|
|
1111
|
+
}
|
|
1112
|
+
let nodeDOM = dom;
|
|
1113
|
+
dom = applyOuterDeco(dom, outerDeco, node);
|
|
1114
|
+
if (spec)
|
|
1115
|
+
return descObj = new CustomNodeViewDesc(parent, node, outerDeco, innerDeco, dom, contentDOM || null, nodeDOM, spec, view, pos + 1);
|
|
1116
|
+
else if (node.isText)
|
|
1117
|
+
return new TextViewDesc(parent, node, outerDeco, innerDeco, dom, nodeDOM, view);
|
|
1118
|
+
else
|
|
1119
|
+
return new _NodeViewDesc(parent, node, outerDeco, innerDeco, dom, contentDOM || null, nodeDOM, view, pos + 1);
|
|
1120
|
+
}
|
|
1121
|
+
parseRule() {
|
|
1122
|
+
if (this.node.type.spec.reparseInView)
|
|
1123
|
+
return null;
|
|
1124
|
+
let rule = { node: this.node.type.name, attrs: this.node.attrs };
|
|
1125
|
+
if (this.node.type.whitespace == "pre")
|
|
1126
|
+
rule.preserveWhitespace = "full";
|
|
1127
|
+
if (!this.contentDOM) {
|
|
1128
|
+
rule.getContent = () => this.node.content;
|
|
1129
|
+
} else if (!this.contentLost) {
|
|
1130
|
+
rule.contentElement = this.contentDOM;
|
|
1131
|
+
} else {
|
|
1132
|
+
for (let i = this.children.length - 1; i >= 0; i--) {
|
|
1133
|
+
let child = this.children[i];
|
|
1134
|
+
if (this.dom.contains(child.dom.parentNode)) {
|
|
1135
|
+
rule.contentElement = child.dom.parentNode;
|
|
1136
|
+
break;
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
if (!rule.contentElement)
|
|
1140
|
+
rule.getContent = () => Fragment.empty;
|
|
1141
|
+
}
|
|
1142
|
+
return rule;
|
|
1143
|
+
}
|
|
1144
|
+
matchesNode(node, outerDeco, innerDeco) {
|
|
1145
|
+
return this.dirty == NOT_DIRTY && node.eq(this.node) && sameOuterDeco(outerDeco, this.outerDeco) && innerDeco.eq(this.innerDeco);
|
|
1146
|
+
}
|
|
1147
|
+
get size() {
|
|
1148
|
+
return this.node.nodeSize;
|
|
1149
|
+
}
|
|
1150
|
+
get border() {
|
|
1151
|
+
return this.node.isLeaf ? 0 : 1;
|
|
1152
|
+
}
|
|
1153
|
+
// Syncs `this.children` to match `this.node.content` and the local
|
|
1154
|
+
// decorations, possibly introducing nesting for marks. Then, in a
|
|
1155
|
+
// separate step, syncs the DOM inside `this.contentDOM` to
|
|
1156
|
+
// `this.children`.
|
|
1157
|
+
updateChildren(view, pos) {
|
|
1158
|
+
let inline = this.node.inlineContent, off = pos;
|
|
1159
|
+
let composition = view.composing ? this.localCompositionInfo(view, pos) : null;
|
|
1160
|
+
let localComposition = composition && composition.pos > -1 ? composition : null;
|
|
1161
|
+
let compositionInChild = composition && composition.pos < 0;
|
|
1162
|
+
let updater = new ViewTreeUpdater(this, localComposition && localComposition.node, view);
|
|
1163
|
+
iterDeco(this.node, this.innerDeco, (widget, i, insideNode) => {
|
|
1164
|
+
if (widget.spec.marks)
|
|
1165
|
+
updater.syncToMarks(widget.spec.marks, inline, view);
|
|
1166
|
+
else if (widget.type.side >= 0 && !insideNode)
|
|
1167
|
+
updater.syncToMarks(i == this.node.childCount ? Mark.none : this.node.child(i).marks, inline, view);
|
|
1168
|
+
updater.placeWidget(widget, view, off);
|
|
1169
|
+
}, (child, outerDeco, innerDeco, i) => {
|
|
1170
|
+
updater.syncToMarks(child.marks, inline, view);
|
|
1171
|
+
let compIndex;
|
|
1172
|
+
if (updater.findNodeMatch(child, outerDeco, innerDeco, i))
|
|
1173
|
+
;
|
|
1174
|
+
else if (compositionInChild && view.state.selection.from > off && view.state.selection.to < off + child.nodeSize && (compIndex = updater.findIndexWithChild(composition.node)) > -1 && updater.updateNodeAt(child, outerDeco, innerDeco, compIndex, view))
|
|
1175
|
+
;
|
|
1176
|
+
else if (updater.updateNextNode(child, outerDeco, innerDeco, view, i, off))
|
|
1177
|
+
;
|
|
1178
|
+
else {
|
|
1179
|
+
updater.addNode(child, outerDeco, innerDeco, view, off);
|
|
1180
|
+
}
|
|
1181
|
+
off += child.nodeSize;
|
|
1182
|
+
});
|
|
1183
|
+
updater.syncToMarks([], inline, view);
|
|
1184
|
+
if (this.node.isTextblock)
|
|
1185
|
+
updater.addTextblockHacks();
|
|
1186
|
+
updater.destroyRest();
|
|
1187
|
+
if (updater.changed || this.dirty == CONTENT_DIRTY) {
|
|
1188
|
+
if (localComposition)
|
|
1189
|
+
this.protectLocalComposition(view, localComposition);
|
|
1190
|
+
renderDescs(this.contentDOM, this.children, view);
|
|
1191
|
+
if (ios)
|
|
1192
|
+
iosHacks(this.dom);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
localCompositionInfo(view, pos) {
|
|
1196
|
+
let { from, to } = view.state.selection;
|
|
1197
|
+
if (!(view.state.selection instanceof TextSelection) || from < pos || to > pos + this.node.content.size)
|
|
1198
|
+
return null;
|
|
1199
|
+
let sel = view.domSelectionRange();
|
|
1200
|
+
let textNode = nearbyTextNode(sel.focusNode, sel.focusOffset);
|
|
1201
|
+
if (!textNode || !this.dom.contains(textNode.parentNode))
|
|
1202
|
+
return null;
|
|
1203
|
+
if (this.node.inlineContent) {
|
|
1204
|
+
let text = textNode.nodeValue;
|
|
1205
|
+
let textPos = findTextInFragment(this.node.content, text, from - pos, to - pos);
|
|
1206
|
+
return textPos < 0 ? null : { node: textNode, pos: textPos, text };
|
|
1207
|
+
} else {
|
|
1208
|
+
return { node: textNode, pos: -1, text: "" };
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
protectLocalComposition(view, { node, pos, text }) {
|
|
1212
|
+
if (this.getDesc(node))
|
|
1213
|
+
return;
|
|
1214
|
+
let topNode = node;
|
|
1215
|
+
for (; ; topNode = topNode.parentNode) {
|
|
1216
|
+
if (topNode.parentNode == this.contentDOM)
|
|
1217
|
+
break;
|
|
1218
|
+
while (topNode.previousSibling)
|
|
1219
|
+
topNode.parentNode.removeChild(topNode.previousSibling);
|
|
1220
|
+
while (topNode.nextSibling)
|
|
1221
|
+
topNode.parentNode.removeChild(topNode.nextSibling);
|
|
1222
|
+
if (topNode.pmViewDesc)
|
|
1223
|
+
topNode.pmViewDesc = void 0;
|
|
1224
|
+
}
|
|
1225
|
+
let desc = new CompositionViewDesc(this, topNode, node, text);
|
|
1226
|
+
view.input.compositionNodes.push(desc);
|
|
1227
|
+
this.children = replaceNodes(this.children, pos, pos + text.length, view, desc);
|
|
1228
|
+
}
|
|
1229
|
+
// If this desc must be updated to match the given node decoration,
|
|
1230
|
+
// do so and return true.
|
|
1231
|
+
update(node, outerDeco, innerDeco, view) {
|
|
1232
|
+
if (this.dirty == NODE_DIRTY || !node.sameMarkup(this.node))
|
|
1233
|
+
return false;
|
|
1234
|
+
this.updateInner(node, outerDeco, innerDeco, view);
|
|
1235
|
+
return true;
|
|
1236
|
+
}
|
|
1237
|
+
updateInner(node, outerDeco, innerDeco, view) {
|
|
1238
|
+
this.updateOuterDeco(outerDeco);
|
|
1239
|
+
this.node = node;
|
|
1240
|
+
this.innerDeco = innerDeco;
|
|
1241
|
+
if (this.contentDOM)
|
|
1242
|
+
this.updateChildren(view, this.posAtStart);
|
|
1243
|
+
this.dirty = NOT_DIRTY;
|
|
1244
|
+
}
|
|
1245
|
+
updateOuterDeco(outerDeco) {
|
|
1246
|
+
if (sameOuterDeco(outerDeco, this.outerDeco))
|
|
1247
|
+
return;
|
|
1248
|
+
let needsWrap = this.nodeDOM.nodeType != 1;
|
|
1249
|
+
let oldDOM = this.dom;
|
|
1250
|
+
this.dom = patchOuterDeco(this.dom, this.nodeDOM, computeOuterDeco(this.outerDeco, this.node, needsWrap), computeOuterDeco(outerDeco, this.node, needsWrap));
|
|
1251
|
+
if (this.dom != oldDOM) {
|
|
1252
|
+
oldDOM.pmViewDesc = void 0;
|
|
1253
|
+
this.dom.pmViewDesc = this;
|
|
1254
|
+
}
|
|
1255
|
+
this.outerDeco = outerDeco;
|
|
1256
|
+
}
|
|
1257
|
+
// Mark this node as being the selected node.
|
|
1258
|
+
selectNode() {
|
|
1259
|
+
if (this.nodeDOM.nodeType == 1)
|
|
1260
|
+
this.nodeDOM.classList.add("ProseMirror-selectednode");
|
|
1261
|
+
if (this.contentDOM || !this.node.type.spec.draggable)
|
|
1262
|
+
this.dom.draggable = true;
|
|
1263
|
+
}
|
|
1264
|
+
// Remove selected node marking from this node.
|
|
1265
|
+
deselectNode() {
|
|
1266
|
+
if (this.nodeDOM.nodeType == 1)
|
|
1267
|
+
this.nodeDOM.classList.remove("ProseMirror-selectednode");
|
|
1268
|
+
if (this.contentDOM || !this.node.type.spec.draggable)
|
|
1269
|
+
this.dom.removeAttribute("draggable");
|
|
1270
|
+
}
|
|
1271
|
+
get domAtom() {
|
|
1272
|
+
return this.node.isAtom;
|
|
1273
|
+
}
|
|
1274
|
+
};
|
|
1275
|
+
function docViewDesc(doc2, outerDeco, innerDeco, dom, view) {
|
|
1276
|
+
applyOuterDeco(dom, outerDeco, doc2);
|
|
1277
|
+
let docView = new NodeViewDesc(void 0, doc2, outerDeco, innerDeco, dom, dom, dom, view, 0);
|
|
1278
|
+
if (docView.contentDOM)
|
|
1279
|
+
docView.updateChildren(view, 0);
|
|
1280
|
+
return docView;
|
|
1281
|
+
}
|
|
1282
|
+
var TextViewDesc = class _TextViewDesc extends NodeViewDesc {
|
|
1283
|
+
constructor(parent, node, outerDeco, innerDeco, dom, nodeDOM, view) {
|
|
1284
|
+
super(parent, node, outerDeco, innerDeco, dom, null, nodeDOM, view, 0);
|
|
1285
|
+
}
|
|
1286
|
+
parseRule() {
|
|
1287
|
+
let skip = this.nodeDOM.parentNode;
|
|
1288
|
+
while (skip && skip != this.dom && !skip.pmIsDeco)
|
|
1289
|
+
skip = skip.parentNode;
|
|
1290
|
+
return { skip: skip || true };
|
|
1291
|
+
}
|
|
1292
|
+
update(node, outerDeco, innerDeco, view) {
|
|
1293
|
+
if (this.dirty == NODE_DIRTY || this.dirty != NOT_DIRTY && !this.inParent() || !node.sameMarkup(this.node))
|
|
1294
|
+
return false;
|
|
1295
|
+
this.updateOuterDeco(outerDeco);
|
|
1296
|
+
if ((this.dirty != NOT_DIRTY || node.text != this.node.text) && node.text != this.nodeDOM.nodeValue) {
|
|
1297
|
+
this.nodeDOM.nodeValue = node.text;
|
|
1298
|
+
if (view.trackWrites == this.nodeDOM)
|
|
1299
|
+
view.trackWrites = null;
|
|
1300
|
+
}
|
|
1301
|
+
this.node = node;
|
|
1302
|
+
this.dirty = NOT_DIRTY;
|
|
1303
|
+
return true;
|
|
1304
|
+
}
|
|
1305
|
+
inParent() {
|
|
1306
|
+
let parentDOM = this.parent.contentDOM;
|
|
1307
|
+
for (let n = this.nodeDOM; n; n = n.parentNode)
|
|
1308
|
+
if (n == parentDOM)
|
|
1309
|
+
return true;
|
|
1310
|
+
return false;
|
|
1311
|
+
}
|
|
1312
|
+
domFromPos(pos) {
|
|
1313
|
+
return { node: this.nodeDOM, offset: pos };
|
|
1314
|
+
}
|
|
1315
|
+
localPosFromDOM(dom, offset, bias) {
|
|
1316
|
+
if (dom == this.nodeDOM)
|
|
1317
|
+
return this.posAtStart + Math.min(offset, this.node.text.length);
|
|
1318
|
+
return super.localPosFromDOM(dom, offset, bias);
|
|
1319
|
+
}
|
|
1320
|
+
ignoreMutation(mutation) {
|
|
1321
|
+
return mutation.type != "characterData" && mutation.type != "selection";
|
|
1322
|
+
}
|
|
1323
|
+
slice(from, to, view) {
|
|
1324
|
+
let node = this.node.cut(from, to), dom = document.createTextNode(node.text);
|
|
1325
|
+
return new _TextViewDesc(this.parent, node, this.outerDeco, this.innerDeco, dom, dom, view);
|
|
1326
|
+
}
|
|
1327
|
+
markDirty(from, to) {
|
|
1328
|
+
super.markDirty(from, to);
|
|
1329
|
+
if (this.dom != this.nodeDOM && (from == 0 || to == this.nodeDOM.nodeValue.length))
|
|
1330
|
+
this.dirty = NODE_DIRTY;
|
|
1331
|
+
}
|
|
1332
|
+
get domAtom() {
|
|
1333
|
+
return false;
|
|
1334
|
+
}
|
|
1335
|
+
};
|
|
1336
|
+
var TrailingHackViewDesc = class extends ViewDesc {
|
|
1337
|
+
parseRule() {
|
|
1338
|
+
return { ignore: true };
|
|
1339
|
+
}
|
|
1340
|
+
matchesHack(nodeName) {
|
|
1341
|
+
return this.dirty == NOT_DIRTY && this.dom.nodeName == nodeName;
|
|
1342
|
+
}
|
|
1343
|
+
get domAtom() {
|
|
1344
|
+
return true;
|
|
1345
|
+
}
|
|
1346
|
+
get ignoreForCoords() {
|
|
1347
|
+
return this.dom.nodeName == "IMG";
|
|
1348
|
+
}
|
|
1349
|
+
};
|
|
1350
|
+
var CustomNodeViewDesc = class extends NodeViewDesc {
|
|
1351
|
+
constructor(parent, node, outerDeco, innerDeco, dom, contentDOM, nodeDOM, spec, view, pos) {
|
|
1352
|
+
super(parent, node, outerDeco, innerDeco, dom, contentDOM, nodeDOM, view, pos);
|
|
1353
|
+
this.spec = spec;
|
|
1354
|
+
}
|
|
1355
|
+
// A custom `update` method gets to decide whether the update goes
|
|
1356
|
+
// through. If it does, and there's a `contentDOM` node, our logic
|
|
1357
|
+
// updates the children.
|
|
1358
|
+
update(node, outerDeco, innerDeco, view) {
|
|
1359
|
+
if (this.dirty == NODE_DIRTY)
|
|
1360
|
+
return false;
|
|
1361
|
+
if (this.spec.update) {
|
|
1362
|
+
let result = this.spec.update(node, outerDeco, innerDeco);
|
|
1363
|
+
if (result)
|
|
1364
|
+
this.updateInner(node, outerDeco, innerDeco, view);
|
|
1365
|
+
return result;
|
|
1366
|
+
} else if (!this.contentDOM && !node.isLeaf) {
|
|
1367
|
+
return false;
|
|
1368
|
+
} else {
|
|
1369
|
+
return super.update(node, outerDeco, innerDeco, view);
|
|
1370
|
+
}
|
|
1371
|
+
}
|
|
1372
|
+
selectNode() {
|
|
1373
|
+
this.spec.selectNode ? this.spec.selectNode() : super.selectNode();
|
|
1374
|
+
}
|
|
1375
|
+
deselectNode() {
|
|
1376
|
+
this.spec.deselectNode ? this.spec.deselectNode() : super.deselectNode();
|
|
1377
|
+
}
|
|
1378
|
+
setSelection(anchor, head, root, force) {
|
|
1379
|
+
this.spec.setSelection ? this.spec.setSelection(anchor, head, root) : super.setSelection(anchor, head, root, force);
|
|
1380
|
+
}
|
|
1381
|
+
destroy() {
|
|
1382
|
+
if (this.spec.destroy)
|
|
1383
|
+
this.spec.destroy();
|
|
1384
|
+
super.destroy();
|
|
1385
|
+
}
|
|
1386
|
+
stopEvent(event) {
|
|
1387
|
+
return this.spec.stopEvent ? this.spec.stopEvent(event) : false;
|
|
1388
|
+
}
|
|
1389
|
+
ignoreMutation(mutation) {
|
|
1390
|
+
return this.spec.ignoreMutation ? this.spec.ignoreMutation(mutation) : super.ignoreMutation(mutation);
|
|
1391
|
+
}
|
|
1392
|
+
};
|
|
1393
|
+
function renderDescs(parentDOM, descs, view) {
|
|
1394
|
+
let dom = parentDOM.firstChild, written = false;
|
|
1395
|
+
for (let i = 0; i < descs.length; i++) {
|
|
1396
|
+
let desc = descs[i], childDOM = desc.dom;
|
|
1397
|
+
if (childDOM.parentNode == parentDOM) {
|
|
1398
|
+
while (childDOM != dom) {
|
|
1399
|
+
dom = rm(dom);
|
|
1400
|
+
written = true;
|
|
1401
|
+
}
|
|
1402
|
+
dom = dom.nextSibling;
|
|
1403
|
+
} else {
|
|
1404
|
+
written = true;
|
|
1405
|
+
parentDOM.insertBefore(childDOM, dom);
|
|
1406
|
+
}
|
|
1407
|
+
if (desc instanceof MarkViewDesc) {
|
|
1408
|
+
let pos = dom ? dom.previousSibling : parentDOM.lastChild;
|
|
1409
|
+
renderDescs(desc.contentDOM, desc.children, view);
|
|
1410
|
+
dom = pos ? pos.nextSibling : parentDOM.firstChild;
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
while (dom) {
|
|
1414
|
+
dom = rm(dom);
|
|
1415
|
+
written = true;
|
|
1416
|
+
}
|
|
1417
|
+
if (written && view.trackWrites == parentDOM)
|
|
1418
|
+
view.trackWrites = null;
|
|
1419
|
+
}
|
|
1420
|
+
var OuterDecoLevel = function(nodeName) {
|
|
1421
|
+
if (nodeName)
|
|
1422
|
+
this.nodeName = nodeName;
|
|
1423
|
+
};
|
|
1424
|
+
OuterDecoLevel.prototype = /* @__PURE__ */ Object.create(null);
|
|
1425
|
+
var noDeco = [new OuterDecoLevel()];
|
|
1426
|
+
function computeOuterDeco(outerDeco, node, needsWrap) {
|
|
1427
|
+
if (outerDeco.length == 0)
|
|
1428
|
+
return noDeco;
|
|
1429
|
+
let top = needsWrap ? noDeco[0] : new OuterDecoLevel(), result = [top];
|
|
1430
|
+
for (let i = 0; i < outerDeco.length; i++) {
|
|
1431
|
+
let attrs = outerDeco[i].type.attrs;
|
|
1432
|
+
if (!attrs)
|
|
1433
|
+
continue;
|
|
1434
|
+
if (attrs.nodeName)
|
|
1435
|
+
result.push(top = new OuterDecoLevel(attrs.nodeName));
|
|
1436
|
+
for (let name in attrs) {
|
|
1437
|
+
let val = attrs[name];
|
|
1438
|
+
if (val == null)
|
|
1439
|
+
continue;
|
|
1440
|
+
if (needsWrap && result.length == 1)
|
|
1441
|
+
result.push(top = new OuterDecoLevel(node.isInline ? "span" : "div"));
|
|
1442
|
+
if (name == "class")
|
|
1443
|
+
top.class = (top.class ? top.class + " " : "") + val;
|
|
1444
|
+
else if (name == "style")
|
|
1445
|
+
top.style = (top.style ? top.style + ";" : "") + val;
|
|
1446
|
+
else if (name != "nodeName")
|
|
1447
|
+
top[name] = val;
|
|
1448
|
+
}
|
|
1449
|
+
}
|
|
1450
|
+
return result;
|
|
1451
|
+
}
|
|
1452
|
+
function patchOuterDeco(outerDOM, nodeDOM, prevComputed, curComputed) {
|
|
1453
|
+
if (prevComputed == noDeco && curComputed == noDeco)
|
|
1454
|
+
return nodeDOM;
|
|
1455
|
+
let curDOM = nodeDOM;
|
|
1456
|
+
for (let i = 0; i < curComputed.length; i++) {
|
|
1457
|
+
let deco = curComputed[i], prev = prevComputed[i];
|
|
1458
|
+
if (i) {
|
|
1459
|
+
let parent;
|
|
1460
|
+
if (prev && prev.nodeName == deco.nodeName && curDOM != outerDOM && (parent = curDOM.parentNode) && parent.nodeName.toLowerCase() == deco.nodeName) {
|
|
1461
|
+
curDOM = parent;
|
|
1462
|
+
} else {
|
|
1463
|
+
parent = document.createElement(deco.nodeName);
|
|
1464
|
+
parent.pmIsDeco = true;
|
|
1465
|
+
parent.appendChild(curDOM);
|
|
1466
|
+
prev = noDeco[0];
|
|
1467
|
+
curDOM = parent;
|
|
1468
|
+
}
|
|
1469
|
+
}
|
|
1470
|
+
patchAttributes(curDOM, prev || noDeco[0], deco);
|
|
1471
|
+
}
|
|
1472
|
+
return curDOM;
|
|
1473
|
+
}
|
|
1474
|
+
function patchAttributes(dom, prev, cur) {
|
|
1475
|
+
for (let name in prev)
|
|
1476
|
+
if (name != "class" && name != "style" && name != "nodeName" && !(name in cur))
|
|
1477
|
+
dom.removeAttribute(name);
|
|
1478
|
+
for (let name in cur)
|
|
1479
|
+
if (name != "class" && name != "style" && name != "nodeName" && cur[name] != prev[name])
|
|
1480
|
+
dom.setAttribute(name, cur[name]);
|
|
1481
|
+
if (prev.class != cur.class) {
|
|
1482
|
+
let prevList = prev.class ? prev.class.split(" ").filter(Boolean) : [];
|
|
1483
|
+
let curList = cur.class ? cur.class.split(" ").filter(Boolean) : [];
|
|
1484
|
+
for (let i = 0; i < prevList.length; i++)
|
|
1485
|
+
if (curList.indexOf(prevList[i]) == -1)
|
|
1486
|
+
dom.classList.remove(prevList[i]);
|
|
1487
|
+
for (let i = 0; i < curList.length; i++)
|
|
1488
|
+
if (prevList.indexOf(curList[i]) == -1)
|
|
1489
|
+
dom.classList.add(curList[i]);
|
|
1490
|
+
if (dom.classList.length == 0)
|
|
1491
|
+
dom.removeAttribute("class");
|
|
1492
|
+
}
|
|
1493
|
+
if (prev.style != cur.style) {
|
|
1494
|
+
if (prev.style) {
|
|
1495
|
+
let prop = /\s*([\w\-\xa1-\uffff]+)\s*:(?:"(?:\\.|[^"])*"|'(?:\\.|[^'])*'|\(.*?\)|[^;])*/g, m;
|
|
1496
|
+
while (m = prop.exec(prev.style))
|
|
1497
|
+
dom.style.removeProperty(m[1]);
|
|
1498
|
+
}
|
|
1499
|
+
if (cur.style)
|
|
1500
|
+
dom.style.cssText += cur.style;
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
function applyOuterDeco(dom, deco, node) {
|
|
1504
|
+
return patchOuterDeco(dom, dom, noDeco, computeOuterDeco(deco, node, dom.nodeType != 1));
|
|
1505
|
+
}
|
|
1506
|
+
function sameOuterDeco(a, b) {
|
|
1507
|
+
if (a.length != b.length)
|
|
1508
|
+
return false;
|
|
1509
|
+
for (let i = 0; i < a.length; i++)
|
|
1510
|
+
if (!a[i].type.eq(b[i].type))
|
|
1511
|
+
return false;
|
|
1512
|
+
return true;
|
|
1513
|
+
}
|
|
1514
|
+
function rm(dom) {
|
|
1515
|
+
let next = dom.nextSibling;
|
|
1516
|
+
dom.parentNode.removeChild(dom);
|
|
1517
|
+
return next;
|
|
1518
|
+
}
|
|
1519
|
+
var ViewTreeUpdater = class {
|
|
1520
|
+
constructor(top, lock, view) {
|
|
1521
|
+
this.lock = lock;
|
|
1522
|
+
this.view = view;
|
|
1523
|
+
this.index = 0;
|
|
1524
|
+
this.stack = [];
|
|
1525
|
+
this.changed = false;
|
|
1526
|
+
this.top = top;
|
|
1527
|
+
this.preMatch = preMatch(top.node.content, top);
|
|
1528
|
+
}
|
|
1529
|
+
// Destroy and remove the children between the given indices in
|
|
1530
|
+
// `this.top`.
|
|
1531
|
+
destroyBetween(start, end) {
|
|
1532
|
+
if (start == end)
|
|
1533
|
+
return;
|
|
1534
|
+
for (let i = start; i < end; i++)
|
|
1535
|
+
this.top.children[i].destroy();
|
|
1536
|
+
this.top.children.splice(start, end - start);
|
|
1537
|
+
this.changed = true;
|
|
1538
|
+
}
|
|
1539
|
+
// Destroy all remaining children in `this.top`.
|
|
1540
|
+
destroyRest() {
|
|
1541
|
+
this.destroyBetween(this.index, this.top.children.length);
|
|
1542
|
+
}
|
|
1543
|
+
// Sync the current stack of mark descs with the given array of
|
|
1544
|
+
// marks, reusing existing mark descs when possible.
|
|
1545
|
+
syncToMarks(marks, inline, view) {
|
|
1546
|
+
let keep = 0, depth = this.stack.length >> 1;
|
|
1547
|
+
let maxKeep = Math.min(depth, marks.length);
|
|
1548
|
+
while (keep < maxKeep && (keep == depth - 1 ? this.top : this.stack[keep + 1 << 1]).matchesMark(marks[keep]) && marks[keep].type.spec.spanning !== false)
|
|
1549
|
+
keep++;
|
|
1550
|
+
while (keep < depth) {
|
|
1551
|
+
this.destroyRest();
|
|
1552
|
+
this.top.dirty = NOT_DIRTY;
|
|
1553
|
+
this.index = this.stack.pop();
|
|
1554
|
+
this.top = this.stack.pop();
|
|
1555
|
+
depth--;
|
|
1556
|
+
}
|
|
1557
|
+
while (depth < marks.length) {
|
|
1558
|
+
this.stack.push(this.top, this.index + 1);
|
|
1559
|
+
let found = -1;
|
|
1560
|
+
for (let i = this.index; i < Math.min(this.index + 3, this.top.children.length); i++) {
|
|
1561
|
+
let next = this.top.children[i];
|
|
1562
|
+
if (next.matchesMark(marks[depth]) && !this.isLocked(next.dom)) {
|
|
1563
|
+
found = i;
|
|
1564
|
+
break;
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
if (found > -1) {
|
|
1568
|
+
if (found > this.index) {
|
|
1569
|
+
this.changed = true;
|
|
1570
|
+
this.destroyBetween(this.index, found);
|
|
1571
|
+
}
|
|
1572
|
+
this.top = this.top.children[this.index];
|
|
1573
|
+
} else {
|
|
1574
|
+
let markDesc = MarkViewDesc.create(this.top, marks[depth], inline, view);
|
|
1575
|
+
this.top.children.splice(this.index, 0, markDesc);
|
|
1576
|
+
this.top = markDesc;
|
|
1577
|
+
this.changed = true;
|
|
1578
|
+
}
|
|
1579
|
+
this.index = 0;
|
|
1580
|
+
depth++;
|
|
1581
|
+
}
|
|
1582
|
+
}
|
|
1583
|
+
// Try to find a node desc matching the given data. Skip over it and
|
|
1584
|
+
// return true when successful.
|
|
1585
|
+
findNodeMatch(node, outerDeco, innerDeco, index) {
|
|
1586
|
+
let found = -1, targetDesc;
|
|
1587
|
+
if (index >= this.preMatch.index && (targetDesc = this.preMatch.matches[index - this.preMatch.index]).parent == this.top && targetDesc.matchesNode(node, outerDeco, innerDeco)) {
|
|
1588
|
+
found = this.top.children.indexOf(targetDesc, this.index);
|
|
1589
|
+
} else {
|
|
1590
|
+
for (let i = this.index, e = Math.min(this.top.children.length, i + 5); i < e; i++) {
|
|
1591
|
+
let child = this.top.children[i];
|
|
1592
|
+
if (child.matchesNode(node, outerDeco, innerDeco) && !this.preMatch.matched.has(child)) {
|
|
1593
|
+
found = i;
|
|
1594
|
+
break;
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
if (found < 0)
|
|
1599
|
+
return false;
|
|
1600
|
+
this.destroyBetween(this.index, found);
|
|
1601
|
+
this.index++;
|
|
1602
|
+
return true;
|
|
1603
|
+
}
|
|
1604
|
+
updateNodeAt(node, outerDeco, innerDeco, index, view) {
|
|
1605
|
+
let child = this.top.children[index];
|
|
1606
|
+
if (child.dirty == NODE_DIRTY && child.dom == child.contentDOM)
|
|
1607
|
+
child.dirty = CONTENT_DIRTY;
|
|
1608
|
+
if (!child.update(node, outerDeco, innerDeco, view))
|
|
1609
|
+
return false;
|
|
1610
|
+
this.destroyBetween(this.index, index);
|
|
1611
|
+
this.index++;
|
|
1612
|
+
return true;
|
|
1613
|
+
}
|
|
1614
|
+
findIndexWithChild(domNode) {
|
|
1615
|
+
for (; ; ) {
|
|
1616
|
+
let parent = domNode.parentNode;
|
|
1617
|
+
if (!parent)
|
|
1618
|
+
return -1;
|
|
1619
|
+
if (parent == this.top.contentDOM) {
|
|
1620
|
+
let desc = domNode.pmViewDesc;
|
|
1621
|
+
if (desc)
|
|
1622
|
+
for (let i = this.index; i < this.top.children.length; i++) {
|
|
1623
|
+
if (this.top.children[i] == desc)
|
|
1624
|
+
return i;
|
|
1625
|
+
}
|
|
1626
|
+
return -1;
|
|
1627
|
+
}
|
|
1628
|
+
domNode = parent;
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
// Try to update the next node, if any, to the given data. Checks
|
|
1632
|
+
// pre-matches to avoid overwriting nodes that could still be used.
|
|
1633
|
+
updateNextNode(node, outerDeco, innerDeco, view, index, pos) {
|
|
1634
|
+
for (let i = this.index; i < this.top.children.length; i++) {
|
|
1635
|
+
let next = this.top.children[i];
|
|
1636
|
+
if (next instanceof NodeViewDesc) {
|
|
1637
|
+
let preMatch2 = this.preMatch.matched.get(next);
|
|
1638
|
+
if (preMatch2 != null && preMatch2 != index)
|
|
1639
|
+
return false;
|
|
1640
|
+
let nextDOM = next.dom, updated;
|
|
1641
|
+
let locked = this.isLocked(nextDOM) && !(node.isText && next.node && next.node.isText && next.nodeDOM.nodeValue == node.text && next.dirty != NODE_DIRTY && sameOuterDeco(outerDeco, next.outerDeco));
|
|
1642
|
+
if (!locked && next.update(node, outerDeco, innerDeco, view)) {
|
|
1643
|
+
this.destroyBetween(this.index, i);
|
|
1644
|
+
if (next.dom != nextDOM)
|
|
1645
|
+
this.changed = true;
|
|
1646
|
+
this.index++;
|
|
1647
|
+
return true;
|
|
1648
|
+
} else if (!locked && (updated = this.recreateWrapper(next, node, outerDeco, innerDeco, view, pos))) {
|
|
1649
|
+
this.top.children[this.index] = updated;
|
|
1650
|
+
updated.dirty = CONTENT_DIRTY;
|
|
1651
|
+
updated.updateChildren(view, pos + 1);
|
|
1652
|
+
updated.dirty = NOT_DIRTY;
|
|
1653
|
+
this.changed = true;
|
|
1654
|
+
this.index++;
|
|
1655
|
+
return true;
|
|
1656
|
+
}
|
|
1657
|
+
break;
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
return false;
|
|
1661
|
+
}
|
|
1662
|
+
// When a node with content is replaced by a different node with
|
|
1663
|
+
// identical content, move over its children.
|
|
1664
|
+
recreateWrapper(next, node, outerDeco, innerDeco, view, pos) {
|
|
1665
|
+
if (next.dirty || node.isAtom || !next.children.length || !next.node.content.eq(node.content))
|
|
1666
|
+
return null;
|
|
1667
|
+
let wrapper = NodeViewDesc.create(this.top, node, outerDeco, innerDeco, view, pos);
|
|
1668
|
+
if (!wrapper.contentDOM)
|
|
1669
|
+
return null;
|
|
1670
|
+
wrapper.children = next.children;
|
|
1671
|
+
next.children = [];
|
|
1672
|
+
next.destroy();
|
|
1673
|
+
for (let ch of wrapper.children)
|
|
1674
|
+
ch.parent = wrapper;
|
|
1675
|
+
return wrapper;
|
|
1676
|
+
}
|
|
1677
|
+
// Insert the node as a newly created node desc.
|
|
1678
|
+
addNode(node, outerDeco, innerDeco, view, pos) {
|
|
1679
|
+
let desc = NodeViewDesc.create(this.top, node, outerDeco, innerDeco, view, pos);
|
|
1680
|
+
if (desc.contentDOM)
|
|
1681
|
+
desc.updateChildren(view, pos + 1);
|
|
1682
|
+
this.top.children.splice(this.index++, 0, desc);
|
|
1683
|
+
this.changed = true;
|
|
1684
|
+
}
|
|
1685
|
+
placeWidget(widget, view, pos) {
|
|
1686
|
+
let next = this.index < this.top.children.length ? this.top.children[this.index] : null;
|
|
1687
|
+
if (next && next.matchesWidget(widget) && (widget == next.widget || !next.widget.type.toDOM.parentNode)) {
|
|
1688
|
+
this.index++;
|
|
1689
|
+
} else {
|
|
1690
|
+
let desc = new WidgetViewDesc(this.top, widget, view, pos);
|
|
1691
|
+
this.top.children.splice(this.index++, 0, desc);
|
|
1692
|
+
this.changed = true;
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
// Make sure a textblock looks and behaves correctly in
|
|
1696
|
+
// contentEditable.
|
|
1697
|
+
addTextblockHacks() {
|
|
1698
|
+
let lastChild = this.top.children[this.index - 1], parent = this.top;
|
|
1699
|
+
while (lastChild instanceof MarkViewDesc) {
|
|
1700
|
+
parent = lastChild;
|
|
1701
|
+
lastChild = parent.children[parent.children.length - 1];
|
|
1702
|
+
}
|
|
1703
|
+
if (!lastChild || // Empty textblock
|
|
1704
|
+
!(lastChild instanceof TextViewDesc) || /\n$/.test(lastChild.node.text) || this.view.requiresGeckoHackNode && /\s$/.test(lastChild.node.text)) {
|
|
1705
|
+
if ((safari || chrome) && lastChild && lastChild.dom.contentEditable == "false")
|
|
1706
|
+
this.addHackNode("IMG", parent);
|
|
1707
|
+
this.addHackNode("BR", this.top);
|
|
1708
|
+
}
|
|
1709
|
+
}
|
|
1710
|
+
addHackNode(nodeName, parent) {
|
|
1711
|
+
if (parent == this.top && this.index < parent.children.length && parent.children[this.index].matchesHack(nodeName)) {
|
|
1712
|
+
this.index++;
|
|
1713
|
+
} else {
|
|
1714
|
+
let dom = document.createElement(nodeName);
|
|
1715
|
+
if (nodeName == "IMG") {
|
|
1716
|
+
dom.className = "ProseMirror-separator";
|
|
1717
|
+
dom.alt = "";
|
|
1718
|
+
}
|
|
1719
|
+
if (nodeName == "BR")
|
|
1720
|
+
dom.className = "ProseMirror-trailingBreak";
|
|
1721
|
+
let hack = new TrailingHackViewDesc(this.top, [], dom, null);
|
|
1722
|
+
if (parent != this.top)
|
|
1723
|
+
parent.children.push(hack);
|
|
1724
|
+
else
|
|
1725
|
+
parent.children.splice(this.index++, 0, hack);
|
|
1726
|
+
this.changed = true;
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
isLocked(node) {
|
|
1730
|
+
return this.lock && (node == this.lock || node.nodeType == 1 && node.contains(this.lock.parentNode));
|
|
1731
|
+
}
|
|
1732
|
+
};
|
|
1733
|
+
function preMatch(frag, parentDesc) {
|
|
1734
|
+
let curDesc = parentDesc, descI = curDesc.children.length;
|
|
1735
|
+
let fI = frag.childCount, matched = /* @__PURE__ */ new Map(), matches = [];
|
|
1736
|
+
outer:
|
|
1737
|
+
while (fI > 0) {
|
|
1738
|
+
let desc;
|
|
1739
|
+
for (; ; ) {
|
|
1740
|
+
if (descI) {
|
|
1741
|
+
let next = curDesc.children[descI - 1];
|
|
1742
|
+
if (next instanceof MarkViewDesc) {
|
|
1743
|
+
curDesc = next;
|
|
1744
|
+
descI = next.children.length;
|
|
1745
|
+
} else {
|
|
1746
|
+
desc = next;
|
|
1747
|
+
descI--;
|
|
1748
|
+
break;
|
|
1749
|
+
}
|
|
1750
|
+
} else if (curDesc == parentDesc) {
|
|
1751
|
+
break outer;
|
|
1752
|
+
} else {
|
|
1753
|
+
descI = curDesc.parent.children.indexOf(curDesc);
|
|
1754
|
+
curDesc = curDesc.parent;
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
let node = desc.node;
|
|
1758
|
+
if (!node)
|
|
1759
|
+
continue;
|
|
1760
|
+
if (node != frag.child(fI - 1))
|
|
1761
|
+
break;
|
|
1762
|
+
--fI;
|
|
1763
|
+
matched.set(desc, fI);
|
|
1764
|
+
matches.push(desc);
|
|
1765
|
+
}
|
|
1766
|
+
return { index: fI, matched, matches: matches.reverse() };
|
|
1767
|
+
}
|
|
1768
|
+
function compareSide(a, b) {
|
|
1769
|
+
return a.type.side - b.type.side;
|
|
1770
|
+
}
|
|
1771
|
+
function iterDeco(parent, deco, onWidget, onNode) {
|
|
1772
|
+
let locals = deco.locals(parent), offset = 0;
|
|
1773
|
+
if (locals.length == 0) {
|
|
1774
|
+
for (let i = 0; i < parent.childCount; i++) {
|
|
1775
|
+
let child = parent.child(i);
|
|
1776
|
+
onNode(child, locals, deco.forChild(offset, child), i);
|
|
1777
|
+
offset += child.nodeSize;
|
|
1778
|
+
}
|
|
1779
|
+
return;
|
|
1780
|
+
}
|
|
1781
|
+
let decoIndex = 0, active = [], restNode = null;
|
|
1782
|
+
for (let parentIndex = 0; ; ) {
|
|
1783
|
+
if (decoIndex < locals.length && locals[decoIndex].to == offset) {
|
|
1784
|
+
let widget = locals[decoIndex++], widgets;
|
|
1785
|
+
while (decoIndex < locals.length && locals[decoIndex].to == offset)
|
|
1786
|
+
(widgets || (widgets = [widget])).push(locals[decoIndex++]);
|
|
1787
|
+
if (widgets) {
|
|
1788
|
+
widgets.sort(compareSide);
|
|
1789
|
+
for (let i = 0; i < widgets.length; i++)
|
|
1790
|
+
onWidget(widgets[i], parentIndex, !!restNode);
|
|
1791
|
+
} else {
|
|
1792
|
+
onWidget(widget, parentIndex, !!restNode);
|
|
1793
|
+
}
|
|
1794
|
+
}
|
|
1795
|
+
let child, index;
|
|
1796
|
+
if (restNode) {
|
|
1797
|
+
index = -1;
|
|
1798
|
+
child = restNode;
|
|
1799
|
+
restNode = null;
|
|
1800
|
+
} else if (parentIndex < parent.childCount) {
|
|
1801
|
+
index = parentIndex;
|
|
1802
|
+
child = parent.child(parentIndex++);
|
|
1803
|
+
} else {
|
|
1804
|
+
break;
|
|
1805
|
+
}
|
|
1806
|
+
for (let i = 0; i < active.length; i++)
|
|
1807
|
+
if (active[i].to <= offset)
|
|
1808
|
+
active.splice(i--, 1);
|
|
1809
|
+
while (decoIndex < locals.length && locals[decoIndex].from <= offset && locals[decoIndex].to > offset)
|
|
1810
|
+
active.push(locals[decoIndex++]);
|
|
1811
|
+
let end = offset + child.nodeSize;
|
|
1812
|
+
if (child.isText) {
|
|
1813
|
+
let cutAt = end;
|
|
1814
|
+
if (decoIndex < locals.length && locals[decoIndex].from < cutAt)
|
|
1815
|
+
cutAt = locals[decoIndex].from;
|
|
1816
|
+
for (let i = 0; i < active.length; i++)
|
|
1817
|
+
if (active[i].to < cutAt)
|
|
1818
|
+
cutAt = active[i].to;
|
|
1819
|
+
if (cutAt < end) {
|
|
1820
|
+
restNode = child.cut(cutAt - offset);
|
|
1821
|
+
child = child.cut(0, cutAt - offset);
|
|
1822
|
+
end = cutAt;
|
|
1823
|
+
index = -1;
|
|
1824
|
+
}
|
|
1825
|
+
}
|
|
1826
|
+
let outerDeco = child.isInline && !child.isLeaf ? active.filter((d) => !d.inline) : active.slice();
|
|
1827
|
+
onNode(child, outerDeco, deco.forChild(offset, child), index);
|
|
1828
|
+
offset = end;
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
function iosHacks(dom) {
|
|
1832
|
+
if (dom.nodeName == "UL" || dom.nodeName == "OL") {
|
|
1833
|
+
let oldCSS = dom.style.cssText;
|
|
1834
|
+
dom.style.cssText = oldCSS + "; list-style: square !important";
|
|
1835
|
+
window.getComputedStyle(dom).listStyle;
|
|
1836
|
+
dom.style.cssText = oldCSS;
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
function nearbyTextNode(node, offset) {
|
|
1840
|
+
for (; ; ) {
|
|
1841
|
+
if (node.nodeType == 3)
|
|
1842
|
+
return node;
|
|
1843
|
+
if (node.nodeType == 1 && offset > 0) {
|
|
1844
|
+
if (node.childNodes.length > offset && node.childNodes[offset].nodeType == 3)
|
|
1845
|
+
return node.childNodes[offset];
|
|
1846
|
+
node = node.childNodes[offset - 1];
|
|
1847
|
+
offset = nodeSize(node);
|
|
1848
|
+
} else if (node.nodeType == 1 && offset < node.childNodes.length) {
|
|
1849
|
+
node = node.childNodes[offset];
|
|
1850
|
+
offset = 0;
|
|
1851
|
+
} else {
|
|
1852
|
+
return null;
|
|
1853
|
+
}
|
|
1854
|
+
}
|
|
1855
|
+
}
|
|
1856
|
+
function findTextInFragment(frag, text, from, to) {
|
|
1857
|
+
for (let i = 0, pos = 0; i < frag.childCount && pos <= to; ) {
|
|
1858
|
+
let child = frag.child(i++), childStart = pos;
|
|
1859
|
+
pos += child.nodeSize;
|
|
1860
|
+
if (!child.isText)
|
|
1861
|
+
continue;
|
|
1862
|
+
let str = child.text;
|
|
1863
|
+
while (i < frag.childCount) {
|
|
1864
|
+
let next = frag.child(i++);
|
|
1865
|
+
pos += next.nodeSize;
|
|
1866
|
+
if (!next.isText)
|
|
1867
|
+
break;
|
|
1868
|
+
str += next.text;
|
|
1869
|
+
}
|
|
1870
|
+
if (pos >= from) {
|
|
1871
|
+
let found = childStart < to ? str.lastIndexOf(text, to - childStart - 1) : -1;
|
|
1872
|
+
if (found >= 0 && found + text.length + childStart >= from)
|
|
1873
|
+
return childStart + found;
|
|
1874
|
+
if (from == to && str.length >= to + text.length - childStart && str.slice(to - childStart, to - childStart + text.length) == text)
|
|
1875
|
+
return to;
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1878
|
+
return -1;
|
|
1879
|
+
}
|
|
1880
|
+
function replaceNodes(nodes, from, to, view, replacement) {
|
|
1881
|
+
let result = [];
|
|
1882
|
+
for (let i = 0, off = 0; i < nodes.length; i++) {
|
|
1883
|
+
let child = nodes[i], start = off, end = off += child.size;
|
|
1884
|
+
if (start >= to || end <= from) {
|
|
1885
|
+
result.push(child);
|
|
1886
|
+
} else {
|
|
1887
|
+
if (start < from)
|
|
1888
|
+
result.push(child.slice(0, from - start, view));
|
|
1889
|
+
if (replacement) {
|
|
1890
|
+
result.push(replacement);
|
|
1891
|
+
replacement = void 0;
|
|
1892
|
+
}
|
|
1893
|
+
if (end > to)
|
|
1894
|
+
result.push(child.slice(to - start, child.size, view));
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
return result;
|
|
1898
|
+
}
|
|
1899
|
+
function selectionFromDOM(view, origin = null) {
|
|
1900
|
+
let domSel = view.domSelectionRange(), doc2 = view.state.doc;
|
|
1901
|
+
if (!domSel.focusNode)
|
|
1902
|
+
return null;
|
|
1903
|
+
let nearestDesc = view.docView.nearestDesc(domSel.focusNode), inWidget = nearestDesc && nearestDesc.size == 0;
|
|
1904
|
+
let head = view.docView.posFromDOM(domSel.focusNode, domSel.focusOffset, 1);
|
|
1905
|
+
if (head < 0)
|
|
1906
|
+
return null;
|
|
1907
|
+
let $head = doc2.resolve(head), $anchor, selection;
|
|
1908
|
+
if (selectionCollapsed(domSel)) {
|
|
1909
|
+
$anchor = $head;
|
|
1910
|
+
while (nearestDesc && !nearestDesc.node)
|
|
1911
|
+
nearestDesc = nearestDesc.parent;
|
|
1912
|
+
let nearestDescNode = nearestDesc.node;
|
|
1913
|
+
if (nearestDesc && nearestDescNode.isAtom && NodeSelection.isSelectable(nearestDescNode) && nearestDesc.parent && !(nearestDescNode.isInline && isOnEdge(domSel.focusNode, domSel.focusOffset, nearestDesc.dom))) {
|
|
1914
|
+
let pos = nearestDesc.posBefore;
|
|
1915
|
+
selection = new NodeSelection(head == pos ? $head : doc2.resolve(pos));
|
|
1916
|
+
}
|
|
1917
|
+
} else {
|
|
1918
|
+
let anchor = view.docView.posFromDOM(domSel.anchorNode, domSel.anchorOffset, 1);
|
|
1919
|
+
if (anchor < 0)
|
|
1920
|
+
return null;
|
|
1921
|
+
$anchor = doc2.resolve(anchor);
|
|
1922
|
+
}
|
|
1923
|
+
if (!selection) {
|
|
1924
|
+
let bias = origin == "pointer" || view.state.selection.head < $head.pos && !inWidget ? 1 : -1;
|
|
1925
|
+
selection = selectionBetween(view, $anchor, $head, bias);
|
|
1926
|
+
}
|
|
1927
|
+
return selection;
|
|
1928
|
+
}
|
|
1929
|
+
function editorOwnsSelection(view) {
|
|
1930
|
+
return view.editable ? view.hasFocus() : hasSelection(view) && document.activeElement && document.activeElement.contains(view.dom);
|
|
1931
|
+
}
|
|
1932
|
+
function selectionToDOM(view, force = false) {
|
|
1933
|
+
let sel = view.state.selection;
|
|
1934
|
+
syncNodeSelection(view, sel);
|
|
1935
|
+
if (!editorOwnsSelection(view))
|
|
1936
|
+
return;
|
|
1937
|
+
if (!force && view.input.mouseDown && view.input.mouseDown.allowDefault && chrome) {
|
|
1938
|
+
let domSel = view.domSelectionRange(), curSel = view.domObserver.currentSelection;
|
|
1939
|
+
if (domSel.anchorNode && curSel.anchorNode && isEquivalentPosition(domSel.anchorNode, domSel.anchorOffset, curSel.anchorNode, curSel.anchorOffset)) {
|
|
1940
|
+
view.input.mouseDown.delayedSelectionSync = true;
|
|
1941
|
+
view.domObserver.setCurSelection();
|
|
1942
|
+
return;
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
view.domObserver.disconnectSelection();
|
|
1946
|
+
if (view.cursorWrapper) {
|
|
1947
|
+
selectCursorWrapper(view);
|
|
1948
|
+
} else {
|
|
1949
|
+
let { anchor, head } = sel, resetEditableFrom, resetEditableTo;
|
|
1950
|
+
if (brokenSelectBetweenUneditable && !(sel instanceof TextSelection)) {
|
|
1951
|
+
if (!sel.$from.parent.inlineContent)
|
|
1952
|
+
resetEditableFrom = temporarilyEditableNear(view, sel.from);
|
|
1953
|
+
if (!sel.empty && !sel.$from.parent.inlineContent)
|
|
1954
|
+
resetEditableTo = temporarilyEditableNear(view, sel.to);
|
|
1955
|
+
}
|
|
1956
|
+
view.docView.setSelection(anchor, head, view.root, force);
|
|
1957
|
+
if (brokenSelectBetweenUneditable) {
|
|
1958
|
+
if (resetEditableFrom)
|
|
1959
|
+
resetEditable(resetEditableFrom);
|
|
1960
|
+
if (resetEditableTo)
|
|
1961
|
+
resetEditable(resetEditableTo);
|
|
1962
|
+
}
|
|
1963
|
+
if (sel.visible) {
|
|
1964
|
+
view.dom.classList.remove("ProseMirror-hideselection");
|
|
1965
|
+
} else {
|
|
1966
|
+
view.dom.classList.add("ProseMirror-hideselection");
|
|
1967
|
+
if ("onselectionchange" in document)
|
|
1968
|
+
removeClassOnSelectionChange(view);
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
view.domObserver.setCurSelection();
|
|
1972
|
+
view.domObserver.connectSelection();
|
|
1973
|
+
}
|
|
1974
|
+
var brokenSelectBetweenUneditable = safari || chrome && chrome_version < 63;
|
|
1975
|
+
function temporarilyEditableNear(view, pos) {
|
|
1976
|
+
let { node, offset } = view.docView.domFromPos(pos, 0);
|
|
1977
|
+
let after = offset < node.childNodes.length ? node.childNodes[offset] : null;
|
|
1978
|
+
let before = offset ? node.childNodes[offset - 1] : null;
|
|
1979
|
+
if (safari && after && after.contentEditable == "false")
|
|
1980
|
+
return setEditable(after);
|
|
1981
|
+
if ((!after || after.contentEditable == "false") && (!before || before.contentEditable == "false")) {
|
|
1982
|
+
if (after)
|
|
1983
|
+
return setEditable(after);
|
|
1984
|
+
else if (before)
|
|
1985
|
+
return setEditable(before);
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
function setEditable(element) {
|
|
1989
|
+
element.contentEditable = "true";
|
|
1990
|
+
if (safari && element.draggable) {
|
|
1991
|
+
element.draggable = false;
|
|
1992
|
+
element.wasDraggable = true;
|
|
1993
|
+
}
|
|
1994
|
+
return element;
|
|
1995
|
+
}
|
|
1996
|
+
function resetEditable(element) {
|
|
1997
|
+
element.contentEditable = "false";
|
|
1998
|
+
if (element.wasDraggable) {
|
|
1999
|
+
element.draggable = true;
|
|
2000
|
+
element.wasDraggable = null;
|
|
2001
|
+
}
|
|
2002
|
+
}
|
|
2003
|
+
function removeClassOnSelectionChange(view) {
|
|
2004
|
+
let doc2 = view.dom.ownerDocument;
|
|
2005
|
+
doc2.removeEventListener("selectionchange", view.input.hideSelectionGuard);
|
|
2006
|
+
let domSel = view.domSelectionRange();
|
|
2007
|
+
let node = domSel.anchorNode, offset = domSel.anchorOffset;
|
|
2008
|
+
doc2.addEventListener("selectionchange", view.input.hideSelectionGuard = () => {
|
|
2009
|
+
if (domSel.anchorNode != node || domSel.anchorOffset != offset) {
|
|
2010
|
+
doc2.removeEventListener("selectionchange", view.input.hideSelectionGuard);
|
|
2011
|
+
setTimeout(() => {
|
|
2012
|
+
if (!editorOwnsSelection(view) || view.state.selection.visible)
|
|
2013
|
+
view.dom.classList.remove("ProseMirror-hideselection");
|
|
2014
|
+
}, 20);
|
|
2015
|
+
}
|
|
2016
|
+
});
|
|
2017
|
+
}
|
|
2018
|
+
function selectCursorWrapper(view) {
|
|
2019
|
+
let domSel = view.domSelection(), range = document.createRange();
|
|
2020
|
+
let node = view.cursorWrapper.dom, img = node.nodeName == "IMG";
|
|
2021
|
+
if (img)
|
|
2022
|
+
range.setEnd(node.parentNode, domIndex(node) + 1);
|
|
2023
|
+
else
|
|
2024
|
+
range.setEnd(node, 0);
|
|
2025
|
+
range.collapse(false);
|
|
2026
|
+
domSel.removeAllRanges();
|
|
2027
|
+
domSel.addRange(range);
|
|
2028
|
+
if (!img && !view.state.selection.visible && ie && ie_version <= 11) {
|
|
2029
|
+
node.disabled = true;
|
|
2030
|
+
node.disabled = false;
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
2033
|
+
function syncNodeSelection(view, sel) {
|
|
2034
|
+
if (sel instanceof NodeSelection) {
|
|
2035
|
+
let desc = view.docView.descAt(sel.from);
|
|
2036
|
+
if (desc != view.lastSelectedViewDesc) {
|
|
2037
|
+
clearNodeSelection(view);
|
|
2038
|
+
if (desc)
|
|
2039
|
+
desc.selectNode();
|
|
2040
|
+
view.lastSelectedViewDesc = desc;
|
|
2041
|
+
}
|
|
2042
|
+
} else {
|
|
2043
|
+
clearNodeSelection(view);
|
|
2044
|
+
}
|
|
2045
|
+
}
|
|
2046
|
+
function clearNodeSelection(view) {
|
|
2047
|
+
if (view.lastSelectedViewDesc) {
|
|
2048
|
+
if (view.lastSelectedViewDesc.parent)
|
|
2049
|
+
view.lastSelectedViewDesc.deselectNode();
|
|
2050
|
+
view.lastSelectedViewDesc = void 0;
|
|
2051
|
+
}
|
|
2052
|
+
}
|
|
2053
|
+
function selectionBetween(view, $anchor, $head, bias) {
|
|
2054
|
+
return view.someProp("createSelectionBetween", (f) => f(view, $anchor, $head)) || TextSelection.between($anchor, $head, bias);
|
|
2055
|
+
}
|
|
2056
|
+
function hasFocusAndSelection(view) {
|
|
2057
|
+
if (view.editable && !view.hasFocus())
|
|
2058
|
+
return false;
|
|
2059
|
+
return hasSelection(view);
|
|
2060
|
+
}
|
|
2061
|
+
function hasSelection(view) {
|
|
2062
|
+
let sel = view.domSelectionRange();
|
|
2063
|
+
if (!sel.anchorNode)
|
|
2064
|
+
return false;
|
|
2065
|
+
try {
|
|
2066
|
+
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));
|
|
2067
|
+
} catch (_) {
|
|
2068
|
+
return false;
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
function anchorInRightPlace(view) {
|
|
2072
|
+
let anchorDOM = view.docView.domFromPos(view.state.selection.anchor, 0);
|
|
2073
|
+
let domSel = view.domSelectionRange();
|
|
2074
|
+
return isEquivalentPosition(anchorDOM.node, anchorDOM.offset, domSel.anchorNode, domSel.anchorOffset);
|
|
2075
|
+
}
|
|
2076
|
+
function moveSelectionBlock(state, dir) {
|
|
2077
|
+
let { $anchor, $head } = state.selection;
|
|
2078
|
+
let $side = dir > 0 ? $anchor.max($head) : $anchor.min($head);
|
|
2079
|
+
let $start = !$side.parent.inlineContent ? $side : $side.depth ? state.doc.resolve(dir > 0 ? $side.after() : $side.before()) : null;
|
|
2080
|
+
return $start && Selection.findFrom($start, dir);
|
|
2081
|
+
}
|
|
2082
|
+
function apply(view, sel) {
|
|
2083
|
+
view.dispatch(view.state.tr.setSelection(sel).scrollIntoView());
|
|
2084
|
+
return true;
|
|
2085
|
+
}
|
|
2086
|
+
function selectHorizontally(view, dir, mods) {
|
|
2087
|
+
let sel = view.state.selection;
|
|
2088
|
+
if (sel instanceof TextSelection) {
|
|
2089
|
+
if (!sel.empty || mods.indexOf("s") > -1) {
|
|
2090
|
+
return false;
|
|
2091
|
+
} else if (view.endOfTextblock(dir > 0 ? "forward" : "backward")) {
|
|
2092
|
+
let next = moveSelectionBlock(view.state, dir);
|
|
2093
|
+
if (next && next instanceof NodeSelection)
|
|
2094
|
+
return apply(view, next);
|
|
2095
|
+
return false;
|
|
2096
|
+
} else if (!(mac && mods.indexOf("m") > -1)) {
|
|
2097
|
+
let $head = sel.$head, node = $head.textOffset ? null : dir < 0 ? $head.nodeBefore : $head.nodeAfter, desc;
|
|
2098
|
+
if (!node || node.isText)
|
|
2099
|
+
return false;
|
|
2100
|
+
let nodePos = dir < 0 ? $head.pos - node.nodeSize : $head.pos;
|
|
2101
|
+
if (!(node.isAtom || (desc = view.docView.descAt(nodePos)) && !desc.contentDOM))
|
|
2102
|
+
return false;
|
|
2103
|
+
if (NodeSelection.isSelectable(node)) {
|
|
2104
|
+
return apply(view, new NodeSelection(dir < 0 ? view.state.doc.resolve($head.pos - node.nodeSize) : $head));
|
|
2105
|
+
} else if (webkit) {
|
|
2106
|
+
return apply(view, new TextSelection(view.state.doc.resolve(dir < 0 ? nodePos : nodePos + node.nodeSize)));
|
|
2107
|
+
} else {
|
|
2108
|
+
return false;
|
|
2109
|
+
}
|
|
2110
|
+
}
|
|
2111
|
+
} else if (sel instanceof NodeSelection && sel.node.isInline) {
|
|
2112
|
+
return apply(view, new TextSelection(dir > 0 ? sel.$to : sel.$from));
|
|
2113
|
+
} else {
|
|
2114
|
+
let next = moveSelectionBlock(view.state, dir);
|
|
2115
|
+
if (next)
|
|
2116
|
+
return apply(view, next);
|
|
2117
|
+
return false;
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
function nodeLen(node) {
|
|
2121
|
+
return node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length;
|
|
2122
|
+
}
|
|
2123
|
+
function isIgnorable(dom) {
|
|
2124
|
+
let desc = dom.pmViewDesc;
|
|
2125
|
+
return desc && desc.size == 0 && (dom.nextSibling || dom.nodeName != "BR");
|
|
2126
|
+
}
|
|
2127
|
+
function skipIgnoredNodes(view, dir) {
|
|
2128
|
+
return dir < 0 ? skipIgnoredNodesBefore(view) : skipIgnoredNodesAfter(view);
|
|
2129
|
+
}
|
|
2130
|
+
function skipIgnoredNodesBefore(view) {
|
|
2131
|
+
let sel = view.domSelectionRange();
|
|
2132
|
+
let node = sel.focusNode, offset = sel.focusOffset;
|
|
2133
|
+
if (!node)
|
|
2134
|
+
return;
|
|
2135
|
+
let moveNode, moveOffset, force = false;
|
|
2136
|
+
if (gecko && node.nodeType == 1 && offset < nodeLen(node) && isIgnorable(node.childNodes[offset]))
|
|
2137
|
+
force = true;
|
|
2138
|
+
for (; ; ) {
|
|
2139
|
+
if (offset > 0) {
|
|
2140
|
+
if (node.nodeType != 1) {
|
|
2141
|
+
break;
|
|
2142
|
+
} else {
|
|
2143
|
+
let before = node.childNodes[offset - 1];
|
|
2144
|
+
if (isIgnorable(before)) {
|
|
2145
|
+
moveNode = node;
|
|
2146
|
+
moveOffset = --offset;
|
|
2147
|
+
} else if (before.nodeType == 3) {
|
|
2148
|
+
node = before;
|
|
2149
|
+
offset = node.nodeValue.length;
|
|
2150
|
+
} else
|
|
2151
|
+
break;
|
|
2152
|
+
}
|
|
2153
|
+
} else if (isBlockNode(node)) {
|
|
2154
|
+
break;
|
|
2155
|
+
} else {
|
|
2156
|
+
let prev = node.previousSibling;
|
|
2157
|
+
while (prev && isIgnorable(prev)) {
|
|
2158
|
+
moveNode = node.parentNode;
|
|
2159
|
+
moveOffset = domIndex(prev);
|
|
2160
|
+
prev = prev.previousSibling;
|
|
2161
|
+
}
|
|
2162
|
+
if (!prev) {
|
|
2163
|
+
node = node.parentNode;
|
|
2164
|
+
if (node == view.dom)
|
|
2165
|
+
break;
|
|
2166
|
+
offset = 0;
|
|
2167
|
+
} else {
|
|
2168
|
+
node = prev;
|
|
2169
|
+
offset = nodeLen(node);
|
|
2170
|
+
}
|
|
2171
|
+
}
|
|
2172
|
+
}
|
|
2173
|
+
if (force)
|
|
2174
|
+
setSelFocus(view, node, offset);
|
|
2175
|
+
else if (moveNode)
|
|
2176
|
+
setSelFocus(view, moveNode, moveOffset);
|
|
2177
|
+
}
|
|
2178
|
+
function skipIgnoredNodesAfter(view) {
|
|
2179
|
+
let sel = view.domSelectionRange();
|
|
2180
|
+
let node = sel.focusNode, offset = sel.focusOffset;
|
|
2181
|
+
if (!node)
|
|
2182
|
+
return;
|
|
2183
|
+
let len = nodeLen(node);
|
|
2184
|
+
let moveNode, moveOffset;
|
|
2185
|
+
for (; ; ) {
|
|
2186
|
+
if (offset < len) {
|
|
2187
|
+
if (node.nodeType != 1)
|
|
2188
|
+
break;
|
|
2189
|
+
let after = node.childNodes[offset];
|
|
2190
|
+
if (isIgnorable(after)) {
|
|
2191
|
+
moveNode = node;
|
|
2192
|
+
moveOffset = ++offset;
|
|
2193
|
+
} else
|
|
2194
|
+
break;
|
|
2195
|
+
} else if (isBlockNode(node)) {
|
|
2196
|
+
break;
|
|
2197
|
+
} else {
|
|
2198
|
+
let next = node.nextSibling;
|
|
2199
|
+
while (next && isIgnorable(next)) {
|
|
2200
|
+
moveNode = next.parentNode;
|
|
2201
|
+
moveOffset = domIndex(next) + 1;
|
|
2202
|
+
next = next.nextSibling;
|
|
2203
|
+
}
|
|
2204
|
+
if (!next) {
|
|
2205
|
+
node = node.parentNode;
|
|
2206
|
+
if (node == view.dom)
|
|
2207
|
+
break;
|
|
2208
|
+
offset = len = 0;
|
|
2209
|
+
} else {
|
|
2210
|
+
node = next;
|
|
2211
|
+
offset = 0;
|
|
2212
|
+
len = nodeLen(node);
|
|
2213
|
+
}
|
|
2214
|
+
}
|
|
2215
|
+
}
|
|
2216
|
+
if (moveNode)
|
|
2217
|
+
setSelFocus(view, moveNode, moveOffset);
|
|
2218
|
+
}
|
|
2219
|
+
function isBlockNode(dom) {
|
|
2220
|
+
let desc = dom.pmViewDesc;
|
|
2221
|
+
return desc && desc.node && desc.node.isBlock;
|
|
2222
|
+
}
|
|
2223
|
+
function setSelFocus(view, node, offset) {
|
|
2224
|
+
let sel = view.domSelection();
|
|
2225
|
+
if (selectionCollapsed(sel)) {
|
|
2226
|
+
let range = document.createRange();
|
|
2227
|
+
range.setEnd(node, offset);
|
|
2228
|
+
range.setStart(node, offset);
|
|
2229
|
+
sel.removeAllRanges();
|
|
2230
|
+
sel.addRange(range);
|
|
2231
|
+
} else if (sel.extend) {
|
|
2232
|
+
sel.extend(node, offset);
|
|
2233
|
+
}
|
|
2234
|
+
view.domObserver.setCurSelection();
|
|
2235
|
+
let { state } = view;
|
|
2236
|
+
setTimeout(() => {
|
|
2237
|
+
if (view.state == state)
|
|
2238
|
+
selectionToDOM(view);
|
|
2239
|
+
}, 50);
|
|
2240
|
+
}
|
|
2241
|
+
function findDirection(view, pos) {
|
|
2242
|
+
let $pos = view.state.doc.resolve(pos);
|
|
2243
|
+
if (!(chrome || windows) && $pos.parent.inlineContent) {
|
|
2244
|
+
let coords = view.coordsAtPos(pos);
|
|
2245
|
+
if (pos > $pos.start()) {
|
|
2246
|
+
let before = view.coordsAtPos(pos - 1);
|
|
2247
|
+
let mid = (before.top + before.bottom) / 2;
|
|
2248
|
+
if (mid > coords.top && mid < coords.bottom && Math.abs(before.left - coords.left) > 1)
|
|
2249
|
+
return before.left < coords.left ? "ltr" : "rtl";
|
|
2250
|
+
}
|
|
2251
|
+
if (pos < $pos.end()) {
|
|
2252
|
+
let after = view.coordsAtPos(pos + 1);
|
|
2253
|
+
let mid = (after.top + after.bottom) / 2;
|
|
2254
|
+
if (mid > coords.top && mid < coords.bottom && Math.abs(after.left - coords.left) > 1)
|
|
2255
|
+
return after.left > coords.left ? "ltr" : "rtl";
|
|
2256
|
+
}
|
|
2257
|
+
}
|
|
2258
|
+
let computed = getComputedStyle(view.dom).direction;
|
|
2259
|
+
return computed == "rtl" ? "rtl" : "ltr";
|
|
2260
|
+
}
|
|
2261
|
+
function selectVertically(view, dir, mods) {
|
|
2262
|
+
let sel = view.state.selection;
|
|
2263
|
+
if (sel instanceof TextSelection && !sel.empty || mods.indexOf("s") > -1)
|
|
2264
|
+
return false;
|
|
2265
|
+
if (mac && mods.indexOf("m") > -1)
|
|
2266
|
+
return false;
|
|
2267
|
+
let { $from, $to } = sel;
|
|
2268
|
+
if (!$from.parent.inlineContent || view.endOfTextblock(dir < 0 ? "up" : "down")) {
|
|
2269
|
+
let next = moveSelectionBlock(view.state, dir);
|
|
2270
|
+
if (next && next instanceof NodeSelection)
|
|
2271
|
+
return apply(view, next);
|
|
2272
|
+
}
|
|
2273
|
+
if (!$from.parent.inlineContent) {
|
|
2274
|
+
let side = dir < 0 ? $from : $to;
|
|
2275
|
+
let beyond = sel instanceof AllSelection ? Selection.near(side, dir) : Selection.findFrom(side, dir);
|
|
2276
|
+
return beyond ? apply(view, beyond) : false;
|
|
2277
|
+
}
|
|
2278
|
+
return false;
|
|
2279
|
+
}
|
|
2280
|
+
function stopNativeHorizontalDelete(view, dir) {
|
|
2281
|
+
if (!(view.state.selection instanceof TextSelection))
|
|
2282
|
+
return true;
|
|
2283
|
+
let { $head, $anchor, empty: empty2 } = view.state.selection;
|
|
2284
|
+
if (!$head.sameParent($anchor))
|
|
2285
|
+
return true;
|
|
2286
|
+
if (!empty2)
|
|
2287
|
+
return false;
|
|
2288
|
+
if (view.endOfTextblock(dir > 0 ? "forward" : "backward"))
|
|
2289
|
+
return true;
|
|
2290
|
+
let nextNode = !$head.textOffset && (dir < 0 ? $head.nodeBefore : $head.nodeAfter);
|
|
2291
|
+
if (nextNode && !nextNode.isText) {
|
|
2292
|
+
let tr = view.state.tr;
|
|
2293
|
+
if (dir < 0)
|
|
2294
|
+
tr.delete($head.pos - nextNode.nodeSize, $head.pos);
|
|
2295
|
+
else
|
|
2296
|
+
tr.delete($head.pos, $head.pos + nextNode.nodeSize);
|
|
2297
|
+
view.dispatch(tr);
|
|
2298
|
+
return true;
|
|
2299
|
+
}
|
|
2300
|
+
return false;
|
|
2301
|
+
}
|
|
2302
|
+
function switchEditable(view, node, state) {
|
|
2303
|
+
view.domObserver.stop();
|
|
2304
|
+
node.contentEditable = state;
|
|
2305
|
+
view.domObserver.start();
|
|
2306
|
+
}
|
|
2307
|
+
function safariDownArrowBug(view) {
|
|
2308
|
+
if (!safari || view.state.selection.$head.parentOffset > 0)
|
|
2309
|
+
return false;
|
|
2310
|
+
let { focusNode, focusOffset } = view.domSelectionRange();
|
|
2311
|
+
if (focusNode && focusNode.nodeType == 1 && focusOffset == 0 && focusNode.firstChild && focusNode.firstChild.contentEditable == "false") {
|
|
2312
|
+
let child = focusNode.firstChild;
|
|
2313
|
+
switchEditable(view, child, "true");
|
|
2314
|
+
setTimeout(() => switchEditable(view, child, "false"), 20);
|
|
2315
|
+
}
|
|
2316
|
+
return false;
|
|
2317
|
+
}
|
|
2318
|
+
function getMods(event) {
|
|
2319
|
+
let result = "";
|
|
2320
|
+
if (event.ctrlKey)
|
|
2321
|
+
result += "c";
|
|
2322
|
+
if (event.metaKey)
|
|
2323
|
+
result += "m";
|
|
2324
|
+
if (event.altKey)
|
|
2325
|
+
result += "a";
|
|
2326
|
+
if (event.shiftKey)
|
|
2327
|
+
result += "s";
|
|
2328
|
+
return result;
|
|
2329
|
+
}
|
|
2330
|
+
function captureKeyDown(view, event) {
|
|
2331
|
+
let code = event.keyCode, mods = getMods(event);
|
|
2332
|
+
if (code == 8 || mac && code == 72 && mods == "c") {
|
|
2333
|
+
return stopNativeHorizontalDelete(view, -1) || skipIgnoredNodes(view, -1);
|
|
2334
|
+
} else if (code == 46 && !event.shiftKey || mac && code == 68 && mods == "c") {
|
|
2335
|
+
return stopNativeHorizontalDelete(view, 1) || skipIgnoredNodes(view, 1);
|
|
2336
|
+
} else if (code == 13 || code == 27) {
|
|
2337
|
+
return true;
|
|
2338
|
+
} else if (code == 37 || mac && code == 66 && mods == "c") {
|
|
2339
|
+
let dir = code == 37 ? findDirection(view, view.state.selection.from) == "ltr" ? -1 : 1 : -1;
|
|
2340
|
+
return selectHorizontally(view, dir, mods) || skipIgnoredNodes(view, dir);
|
|
2341
|
+
} else if (code == 39 || mac && code == 70 && mods == "c") {
|
|
2342
|
+
let dir = code == 39 ? findDirection(view, view.state.selection.from) == "ltr" ? 1 : -1 : 1;
|
|
2343
|
+
return selectHorizontally(view, dir, mods) || skipIgnoredNodes(view, dir);
|
|
2344
|
+
} else if (code == 38 || mac && code == 80 && mods == "c") {
|
|
2345
|
+
return selectVertically(view, -1, mods) || skipIgnoredNodes(view, -1);
|
|
2346
|
+
} else if (code == 40 || mac && code == 78 && mods == "c") {
|
|
2347
|
+
return safariDownArrowBug(view) || selectVertically(view, 1, mods) || skipIgnoredNodesAfter(view);
|
|
2348
|
+
} else if (mods == (mac ? "m" : "c") && (code == 66 || code == 73 || code == 89 || code == 90)) {
|
|
2349
|
+
return true;
|
|
2350
|
+
}
|
|
2351
|
+
return false;
|
|
2352
|
+
}
|
|
2353
|
+
function serializeForClipboard(view, slice) {
|
|
2354
|
+
view.someProp("transformCopied", (f) => {
|
|
2355
|
+
slice = f(slice, view);
|
|
2356
|
+
});
|
|
2357
|
+
let context = [], { content, openStart, openEnd } = slice;
|
|
2358
|
+
while (openStart > 1 && openEnd > 1 && content.childCount == 1 && content.firstChild.childCount == 1) {
|
|
2359
|
+
openStart--;
|
|
2360
|
+
openEnd--;
|
|
2361
|
+
let node = content.firstChild;
|
|
2362
|
+
context.push(node.type.name, node.attrs != node.type.defaultAttrs ? node.attrs : null);
|
|
2363
|
+
content = node.content;
|
|
2364
|
+
}
|
|
2365
|
+
let serializer = view.someProp("clipboardSerializer") || DOMSerializer.fromSchema(view.state.schema);
|
|
2366
|
+
let doc2 = detachedDoc(), wrap = doc2.createElement("div");
|
|
2367
|
+
wrap.appendChild(serializer.serializeFragment(content, { document: doc2 }));
|
|
2368
|
+
let firstChild = wrap.firstChild, needsWrap, wrappers = 0;
|
|
2369
|
+
while (firstChild && firstChild.nodeType == 1 && (needsWrap = wrapMap[firstChild.nodeName.toLowerCase()])) {
|
|
2370
|
+
for (let i = needsWrap.length - 1; i >= 0; i--) {
|
|
2371
|
+
let wrapper = doc2.createElement(needsWrap[i]);
|
|
2372
|
+
while (wrap.firstChild)
|
|
2373
|
+
wrapper.appendChild(wrap.firstChild);
|
|
2374
|
+
wrap.appendChild(wrapper);
|
|
2375
|
+
wrappers++;
|
|
2376
|
+
}
|
|
2377
|
+
firstChild = wrap.firstChild;
|
|
2378
|
+
}
|
|
2379
|
+
if (firstChild && firstChild.nodeType == 1)
|
|
2380
|
+
firstChild.setAttribute("data-pm-slice", `${openStart} ${openEnd}${wrappers ? ` -${wrappers}` : ""} ${JSON.stringify(context)}`);
|
|
2381
|
+
let text = view.someProp("clipboardTextSerializer", (f) => f(slice, view)) || slice.content.textBetween(0, slice.content.size, "\n\n");
|
|
2382
|
+
return { dom: wrap, text };
|
|
2383
|
+
}
|
|
2384
|
+
function parseFromClipboard(view, text, html, plainText, $context) {
|
|
2385
|
+
let inCode = $context.parent.type.spec.code;
|
|
2386
|
+
let dom, slice;
|
|
2387
|
+
if (!html && !text)
|
|
2388
|
+
return null;
|
|
2389
|
+
let asText = text && (plainText || inCode || !html);
|
|
2390
|
+
if (asText) {
|
|
2391
|
+
view.someProp("transformPastedText", (f) => {
|
|
2392
|
+
text = f(text, inCode || plainText, view);
|
|
2393
|
+
});
|
|
2394
|
+
if (inCode)
|
|
2395
|
+
return text ? new Slice(Fragment.from(view.state.schema.text(text.replace(/\r\n?/g, "\n"))), 0, 0) : Slice.empty;
|
|
2396
|
+
let parsed = view.someProp("clipboardTextParser", (f) => f(text, $context, plainText, view));
|
|
2397
|
+
if (parsed) {
|
|
2398
|
+
slice = parsed;
|
|
2399
|
+
} else {
|
|
2400
|
+
let marks = $context.marks();
|
|
2401
|
+
let { schema } = view.state, serializer = DOMSerializer.fromSchema(schema);
|
|
2402
|
+
dom = document.createElement("div");
|
|
2403
|
+
text.split(/(?:\r\n?|\n)+/).forEach((block) => {
|
|
2404
|
+
let p = dom.appendChild(document.createElement("p"));
|
|
2405
|
+
if (block)
|
|
2406
|
+
p.appendChild(serializer.serializeNode(schema.text(block, marks)));
|
|
2407
|
+
});
|
|
2408
|
+
}
|
|
2409
|
+
} else {
|
|
2410
|
+
view.someProp("transformPastedHTML", (f) => {
|
|
2411
|
+
html = f(html, view);
|
|
2412
|
+
});
|
|
2413
|
+
dom = readHTML(html);
|
|
2414
|
+
if (webkit)
|
|
2415
|
+
restoreReplacedSpaces(dom);
|
|
2416
|
+
}
|
|
2417
|
+
let contextNode = dom && dom.querySelector("[data-pm-slice]");
|
|
2418
|
+
let sliceData = contextNode && /^(\d+) (\d+)(?: -(\d+))? (.*)/.exec(contextNode.getAttribute("data-pm-slice") || "");
|
|
2419
|
+
if (sliceData && sliceData[3])
|
|
2420
|
+
for (let i = +sliceData[3]; i > 0; i--) {
|
|
2421
|
+
let child = dom.firstChild;
|
|
2422
|
+
while (child && child.nodeType != 1)
|
|
2423
|
+
child = child.nextSibling;
|
|
2424
|
+
if (!child)
|
|
2425
|
+
break;
|
|
2426
|
+
dom = child;
|
|
2427
|
+
}
|
|
2428
|
+
if (!slice) {
|
|
2429
|
+
let parser = view.someProp("clipboardParser") || view.someProp("domParser") || DOMParser.fromSchema(view.state.schema);
|
|
2430
|
+
slice = parser.parseSlice(dom, {
|
|
2431
|
+
preserveWhitespace: !!(asText || sliceData),
|
|
2432
|
+
context: $context,
|
|
2433
|
+
ruleFromNode(dom2) {
|
|
2434
|
+
if (dom2.nodeName == "BR" && !dom2.nextSibling && dom2.parentNode && !inlineParents.test(dom2.parentNode.nodeName))
|
|
2435
|
+
return { ignore: true };
|
|
2436
|
+
return null;
|
|
2437
|
+
}
|
|
2438
|
+
});
|
|
2439
|
+
}
|
|
2440
|
+
if (sliceData) {
|
|
2441
|
+
slice = addContext(closeSlice(slice, +sliceData[1], +sliceData[2]), sliceData[4]);
|
|
2442
|
+
} else {
|
|
2443
|
+
slice = Slice.maxOpen(normalizeSiblings(slice.content, $context), true);
|
|
2444
|
+
if (slice.openStart || slice.openEnd) {
|
|
2445
|
+
let openStart = 0, openEnd = 0;
|
|
2446
|
+
for (let node = slice.content.firstChild; openStart < slice.openStart && !node.type.spec.isolating; openStart++, node = node.firstChild) {
|
|
2447
|
+
}
|
|
2448
|
+
for (let node = slice.content.lastChild; openEnd < slice.openEnd && !node.type.spec.isolating; openEnd++, node = node.lastChild) {
|
|
2449
|
+
}
|
|
2450
|
+
slice = closeSlice(slice, openStart, openEnd);
|
|
2451
|
+
}
|
|
2452
|
+
}
|
|
2453
|
+
view.someProp("transformPasted", (f) => {
|
|
2454
|
+
slice = f(slice, view);
|
|
2455
|
+
});
|
|
2456
|
+
return slice;
|
|
2457
|
+
}
|
|
2458
|
+
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;
|
|
2459
|
+
function normalizeSiblings(fragment, $context) {
|
|
2460
|
+
if (fragment.childCount < 2)
|
|
2461
|
+
return fragment;
|
|
2462
|
+
for (let d = $context.depth; d >= 0; d--) {
|
|
2463
|
+
let parent = $context.node(d);
|
|
2464
|
+
let match = parent.contentMatchAt($context.index(d));
|
|
2465
|
+
let lastWrap, result = [];
|
|
2466
|
+
fragment.forEach((node) => {
|
|
2467
|
+
if (!result)
|
|
2468
|
+
return;
|
|
2469
|
+
let wrap = match.findWrapping(node.type), inLast;
|
|
2470
|
+
if (!wrap)
|
|
2471
|
+
return result = null;
|
|
2472
|
+
if (inLast = result.length && lastWrap.length && addToSibling(wrap, lastWrap, node, result[result.length - 1], 0)) {
|
|
2473
|
+
result[result.length - 1] = inLast;
|
|
2474
|
+
} else {
|
|
2475
|
+
if (result.length)
|
|
2476
|
+
result[result.length - 1] = closeRight(result[result.length - 1], lastWrap.length);
|
|
2477
|
+
let wrapped = withWrappers(node, wrap);
|
|
2478
|
+
result.push(wrapped);
|
|
2479
|
+
match = match.matchType(wrapped.type);
|
|
2480
|
+
lastWrap = wrap;
|
|
2481
|
+
}
|
|
2482
|
+
});
|
|
2483
|
+
if (result)
|
|
2484
|
+
return Fragment.from(result);
|
|
2485
|
+
}
|
|
2486
|
+
return fragment;
|
|
2487
|
+
}
|
|
2488
|
+
function withWrappers(node, wrap, from = 0) {
|
|
2489
|
+
for (let i = wrap.length - 1; i >= from; i--)
|
|
2490
|
+
node = wrap[i].create(null, Fragment.from(node));
|
|
2491
|
+
return node;
|
|
2492
|
+
}
|
|
2493
|
+
function addToSibling(wrap, lastWrap, node, sibling, depth) {
|
|
2494
|
+
if (depth < wrap.length && depth < lastWrap.length && wrap[depth] == lastWrap[depth]) {
|
|
2495
|
+
let inner = addToSibling(wrap, lastWrap, node, sibling.lastChild, depth + 1);
|
|
2496
|
+
if (inner)
|
|
2497
|
+
return sibling.copy(sibling.content.replaceChild(sibling.childCount - 1, inner));
|
|
2498
|
+
let match = sibling.contentMatchAt(sibling.childCount);
|
|
2499
|
+
if (match.matchType(depth == wrap.length - 1 ? node.type : wrap[depth + 1]))
|
|
2500
|
+
return sibling.copy(sibling.content.append(Fragment.from(withWrappers(node, wrap, depth + 1))));
|
|
2501
|
+
}
|
|
2502
|
+
}
|
|
2503
|
+
function closeRight(node, depth) {
|
|
2504
|
+
if (depth == 0)
|
|
2505
|
+
return node;
|
|
2506
|
+
let fragment = node.content.replaceChild(node.childCount - 1, closeRight(node.lastChild, depth - 1));
|
|
2507
|
+
let fill = node.contentMatchAt(node.childCount).fillBefore(Fragment.empty, true);
|
|
2508
|
+
return node.copy(fragment.append(fill));
|
|
2509
|
+
}
|
|
2510
|
+
function closeRange(fragment, side, from, to, depth, openEnd) {
|
|
2511
|
+
let node = side < 0 ? fragment.firstChild : fragment.lastChild, inner = node.content;
|
|
2512
|
+
if (fragment.childCount > 1)
|
|
2513
|
+
openEnd = 0;
|
|
2514
|
+
if (depth < to - 1)
|
|
2515
|
+
inner = closeRange(inner, side, from, to, depth + 1, openEnd);
|
|
2516
|
+
if (depth >= from)
|
|
2517
|
+
inner = side < 0 ? node.contentMatchAt(0).fillBefore(inner, openEnd <= depth).append(inner) : inner.append(node.contentMatchAt(node.childCount).fillBefore(Fragment.empty, true));
|
|
2518
|
+
return fragment.replaceChild(side < 0 ? 0 : fragment.childCount - 1, node.copy(inner));
|
|
2519
|
+
}
|
|
2520
|
+
function closeSlice(slice, openStart, openEnd) {
|
|
2521
|
+
if (openStart < slice.openStart)
|
|
2522
|
+
slice = new Slice(closeRange(slice.content, -1, openStart, slice.openStart, 0, slice.openEnd), openStart, slice.openEnd);
|
|
2523
|
+
if (openEnd < slice.openEnd)
|
|
2524
|
+
slice = new Slice(closeRange(slice.content, 1, openEnd, slice.openEnd, 0, 0), slice.openStart, openEnd);
|
|
2525
|
+
return slice;
|
|
2526
|
+
}
|
|
2527
|
+
var wrapMap = {
|
|
2528
|
+
thead: ["table"],
|
|
2529
|
+
tbody: ["table"],
|
|
2530
|
+
tfoot: ["table"],
|
|
2531
|
+
caption: ["table"],
|
|
2532
|
+
colgroup: ["table"],
|
|
2533
|
+
col: ["table", "colgroup"],
|
|
2534
|
+
tr: ["table", "tbody"],
|
|
2535
|
+
td: ["table", "tbody", "tr"],
|
|
2536
|
+
th: ["table", "tbody", "tr"]
|
|
2537
|
+
};
|
|
2538
|
+
var _detachedDoc = null;
|
|
2539
|
+
function detachedDoc() {
|
|
2540
|
+
return _detachedDoc || (_detachedDoc = document.implementation.createHTMLDocument("title"));
|
|
2541
|
+
}
|
|
2542
|
+
function readHTML(html) {
|
|
2543
|
+
let metas = /^(\s*<meta [^>]*>)*/.exec(html);
|
|
2544
|
+
if (metas)
|
|
2545
|
+
html = html.slice(metas[0].length);
|
|
2546
|
+
let elt = detachedDoc().createElement("div");
|
|
2547
|
+
let firstTag = /<([a-z][^>\s]+)/i.exec(html), wrap;
|
|
2548
|
+
if (wrap = firstTag && wrapMap[firstTag[1].toLowerCase()])
|
|
2549
|
+
html = wrap.map((n) => "<" + n + ">").join("") + html + wrap.map((n) => "</" + n + ">").reverse().join("");
|
|
2550
|
+
elt.innerHTML = html;
|
|
2551
|
+
if (wrap)
|
|
2552
|
+
for (let i = 0; i < wrap.length; i++)
|
|
2553
|
+
elt = elt.querySelector(wrap[i]) || elt;
|
|
2554
|
+
return elt;
|
|
2555
|
+
}
|
|
2556
|
+
function restoreReplacedSpaces(dom) {
|
|
2557
|
+
let nodes = dom.querySelectorAll(chrome ? "span:not([class]):not([style])" : "span.Apple-converted-space");
|
|
2558
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
2559
|
+
let node = nodes[i];
|
|
2560
|
+
if (node.childNodes.length == 1 && node.textContent == "\xA0" && node.parentNode)
|
|
2561
|
+
node.parentNode.replaceChild(dom.ownerDocument.createTextNode(" "), node);
|
|
2562
|
+
}
|
|
2563
|
+
}
|
|
2564
|
+
function addContext(slice, context) {
|
|
2565
|
+
if (!slice.size)
|
|
2566
|
+
return slice;
|
|
2567
|
+
let schema = slice.content.firstChild.type.schema, array;
|
|
2568
|
+
try {
|
|
2569
|
+
array = JSON.parse(context);
|
|
2570
|
+
} catch (e) {
|
|
2571
|
+
return slice;
|
|
2572
|
+
}
|
|
2573
|
+
let { content, openStart, openEnd } = slice;
|
|
2574
|
+
for (let i = array.length - 2; i >= 0; i -= 2) {
|
|
2575
|
+
let type = schema.nodes[array[i]];
|
|
2576
|
+
if (!type || type.hasRequiredAttrs())
|
|
2577
|
+
break;
|
|
2578
|
+
content = Fragment.from(type.create(array[i + 1], content));
|
|
2579
|
+
openStart++;
|
|
2580
|
+
openEnd++;
|
|
2581
|
+
}
|
|
2582
|
+
return new Slice(content, openStart, openEnd);
|
|
2583
|
+
}
|
|
2584
|
+
var handlers = {};
|
|
2585
|
+
var editHandlers = {};
|
|
2586
|
+
var passiveHandlers = { touchstart: true, touchmove: true };
|
|
2587
|
+
var InputState = class {
|
|
2588
|
+
constructor() {
|
|
2589
|
+
this.shiftKey = false;
|
|
2590
|
+
this.mouseDown = null;
|
|
2591
|
+
this.lastKeyCode = null;
|
|
2592
|
+
this.lastKeyCodeTime = 0;
|
|
2593
|
+
this.lastClick = { time: 0, x: 0, y: 0, type: "" };
|
|
2594
|
+
this.lastSelectionOrigin = null;
|
|
2595
|
+
this.lastSelectionTime = 0;
|
|
2596
|
+
this.lastIOSEnter = 0;
|
|
2597
|
+
this.lastIOSEnterFallbackTimeout = -1;
|
|
2598
|
+
this.lastFocus = 0;
|
|
2599
|
+
this.lastTouch = 0;
|
|
2600
|
+
this.lastAndroidDelete = 0;
|
|
2601
|
+
this.composing = false;
|
|
2602
|
+
this.composingTimeout = -1;
|
|
2603
|
+
this.compositionNodes = [];
|
|
2604
|
+
this.compositionEndedAt = -2e8;
|
|
2605
|
+
this.compositionID = 1;
|
|
2606
|
+
this.domChangeCount = 0;
|
|
2607
|
+
this.eventHandlers = /* @__PURE__ */ Object.create(null);
|
|
2608
|
+
this.hideSelectionGuard = null;
|
|
2609
|
+
}
|
|
2610
|
+
};
|
|
2611
|
+
function initInput(view) {
|
|
2612
|
+
for (let event in handlers) {
|
|
2613
|
+
let handler = handlers[event];
|
|
2614
|
+
view.dom.addEventListener(event, view.input.eventHandlers[event] = (event2) => {
|
|
2615
|
+
if (eventBelongsToView(view, event2) && !runCustomHandler(view, event2) && (view.editable || !(event2.type in editHandlers)))
|
|
2616
|
+
handler(view, event2);
|
|
2617
|
+
}, passiveHandlers[event] ? { passive: true } : void 0);
|
|
2618
|
+
}
|
|
2619
|
+
if (safari)
|
|
2620
|
+
view.dom.addEventListener("input", () => null);
|
|
2621
|
+
ensureListeners(view);
|
|
2622
|
+
}
|
|
2623
|
+
function setSelectionOrigin(view, origin) {
|
|
2624
|
+
view.input.lastSelectionOrigin = origin;
|
|
2625
|
+
view.input.lastSelectionTime = Date.now();
|
|
2626
|
+
}
|
|
2627
|
+
function destroyInput(view) {
|
|
2628
|
+
view.domObserver.stop();
|
|
2629
|
+
for (let type in view.input.eventHandlers)
|
|
2630
|
+
view.dom.removeEventListener(type, view.input.eventHandlers[type]);
|
|
2631
|
+
clearTimeout(view.input.composingTimeout);
|
|
2632
|
+
clearTimeout(view.input.lastIOSEnterFallbackTimeout);
|
|
2633
|
+
}
|
|
2634
|
+
function ensureListeners(view) {
|
|
2635
|
+
view.someProp("handleDOMEvents", (currentHandlers) => {
|
|
2636
|
+
for (let type in currentHandlers)
|
|
2637
|
+
if (!view.input.eventHandlers[type])
|
|
2638
|
+
view.dom.addEventListener(type, view.input.eventHandlers[type] = (event) => runCustomHandler(view, event));
|
|
2639
|
+
});
|
|
2640
|
+
}
|
|
2641
|
+
function runCustomHandler(view, event) {
|
|
2642
|
+
return view.someProp("handleDOMEvents", (handlers2) => {
|
|
2643
|
+
let handler = handlers2[event.type];
|
|
2644
|
+
return handler ? handler(view, event) || event.defaultPrevented : false;
|
|
2645
|
+
});
|
|
2646
|
+
}
|
|
2647
|
+
function eventBelongsToView(view, event) {
|
|
2648
|
+
if (!event.bubbles)
|
|
2649
|
+
return true;
|
|
2650
|
+
if (event.defaultPrevented)
|
|
2651
|
+
return false;
|
|
2652
|
+
for (let node = event.target; node != view.dom; node = node.parentNode)
|
|
2653
|
+
if (!node || node.nodeType == 11 || node.pmViewDesc && node.pmViewDesc.stopEvent(event))
|
|
2654
|
+
return false;
|
|
2655
|
+
return true;
|
|
2656
|
+
}
|
|
2657
|
+
function dispatchEvent(view, event) {
|
|
2658
|
+
if (!runCustomHandler(view, event) && handlers[event.type] && (view.editable || !(event.type in editHandlers)))
|
|
2659
|
+
handlers[event.type](view, event);
|
|
2660
|
+
}
|
|
2661
|
+
editHandlers.keydown = (view, _event) => {
|
|
2662
|
+
let event = _event;
|
|
2663
|
+
view.input.shiftKey = event.keyCode == 16 || event.shiftKey;
|
|
2664
|
+
if (inOrNearComposition(view, event))
|
|
2665
|
+
return;
|
|
2666
|
+
view.input.lastKeyCode = event.keyCode;
|
|
2667
|
+
view.input.lastKeyCodeTime = Date.now();
|
|
2668
|
+
if (android && chrome && event.keyCode == 13)
|
|
2669
|
+
return;
|
|
2670
|
+
if (event.keyCode != 229)
|
|
2671
|
+
view.domObserver.forceFlush();
|
|
2672
|
+
if (ios && event.keyCode == 13 && !event.ctrlKey && !event.altKey && !event.metaKey) {
|
|
2673
|
+
let now = Date.now();
|
|
2674
|
+
view.input.lastIOSEnter = now;
|
|
2675
|
+
view.input.lastIOSEnterFallbackTimeout = setTimeout(() => {
|
|
2676
|
+
if (view.input.lastIOSEnter == now) {
|
|
2677
|
+
view.someProp("handleKeyDown", (f) => f(view, keyEvent(13, "Enter")));
|
|
2678
|
+
view.input.lastIOSEnter = 0;
|
|
2679
|
+
}
|
|
2680
|
+
}, 200);
|
|
2681
|
+
} else if (view.someProp("handleKeyDown", (f) => f(view, event)) || captureKeyDown(view, event)) {
|
|
2682
|
+
event.preventDefault();
|
|
2683
|
+
} else {
|
|
2684
|
+
setSelectionOrigin(view, "key");
|
|
2685
|
+
}
|
|
2686
|
+
};
|
|
2687
|
+
editHandlers.keyup = (view, event) => {
|
|
2688
|
+
if (event.keyCode == 16)
|
|
2689
|
+
view.input.shiftKey = false;
|
|
2690
|
+
};
|
|
2691
|
+
editHandlers.keypress = (view, _event) => {
|
|
2692
|
+
let event = _event;
|
|
2693
|
+
if (inOrNearComposition(view, event) || !event.charCode || event.ctrlKey && !event.altKey || mac && event.metaKey)
|
|
2694
|
+
return;
|
|
2695
|
+
if (view.someProp("handleKeyPress", (f) => f(view, event))) {
|
|
2696
|
+
event.preventDefault();
|
|
2697
|
+
return;
|
|
2698
|
+
}
|
|
2699
|
+
let sel = view.state.selection;
|
|
2700
|
+
if (!(sel instanceof TextSelection) || !sel.$from.sameParent(sel.$to)) {
|
|
2701
|
+
let text = String.fromCharCode(event.charCode);
|
|
2702
|
+
if (!/[\r\n]/.test(text) && !view.someProp("handleTextInput", (f) => f(view, sel.$from.pos, sel.$to.pos, text)))
|
|
2703
|
+
view.dispatch(view.state.tr.insertText(text).scrollIntoView());
|
|
2704
|
+
event.preventDefault();
|
|
2705
|
+
}
|
|
2706
|
+
};
|
|
2707
|
+
function eventCoords(event) {
|
|
2708
|
+
return { left: event.clientX, top: event.clientY };
|
|
2709
|
+
}
|
|
2710
|
+
function isNear(event, click) {
|
|
2711
|
+
let dx = click.x - event.clientX, dy = click.y - event.clientY;
|
|
2712
|
+
return dx * dx + dy * dy < 100;
|
|
2713
|
+
}
|
|
2714
|
+
function runHandlerOnContext(view, propName, pos, inside, event) {
|
|
2715
|
+
if (inside == -1)
|
|
2716
|
+
return false;
|
|
2717
|
+
let $pos = view.state.doc.resolve(inside);
|
|
2718
|
+
for (let i = $pos.depth + 1; i > 0; i--) {
|
|
2719
|
+
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)))
|
|
2720
|
+
return true;
|
|
2721
|
+
}
|
|
2722
|
+
return false;
|
|
2723
|
+
}
|
|
2724
|
+
function updateSelection(view, selection, origin) {
|
|
2725
|
+
if (!view.focused)
|
|
2726
|
+
view.focus();
|
|
2727
|
+
let tr = view.state.tr.setSelection(selection);
|
|
2728
|
+
if (origin == "pointer")
|
|
2729
|
+
tr.setMeta("pointer", true);
|
|
2730
|
+
view.dispatch(tr);
|
|
2731
|
+
}
|
|
2732
|
+
function selectClickedLeaf(view, inside) {
|
|
2733
|
+
if (inside == -1)
|
|
2734
|
+
return false;
|
|
2735
|
+
let $pos = view.state.doc.resolve(inside), node = $pos.nodeAfter;
|
|
2736
|
+
if (node && node.isAtom && NodeSelection.isSelectable(node)) {
|
|
2737
|
+
updateSelection(view, new NodeSelection($pos), "pointer");
|
|
2738
|
+
return true;
|
|
2739
|
+
}
|
|
2740
|
+
return false;
|
|
2741
|
+
}
|
|
2742
|
+
function selectClickedNode(view, inside) {
|
|
2743
|
+
if (inside == -1)
|
|
2744
|
+
return false;
|
|
2745
|
+
let sel = view.state.selection, selectedNode, selectAt;
|
|
2746
|
+
if (sel instanceof NodeSelection)
|
|
2747
|
+
selectedNode = sel.node;
|
|
2748
|
+
let $pos = view.state.doc.resolve(inside);
|
|
2749
|
+
for (let i = $pos.depth + 1; i > 0; i--) {
|
|
2750
|
+
let node = i > $pos.depth ? $pos.nodeAfter : $pos.node(i);
|
|
2751
|
+
if (NodeSelection.isSelectable(node)) {
|
|
2752
|
+
if (selectedNode && sel.$from.depth > 0 && i >= sel.$from.depth && $pos.before(sel.$from.depth + 1) == sel.$from.pos)
|
|
2753
|
+
selectAt = $pos.before(sel.$from.depth);
|
|
2754
|
+
else
|
|
2755
|
+
selectAt = $pos.before(i);
|
|
2756
|
+
break;
|
|
2757
|
+
}
|
|
2758
|
+
}
|
|
2759
|
+
if (selectAt != null) {
|
|
2760
|
+
updateSelection(view, NodeSelection.create(view.state.doc, selectAt), "pointer");
|
|
2761
|
+
return true;
|
|
2762
|
+
} else {
|
|
2763
|
+
return false;
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
2766
|
+
function handleSingleClick(view, pos, inside, event, selectNode) {
|
|
2767
|
+
return runHandlerOnContext(view, "handleClickOn", pos, inside, event) || view.someProp("handleClick", (f) => f(view, pos, event)) || (selectNode ? selectClickedNode(view, inside) : selectClickedLeaf(view, inside));
|
|
2768
|
+
}
|
|
2769
|
+
function handleDoubleClick(view, pos, inside, event) {
|
|
2770
|
+
return runHandlerOnContext(view, "handleDoubleClickOn", pos, inside, event) || view.someProp("handleDoubleClick", (f) => f(view, pos, event));
|
|
2771
|
+
}
|
|
2772
|
+
function handleTripleClick(view, pos, inside, event) {
|
|
2773
|
+
return runHandlerOnContext(view, "handleTripleClickOn", pos, inside, event) || view.someProp("handleTripleClick", (f) => f(view, pos, event)) || defaultTripleClick(view, inside, event);
|
|
2774
|
+
}
|
|
2775
|
+
function defaultTripleClick(view, inside, event) {
|
|
2776
|
+
if (event.button != 0)
|
|
2777
|
+
return false;
|
|
2778
|
+
let doc2 = view.state.doc;
|
|
2779
|
+
if (inside == -1) {
|
|
2780
|
+
if (doc2.inlineContent) {
|
|
2781
|
+
updateSelection(view, TextSelection.create(doc2, 0, doc2.content.size), "pointer");
|
|
2782
|
+
return true;
|
|
2783
|
+
}
|
|
2784
|
+
return false;
|
|
2785
|
+
}
|
|
2786
|
+
let $pos = doc2.resolve(inside);
|
|
2787
|
+
for (let i = $pos.depth + 1; i > 0; i--) {
|
|
2788
|
+
let node = i > $pos.depth ? $pos.nodeAfter : $pos.node(i);
|
|
2789
|
+
let nodePos = $pos.before(i);
|
|
2790
|
+
if (node.inlineContent)
|
|
2791
|
+
updateSelection(view, TextSelection.create(doc2, nodePos + 1, nodePos + 1 + node.content.size), "pointer");
|
|
2792
|
+
else if (NodeSelection.isSelectable(node))
|
|
2793
|
+
updateSelection(view, NodeSelection.create(doc2, nodePos), "pointer");
|
|
2794
|
+
else
|
|
2795
|
+
continue;
|
|
2796
|
+
return true;
|
|
2797
|
+
}
|
|
2798
|
+
}
|
|
2799
|
+
function forceDOMFlush(view) {
|
|
2800
|
+
return endComposition(view);
|
|
2801
|
+
}
|
|
2802
|
+
var selectNodeModifier = mac ? "metaKey" : "ctrlKey";
|
|
2803
|
+
handlers.mousedown = (view, _event) => {
|
|
2804
|
+
let event = _event;
|
|
2805
|
+
view.input.shiftKey = event.shiftKey;
|
|
2806
|
+
let flushed = forceDOMFlush(view);
|
|
2807
|
+
let now = Date.now(), type = "singleClick";
|
|
2808
|
+
if (now - view.input.lastClick.time < 500 && isNear(event, view.input.lastClick) && !event[selectNodeModifier]) {
|
|
2809
|
+
if (view.input.lastClick.type == "singleClick")
|
|
2810
|
+
type = "doubleClick";
|
|
2811
|
+
else if (view.input.lastClick.type == "doubleClick")
|
|
2812
|
+
type = "tripleClick";
|
|
2813
|
+
}
|
|
2814
|
+
view.input.lastClick = { time: now, x: event.clientX, y: event.clientY, type };
|
|
2815
|
+
let pos = view.posAtCoords(eventCoords(event));
|
|
2816
|
+
if (!pos)
|
|
2817
|
+
return;
|
|
2818
|
+
if (type == "singleClick") {
|
|
2819
|
+
if (view.input.mouseDown)
|
|
2820
|
+
view.input.mouseDown.done();
|
|
2821
|
+
view.input.mouseDown = new MouseDown(view, pos, event, !!flushed);
|
|
2822
|
+
} else if ((type == "doubleClick" ? handleDoubleClick : handleTripleClick)(view, pos.pos, pos.inside, event)) {
|
|
2823
|
+
event.preventDefault();
|
|
2824
|
+
} else {
|
|
2825
|
+
setSelectionOrigin(view, "pointer");
|
|
2826
|
+
}
|
|
2827
|
+
};
|
|
2828
|
+
var MouseDown = class {
|
|
2829
|
+
constructor(view, pos, event, flushed) {
|
|
2830
|
+
this.view = view;
|
|
2831
|
+
this.pos = pos;
|
|
2832
|
+
this.event = event;
|
|
2833
|
+
this.flushed = flushed;
|
|
2834
|
+
this.delayedSelectionSync = false;
|
|
2835
|
+
this.mightDrag = null;
|
|
2836
|
+
this.startDoc = view.state.doc;
|
|
2837
|
+
this.selectNode = !!event[selectNodeModifier];
|
|
2838
|
+
this.allowDefault = event.shiftKey;
|
|
2839
|
+
let targetNode, targetPos;
|
|
2840
|
+
if (pos.inside > -1) {
|
|
2841
|
+
targetNode = view.state.doc.nodeAt(pos.inside);
|
|
2842
|
+
targetPos = pos.inside;
|
|
2843
|
+
} else {
|
|
2844
|
+
let $pos = view.state.doc.resolve(pos.pos);
|
|
2845
|
+
targetNode = $pos.parent;
|
|
2846
|
+
targetPos = $pos.depth ? $pos.before() : 0;
|
|
2847
|
+
}
|
|
2848
|
+
const target = flushed ? null : event.target;
|
|
2849
|
+
const targetDesc = target ? view.docView.nearestDesc(target, true) : null;
|
|
2850
|
+
this.target = targetDesc ? targetDesc.dom : null;
|
|
2851
|
+
let { selection } = view.state;
|
|
2852
|
+
if (event.button == 0 && targetNode.type.spec.draggable && targetNode.type.spec.selectable !== false || selection instanceof NodeSelection && selection.from <= targetPos && selection.to > targetPos)
|
|
2853
|
+
this.mightDrag = {
|
|
2854
|
+
node: targetNode,
|
|
2855
|
+
pos: targetPos,
|
|
2856
|
+
addAttr: !!(this.target && !this.target.draggable),
|
|
2857
|
+
setUneditable: !!(this.target && gecko && !this.target.hasAttribute("contentEditable"))
|
|
2858
|
+
};
|
|
2859
|
+
if (this.target && this.mightDrag && (this.mightDrag.addAttr || this.mightDrag.setUneditable)) {
|
|
2860
|
+
this.view.domObserver.stop();
|
|
2861
|
+
if (this.mightDrag.addAttr)
|
|
2862
|
+
this.target.draggable = true;
|
|
2863
|
+
if (this.mightDrag.setUneditable)
|
|
2864
|
+
setTimeout(() => {
|
|
2865
|
+
if (this.view.input.mouseDown == this)
|
|
2866
|
+
this.target.setAttribute("contentEditable", "false");
|
|
2867
|
+
}, 20);
|
|
2868
|
+
this.view.domObserver.start();
|
|
2869
|
+
}
|
|
2870
|
+
view.root.addEventListener("mouseup", this.up = this.up.bind(this));
|
|
2871
|
+
view.root.addEventListener("mousemove", this.move = this.move.bind(this));
|
|
2872
|
+
setSelectionOrigin(view, "pointer");
|
|
2873
|
+
}
|
|
2874
|
+
done() {
|
|
2875
|
+
this.view.root.removeEventListener("mouseup", this.up);
|
|
2876
|
+
this.view.root.removeEventListener("mousemove", this.move);
|
|
2877
|
+
if (this.mightDrag && this.target) {
|
|
2878
|
+
this.view.domObserver.stop();
|
|
2879
|
+
if (this.mightDrag.addAttr)
|
|
2880
|
+
this.target.removeAttribute("draggable");
|
|
2881
|
+
if (this.mightDrag.setUneditable)
|
|
2882
|
+
this.target.removeAttribute("contentEditable");
|
|
2883
|
+
this.view.domObserver.start();
|
|
2884
|
+
}
|
|
2885
|
+
if (this.delayedSelectionSync)
|
|
2886
|
+
setTimeout(() => selectionToDOM(this.view));
|
|
2887
|
+
this.view.input.mouseDown = null;
|
|
2888
|
+
}
|
|
2889
|
+
up(event) {
|
|
2890
|
+
this.done();
|
|
2891
|
+
if (!this.view.dom.contains(event.target))
|
|
2892
|
+
return;
|
|
2893
|
+
let pos = this.pos;
|
|
2894
|
+
if (this.view.state.doc != this.startDoc)
|
|
2895
|
+
pos = this.view.posAtCoords(eventCoords(event));
|
|
2896
|
+
this.updateAllowDefault(event);
|
|
2897
|
+
if (this.allowDefault || !pos) {
|
|
2898
|
+
setSelectionOrigin(this.view, "pointer");
|
|
2899
|
+
} else if (handleSingleClick(this.view, pos.pos, pos.inside, event, this.selectNode)) {
|
|
2900
|
+
event.preventDefault();
|
|
2901
|
+
} else if (event.button == 0 && (this.flushed || // Safari ignores clicks on draggable elements
|
|
2902
|
+
safari && this.mightDrag && !this.mightDrag.node.isAtom || // Chrome will sometimes treat a node selection as a
|
|
2903
|
+
// cursor, but still report that the node is selected
|
|
2904
|
+
// when asked through getSelection. You'll then get a
|
|
2905
|
+
// situation where clicking at the point where that
|
|
2906
|
+
// (hidden) cursor is doesn't change the selection, and
|
|
2907
|
+
// thus doesn't get a reaction from ProseMirror. This
|
|
2908
|
+
// works around that.
|
|
2909
|
+
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)) {
|
|
2910
|
+
updateSelection(this.view, Selection.near(this.view.state.doc.resolve(pos.pos)), "pointer");
|
|
2911
|
+
event.preventDefault();
|
|
2912
|
+
} else {
|
|
2913
|
+
setSelectionOrigin(this.view, "pointer");
|
|
2914
|
+
}
|
|
2915
|
+
}
|
|
2916
|
+
move(event) {
|
|
2917
|
+
this.updateAllowDefault(event);
|
|
2918
|
+
setSelectionOrigin(this.view, "pointer");
|
|
2919
|
+
if (event.buttons == 0)
|
|
2920
|
+
this.done();
|
|
2921
|
+
}
|
|
2922
|
+
updateAllowDefault(event) {
|
|
2923
|
+
if (!this.allowDefault && (Math.abs(this.event.x - event.clientX) > 4 || Math.abs(this.event.y - event.clientY) > 4))
|
|
2924
|
+
this.allowDefault = true;
|
|
2925
|
+
}
|
|
2926
|
+
};
|
|
2927
|
+
handlers.touchstart = (view) => {
|
|
2928
|
+
view.input.lastTouch = Date.now();
|
|
2929
|
+
forceDOMFlush(view);
|
|
2930
|
+
setSelectionOrigin(view, "pointer");
|
|
2931
|
+
};
|
|
2932
|
+
handlers.touchmove = (view) => {
|
|
2933
|
+
view.input.lastTouch = Date.now();
|
|
2934
|
+
setSelectionOrigin(view, "pointer");
|
|
2935
|
+
};
|
|
2936
|
+
handlers.contextmenu = (view) => forceDOMFlush(view);
|
|
2937
|
+
function inOrNearComposition(view, event) {
|
|
2938
|
+
if (view.composing)
|
|
2939
|
+
return true;
|
|
2940
|
+
if (safari && Math.abs(event.timeStamp - view.input.compositionEndedAt) < 500) {
|
|
2941
|
+
view.input.compositionEndedAt = -2e8;
|
|
2942
|
+
return true;
|
|
2943
|
+
}
|
|
2944
|
+
return false;
|
|
2945
|
+
}
|
|
2946
|
+
var timeoutComposition = android ? 5e3 : -1;
|
|
2947
|
+
editHandlers.compositionstart = editHandlers.compositionupdate = (view) => {
|
|
2948
|
+
if (!view.composing) {
|
|
2949
|
+
view.domObserver.flush();
|
|
2950
|
+
let { state } = view, $pos = state.selection.$from;
|
|
2951
|
+
if (state.selection.empty && (state.storedMarks || !$pos.textOffset && $pos.parentOffset && $pos.nodeBefore.marks.some((m) => m.type.spec.inclusive === false))) {
|
|
2952
|
+
view.markCursor = view.state.storedMarks || $pos.marks();
|
|
2953
|
+
endComposition(view, true);
|
|
2954
|
+
view.markCursor = null;
|
|
2955
|
+
} else {
|
|
2956
|
+
endComposition(view);
|
|
2957
|
+
if (gecko && state.selection.empty && $pos.parentOffset && !$pos.textOffset && $pos.nodeBefore.marks.length) {
|
|
2958
|
+
let sel = view.domSelectionRange();
|
|
2959
|
+
for (let node = sel.focusNode, offset = sel.focusOffset; node && node.nodeType == 1 && offset != 0; ) {
|
|
2960
|
+
let before = offset < 0 ? node.lastChild : node.childNodes[offset - 1];
|
|
2961
|
+
if (!before)
|
|
2962
|
+
break;
|
|
2963
|
+
if (before.nodeType == 3) {
|
|
2964
|
+
view.domSelection().collapse(before, before.nodeValue.length);
|
|
2965
|
+
break;
|
|
2966
|
+
} else {
|
|
2967
|
+
node = before;
|
|
2968
|
+
offset = -1;
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2971
|
+
}
|
|
2972
|
+
}
|
|
2973
|
+
view.input.composing = true;
|
|
2974
|
+
}
|
|
2975
|
+
scheduleComposeEnd(view, timeoutComposition);
|
|
2976
|
+
};
|
|
2977
|
+
editHandlers.compositionend = (view, event) => {
|
|
2978
|
+
if (view.composing) {
|
|
2979
|
+
view.input.composing = false;
|
|
2980
|
+
view.input.compositionEndedAt = event.timeStamp;
|
|
2981
|
+
view.input.compositionID++;
|
|
2982
|
+
scheduleComposeEnd(view, 20);
|
|
2983
|
+
}
|
|
2984
|
+
};
|
|
2985
|
+
function scheduleComposeEnd(view, delay) {
|
|
2986
|
+
clearTimeout(view.input.composingTimeout);
|
|
2987
|
+
if (delay > -1)
|
|
2988
|
+
view.input.composingTimeout = setTimeout(() => endComposition(view), delay);
|
|
2989
|
+
}
|
|
2990
|
+
function clearComposition(view) {
|
|
2991
|
+
if (view.composing) {
|
|
2992
|
+
view.input.composing = false;
|
|
2993
|
+
view.input.compositionEndedAt = timestampFromCustomEvent();
|
|
2994
|
+
}
|
|
2995
|
+
while (view.input.compositionNodes.length > 0)
|
|
2996
|
+
view.input.compositionNodes.pop().markParentsDirty();
|
|
2997
|
+
}
|
|
2998
|
+
function timestampFromCustomEvent() {
|
|
2999
|
+
let event = document.createEvent("Event");
|
|
3000
|
+
event.initEvent("event", true, true);
|
|
3001
|
+
return event.timeStamp;
|
|
3002
|
+
}
|
|
3003
|
+
function endComposition(view, forceUpdate = false) {
|
|
3004
|
+
if (android && view.domObserver.flushingSoon >= 0)
|
|
3005
|
+
return;
|
|
3006
|
+
view.domObserver.forceFlush();
|
|
3007
|
+
clearComposition(view);
|
|
3008
|
+
if (forceUpdate || view.docView && view.docView.dirty) {
|
|
3009
|
+
let sel = selectionFromDOM(view);
|
|
3010
|
+
if (sel && !sel.eq(view.state.selection))
|
|
3011
|
+
view.dispatch(view.state.tr.setSelection(sel));
|
|
3012
|
+
else
|
|
3013
|
+
view.updateState(view.state);
|
|
3014
|
+
return true;
|
|
3015
|
+
}
|
|
3016
|
+
return false;
|
|
3017
|
+
}
|
|
3018
|
+
function captureCopy(view, dom) {
|
|
3019
|
+
if (!view.dom.parentNode)
|
|
3020
|
+
return;
|
|
3021
|
+
let wrap = view.dom.parentNode.appendChild(document.createElement("div"));
|
|
3022
|
+
wrap.appendChild(dom);
|
|
3023
|
+
wrap.style.cssText = "position: fixed; left: -10000px; top: 10px";
|
|
3024
|
+
let sel = getSelection(), range = document.createRange();
|
|
3025
|
+
range.selectNodeContents(dom);
|
|
3026
|
+
view.dom.blur();
|
|
3027
|
+
sel.removeAllRanges();
|
|
3028
|
+
sel.addRange(range);
|
|
3029
|
+
setTimeout(() => {
|
|
3030
|
+
if (wrap.parentNode)
|
|
3031
|
+
wrap.parentNode.removeChild(wrap);
|
|
3032
|
+
view.focus();
|
|
3033
|
+
}, 50);
|
|
3034
|
+
}
|
|
3035
|
+
var brokenClipboardAPI = ie && ie_version < 15 || ios && webkit_version < 604;
|
|
3036
|
+
handlers.copy = editHandlers.cut = (view, _event) => {
|
|
3037
|
+
let event = _event;
|
|
3038
|
+
let sel = view.state.selection, cut = event.type == "cut";
|
|
3039
|
+
if (sel.empty)
|
|
3040
|
+
return;
|
|
3041
|
+
let data = brokenClipboardAPI ? null : event.clipboardData;
|
|
3042
|
+
let slice = sel.content(), { dom, text } = serializeForClipboard(view, slice);
|
|
3043
|
+
if (data) {
|
|
3044
|
+
event.preventDefault();
|
|
3045
|
+
data.clearData();
|
|
3046
|
+
data.setData("text/html", dom.innerHTML);
|
|
3047
|
+
data.setData("text/plain", text);
|
|
3048
|
+
} else {
|
|
3049
|
+
captureCopy(view, dom);
|
|
3050
|
+
}
|
|
3051
|
+
if (cut)
|
|
3052
|
+
view.dispatch(view.state.tr.deleteSelection().scrollIntoView().setMeta("uiEvent", "cut"));
|
|
3053
|
+
};
|
|
3054
|
+
function sliceSingleNode(slice) {
|
|
3055
|
+
return slice.openStart == 0 && slice.openEnd == 0 && slice.content.childCount == 1 ? slice.content.firstChild : null;
|
|
3056
|
+
}
|
|
3057
|
+
function capturePaste(view, event) {
|
|
3058
|
+
if (!view.dom.parentNode)
|
|
3059
|
+
return;
|
|
3060
|
+
let plainText = view.input.shiftKey || view.state.selection.$from.parent.type.spec.code;
|
|
3061
|
+
let target = view.dom.parentNode.appendChild(document.createElement(plainText ? "textarea" : "div"));
|
|
3062
|
+
if (!plainText)
|
|
3063
|
+
target.contentEditable = "true";
|
|
3064
|
+
target.style.cssText = "position: fixed; left: -10000px; top: 10px";
|
|
3065
|
+
target.focus();
|
|
3066
|
+
let plain = view.input.shiftKey && view.input.lastKeyCode != 45;
|
|
3067
|
+
setTimeout(() => {
|
|
3068
|
+
view.focus();
|
|
3069
|
+
if (target.parentNode)
|
|
3070
|
+
target.parentNode.removeChild(target);
|
|
3071
|
+
if (plainText)
|
|
3072
|
+
doPaste(view, target.value, null, plain, event);
|
|
3073
|
+
else
|
|
3074
|
+
doPaste(view, target.textContent, target.innerHTML, plain, event);
|
|
3075
|
+
}, 50);
|
|
3076
|
+
}
|
|
3077
|
+
function doPaste(view, text, html, preferPlain, event) {
|
|
3078
|
+
let slice = parseFromClipboard(view, text, html, preferPlain, view.state.selection.$from);
|
|
3079
|
+
if (view.someProp("handlePaste", (f) => f(view, event, slice || Slice.empty)))
|
|
3080
|
+
return true;
|
|
3081
|
+
if (!slice)
|
|
3082
|
+
return false;
|
|
3083
|
+
let singleNode = sliceSingleNode(slice);
|
|
3084
|
+
let tr = singleNode ? view.state.tr.replaceSelectionWith(singleNode, preferPlain) : view.state.tr.replaceSelection(slice);
|
|
3085
|
+
view.dispatch(tr.scrollIntoView().setMeta("paste", true).setMeta("uiEvent", "paste"));
|
|
3086
|
+
return true;
|
|
3087
|
+
}
|
|
3088
|
+
editHandlers.paste = (view, _event) => {
|
|
3089
|
+
let event = _event;
|
|
3090
|
+
if (view.composing && !android)
|
|
3091
|
+
return;
|
|
3092
|
+
let data = brokenClipboardAPI ? null : event.clipboardData;
|
|
3093
|
+
let plain = view.input.shiftKey && view.input.lastKeyCode != 45;
|
|
3094
|
+
if (data && doPaste(view, data.getData("text/plain"), data.getData("text/html"), plain, event))
|
|
3095
|
+
event.preventDefault();
|
|
3096
|
+
else
|
|
3097
|
+
capturePaste(view, event);
|
|
3098
|
+
};
|
|
3099
|
+
var Dragging = class {
|
|
3100
|
+
constructor(slice, move) {
|
|
3101
|
+
this.slice = slice;
|
|
3102
|
+
this.move = move;
|
|
3103
|
+
}
|
|
3104
|
+
};
|
|
3105
|
+
var dragCopyModifier = mac ? "altKey" : "ctrlKey";
|
|
3106
|
+
handlers.dragstart = (view, _event) => {
|
|
3107
|
+
let event = _event;
|
|
3108
|
+
let mouseDown = view.input.mouseDown;
|
|
3109
|
+
if (mouseDown)
|
|
3110
|
+
mouseDown.done();
|
|
3111
|
+
if (!event.dataTransfer)
|
|
3112
|
+
return;
|
|
3113
|
+
let sel = view.state.selection;
|
|
3114
|
+
let pos = sel.empty ? null : view.posAtCoords(eventCoords(event));
|
|
3115
|
+
if (pos && pos.pos >= sel.from && pos.pos <= (sel instanceof NodeSelection ? sel.to - 1 : sel.to))
|
|
3116
|
+
;
|
|
3117
|
+
else if (mouseDown && mouseDown.mightDrag) {
|
|
3118
|
+
view.dispatch(view.state.tr.setSelection(NodeSelection.create(view.state.doc, mouseDown.mightDrag.pos)));
|
|
3119
|
+
} else if (event.target && event.target.nodeType == 1) {
|
|
3120
|
+
let desc = view.docView.nearestDesc(event.target, true);
|
|
3121
|
+
if (desc && desc.node.type.spec.draggable && desc != view.docView)
|
|
3122
|
+
view.dispatch(view.state.tr.setSelection(NodeSelection.create(view.state.doc, desc.posBefore)));
|
|
3123
|
+
}
|
|
3124
|
+
let slice = view.state.selection.content(), { dom, text } = serializeForClipboard(view, slice);
|
|
3125
|
+
event.dataTransfer.clearData();
|
|
3126
|
+
event.dataTransfer.setData(brokenClipboardAPI ? "Text" : "text/html", dom.innerHTML);
|
|
3127
|
+
event.dataTransfer.effectAllowed = "copyMove";
|
|
3128
|
+
if (!brokenClipboardAPI)
|
|
3129
|
+
event.dataTransfer.setData("text/plain", text);
|
|
3130
|
+
view.dragging = new Dragging(slice, !event[dragCopyModifier]);
|
|
3131
|
+
};
|
|
3132
|
+
handlers.dragend = (view) => {
|
|
3133
|
+
let dragging = view.dragging;
|
|
3134
|
+
window.setTimeout(() => {
|
|
3135
|
+
if (view.dragging == dragging)
|
|
3136
|
+
view.dragging = null;
|
|
3137
|
+
}, 50);
|
|
3138
|
+
};
|
|
3139
|
+
editHandlers.dragover = editHandlers.dragenter = (_, e) => e.preventDefault();
|
|
3140
|
+
editHandlers.drop = (view, _event) => {
|
|
3141
|
+
let event = _event;
|
|
3142
|
+
let dragging = view.dragging;
|
|
3143
|
+
view.dragging = null;
|
|
3144
|
+
if (!event.dataTransfer)
|
|
3145
|
+
return;
|
|
3146
|
+
let eventPos = view.posAtCoords(eventCoords(event));
|
|
3147
|
+
if (!eventPos)
|
|
3148
|
+
return;
|
|
3149
|
+
let $mouse = view.state.doc.resolve(eventPos.pos);
|
|
3150
|
+
let slice = dragging && dragging.slice;
|
|
3151
|
+
if (slice) {
|
|
3152
|
+
view.someProp("transformPasted", (f) => {
|
|
3153
|
+
slice = f(slice, view);
|
|
3154
|
+
});
|
|
3155
|
+
} else {
|
|
3156
|
+
slice = parseFromClipboard(view, event.dataTransfer.getData(brokenClipboardAPI ? "Text" : "text/plain"), brokenClipboardAPI ? null : event.dataTransfer.getData("text/html"), false, $mouse);
|
|
3157
|
+
}
|
|
3158
|
+
let move = !!(dragging && !event[dragCopyModifier]);
|
|
3159
|
+
if (view.someProp("handleDrop", (f) => f(view, event, slice || Slice.empty, move))) {
|
|
3160
|
+
event.preventDefault();
|
|
3161
|
+
return;
|
|
3162
|
+
}
|
|
3163
|
+
if (!slice)
|
|
3164
|
+
return;
|
|
3165
|
+
event.preventDefault();
|
|
3166
|
+
let insertPos = slice ? dropPoint(view.state.doc, $mouse.pos, slice) : $mouse.pos;
|
|
3167
|
+
if (insertPos == null)
|
|
3168
|
+
insertPos = $mouse.pos;
|
|
3169
|
+
let tr = view.state.tr;
|
|
3170
|
+
if (move)
|
|
3171
|
+
tr.deleteSelection();
|
|
3172
|
+
let pos = tr.mapping.map(insertPos);
|
|
3173
|
+
let isNode = slice.openStart == 0 && slice.openEnd == 0 && slice.content.childCount == 1;
|
|
3174
|
+
let beforeInsert = tr.doc;
|
|
3175
|
+
if (isNode)
|
|
3176
|
+
tr.replaceRangeWith(pos, pos, slice.content.firstChild);
|
|
3177
|
+
else
|
|
3178
|
+
tr.replaceRange(pos, pos, slice);
|
|
3179
|
+
if (tr.doc.eq(beforeInsert))
|
|
3180
|
+
return;
|
|
3181
|
+
let $pos = tr.doc.resolve(pos);
|
|
3182
|
+
if (isNode && NodeSelection.isSelectable(slice.content.firstChild) && $pos.nodeAfter && $pos.nodeAfter.sameMarkup(slice.content.firstChild)) {
|
|
3183
|
+
tr.setSelection(new NodeSelection($pos));
|
|
3184
|
+
} else {
|
|
3185
|
+
let end = tr.mapping.map(insertPos);
|
|
3186
|
+
tr.mapping.maps[tr.mapping.maps.length - 1].forEach((_from, _to, _newFrom, newTo) => end = newTo);
|
|
3187
|
+
tr.setSelection(selectionBetween(view, $pos, tr.doc.resolve(end)));
|
|
3188
|
+
}
|
|
3189
|
+
view.focus();
|
|
3190
|
+
view.dispatch(tr.setMeta("uiEvent", "drop"));
|
|
3191
|
+
};
|
|
3192
|
+
handlers.focus = (view) => {
|
|
3193
|
+
view.input.lastFocus = Date.now();
|
|
3194
|
+
if (!view.focused) {
|
|
3195
|
+
view.domObserver.stop();
|
|
3196
|
+
view.dom.classList.add("ProseMirror-focused");
|
|
3197
|
+
view.domObserver.start();
|
|
3198
|
+
view.focused = true;
|
|
3199
|
+
setTimeout(() => {
|
|
3200
|
+
if (view.docView && view.hasFocus() && !view.domObserver.currentSelection.eq(view.domSelectionRange()))
|
|
3201
|
+
selectionToDOM(view);
|
|
3202
|
+
}, 20);
|
|
3203
|
+
}
|
|
3204
|
+
};
|
|
3205
|
+
handlers.blur = (view, _event) => {
|
|
3206
|
+
let event = _event;
|
|
3207
|
+
if (view.focused) {
|
|
3208
|
+
view.domObserver.stop();
|
|
3209
|
+
view.dom.classList.remove("ProseMirror-focused");
|
|
3210
|
+
view.domObserver.start();
|
|
3211
|
+
if (event.relatedTarget && view.dom.contains(event.relatedTarget))
|
|
3212
|
+
view.domObserver.currentSelection.clear();
|
|
3213
|
+
view.focused = false;
|
|
3214
|
+
}
|
|
3215
|
+
};
|
|
3216
|
+
handlers.beforeinput = (view, _event) => {
|
|
3217
|
+
let event = _event;
|
|
3218
|
+
if (chrome && android && event.inputType == "deleteContentBackward") {
|
|
3219
|
+
view.domObserver.flushSoon();
|
|
3220
|
+
let { domChangeCount } = view.input;
|
|
3221
|
+
setTimeout(() => {
|
|
3222
|
+
if (view.input.domChangeCount != domChangeCount)
|
|
3223
|
+
return;
|
|
3224
|
+
view.dom.blur();
|
|
3225
|
+
view.focus();
|
|
3226
|
+
if (view.someProp("handleKeyDown", (f) => f(view, keyEvent(8, "Backspace"))))
|
|
3227
|
+
return;
|
|
3228
|
+
let { $cursor } = view.state.selection;
|
|
3229
|
+
if ($cursor && $cursor.pos > 0)
|
|
3230
|
+
view.dispatch(view.state.tr.delete($cursor.pos - 1, $cursor.pos).scrollIntoView());
|
|
3231
|
+
}, 50);
|
|
3232
|
+
}
|
|
3233
|
+
};
|
|
3234
|
+
for (let prop in editHandlers)
|
|
3235
|
+
handlers[prop] = editHandlers[prop];
|
|
3236
|
+
function compareObjs(a, b) {
|
|
3237
|
+
if (a == b)
|
|
3238
|
+
return true;
|
|
3239
|
+
for (let p in a)
|
|
3240
|
+
if (a[p] !== b[p])
|
|
3241
|
+
return false;
|
|
3242
|
+
for (let p in b)
|
|
3243
|
+
if (!(p in a))
|
|
3244
|
+
return false;
|
|
3245
|
+
return true;
|
|
3246
|
+
}
|
|
3247
|
+
var WidgetType = class _WidgetType {
|
|
3248
|
+
constructor(toDOM, spec) {
|
|
3249
|
+
this.toDOM = toDOM;
|
|
3250
|
+
this.spec = spec || noSpec;
|
|
3251
|
+
this.side = this.spec.side || 0;
|
|
3252
|
+
}
|
|
3253
|
+
map(mapping, span, offset, oldOffset) {
|
|
3254
|
+
let { pos, deleted } = mapping.mapResult(span.from + oldOffset, this.side < 0 ? -1 : 1);
|
|
3255
|
+
return deleted ? null : new Decoration(pos - offset, pos - offset, this);
|
|
3256
|
+
}
|
|
3257
|
+
valid() {
|
|
3258
|
+
return true;
|
|
3259
|
+
}
|
|
3260
|
+
eq(other) {
|
|
3261
|
+
return this == other || other instanceof _WidgetType && (this.spec.key && this.spec.key == other.spec.key || this.toDOM == other.toDOM && compareObjs(this.spec, other.spec));
|
|
3262
|
+
}
|
|
3263
|
+
destroy(node) {
|
|
3264
|
+
if (this.spec.destroy)
|
|
3265
|
+
this.spec.destroy(node);
|
|
3266
|
+
}
|
|
3267
|
+
};
|
|
3268
|
+
var InlineType = class _InlineType {
|
|
3269
|
+
constructor(attrs, spec) {
|
|
3270
|
+
this.attrs = attrs;
|
|
3271
|
+
this.spec = spec || noSpec;
|
|
3272
|
+
}
|
|
3273
|
+
map(mapping, span, offset, oldOffset) {
|
|
3274
|
+
let from = mapping.map(span.from + oldOffset, this.spec.inclusiveStart ? -1 : 1) - offset;
|
|
3275
|
+
let to = mapping.map(span.to + oldOffset, this.spec.inclusiveEnd ? 1 : -1) - offset;
|
|
3276
|
+
return from >= to ? null : new Decoration(from, to, this);
|
|
3277
|
+
}
|
|
3278
|
+
valid(_, span) {
|
|
3279
|
+
return span.from < span.to;
|
|
3280
|
+
}
|
|
3281
|
+
eq(other) {
|
|
3282
|
+
return this == other || other instanceof _InlineType && compareObjs(this.attrs, other.attrs) && compareObjs(this.spec, other.spec);
|
|
3283
|
+
}
|
|
3284
|
+
static is(span) {
|
|
3285
|
+
return span.type instanceof _InlineType;
|
|
3286
|
+
}
|
|
3287
|
+
destroy() {
|
|
3288
|
+
}
|
|
3289
|
+
};
|
|
3290
|
+
var NodeType = class _NodeType {
|
|
3291
|
+
constructor(attrs, spec) {
|
|
3292
|
+
this.attrs = attrs;
|
|
3293
|
+
this.spec = spec || noSpec;
|
|
3294
|
+
}
|
|
3295
|
+
map(mapping, span, offset, oldOffset) {
|
|
3296
|
+
let from = mapping.mapResult(span.from + oldOffset, 1);
|
|
3297
|
+
if (from.deleted)
|
|
3298
|
+
return null;
|
|
3299
|
+
let to = mapping.mapResult(span.to + oldOffset, -1);
|
|
3300
|
+
if (to.deleted || to.pos <= from.pos)
|
|
3301
|
+
return null;
|
|
3302
|
+
return new Decoration(from.pos - offset, to.pos - offset, this);
|
|
3303
|
+
}
|
|
3304
|
+
valid(node, span) {
|
|
3305
|
+
let { index, offset } = node.content.findIndex(span.from), child;
|
|
3306
|
+
return offset == span.from && !(child = node.child(index)).isText && offset + child.nodeSize == span.to;
|
|
3307
|
+
}
|
|
3308
|
+
eq(other) {
|
|
3309
|
+
return this == other || other instanceof _NodeType && compareObjs(this.attrs, other.attrs) && compareObjs(this.spec, other.spec);
|
|
3310
|
+
}
|
|
3311
|
+
destroy() {
|
|
3312
|
+
}
|
|
3313
|
+
};
|
|
3314
|
+
var Decoration = class _Decoration {
|
|
3315
|
+
/**
|
|
3316
|
+
@internal
|
|
3317
|
+
*/
|
|
3318
|
+
constructor(from, to, type) {
|
|
3319
|
+
this.from = from;
|
|
3320
|
+
this.to = to;
|
|
3321
|
+
this.type = type;
|
|
3322
|
+
}
|
|
3323
|
+
/**
|
|
3324
|
+
@internal
|
|
3325
|
+
*/
|
|
3326
|
+
copy(from, to) {
|
|
3327
|
+
return new _Decoration(from, to, this.type);
|
|
3328
|
+
}
|
|
3329
|
+
/**
|
|
3330
|
+
@internal
|
|
3331
|
+
*/
|
|
3332
|
+
eq(other, offset = 0) {
|
|
3333
|
+
return this.type.eq(other.type) && this.from + offset == other.from && this.to + offset == other.to;
|
|
3334
|
+
}
|
|
3335
|
+
/**
|
|
3336
|
+
@internal
|
|
3337
|
+
*/
|
|
3338
|
+
map(mapping, offset, oldOffset) {
|
|
3339
|
+
return this.type.map(mapping, this, offset, oldOffset);
|
|
3340
|
+
}
|
|
3341
|
+
/**
|
|
3342
|
+
Creates a widget decoration, which is a DOM node that's shown in
|
|
3343
|
+
the document at the given position. It is recommended that you
|
|
3344
|
+
delay rendering the widget by passing a function that will be
|
|
3345
|
+
called when the widget is actually drawn in a view, but you can
|
|
3346
|
+
also directly pass a DOM node. `getPos` can be used to find the
|
|
3347
|
+
widget's current document position.
|
|
3348
|
+
*/
|
|
3349
|
+
static widget(pos, toDOM, spec) {
|
|
3350
|
+
return new _Decoration(pos, pos, new WidgetType(toDOM, spec));
|
|
3351
|
+
}
|
|
3352
|
+
/**
|
|
3353
|
+
Creates an inline decoration, which adds the given attributes to
|
|
3354
|
+
each inline node between `from` and `to`.
|
|
3355
|
+
*/
|
|
3356
|
+
static inline(from, to, attrs, spec) {
|
|
3357
|
+
return new _Decoration(from, to, new InlineType(attrs, spec));
|
|
3358
|
+
}
|
|
3359
|
+
/**
|
|
3360
|
+
Creates a node decoration. `from` and `to` should point precisely
|
|
3361
|
+
before and after a node in the document. That node, and only that
|
|
3362
|
+
node, will receive the given attributes.
|
|
3363
|
+
*/
|
|
3364
|
+
static node(from, to, attrs, spec) {
|
|
3365
|
+
return new _Decoration(from, to, new NodeType(attrs, spec));
|
|
3366
|
+
}
|
|
3367
|
+
/**
|
|
3368
|
+
The spec provided when creating this decoration. Can be useful
|
|
3369
|
+
if you've stored extra information in that object.
|
|
3370
|
+
*/
|
|
3371
|
+
get spec() {
|
|
3372
|
+
return this.type.spec;
|
|
3373
|
+
}
|
|
3374
|
+
/**
|
|
3375
|
+
@internal
|
|
3376
|
+
*/
|
|
3377
|
+
get inline() {
|
|
3378
|
+
return this.type instanceof InlineType;
|
|
3379
|
+
}
|
|
3380
|
+
};
|
|
3381
|
+
var none = [];
|
|
3382
|
+
var noSpec = {};
|
|
3383
|
+
var DecorationSet = class _DecorationSet {
|
|
3384
|
+
/**
|
|
3385
|
+
@internal
|
|
3386
|
+
*/
|
|
3387
|
+
constructor(local, children) {
|
|
3388
|
+
this.local = local.length ? local : none;
|
|
3389
|
+
this.children = children.length ? children : none;
|
|
3390
|
+
}
|
|
3391
|
+
/**
|
|
3392
|
+
Create a set of decorations, using the structure of the given
|
|
3393
|
+
document.
|
|
3394
|
+
*/
|
|
3395
|
+
static create(doc2, decorations) {
|
|
3396
|
+
return decorations.length ? buildTree(decorations, doc2, 0, noSpec) : empty;
|
|
3397
|
+
}
|
|
3398
|
+
/**
|
|
3399
|
+
Find all decorations in this set which touch the given range
|
|
3400
|
+
(including decorations that start or end directly at the
|
|
3401
|
+
boundaries) and match the given predicate on their spec. When
|
|
3402
|
+
`start` and `end` are omitted, all decorations in the set are
|
|
3403
|
+
considered. When `predicate` isn't given, all decorations are
|
|
3404
|
+
assumed to match.
|
|
3405
|
+
*/
|
|
3406
|
+
find(start, end, predicate) {
|
|
3407
|
+
let result = [];
|
|
3408
|
+
this.findInner(start == null ? 0 : start, end == null ? 1e9 : end, result, 0, predicate);
|
|
3409
|
+
return result;
|
|
3410
|
+
}
|
|
3411
|
+
findInner(start, end, result, offset, predicate) {
|
|
3412
|
+
for (let i = 0; i < this.local.length; i++) {
|
|
3413
|
+
let span = this.local[i];
|
|
3414
|
+
if (span.from <= end && span.to >= start && (!predicate || predicate(span.spec)))
|
|
3415
|
+
result.push(span.copy(span.from + offset, span.to + offset));
|
|
3416
|
+
}
|
|
3417
|
+
for (let i = 0; i < this.children.length; i += 3) {
|
|
3418
|
+
if (this.children[i] < end && this.children[i + 1] > start) {
|
|
3419
|
+
let childOff = this.children[i] + 1;
|
|
3420
|
+
this.children[i + 2].findInner(start - childOff, end - childOff, result, offset + childOff, predicate);
|
|
3421
|
+
}
|
|
3422
|
+
}
|
|
3423
|
+
}
|
|
3424
|
+
/**
|
|
3425
|
+
Map the set of decorations in response to a change in the
|
|
3426
|
+
document.
|
|
3427
|
+
*/
|
|
3428
|
+
map(mapping, doc2, options) {
|
|
3429
|
+
if (this == empty || mapping.maps.length == 0)
|
|
3430
|
+
return this;
|
|
3431
|
+
return this.mapInner(mapping, doc2, 0, 0, options || noSpec);
|
|
3432
|
+
}
|
|
3433
|
+
/**
|
|
3434
|
+
@internal
|
|
3435
|
+
*/
|
|
3436
|
+
mapInner(mapping, node, offset, oldOffset, options) {
|
|
3437
|
+
let newLocal;
|
|
3438
|
+
for (let i = 0; i < this.local.length; i++) {
|
|
3439
|
+
let mapped = this.local[i].map(mapping, offset, oldOffset);
|
|
3440
|
+
if (mapped && mapped.type.valid(node, mapped))
|
|
3441
|
+
(newLocal || (newLocal = [])).push(mapped);
|
|
3442
|
+
else if (options.onRemove)
|
|
3443
|
+
options.onRemove(this.local[i].spec);
|
|
3444
|
+
}
|
|
3445
|
+
if (this.children.length)
|
|
3446
|
+
return mapChildren(this.children, newLocal || [], mapping, node, offset, oldOffset, options);
|
|
3447
|
+
else
|
|
3448
|
+
return newLocal ? new _DecorationSet(newLocal.sort(byPos), none) : empty;
|
|
3449
|
+
}
|
|
3450
|
+
/**
|
|
3451
|
+
Add the given array of decorations to the ones in the set,
|
|
3452
|
+
producing a new set. Needs access to the current document to
|
|
3453
|
+
create the appropriate tree structure.
|
|
3454
|
+
*/
|
|
3455
|
+
add(doc2, decorations) {
|
|
3456
|
+
if (!decorations.length)
|
|
3457
|
+
return this;
|
|
3458
|
+
if (this == empty)
|
|
3459
|
+
return _DecorationSet.create(doc2, decorations);
|
|
3460
|
+
return this.addInner(doc2, decorations, 0);
|
|
3461
|
+
}
|
|
3462
|
+
addInner(doc2, decorations, offset) {
|
|
3463
|
+
let children, childIndex = 0;
|
|
3464
|
+
doc2.forEach((childNode, childOffset) => {
|
|
3465
|
+
let baseOffset = childOffset + offset, found;
|
|
3466
|
+
if (!(found = takeSpansForNode(decorations, childNode, baseOffset)))
|
|
3467
|
+
return;
|
|
3468
|
+
if (!children)
|
|
3469
|
+
children = this.children.slice();
|
|
3470
|
+
while (childIndex < children.length && children[childIndex] < childOffset)
|
|
3471
|
+
childIndex += 3;
|
|
3472
|
+
if (children[childIndex] == childOffset)
|
|
3473
|
+
children[childIndex + 2] = children[childIndex + 2].addInner(childNode, found, baseOffset + 1);
|
|
3474
|
+
else
|
|
3475
|
+
children.splice(childIndex, 0, childOffset, childOffset + childNode.nodeSize, buildTree(found, childNode, baseOffset + 1, noSpec));
|
|
3476
|
+
childIndex += 3;
|
|
3477
|
+
});
|
|
3478
|
+
let local = moveSpans(childIndex ? withoutNulls(decorations) : decorations, -offset);
|
|
3479
|
+
for (let i = 0; i < local.length; i++)
|
|
3480
|
+
if (!local[i].type.valid(doc2, local[i]))
|
|
3481
|
+
local.splice(i--, 1);
|
|
3482
|
+
return new _DecorationSet(local.length ? this.local.concat(local).sort(byPos) : this.local, children || this.children);
|
|
3483
|
+
}
|
|
3484
|
+
/**
|
|
3485
|
+
Create a new set that contains the decorations in this set, minus
|
|
3486
|
+
the ones in the given array.
|
|
3487
|
+
*/
|
|
3488
|
+
remove(decorations) {
|
|
3489
|
+
if (decorations.length == 0 || this == empty)
|
|
3490
|
+
return this;
|
|
3491
|
+
return this.removeInner(decorations, 0);
|
|
3492
|
+
}
|
|
3493
|
+
removeInner(decorations, offset) {
|
|
3494
|
+
let children = this.children, local = this.local;
|
|
3495
|
+
for (let i = 0; i < children.length; i += 3) {
|
|
3496
|
+
let found;
|
|
3497
|
+
let from = children[i] + offset, to = children[i + 1] + offset;
|
|
3498
|
+
for (let j = 0, span; j < decorations.length; j++)
|
|
3499
|
+
if (span = decorations[j]) {
|
|
3500
|
+
if (span.from > from && span.to < to) {
|
|
3501
|
+
decorations[j] = null;
|
|
3502
|
+
(found || (found = [])).push(span);
|
|
3503
|
+
}
|
|
3504
|
+
}
|
|
3505
|
+
if (!found)
|
|
3506
|
+
continue;
|
|
3507
|
+
if (children == this.children)
|
|
3508
|
+
children = this.children.slice();
|
|
3509
|
+
let removed = children[i + 2].removeInner(found, from + 1);
|
|
3510
|
+
if (removed != empty) {
|
|
3511
|
+
children[i + 2] = removed;
|
|
3512
|
+
} else {
|
|
3513
|
+
children.splice(i, 3);
|
|
3514
|
+
i -= 3;
|
|
3515
|
+
}
|
|
3516
|
+
}
|
|
3517
|
+
if (local.length) {
|
|
3518
|
+
for (let i = 0, span; i < decorations.length; i++)
|
|
3519
|
+
if (span = decorations[i]) {
|
|
3520
|
+
for (let j = 0; j < local.length; j++)
|
|
3521
|
+
if (local[j].eq(span, offset)) {
|
|
3522
|
+
if (local == this.local)
|
|
3523
|
+
local = this.local.slice();
|
|
3524
|
+
local.splice(j--, 1);
|
|
3525
|
+
}
|
|
3526
|
+
}
|
|
3527
|
+
}
|
|
3528
|
+
if (children == this.children && local == this.local)
|
|
3529
|
+
return this;
|
|
3530
|
+
return local.length || children.length ? new _DecorationSet(local, children) : empty;
|
|
3531
|
+
}
|
|
3532
|
+
/**
|
|
3533
|
+
@internal
|
|
3534
|
+
*/
|
|
3535
|
+
forChild(offset, node) {
|
|
3536
|
+
if (this == empty)
|
|
3537
|
+
return this;
|
|
3538
|
+
if (node.isLeaf)
|
|
3539
|
+
return _DecorationSet.empty;
|
|
3540
|
+
let child, local;
|
|
3541
|
+
for (let i = 0; i < this.children.length; i += 3)
|
|
3542
|
+
if (this.children[i] >= offset) {
|
|
3543
|
+
if (this.children[i] == offset)
|
|
3544
|
+
child = this.children[i + 2];
|
|
3545
|
+
break;
|
|
3546
|
+
}
|
|
3547
|
+
let start = offset + 1, end = start + node.content.size;
|
|
3548
|
+
for (let i = 0; i < this.local.length; i++) {
|
|
3549
|
+
let dec = this.local[i];
|
|
3550
|
+
if (dec.from < end && dec.to > start && dec.type instanceof InlineType) {
|
|
3551
|
+
let from = Math.max(start, dec.from) - start, to = Math.min(end, dec.to) - start;
|
|
3552
|
+
if (from < to)
|
|
3553
|
+
(local || (local = [])).push(dec.copy(from, to));
|
|
3554
|
+
}
|
|
3555
|
+
}
|
|
3556
|
+
if (local) {
|
|
3557
|
+
let localSet = new _DecorationSet(local.sort(byPos), none);
|
|
3558
|
+
return child ? new DecorationGroup([localSet, child]) : localSet;
|
|
3559
|
+
}
|
|
3560
|
+
return child || empty;
|
|
3561
|
+
}
|
|
3562
|
+
/**
|
|
3563
|
+
@internal
|
|
3564
|
+
*/
|
|
3565
|
+
eq(other) {
|
|
3566
|
+
if (this == other)
|
|
3567
|
+
return true;
|
|
3568
|
+
if (!(other instanceof _DecorationSet) || this.local.length != other.local.length || this.children.length != other.children.length)
|
|
3569
|
+
return false;
|
|
3570
|
+
for (let i = 0; i < this.local.length; i++)
|
|
3571
|
+
if (!this.local[i].eq(other.local[i]))
|
|
3572
|
+
return false;
|
|
3573
|
+
for (let i = 0; i < this.children.length; i += 3)
|
|
3574
|
+
if (this.children[i] != other.children[i] || this.children[i + 1] != other.children[i + 1] || !this.children[i + 2].eq(other.children[i + 2]))
|
|
3575
|
+
return false;
|
|
3576
|
+
return true;
|
|
3577
|
+
}
|
|
3578
|
+
/**
|
|
3579
|
+
@internal
|
|
3580
|
+
*/
|
|
3581
|
+
locals(node) {
|
|
3582
|
+
return removeOverlap(this.localsInner(node));
|
|
3583
|
+
}
|
|
3584
|
+
/**
|
|
3585
|
+
@internal
|
|
3586
|
+
*/
|
|
3587
|
+
localsInner(node) {
|
|
3588
|
+
if (this == empty)
|
|
3589
|
+
return none;
|
|
3590
|
+
if (node.inlineContent || !this.local.some(InlineType.is))
|
|
3591
|
+
return this.local;
|
|
3592
|
+
let result = [];
|
|
3593
|
+
for (let i = 0; i < this.local.length; i++) {
|
|
3594
|
+
if (!(this.local[i].type instanceof InlineType))
|
|
3595
|
+
result.push(this.local[i]);
|
|
3596
|
+
}
|
|
3597
|
+
return result;
|
|
3598
|
+
}
|
|
3599
|
+
};
|
|
3600
|
+
DecorationSet.empty = new DecorationSet([], []);
|
|
3601
|
+
DecorationSet.removeOverlap = removeOverlap;
|
|
3602
|
+
var empty = DecorationSet.empty;
|
|
3603
|
+
var DecorationGroup = class _DecorationGroup {
|
|
3604
|
+
constructor(members) {
|
|
3605
|
+
this.members = members;
|
|
3606
|
+
}
|
|
3607
|
+
map(mapping, doc2) {
|
|
3608
|
+
const mappedDecos = this.members.map((member) => member.map(mapping, doc2, noSpec));
|
|
3609
|
+
return _DecorationGroup.from(mappedDecos);
|
|
3610
|
+
}
|
|
3611
|
+
forChild(offset, child) {
|
|
3612
|
+
if (child.isLeaf)
|
|
3613
|
+
return DecorationSet.empty;
|
|
3614
|
+
let found = [];
|
|
3615
|
+
for (let i = 0; i < this.members.length; i++) {
|
|
3616
|
+
let result = this.members[i].forChild(offset, child);
|
|
3617
|
+
if (result == empty)
|
|
3618
|
+
continue;
|
|
3619
|
+
if (result instanceof _DecorationGroup)
|
|
3620
|
+
found = found.concat(result.members);
|
|
3621
|
+
else
|
|
3622
|
+
found.push(result);
|
|
3623
|
+
}
|
|
3624
|
+
return _DecorationGroup.from(found);
|
|
3625
|
+
}
|
|
3626
|
+
eq(other) {
|
|
3627
|
+
if (!(other instanceof _DecorationGroup) || other.members.length != this.members.length)
|
|
3628
|
+
return false;
|
|
3629
|
+
for (let i = 0; i < this.members.length; i++)
|
|
3630
|
+
if (!this.members[i].eq(other.members[i]))
|
|
3631
|
+
return false;
|
|
3632
|
+
return true;
|
|
3633
|
+
}
|
|
3634
|
+
locals(node) {
|
|
3635
|
+
let result, sorted = true;
|
|
3636
|
+
for (let i = 0; i < this.members.length; i++) {
|
|
3637
|
+
let locals = this.members[i].localsInner(node);
|
|
3638
|
+
if (!locals.length)
|
|
3639
|
+
continue;
|
|
3640
|
+
if (!result) {
|
|
3641
|
+
result = locals;
|
|
3642
|
+
} else {
|
|
3643
|
+
if (sorted) {
|
|
3644
|
+
result = result.slice();
|
|
3645
|
+
sorted = false;
|
|
3646
|
+
}
|
|
3647
|
+
for (let j = 0; j < locals.length; j++)
|
|
3648
|
+
result.push(locals[j]);
|
|
3649
|
+
}
|
|
3650
|
+
}
|
|
3651
|
+
return result ? removeOverlap(sorted ? result : result.sort(byPos)) : none;
|
|
3652
|
+
}
|
|
3653
|
+
// Create a group for the given array of decoration sets, or return
|
|
3654
|
+
// a single set when possible.
|
|
3655
|
+
static from(members) {
|
|
3656
|
+
switch (members.length) {
|
|
3657
|
+
case 0:
|
|
3658
|
+
return empty;
|
|
3659
|
+
case 1:
|
|
3660
|
+
return members[0];
|
|
3661
|
+
default:
|
|
3662
|
+
return new _DecorationGroup(members.every((m) => m instanceof DecorationSet) ? members : members.reduce((r, m) => r.concat(m instanceof DecorationSet ? m : m.members), []));
|
|
3663
|
+
}
|
|
3664
|
+
}
|
|
3665
|
+
};
|
|
3666
|
+
function mapChildren(oldChildren, newLocal, mapping, node, offset, oldOffset, options) {
|
|
3667
|
+
let children = oldChildren.slice();
|
|
3668
|
+
for (let i = 0, baseOffset = oldOffset; i < mapping.maps.length; i++) {
|
|
3669
|
+
let moved = 0;
|
|
3670
|
+
mapping.maps[i].forEach((oldStart, oldEnd, newStart, newEnd) => {
|
|
3671
|
+
let dSize = newEnd - newStart - (oldEnd - oldStart);
|
|
3672
|
+
for (let i2 = 0; i2 < children.length; i2 += 3) {
|
|
3673
|
+
let end = children[i2 + 1];
|
|
3674
|
+
if (end < 0 || oldStart > end + baseOffset - moved)
|
|
3675
|
+
continue;
|
|
3676
|
+
let start = children[i2] + baseOffset - moved;
|
|
3677
|
+
if (oldEnd >= start) {
|
|
3678
|
+
children[i2 + 1] = oldStart <= start ? -2 : -1;
|
|
3679
|
+
} else if (newStart >= offset && dSize) {
|
|
3680
|
+
children[i2] += dSize;
|
|
3681
|
+
children[i2 + 1] += dSize;
|
|
3682
|
+
}
|
|
3683
|
+
}
|
|
3684
|
+
moved += dSize;
|
|
3685
|
+
});
|
|
3686
|
+
baseOffset = mapping.maps[i].map(baseOffset, -1);
|
|
3687
|
+
}
|
|
3688
|
+
let mustRebuild = false;
|
|
3689
|
+
for (let i = 0; i < children.length; i += 3)
|
|
3690
|
+
if (children[i + 1] < 0) {
|
|
3691
|
+
if (children[i + 1] == -2) {
|
|
3692
|
+
mustRebuild = true;
|
|
3693
|
+
children[i + 1] = -1;
|
|
3694
|
+
continue;
|
|
3695
|
+
}
|
|
3696
|
+
let from = mapping.map(oldChildren[i] + oldOffset), fromLocal = from - offset;
|
|
3697
|
+
if (fromLocal < 0 || fromLocal >= node.content.size) {
|
|
3698
|
+
mustRebuild = true;
|
|
3699
|
+
continue;
|
|
3700
|
+
}
|
|
3701
|
+
let to = mapping.map(oldChildren[i + 1] + oldOffset, -1), toLocal = to - offset;
|
|
3702
|
+
let { index, offset: childOffset } = node.content.findIndex(fromLocal);
|
|
3703
|
+
let childNode = node.maybeChild(index);
|
|
3704
|
+
if (childNode && childOffset == fromLocal && childOffset + childNode.nodeSize == toLocal) {
|
|
3705
|
+
let mapped = children[i + 2].mapInner(mapping, childNode, from + 1, oldChildren[i] + oldOffset + 1, options);
|
|
3706
|
+
if (mapped != empty) {
|
|
3707
|
+
children[i] = fromLocal;
|
|
3708
|
+
children[i + 1] = toLocal;
|
|
3709
|
+
children[i + 2] = mapped;
|
|
3710
|
+
} else {
|
|
3711
|
+
children[i + 1] = -2;
|
|
3712
|
+
mustRebuild = true;
|
|
3713
|
+
}
|
|
3714
|
+
} else {
|
|
3715
|
+
mustRebuild = true;
|
|
3716
|
+
}
|
|
3717
|
+
}
|
|
3718
|
+
if (mustRebuild) {
|
|
3719
|
+
let decorations = mapAndGatherRemainingDecorations(children, oldChildren, newLocal, mapping, offset, oldOffset, options);
|
|
3720
|
+
let built = buildTree(decorations, node, 0, options);
|
|
3721
|
+
newLocal = built.local;
|
|
3722
|
+
for (let i = 0; i < children.length; i += 3)
|
|
3723
|
+
if (children[i + 1] < 0) {
|
|
3724
|
+
children.splice(i, 3);
|
|
3725
|
+
i -= 3;
|
|
3726
|
+
}
|
|
3727
|
+
for (let i = 0, j = 0; i < built.children.length; i += 3) {
|
|
3728
|
+
let from = built.children[i];
|
|
3729
|
+
while (j < children.length && children[j] < from)
|
|
3730
|
+
j += 3;
|
|
3731
|
+
children.splice(j, 0, built.children[i], built.children[i + 1], built.children[i + 2]);
|
|
3732
|
+
}
|
|
3733
|
+
}
|
|
3734
|
+
return new DecorationSet(newLocal.sort(byPos), children);
|
|
3735
|
+
}
|
|
3736
|
+
function moveSpans(spans, offset) {
|
|
3737
|
+
if (!offset || !spans.length)
|
|
3738
|
+
return spans;
|
|
3739
|
+
let result = [];
|
|
3740
|
+
for (let i = 0; i < spans.length; i++) {
|
|
3741
|
+
let span = spans[i];
|
|
3742
|
+
result.push(new Decoration(span.from + offset, span.to + offset, span.type));
|
|
3743
|
+
}
|
|
3744
|
+
return result;
|
|
3745
|
+
}
|
|
3746
|
+
function mapAndGatherRemainingDecorations(children, oldChildren, decorations, mapping, offset, oldOffset, options) {
|
|
3747
|
+
function gather(set, oldOffset2) {
|
|
3748
|
+
for (let i = 0; i < set.local.length; i++) {
|
|
3749
|
+
let mapped = set.local[i].map(mapping, offset, oldOffset2);
|
|
3750
|
+
if (mapped)
|
|
3751
|
+
decorations.push(mapped);
|
|
3752
|
+
else if (options.onRemove)
|
|
3753
|
+
options.onRemove(set.local[i].spec);
|
|
3754
|
+
}
|
|
3755
|
+
for (let i = 0; i < set.children.length; i += 3)
|
|
3756
|
+
gather(set.children[i + 2], set.children[i] + oldOffset2 + 1);
|
|
3757
|
+
}
|
|
3758
|
+
for (let i = 0; i < children.length; i += 3)
|
|
3759
|
+
if (children[i + 1] == -1)
|
|
3760
|
+
gather(children[i + 2], oldChildren[i] + oldOffset + 1);
|
|
3761
|
+
return decorations;
|
|
3762
|
+
}
|
|
3763
|
+
function takeSpansForNode(spans, node, offset) {
|
|
3764
|
+
if (node.isLeaf)
|
|
3765
|
+
return null;
|
|
3766
|
+
let end = offset + node.nodeSize, found = null;
|
|
3767
|
+
for (let i = 0, span; i < spans.length; i++) {
|
|
3768
|
+
if ((span = spans[i]) && span.from > offset && span.to < end) {
|
|
3769
|
+
(found || (found = [])).push(span);
|
|
3770
|
+
spans[i] = null;
|
|
3771
|
+
}
|
|
3772
|
+
}
|
|
3773
|
+
return found;
|
|
3774
|
+
}
|
|
3775
|
+
function withoutNulls(array) {
|
|
3776
|
+
let result = [];
|
|
3777
|
+
for (let i = 0; i < array.length; i++)
|
|
3778
|
+
if (array[i] != null)
|
|
3779
|
+
result.push(array[i]);
|
|
3780
|
+
return result;
|
|
3781
|
+
}
|
|
3782
|
+
function buildTree(spans, node, offset, options) {
|
|
3783
|
+
let children = [], hasNulls = false;
|
|
3784
|
+
node.forEach((childNode, localStart) => {
|
|
3785
|
+
let found = takeSpansForNode(spans, childNode, localStart + offset);
|
|
3786
|
+
if (found) {
|
|
3787
|
+
hasNulls = true;
|
|
3788
|
+
let subtree = buildTree(found, childNode, offset + localStart + 1, options);
|
|
3789
|
+
if (subtree != empty)
|
|
3790
|
+
children.push(localStart, localStart + childNode.nodeSize, subtree);
|
|
3791
|
+
}
|
|
3792
|
+
});
|
|
3793
|
+
let locals = moveSpans(hasNulls ? withoutNulls(spans) : spans, -offset).sort(byPos);
|
|
3794
|
+
for (let i = 0; i < locals.length; i++)
|
|
3795
|
+
if (!locals[i].type.valid(node, locals[i])) {
|
|
3796
|
+
if (options.onRemove)
|
|
3797
|
+
options.onRemove(locals[i].spec);
|
|
3798
|
+
locals.splice(i--, 1);
|
|
3799
|
+
}
|
|
3800
|
+
return locals.length || children.length ? new DecorationSet(locals, children) : empty;
|
|
3801
|
+
}
|
|
3802
|
+
function byPos(a, b) {
|
|
3803
|
+
return a.from - b.from || a.to - b.to;
|
|
3804
|
+
}
|
|
3805
|
+
function removeOverlap(spans) {
|
|
3806
|
+
let working = spans;
|
|
3807
|
+
for (let i = 0; i < working.length - 1; i++) {
|
|
3808
|
+
let span = working[i];
|
|
3809
|
+
if (span.from != span.to)
|
|
3810
|
+
for (let j = i + 1; j < working.length; j++) {
|
|
3811
|
+
let next = working[j];
|
|
3812
|
+
if (next.from == span.from) {
|
|
3813
|
+
if (next.to != span.to) {
|
|
3814
|
+
if (working == spans)
|
|
3815
|
+
working = spans.slice();
|
|
3816
|
+
working[j] = next.copy(next.from, span.to);
|
|
3817
|
+
insertAhead(working, j + 1, next.copy(span.to, next.to));
|
|
3818
|
+
}
|
|
3819
|
+
continue;
|
|
3820
|
+
} else {
|
|
3821
|
+
if (next.from < span.to) {
|
|
3822
|
+
if (working == spans)
|
|
3823
|
+
working = spans.slice();
|
|
3824
|
+
working[i] = span.copy(span.from, next.from);
|
|
3825
|
+
insertAhead(working, j, span.copy(next.from, span.to));
|
|
3826
|
+
}
|
|
3827
|
+
break;
|
|
3828
|
+
}
|
|
3829
|
+
}
|
|
3830
|
+
}
|
|
3831
|
+
return working;
|
|
3832
|
+
}
|
|
3833
|
+
function insertAhead(array, i, deco) {
|
|
3834
|
+
while (i < array.length && byPos(deco, array[i]) > 0)
|
|
3835
|
+
i++;
|
|
3836
|
+
array.splice(i, 0, deco);
|
|
3837
|
+
}
|
|
3838
|
+
function viewDecorations(view) {
|
|
3839
|
+
let found = [];
|
|
3840
|
+
view.someProp("decorations", (f) => {
|
|
3841
|
+
let result = f(view.state);
|
|
3842
|
+
if (result && result != empty)
|
|
3843
|
+
found.push(result);
|
|
3844
|
+
});
|
|
3845
|
+
if (view.cursorWrapper)
|
|
3846
|
+
found.push(DecorationSet.create(view.state.doc, [view.cursorWrapper.deco]));
|
|
3847
|
+
return DecorationGroup.from(found);
|
|
3848
|
+
}
|
|
3849
|
+
var observeOptions = {
|
|
3850
|
+
childList: true,
|
|
3851
|
+
characterData: true,
|
|
3852
|
+
characterDataOldValue: true,
|
|
3853
|
+
attributes: true,
|
|
3854
|
+
attributeOldValue: true,
|
|
3855
|
+
subtree: true
|
|
3856
|
+
};
|
|
3857
|
+
var useCharData = ie && ie_version <= 11;
|
|
3858
|
+
var SelectionState = class {
|
|
3859
|
+
constructor() {
|
|
3860
|
+
this.anchorNode = null;
|
|
3861
|
+
this.anchorOffset = 0;
|
|
3862
|
+
this.focusNode = null;
|
|
3863
|
+
this.focusOffset = 0;
|
|
3864
|
+
}
|
|
3865
|
+
set(sel) {
|
|
3866
|
+
this.anchorNode = sel.anchorNode;
|
|
3867
|
+
this.anchorOffset = sel.anchorOffset;
|
|
3868
|
+
this.focusNode = sel.focusNode;
|
|
3869
|
+
this.focusOffset = sel.focusOffset;
|
|
3870
|
+
}
|
|
3871
|
+
clear() {
|
|
3872
|
+
this.anchorNode = this.focusNode = null;
|
|
3873
|
+
}
|
|
3874
|
+
eq(sel) {
|
|
3875
|
+
return sel.anchorNode == this.anchorNode && sel.anchorOffset == this.anchorOffset && sel.focusNode == this.focusNode && sel.focusOffset == this.focusOffset;
|
|
3876
|
+
}
|
|
3877
|
+
};
|
|
3878
|
+
var DOMObserver = class {
|
|
3879
|
+
constructor(view, handleDOMChange) {
|
|
3880
|
+
this.view = view;
|
|
3881
|
+
this.handleDOMChange = handleDOMChange;
|
|
3882
|
+
this.queue = [];
|
|
3883
|
+
this.flushingSoon = -1;
|
|
3884
|
+
this.observer = null;
|
|
3885
|
+
this.currentSelection = new SelectionState();
|
|
3886
|
+
this.onCharData = null;
|
|
3887
|
+
this.suppressingSelectionUpdates = false;
|
|
3888
|
+
this.observer = window.MutationObserver && new window.MutationObserver((mutations) => {
|
|
3889
|
+
for (let i = 0; i < mutations.length; i++)
|
|
3890
|
+
this.queue.push(mutations[i]);
|
|
3891
|
+
if (ie && ie_version <= 11 && mutations.some((m) => m.type == "childList" && m.removedNodes.length || m.type == "characterData" && m.oldValue.length > m.target.nodeValue.length))
|
|
3892
|
+
this.flushSoon();
|
|
3893
|
+
else
|
|
3894
|
+
this.flush();
|
|
3895
|
+
});
|
|
3896
|
+
if (useCharData) {
|
|
3897
|
+
this.onCharData = (e) => {
|
|
3898
|
+
this.queue.push({ target: e.target, type: "characterData", oldValue: e.prevValue });
|
|
3899
|
+
this.flushSoon();
|
|
3900
|
+
};
|
|
3901
|
+
}
|
|
3902
|
+
this.onSelectionChange = this.onSelectionChange.bind(this);
|
|
3903
|
+
}
|
|
3904
|
+
flushSoon() {
|
|
3905
|
+
if (this.flushingSoon < 0)
|
|
3906
|
+
this.flushingSoon = window.setTimeout(() => {
|
|
3907
|
+
this.flushingSoon = -1;
|
|
3908
|
+
this.flush();
|
|
3909
|
+
}, 20);
|
|
3910
|
+
}
|
|
3911
|
+
forceFlush() {
|
|
3912
|
+
if (this.flushingSoon > -1) {
|
|
3913
|
+
window.clearTimeout(this.flushingSoon);
|
|
3914
|
+
this.flushingSoon = -1;
|
|
3915
|
+
this.flush();
|
|
3916
|
+
}
|
|
3917
|
+
}
|
|
3918
|
+
start() {
|
|
3919
|
+
if (this.observer) {
|
|
3920
|
+
this.observer.takeRecords();
|
|
3921
|
+
this.observer.observe(this.view.dom, observeOptions);
|
|
3922
|
+
}
|
|
3923
|
+
if (this.onCharData)
|
|
3924
|
+
this.view.dom.addEventListener("DOMCharacterDataModified", this.onCharData);
|
|
3925
|
+
this.connectSelection();
|
|
3926
|
+
}
|
|
3927
|
+
stop() {
|
|
3928
|
+
if (this.observer) {
|
|
3929
|
+
let take = this.observer.takeRecords();
|
|
3930
|
+
if (take.length) {
|
|
3931
|
+
for (let i = 0; i < take.length; i++)
|
|
3932
|
+
this.queue.push(take[i]);
|
|
3933
|
+
window.setTimeout(() => this.flush(), 20);
|
|
3934
|
+
}
|
|
3935
|
+
this.observer.disconnect();
|
|
3936
|
+
}
|
|
3937
|
+
if (this.onCharData)
|
|
3938
|
+
this.view.dom.removeEventListener("DOMCharacterDataModified", this.onCharData);
|
|
3939
|
+
this.disconnectSelection();
|
|
3940
|
+
}
|
|
3941
|
+
connectSelection() {
|
|
3942
|
+
this.view.dom.ownerDocument.addEventListener("selectionchange", this.onSelectionChange);
|
|
3943
|
+
}
|
|
3944
|
+
disconnectSelection() {
|
|
3945
|
+
this.view.dom.ownerDocument.removeEventListener("selectionchange", this.onSelectionChange);
|
|
3946
|
+
}
|
|
3947
|
+
suppressSelectionUpdates() {
|
|
3948
|
+
this.suppressingSelectionUpdates = true;
|
|
3949
|
+
setTimeout(() => this.suppressingSelectionUpdates = false, 50);
|
|
3950
|
+
}
|
|
3951
|
+
onSelectionChange() {
|
|
3952
|
+
if (!hasFocusAndSelection(this.view))
|
|
3953
|
+
return;
|
|
3954
|
+
if (this.suppressingSelectionUpdates)
|
|
3955
|
+
return selectionToDOM(this.view);
|
|
3956
|
+
if (ie && ie_version <= 11 && !this.view.state.selection.empty) {
|
|
3957
|
+
let sel = this.view.domSelectionRange();
|
|
3958
|
+
if (sel.focusNode && isEquivalentPosition(sel.focusNode, sel.focusOffset, sel.anchorNode, sel.anchorOffset))
|
|
3959
|
+
return this.flushSoon();
|
|
3960
|
+
}
|
|
3961
|
+
this.flush();
|
|
3962
|
+
}
|
|
3963
|
+
setCurSelection() {
|
|
3964
|
+
this.currentSelection.set(this.view.domSelectionRange());
|
|
3965
|
+
}
|
|
3966
|
+
ignoreSelectionChange(sel) {
|
|
3967
|
+
if (!sel.focusNode)
|
|
3968
|
+
return true;
|
|
3969
|
+
let ancestors = /* @__PURE__ */ new Set(), container;
|
|
3970
|
+
for (let scan = sel.focusNode; scan; scan = parentNode(scan))
|
|
3971
|
+
ancestors.add(scan);
|
|
3972
|
+
for (let scan = sel.anchorNode; scan; scan = parentNode(scan))
|
|
3973
|
+
if (ancestors.has(scan)) {
|
|
3974
|
+
container = scan;
|
|
3975
|
+
break;
|
|
3976
|
+
}
|
|
3977
|
+
let desc = container && this.view.docView.nearestDesc(container);
|
|
3978
|
+
if (desc && desc.ignoreMutation({
|
|
3979
|
+
type: "selection",
|
|
3980
|
+
target: container.nodeType == 3 ? container.parentNode : container
|
|
3981
|
+
})) {
|
|
3982
|
+
this.setCurSelection();
|
|
3983
|
+
return true;
|
|
3984
|
+
}
|
|
3985
|
+
}
|
|
3986
|
+
flush() {
|
|
3987
|
+
let { view } = this;
|
|
3988
|
+
if (!view.docView || this.flushingSoon > -1)
|
|
3989
|
+
return;
|
|
3990
|
+
let mutations = this.observer ? this.observer.takeRecords() : [];
|
|
3991
|
+
if (this.queue.length) {
|
|
3992
|
+
mutations = this.queue.concat(mutations);
|
|
3993
|
+
this.queue.length = 0;
|
|
3994
|
+
}
|
|
3995
|
+
let sel = view.domSelectionRange();
|
|
3996
|
+
let newSel = !this.suppressingSelectionUpdates && !this.currentSelection.eq(sel) && hasFocusAndSelection(view) && !this.ignoreSelectionChange(sel);
|
|
3997
|
+
let from = -1, to = -1, typeOver = false, added = [];
|
|
3998
|
+
if (view.editable) {
|
|
3999
|
+
for (let i = 0; i < mutations.length; i++) {
|
|
4000
|
+
let result = this.registerMutation(mutations[i], added);
|
|
4001
|
+
if (result) {
|
|
4002
|
+
from = from < 0 ? result.from : Math.min(result.from, from);
|
|
4003
|
+
to = to < 0 ? result.to : Math.max(result.to, to);
|
|
4004
|
+
if (result.typeOver)
|
|
4005
|
+
typeOver = true;
|
|
4006
|
+
}
|
|
4007
|
+
}
|
|
4008
|
+
}
|
|
4009
|
+
if (gecko && added.length > 1) {
|
|
4010
|
+
let brs = added.filter((n) => n.nodeName == "BR");
|
|
4011
|
+
if (brs.length == 2) {
|
|
4012
|
+
let a = brs[0], b = brs[1];
|
|
4013
|
+
if (a.parentNode && a.parentNode.parentNode == b.parentNode)
|
|
4014
|
+
b.remove();
|
|
4015
|
+
else
|
|
4016
|
+
a.remove();
|
|
4017
|
+
}
|
|
4018
|
+
}
|
|
4019
|
+
let readSel = null;
|
|
4020
|
+
if (from < 0 && newSel && view.input.lastFocus > Date.now() - 200 && Math.max(view.input.lastTouch, view.input.lastClick.time) < Date.now() - 300 && selectionCollapsed(sel) && (readSel = selectionFromDOM(view)) && readSel.eq(Selection.near(view.state.doc.resolve(0), 1))) {
|
|
4021
|
+
view.input.lastFocus = 0;
|
|
4022
|
+
selectionToDOM(view);
|
|
4023
|
+
this.currentSelection.set(sel);
|
|
4024
|
+
view.scrollToSelection();
|
|
4025
|
+
} else if (from > -1 || newSel) {
|
|
4026
|
+
if (from > -1) {
|
|
4027
|
+
view.docView.markDirty(from, to);
|
|
4028
|
+
checkCSS(view);
|
|
4029
|
+
}
|
|
4030
|
+
this.handleDOMChange(from, to, typeOver, added);
|
|
4031
|
+
if (view.docView && view.docView.dirty)
|
|
4032
|
+
view.updateState(view.state);
|
|
4033
|
+
else if (!this.currentSelection.eq(sel))
|
|
4034
|
+
selectionToDOM(view);
|
|
4035
|
+
this.currentSelection.set(sel);
|
|
4036
|
+
}
|
|
4037
|
+
}
|
|
4038
|
+
registerMutation(mut, added) {
|
|
4039
|
+
if (added.indexOf(mut.target) > -1)
|
|
4040
|
+
return null;
|
|
4041
|
+
let desc = this.view.docView.nearestDesc(mut.target);
|
|
4042
|
+
if (mut.type == "attributes" && (desc == this.view.docView || mut.attributeName == "contenteditable" || // Firefox sometimes fires spurious events for null/empty styles
|
|
4043
|
+
mut.attributeName == "style" && !mut.oldValue && !mut.target.getAttribute("style")))
|
|
4044
|
+
return null;
|
|
4045
|
+
if (!desc || desc.ignoreMutation(mut))
|
|
4046
|
+
return null;
|
|
4047
|
+
if (mut.type == "childList") {
|
|
4048
|
+
for (let i = 0; i < mut.addedNodes.length; i++)
|
|
4049
|
+
added.push(mut.addedNodes[i]);
|
|
4050
|
+
if (desc.contentDOM && desc.contentDOM != desc.dom && !desc.contentDOM.contains(mut.target))
|
|
4051
|
+
return { from: desc.posBefore, to: desc.posAfter };
|
|
4052
|
+
let prev = mut.previousSibling, next = mut.nextSibling;
|
|
4053
|
+
if (ie && ie_version <= 11 && mut.addedNodes.length) {
|
|
4054
|
+
for (let i = 0; i < mut.addedNodes.length; i++) {
|
|
4055
|
+
let { previousSibling, nextSibling } = mut.addedNodes[i];
|
|
4056
|
+
if (!previousSibling || Array.prototype.indexOf.call(mut.addedNodes, previousSibling) < 0)
|
|
4057
|
+
prev = previousSibling;
|
|
4058
|
+
if (!nextSibling || Array.prototype.indexOf.call(mut.addedNodes, nextSibling) < 0)
|
|
4059
|
+
next = nextSibling;
|
|
4060
|
+
}
|
|
4061
|
+
}
|
|
4062
|
+
let fromOffset = prev && prev.parentNode == mut.target ? domIndex(prev) + 1 : 0;
|
|
4063
|
+
let from = desc.localPosFromDOM(mut.target, fromOffset, -1);
|
|
4064
|
+
let toOffset = next && next.parentNode == mut.target ? domIndex(next) : mut.target.childNodes.length;
|
|
4065
|
+
let to = desc.localPosFromDOM(mut.target, toOffset, 1);
|
|
4066
|
+
return { from, to };
|
|
4067
|
+
} else if (mut.type == "attributes") {
|
|
4068
|
+
return { from: desc.posAtStart - desc.border, to: desc.posAtEnd + desc.border };
|
|
4069
|
+
} else {
|
|
4070
|
+
return {
|
|
4071
|
+
from: desc.posAtStart,
|
|
4072
|
+
to: desc.posAtEnd,
|
|
4073
|
+
// An event was generated for a text change that didn't change
|
|
4074
|
+
// any text. Mark the dom change to fall back to assuming the
|
|
4075
|
+
// selection was typed over with an identical value if it can't
|
|
4076
|
+
// find another change.
|
|
4077
|
+
typeOver: mut.target.nodeValue == mut.oldValue
|
|
4078
|
+
};
|
|
4079
|
+
}
|
|
4080
|
+
}
|
|
4081
|
+
};
|
|
4082
|
+
var cssChecked = /* @__PURE__ */ new WeakMap();
|
|
4083
|
+
var cssCheckWarned = false;
|
|
4084
|
+
function checkCSS(view) {
|
|
4085
|
+
if (cssChecked.has(view))
|
|
4086
|
+
return;
|
|
4087
|
+
cssChecked.set(view, null);
|
|
4088
|
+
if (["normal", "nowrap", "pre-line"].indexOf(getComputedStyle(view.dom).whiteSpace) !== -1) {
|
|
4089
|
+
view.requiresGeckoHackNode = gecko;
|
|
4090
|
+
if (cssCheckWarned)
|
|
4091
|
+
return;
|
|
4092
|
+
console["warn"]("ProseMirror expects the CSS white-space property to be set, preferably to 'pre-wrap'. It is recommended to load style/prosemirror.css from the prosemirror-view package.");
|
|
4093
|
+
cssCheckWarned = true;
|
|
4094
|
+
}
|
|
4095
|
+
}
|
|
4096
|
+
function safariShadowSelectionRange(view) {
|
|
4097
|
+
let found;
|
|
4098
|
+
function read(event) {
|
|
4099
|
+
event.preventDefault();
|
|
4100
|
+
event.stopImmediatePropagation();
|
|
4101
|
+
found = event.getTargetRanges()[0];
|
|
4102
|
+
}
|
|
4103
|
+
view.dom.addEventListener("beforeinput", read, true);
|
|
4104
|
+
document.execCommand("indent");
|
|
4105
|
+
view.dom.removeEventListener("beforeinput", read, true);
|
|
4106
|
+
let anchorNode = found.startContainer, anchorOffset = found.startOffset;
|
|
4107
|
+
let focusNode = found.endContainer, focusOffset = found.endOffset;
|
|
4108
|
+
let currentAnchor = view.domAtPos(view.state.selection.anchor);
|
|
4109
|
+
if (isEquivalentPosition(currentAnchor.node, currentAnchor.offset, focusNode, focusOffset))
|
|
4110
|
+
[anchorNode, anchorOffset, focusNode, focusOffset] = [focusNode, focusOffset, anchorNode, anchorOffset];
|
|
4111
|
+
return { anchorNode, anchorOffset, focusNode, focusOffset };
|
|
4112
|
+
}
|
|
4113
|
+
function parseBetween(view, from_, to_) {
|
|
4114
|
+
let { node: parent, fromOffset, toOffset, from, to } = view.docView.parseRange(from_, to_);
|
|
4115
|
+
let domSel = view.domSelectionRange();
|
|
4116
|
+
let find;
|
|
4117
|
+
let anchor = domSel.anchorNode;
|
|
4118
|
+
if (anchor && view.dom.contains(anchor.nodeType == 1 ? anchor : anchor.parentNode)) {
|
|
4119
|
+
find = [{ node: anchor, offset: domSel.anchorOffset }];
|
|
4120
|
+
if (!selectionCollapsed(domSel))
|
|
4121
|
+
find.push({ node: domSel.focusNode, offset: domSel.focusOffset });
|
|
4122
|
+
}
|
|
4123
|
+
if (chrome && view.input.lastKeyCode === 8) {
|
|
4124
|
+
for (let off = toOffset; off > fromOffset; off--) {
|
|
4125
|
+
let node = parent.childNodes[off - 1], desc = node.pmViewDesc;
|
|
4126
|
+
if (node.nodeName == "BR" && !desc) {
|
|
4127
|
+
toOffset = off;
|
|
4128
|
+
break;
|
|
4129
|
+
}
|
|
4130
|
+
if (!desc || desc.size)
|
|
4131
|
+
break;
|
|
4132
|
+
}
|
|
4133
|
+
}
|
|
4134
|
+
let startDoc = view.state.doc;
|
|
4135
|
+
let parser = view.someProp("domParser") || DOMParser.fromSchema(view.state.schema);
|
|
4136
|
+
let $from = startDoc.resolve(from);
|
|
4137
|
+
let sel = null, doc2 = parser.parse(parent, {
|
|
4138
|
+
topNode: $from.parent,
|
|
4139
|
+
topMatch: $from.parent.contentMatchAt($from.index()),
|
|
4140
|
+
topOpen: true,
|
|
4141
|
+
from: fromOffset,
|
|
4142
|
+
to: toOffset,
|
|
4143
|
+
preserveWhitespace: $from.parent.type.whitespace == "pre" ? "full" : true,
|
|
4144
|
+
findPositions: find,
|
|
4145
|
+
ruleFromNode,
|
|
4146
|
+
context: $from
|
|
4147
|
+
});
|
|
4148
|
+
if (find && find[0].pos != null) {
|
|
4149
|
+
let anchor2 = find[0].pos, head = find[1] && find[1].pos;
|
|
4150
|
+
if (head == null)
|
|
4151
|
+
head = anchor2;
|
|
4152
|
+
sel = { anchor: anchor2 + from, head: head + from };
|
|
4153
|
+
}
|
|
4154
|
+
return { doc: doc2, sel, from, to };
|
|
4155
|
+
}
|
|
4156
|
+
function ruleFromNode(dom) {
|
|
4157
|
+
let desc = dom.pmViewDesc;
|
|
4158
|
+
if (desc) {
|
|
4159
|
+
return desc.parseRule();
|
|
4160
|
+
} else if (dom.nodeName == "BR" && dom.parentNode) {
|
|
4161
|
+
if (safari && /^(ul|ol)$/i.test(dom.parentNode.nodeName)) {
|
|
4162
|
+
let skip = document.createElement("div");
|
|
4163
|
+
skip.appendChild(document.createElement("li"));
|
|
4164
|
+
return { skip };
|
|
4165
|
+
} else if (dom.parentNode.lastChild == dom || safari && /^(tr|table)$/i.test(dom.parentNode.nodeName)) {
|
|
4166
|
+
return { ignore: true };
|
|
4167
|
+
}
|
|
4168
|
+
} else if (dom.nodeName == "IMG" && dom.getAttribute("mark-placeholder")) {
|
|
4169
|
+
return { ignore: true };
|
|
4170
|
+
}
|
|
4171
|
+
return null;
|
|
4172
|
+
}
|
|
4173
|
+
var isInline = /^(a|abbr|acronym|b|bd[io]|big|br|button|cite|code|data(list)?|del|dfn|em|i|ins|kbd|label|map|mark|meter|output|q|ruby|s|samp|small|span|strong|su[bp]|time|u|tt|var)$/i;
|
|
4174
|
+
function readDOMChange(view, from, to, typeOver, addedNodes) {
|
|
4175
|
+
if (from < 0) {
|
|
4176
|
+
let origin = view.input.lastSelectionTime > Date.now() - 50 ? view.input.lastSelectionOrigin : null;
|
|
4177
|
+
let newSel = selectionFromDOM(view, origin);
|
|
4178
|
+
if (newSel && !view.state.selection.eq(newSel)) {
|
|
4179
|
+
if (chrome && android && view.input.lastKeyCode === 13 && Date.now() - 100 < view.input.lastKeyCodeTime && view.someProp("handleKeyDown", (f) => f(view, keyEvent(13, "Enter"))))
|
|
4180
|
+
return;
|
|
4181
|
+
let tr2 = view.state.tr.setSelection(newSel);
|
|
4182
|
+
if (origin == "pointer")
|
|
4183
|
+
tr2.setMeta("pointer", true);
|
|
4184
|
+
else if (origin == "key")
|
|
4185
|
+
tr2.scrollIntoView();
|
|
4186
|
+
if (view.composing)
|
|
4187
|
+
tr2.setMeta("composition", view.input.compositionID);
|
|
4188
|
+
view.dispatch(tr2);
|
|
4189
|
+
}
|
|
4190
|
+
return;
|
|
4191
|
+
}
|
|
4192
|
+
let $before = view.state.doc.resolve(from);
|
|
4193
|
+
let shared = $before.sharedDepth(to);
|
|
4194
|
+
from = $before.before(shared + 1);
|
|
4195
|
+
to = view.state.doc.resolve(to).after(shared + 1);
|
|
4196
|
+
let sel = view.state.selection;
|
|
4197
|
+
let parse = parseBetween(view, from, to);
|
|
4198
|
+
let doc2 = view.state.doc, compare = doc2.slice(parse.from, parse.to);
|
|
4199
|
+
let preferredPos, preferredSide;
|
|
4200
|
+
if (view.input.lastKeyCode === 8 && Date.now() - 100 < view.input.lastKeyCodeTime) {
|
|
4201
|
+
preferredPos = view.state.selection.to;
|
|
4202
|
+
preferredSide = "end";
|
|
4203
|
+
} else {
|
|
4204
|
+
preferredPos = view.state.selection.from;
|
|
4205
|
+
preferredSide = "start";
|
|
4206
|
+
}
|
|
4207
|
+
view.input.lastKeyCode = null;
|
|
4208
|
+
let change = findDiff(compare.content, parse.doc.content, parse.from, preferredPos, preferredSide);
|
|
4209
|
+
if ((ios && view.input.lastIOSEnter > Date.now() - 225 || android) && addedNodes.some((n) => n.nodeType == 1 && !isInline.test(n.nodeName)) && (!change || change.endA >= change.endB) && view.someProp("handleKeyDown", (f) => f(view, keyEvent(13, "Enter")))) {
|
|
4210
|
+
view.input.lastIOSEnter = 0;
|
|
4211
|
+
return;
|
|
4212
|
+
}
|
|
4213
|
+
if (!change) {
|
|
4214
|
+
if (typeOver && sel instanceof TextSelection && !sel.empty && sel.$head.sameParent(sel.$anchor) && !view.composing && !(parse.sel && parse.sel.anchor != parse.sel.head)) {
|
|
4215
|
+
change = { start: sel.from, endA: sel.to, endB: sel.to };
|
|
4216
|
+
} else {
|
|
4217
|
+
if (parse.sel) {
|
|
4218
|
+
let sel2 = resolveSelection(view, view.state.doc, parse.sel);
|
|
4219
|
+
if (sel2 && !sel2.eq(view.state.selection)) {
|
|
4220
|
+
let tr2 = view.state.tr.setSelection(sel2);
|
|
4221
|
+
if (view.composing)
|
|
4222
|
+
tr2.setMeta("composition", view.input.compositionID);
|
|
4223
|
+
view.dispatch(tr2);
|
|
4224
|
+
}
|
|
4225
|
+
}
|
|
4226
|
+
return;
|
|
4227
|
+
}
|
|
4228
|
+
}
|
|
4229
|
+
if (chrome && view.cursorWrapper && parse.sel && parse.sel.anchor == view.cursorWrapper.deco.from && parse.sel.head == parse.sel.anchor) {
|
|
4230
|
+
let size = change.endB - change.start;
|
|
4231
|
+
parse.sel = { anchor: parse.sel.anchor + size, head: parse.sel.anchor + size };
|
|
4232
|
+
}
|
|
4233
|
+
view.input.domChangeCount++;
|
|
4234
|
+
if (view.state.selection.from < view.state.selection.to && change.start == change.endB && view.state.selection instanceof TextSelection) {
|
|
4235
|
+
if (change.start > view.state.selection.from && change.start <= view.state.selection.from + 2 && view.state.selection.from >= parse.from) {
|
|
4236
|
+
change.start = view.state.selection.from;
|
|
4237
|
+
} else if (change.endA < view.state.selection.to && change.endA >= view.state.selection.to - 2 && view.state.selection.to <= parse.to) {
|
|
4238
|
+
change.endB += view.state.selection.to - change.endA;
|
|
4239
|
+
change.endA = view.state.selection.to;
|
|
4240
|
+
}
|
|
4241
|
+
}
|
|
4242
|
+
if (ie && ie_version <= 11 && change.endB == change.start + 1 && change.endA == change.start && change.start > parse.from && parse.doc.textBetween(change.start - parse.from - 1, change.start - parse.from + 1) == " \xA0") {
|
|
4243
|
+
change.start--;
|
|
4244
|
+
change.endA--;
|
|
4245
|
+
change.endB--;
|
|
4246
|
+
}
|
|
4247
|
+
let $from = parse.doc.resolveNoCache(change.start - parse.from);
|
|
4248
|
+
let $to = parse.doc.resolveNoCache(change.endB - parse.from);
|
|
4249
|
+
let $fromA = doc2.resolve(change.start);
|
|
4250
|
+
let inlineChange = $from.sameParent($to) && $from.parent.inlineContent && $fromA.end() >= change.endA;
|
|
4251
|
+
let nextSel;
|
|
4252
|
+
if ((ios && view.input.lastIOSEnter > Date.now() - 225 && (!inlineChange || addedNodes.some((n) => n.nodeName == "DIV" || n.nodeName == "P")) || !inlineChange && $from.pos < parse.doc.content.size && !$from.sameParent($to) && (nextSel = Selection.findFrom(parse.doc.resolve($from.pos + 1), 1, true)) && nextSel.head == $to.pos) && view.someProp("handleKeyDown", (f) => f(view, keyEvent(13, "Enter")))) {
|
|
4253
|
+
view.input.lastIOSEnter = 0;
|
|
4254
|
+
return;
|
|
4255
|
+
}
|
|
4256
|
+
if (view.state.selection.anchor > change.start && looksLikeJoin(doc2, change.start, change.endA, $from, $to) && view.someProp("handleKeyDown", (f) => f(view, keyEvent(8, "Backspace")))) {
|
|
4257
|
+
if (android && chrome)
|
|
4258
|
+
view.domObserver.suppressSelectionUpdates();
|
|
4259
|
+
return;
|
|
4260
|
+
}
|
|
4261
|
+
if (chrome && android && change.endB == change.start)
|
|
4262
|
+
view.input.lastAndroidDelete = Date.now();
|
|
4263
|
+
if (android && !inlineChange && $from.start() != $to.start() && $to.parentOffset == 0 && $from.depth == $to.depth && parse.sel && parse.sel.anchor == parse.sel.head && parse.sel.head == change.endA) {
|
|
4264
|
+
change.endB -= 2;
|
|
4265
|
+
$to = parse.doc.resolveNoCache(change.endB - parse.from);
|
|
4266
|
+
setTimeout(() => {
|
|
4267
|
+
view.someProp("handleKeyDown", function(f) {
|
|
4268
|
+
return f(view, keyEvent(13, "Enter"));
|
|
4269
|
+
});
|
|
4270
|
+
}, 20);
|
|
4271
|
+
}
|
|
4272
|
+
let chFrom = change.start, chTo = change.endA;
|
|
4273
|
+
let tr, storedMarks, markChange;
|
|
4274
|
+
if (inlineChange) {
|
|
4275
|
+
if ($from.pos == $to.pos) {
|
|
4276
|
+
if (ie && ie_version <= 11 && $from.parentOffset == 0) {
|
|
4277
|
+
view.domObserver.suppressSelectionUpdates();
|
|
4278
|
+
setTimeout(() => selectionToDOM(view), 20);
|
|
4279
|
+
}
|
|
4280
|
+
tr = view.state.tr.delete(chFrom, chTo);
|
|
4281
|
+
storedMarks = doc2.resolve(change.start).marksAcross(doc2.resolve(change.endA));
|
|
4282
|
+
} else if (
|
|
4283
|
+
// Adding or removing a mark
|
|
4284
|
+
change.endA == change.endB && (markChange = isMarkChange($from.parent.content.cut($from.parentOffset, $to.parentOffset), $fromA.parent.content.cut($fromA.parentOffset, change.endA - $fromA.start())))
|
|
4285
|
+
) {
|
|
4286
|
+
tr = view.state.tr;
|
|
4287
|
+
if (markChange.type == "add")
|
|
4288
|
+
tr.addMark(chFrom, chTo, markChange.mark);
|
|
4289
|
+
else
|
|
4290
|
+
tr.removeMark(chFrom, chTo, markChange.mark);
|
|
4291
|
+
} else if ($from.parent.child($from.index()).isText && $from.index() == $to.index() - ($to.textOffset ? 0 : 1)) {
|
|
4292
|
+
let text = $from.parent.textBetween($from.parentOffset, $to.parentOffset);
|
|
4293
|
+
if (view.someProp("handleTextInput", (f) => f(view, chFrom, chTo, text)))
|
|
4294
|
+
return;
|
|
4295
|
+
tr = view.state.tr.insertText(text, chFrom, chTo);
|
|
4296
|
+
}
|
|
4297
|
+
}
|
|
4298
|
+
if (!tr)
|
|
4299
|
+
tr = view.state.tr.replace(chFrom, chTo, parse.doc.slice(change.start - parse.from, change.endB - parse.from));
|
|
4300
|
+
if (parse.sel) {
|
|
4301
|
+
let sel2 = resolveSelection(view, tr.doc, parse.sel);
|
|
4302
|
+
if (sel2 && !(chrome && android && view.composing && sel2.empty && (change.start != change.endB || view.input.lastAndroidDelete < Date.now() - 100) && (sel2.head == chFrom || sel2.head == tr.mapping.map(chTo) - 1) || ie && sel2.empty && sel2.head == chFrom))
|
|
4303
|
+
tr.setSelection(sel2);
|
|
4304
|
+
}
|
|
4305
|
+
if (storedMarks)
|
|
4306
|
+
tr.ensureMarks(storedMarks);
|
|
4307
|
+
if (view.composing)
|
|
4308
|
+
tr.setMeta("composition", view.input.compositionID);
|
|
4309
|
+
view.dispatch(tr.scrollIntoView());
|
|
4310
|
+
}
|
|
4311
|
+
function resolveSelection(view, doc2, parsedSel) {
|
|
4312
|
+
if (Math.max(parsedSel.anchor, parsedSel.head) > doc2.content.size)
|
|
4313
|
+
return null;
|
|
4314
|
+
return selectionBetween(view, doc2.resolve(parsedSel.anchor), doc2.resolve(parsedSel.head));
|
|
4315
|
+
}
|
|
4316
|
+
function isMarkChange(cur, prev) {
|
|
4317
|
+
let curMarks = cur.firstChild.marks, prevMarks = prev.firstChild.marks;
|
|
4318
|
+
let added = curMarks, removed = prevMarks, type, mark, update;
|
|
4319
|
+
for (let i = 0; i < prevMarks.length; i++)
|
|
4320
|
+
added = prevMarks[i].removeFromSet(added);
|
|
4321
|
+
for (let i = 0; i < curMarks.length; i++)
|
|
4322
|
+
removed = curMarks[i].removeFromSet(removed);
|
|
4323
|
+
if (added.length == 1 && removed.length == 0) {
|
|
4324
|
+
mark = added[0];
|
|
4325
|
+
type = "add";
|
|
4326
|
+
update = (node) => node.mark(mark.addToSet(node.marks));
|
|
4327
|
+
} else if (added.length == 0 && removed.length == 1) {
|
|
4328
|
+
mark = removed[0];
|
|
4329
|
+
type = "remove";
|
|
4330
|
+
update = (node) => node.mark(mark.removeFromSet(node.marks));
|
|
4331
|
+
} else {
|
|
4332
|
+
return null;
|
|
4333
|
+
}
|
|
4334
|
+
let updated = [];
|
|
4335
|
+
for (let i = 0; i < prev.childCount; i++)
|
|
4336
|
+
updated.push(update(prev.child(i)));
|
|
4337
|
+
if (Fragment.from(updated).eq(cur))
|
|
4338
|
+
return { mark, type };
|
|
4339
|
+
}
|
|
4340
|
+
function looksLikeJoin(old, start, end, $newStart, $newEnd) {
|
|
4341
|
+
if (!$newStart.parent.isTextblock || // The content must have shrunk
|
|
4342
|
+
end - start <= $newEnd.pos - $newStart.pos || // newEnd must point directly at or after the end of the block that newStart points into
|
|
4343
|
+
skipClosingAndOpening($newStart, true, false) < $newEnd.pos)
|
|
4344
|
+
return false;
|
|
4345
|
+
let $start = old.resolve(start);
|
|
4346
|
+
if ($start.parentOffset < $start.parent.content.size || !$start.parent.isTextblock)
|
|
4347
|
+
return false;
|
|
4348
|
+
let $next = old.resolve(skipClosingAndOpening($start, true, true));
|
|
4349
|
+
if (!$next.parent.isTextblock || $next.pos > end || skipClosingAndOpening($next, true, false) < end)
|
|
4350
|
+
return false;
|
|
4351
|
+
return $newStart.parent.content.cut($newStart.parentOffset).eq($next.parent.content);
|
|
4352
|
+
}
|
|
4353
|
+
function skipClosingAndOpening($pos, fromEnd, mayOpen) {
|
|
4354
|
+
let depth = $pos.depth, end = fromEnd ? $pos.end() : $pos.pos;
|
|
4355
|
+
while (depth > 0 && (fromEnd || $pos.indexAfter(depth) == $pos.node(depth).childCount)) {
|
|
4356
|
+
depth--;
|
|
4357
|
+
end++;
|
|
4358
|
+
fromEnd = false;
|
|
4359
|
+
}
|
|
4360
|
+
if (mayOpen) {
|
|
4361
|
+
let next = $pos.node(depth).maybeChild($pos.indexAfter(depth));
|
|
4362
|
+
while (next && !next.isLeaf) {
|
|
4363
|
+
next = next.firstChild;
|
|
4364
|
+
end++;
|
|
4365
|
+
}
|
|
4366
|
+
}
|
|
4367
|
+
return end;
|
|
4368
|
+
}
|
|
4369
|
+
function findDiff(a, b, pos, preferredPos, preferredSide) {
|
|
4370
|
+
let start = a.findDiffStart(b, pos);
|
|
4371
|
+
if (start == null)
|
|
4372
|
+
return null;
|
|
4373
|
+
let { a: endA, b: endB } = a.findDiffEnd(b, pos + a.size, pos + b.size);
|
|
4374
|
+
if (preferredSide == "end") {
|
|
4375
|
+
let adjust = Math.max(0, start - Math.min(endA, endB));
|
|
4376
|
+
preferredPos -= endA + adjust - start;
|
|
4377
|
+
}
|
|
4378
|
+
if (endA < start && a.size < b.size) {
|
|
4379
|
+
let move = preferredPos <= start && preferredPos >= endA ? start - preferredPos : 0;
|
|
4380
|
+
start -= move;
|
|
4381
|
+
endB = start + (endB - endA);
|
|
4382
|
+
endA = start;
|
|
4383
|
+
} else if (endB < start) {
|
|
4384
|
+
let move = preferredPos <= start && preferredPos >= endB ? start - preferredPos : 0;
|
|
4385
|
+
start -= move;
|
|
4386
|
+
endA = start + (endA - endB);
|
|
4387
|
+
endB = start;
|
|
4388
|
+
}
|
|
4389
|
+
return { start, endA, endB };
|
|
4390
|
+
}
|
|
4391
|
+
var __serializeForClipboard = serializeForClipboard;
|
|
4392
|
+
var __parseFromClipboard = parseFromClipboard;
|
|
4393
|
+
var __endComposition = endComposition;
|
|
4394
|
+
var EditorView = class {
|
|
4395
|
+
/**
|
|
4396
|
+
Create a view. `place` may be a DOM node that the editor should
|
|
4397
|
+
be appended to, a function that will place it into the document,
|
|
4398
|
+
or an object whose `mount` property holds the node to use as the
|
|
4399
|
+
document container. If it is `null`, the editor will not be
|
|
4400
|
+
added to the document.
|
|
4401
|
+
*/
|
|
4402
|
+
constructor(place, props) {
|
|
4403
|
+
this._root = null;
|
|
4404
|
+
this.focused = false;
|
|
4405
|
+
this.trackWrites = null;
|
|
4406
|
+
this.mounted = false;
|
|
4407
|
+
this.markCursor = null;
|
|
4408
|
+
this.cursorWrapper = null;
|
|
4409
|
+
this.lastSelectedViewDesc = void 0;
|
|
4410
|
+
this.input = new InputState();
|
|
4411
|
+
this.prevDirectPlugins = [];
|
|
4412
|
+
this.pluginViews = [];
|
|
4413
|
+
this.requiresGeckoHackNode = false;
|
|
4414
|
+
this.dragging = null;
|
|
4415
|
+
this._props = props;
|
|
4416
|
+
this.state = props.state;
|
|
4417
|
+
this.directPlugins = props.plugins || [];
|
|
4418
|
+
this.directPlugins.forEach(checkStateComponent);
|
|
4419
|
+
this.dispatch = this.dispatch.bind(this);
|
|
4420
|
+
this.dom = place && place.mount || document.createElement("div");
|
|
4421
|
+
if (place) {
|
|
4422
|
+
if (place.appendChild)
|
|
4423
|
+
place.appendChild(this.dom);
|
|
4424
|
+
else if (typeof place == "function")
|
|
4425
|
+
place(this.dom);
|
|
4426
|
+
else if (place.mount)
|
|
4427
|
+
this.mounted = true;
|
|
4428
|
+
}
|
|
4429
|
+
this.editable = getEditable(this);
|
|
4430
|
+
updateCursorWrapper(this);
|
|
4431
|
+
this.nodeViews = buildNodeViews(this);
|
|
4432
|
+
this.docView = docViewDesc(this.state.doc, computeDocDeco(this), viewDecorations(this), this.dom, this);
|
|
4433
|
+
this.domObserver = new DOMObserver(this, (from, to, typeOver, added) => readDOMChange(this, from, to, typeOver, added));
|
|
4434
|
+
this.domObserver.start();
|
|
4435
|
+
initInput(this);
|
|
4436
|
+
this.updatePluginViews();
|
|
4437
|
+
}
|
|
4438
|
+
/**
|
|
4439
|
+
Holds `true` when a
|
|
4440
|
+
[composition](https://w3c.github.io/uievents/#events-compositionevents)
|
|
4441
|
+
is active.
|
|
4442
|
+
*/
|
|
4443
|
+
get composing() {
|
|
4444
|
+
return this.input.composing;
|
|
4445
|
+
}
|
|
4446
|
+
/**
|
|
4447
|
+
The view's current [props](https://prosemirror.net/docs/ref/#view.EditorProps).
|
|
4448
|
+
*/
|
|
4449
|
+
get props() {
|
|
4450
|
+
if (this._props.state != this.state) {
|
|
4451
|
+
let prev = this._props;
|
|
4452
|
+
this._props = {};
|
|
4453
|
+
for (let name in prev)
|
|
4454
|
+
this._props[name] = prev[name];
|
|
4455
|
+
this._props.state = this.state;
|
|
4456
|
+
}
|
|
4457
|
+
return this._props;
|
|
4458
|
+
}
|
|
4459
|
+
/**
|
|
4460
|
+
Update the view's props. Will immediately cause an update to
|
|
4461
|
+
the DOM.
|
|
4462
|
+
*/
|
|
4463
|
+
update(props) {
|
|
4464
|
+
if (props.handleDOMEvents != this._props.handleDOMEvents)
|
|
4465
|
+
ensureListeners(this);
|
|
4466
|
+
let prevProps = this._props;
|
|
4467
|
+
this._props = props;
|
|
4468
|
+
if (props.plugins) {
|
|
4469
|
+
props.plugins.forEach(checkStateComponent);
|
|
4470
|
+
this.directPlugins = props.plugins;
|
|
4471
|
+
}
|
|
4472
|
+
this.updateStateInner(props.state, prevProps);
|
|
4473
|
+
}
|
|
4474
|
+
/**
|
|
4475
|
+
Update the view by updating existing props object with the object
|
|
4476
|
+
given as argument. Equivalent to `view.update(Object.assign({},
|
|
4477
|
+
view.props, props))`.
|
|
4478
|
+
*/
|
|
4479
|
+
setProps(props) {
|
|
4480
|
+
let updated = {};
|
|
4481
|
+
for (let name in this._props)
|
|
4482
|
+
updated[name] = this._props[name];
|
|
4483
|
+
updated.state = this.state;
|
|
4484
|
+
for (let name in props)
|
|
4485
|
+
updated[name] = props[name];
|
|
4486
|
+
this.update(updated);
|
|
4487
|
+
}
|
|
4488
|
+
/**
|
|
4489
|
+
Update the editor's `state` prop, without touching any of the
|
|
4490
|
+
other props.
|
|
4491
|
+
*/
|
|
4492
|
+
updateState(state) {
|
|
4493
|
+
this.updateStateInner(state, this._props);
|
|
4494
|
+
}
|
|
4495
|
+
updateStateInner(state, prevProps) {
|
|
4496
|
+
let prev = this.state, redraw = false, updateSel = false;
|
|
4497
|
+
if (state.storedMarks && this.composing) {
|
|
4498
|
+
clearComposition(this);
|
|
4499
|
+
updateSel = true;
|
|
4500
|
+
}
|
|
4501
|
+
this.state = state;
|
|
4502
|
+
let pluginsChanged = prev.plugins != state.plugins || this._props.plugins != prevProps.plugins;
|
|
4503
|
+
if (pluginsChanged || this._props.plugins != prevProps.plugins || this._props.nodeViews != prevProps.nodeViews) {
|
|
4504
|
+
let nodeViews = buildNodeViews(this);
|
|
4505
|
+
if (changedNodeViews(nodeViews, this.nodeViews)) {
|
|
4506
|
+
this.nodeViews = nodeViews;
|
|
4507
|
+
redraw = true;
|
|
4508
|
+
}
|
|
4509
|
+
}
|
|
4510
|
+
if (pluginsChanged || prevProps.handleDOMEvents != this._props.handleDOMEvents) {
|
|
4511
|
+
ensureListeners(this);
|
|
4512
|
+
}
|
|
4513
|
+
this.editable = getEditable(this);
|
|
4514
|
+
updateCursorWrapper(this);
|
|
4515
|
+
let innerDeco = viewDecorations(this), outerDeco = computeDocDeco(this);
|
|
4516
|
+
let scroll = prev.plugins != state.plugins && !prev.doc.eq(state.doc) ? "reset" : state.scrollToSelection > prev.scrollToSelection ? "to selection" : "preserve";
|
|
4517
|
+
let updateDoc = redraw || !this.docView.matchesNode(state.doc, outerDeco, innerDeco);
|
|
4518
|
+
if (updateDoc || !state.selection.eq(prev.selection))
|
|
4519
|
+
updateSel = true;
|
|
4520
|
+
let oldScrollPos = scroll == "preserve" && updateSel && this.dom.style.overflowAnchor == null && storeScrollPos(this);
|
|
4521
|
+
if (updateSel) {
|
|
4522
|
+
this.domObserver.stop();
|
|
4523
|
+
let forceSelUpdate = updateDoc && (ie || chrome) && !this.composing && !prev.selection.empty && !state.selection.empty && selectionContextChanged(prev.selection, state.selection);
|
|
4524
|
+
if (updateDoc) {
|
|
4525
|
+
let chromeKludge = chrome ? this.trackWrites = this.domSelectionRange().focusNode : null;
|
|
4526
|
+
if (redraw || !this.docView.update(state.doc, outerDeco, innerDeco, this)) {
|
|
4527
|
+
this.docView.updateOuterDeco([]);
|
|
4528
|
+
this.docView.destroy();
|
|
4529
|
+
this.docView = docViewDesc(state.doc, outerDeco, innerDeco, this.dom, this);
|
|
4530
|
+
}
|
|
4531
|
+
if (chromeKludge && !this.trackWrites)
|
|
4532
|
+
forceSelUpdate = true;
|
|
4533
|
+
}
|
|
4534
|
+
if (forceSelUpdate || !(this.input.mouseDown && this.domObserver.currentSelection.eq(this.domSelectionRange()) && anchorInRightPlace(this))) {
|
|
4535
|
+
selectionToDOM(this, forceSelUpdate);
|
|
4536
|
+
} else {
|
|
4537
|
+
syncNodeSelection(this, state.selection);
|
|
4538
|
+
this.domObserver.setCurSelection();
|
|
4539
|
+
}
|
|
4540
|
+
this.domObserver.start();
|
|
4541
|
+
}
|
|
4542
|
+
this.updatePluginViews(prev);
|
|
4543
|
+
if (scroll == "reset") {
|
|
4544
|
+
this.dom.scrollTop = 0;
|
|
4545
|
+
} else if (scroll == "to selection") {
|
|
4546
|
+
this.scrollToSelection();
|
|
4547
|
+
} else if (oldScrollPos) {
|
|
4548
|
+
resetScrollPos(oldScrollPos);
|
|
4549
|
+
}
|
|
4550
|
+
}
|
|
4551
|
+
/**
|
|
4552
|
+
@internal
|
|
4553
|
+
*/
|
|
4554
|
+
scrollToSelection() {
|
|
4555
|
+
let startDOM = this.domSelectionRange().focusNode;
|
|
4556
|
+
if (this.someProp("handleScrollToSelection", (f) => f(this)))
|
|
4557
|
+
;
|
|
4558
|
+
else if (this.state.selection instanceof NodeSelection) {
|
|
4559
|
+
let target = this.docView.domAfterPos(this.state.selection.from);
|
|
4560
|
+
if (target.nodeType == 1)
|
|
4561
|
+
scrollRectIntoView(this, target.getBoundingClientRect(), startDOM);
|
|
4562
|
+
} else {
|
|
4563
|
+
scrollRectIntoView(this, this.coordsAtPos(this.state.selection.head, 1), startDOM);
|
|
4564
|
+
}
|
|
4565
|
+
}
|
|
4566
|
+
destroyPluginViews() {
|
|
4567
|
+
let view;
|
|
4568
|
+
while (view = this.pluginViews.pop())
|
|
4569
|
+
if (view.destroy)
|
|
4570
|
+
view.destroy();
|
|
4571
|
+
}
|
|
4572
|
+
updatePluginViews(prevState) {
|
|
4573
|
+
if (!prevState || prevState.plugins != this.state.plugins || this.directPlugins != this.prevDirectPlugins) {
|
|
4574
|
+
this.prevDirectPlugins = this.directPlugins;
|
|
4575
|
+
this.destroyPluginViews();
|
|
4576
|
+
for (let i = 0; i < this.directPlugins.length; i++) {
|
|
4577
|
+
let plugin = this.directPlugins[i];
|
|
4578
|
+
if (plugin.spec.view)
|
|
4579
|
+
this.pluginViews.push(plugin.spec.view(this));
|
|
4580
|
+
}
|
|
4581
|
+
for (let i = 0; i < this.state.plugins.length; i++) {
|
|
4582
|
+
let plugin = this.state.plugins[i];
|
|
4583
|
+
if (plugin.spec.view)
|
|
4584
|
+
this.pluginViews.push(plugin.spec.view(this));
|
|
4585
|
+
}
|
|
4586
|
+
} else {
|
|
4587
|
+
for (let i = 0; i < this.pluginViews.length; i++) {
|
|
4588
|
+
let pluginView = this.pluginViews[i];
|
|
4589
|
+
if (pluginView.update)
|
|
4590
|
+
pluginView.update(this, prevState);
|
|
4591
|
+
}
|
|
4592
|
+
}
|
|
4593
|
+
}
|
|
4594
|
+
someProp(propName, f) {
|
|
4595
|
+
let prop = this._props && this._props[propName], value;
|
|
4596
|
+
if (prop != null && (value = f ? f(prop) : prop))
|
|
4597
|
+
return value;
|
|
4598
|
+
for (let i = 0; i < this.directPlugins.length; i++) {
|
|
4599
|
+
let prop2 = this.directPlugins[i].props[propName];
|
|
4600
|
+
if (prop2 != null && (value = f ? f(prop2) : prop2))
|
|
4601
|
+
return value;
|
|
4602
|
+
}
|
|
4603
|
+
let plugins = this.state.plugins;
|
|
4604
|
+
if (plugins)
|
|
4605
|
+
for (let i = 0; i < plugins.length; i++) {
|
|
4606
|
+
let prop2 = plugins[i].props[propName];
|
|
4607
|
+
if (prop2 != null && (value = f ? f(prop2) : prop2))
|
|
4608
|
+
return value;
|
|
4609
|
+
}
|
|
4610
|
+
}
|
|
4611
|
+
/**
|
|
4612
|
+
Query whether the view has focus.
|
|
4613
|
+
*/
|
|
4614
|
+
hasFocus() {
|
|
4615
|
+
if (ie) {
|
|
4616
|
+
let node = this.root.activeElement;
|
|
4617
|
+
if (node == this.dom)
|
|
4618
|
+
return true;
|
|
4619
|
+
if (!node || !this.dom.contains(node))
|
|
4620
|
+
return false;
|
|
4621
|
+
while (node && this.dom != node && this.dom.contains(node)) {
|
|
4622
|
+
if (node.contentEditable == "false")
|
|
4623
|
+
return false;
|
|
4624
|
+
node = node.parentElement;
|
|
4625
|
+
}
|
|
4626
|
+
return true;
|
|
4627
|
+
}
|
|
4628
|
+
return this.root.activeElement == this.dom;
|
|
4629
|
+
}
|
|
4630
|
+
/**
|
|
4631
|
+
Focus the editor.
|
|
4632
|
+
*/
|
|
4633
|
+
focus() {
|
|
4634
|
+
this.domObserver.stop();
|
|
4635
|
+
if (this.editable)
|
|
4636
|
+
focusPreventScroll(this.dom);
|
|
4637
|
+
selectionToDOM(this);
|
|
4638
|
+
this.domObserver.start();
|
|
4639
|
+
}
|
|
4640
|
+
/**
|
|
4641
|
+
Get the document root in which the editor exists. This will
|
|
4642
|
+
usually be the top-level `document`, but might be a [shadow
|
|
4643
|
+
DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Shadow_DOM)
|
|
4644
|
+
root if the editor is inside one.
|
|
4645
|
+
*/
|
|
4646
|
+
get root() {
|
|
4647
|
+
let cached = this._root;
|
|
4648
|
+
if (cached == null)
|
|
4649
|
+
for (let search = this.dom.parentNode; search; search = search.parentNode) {
|
|
4650
|
+
if (search.nodeType == 9 || search.nodeType == 11 && search.host) {
|
|
4651
|
+
if (!search.getSelection)
|
|
4652
|
+
Object.getPrototypeOf(search).getSelection = () => search.ownerDocument.getSelection();
|
|
4653
|
+
return this._root = search;
|
|
4654
|
+
}
|
|
4655
|
+
}
|
|
4656
|
+
return cached || document;
|
|
4657
|
+
}
|
|
4658
|
+
/**
|
|
4659
|
+
Given a pair of viewport coordinates, return the document
|
|
4660
|
+
position that corresponds to them. May return null if the given
|
|
4661
|
+
coordinates aren't inside of the editor. When an object is
|
|
4662
|
+
returned, its `pos` property is the position nearest to the
|
|
4663
|
+
coordinates, and its `inside` property holds the position of the
|
|
4664
|
+
inner node that the position falls inside of, or -1 if it is at
|
|
4665
|
+
the top level, not in any node.
|
|
4666
|
+
*/
|
|
4667
|
+
posAtCoords(coords) {
|
|
4668
|
+
return posAtCoords(this, coords);
|
|
4669
|
+
}
|
|
4670
|
+
/**
|
|
4671
|
+
Returns the viewport rectangle at a given document position.
|
|
4672
|
+
`left` and `right` will be the same number, as this returns a
|
|
4673
|
+
flat cursor-ish rectangle. If the position is between two things
|
|
4674
|
+
that aren't directly adjacent, `side` determines which element
|
|
4675
|
+
is used. When < 0, the element before the position is used,
|
|
4676
|
+
otherwise the element after.
|
|
4677
|
+
*/
|
|
4678
|
+
coordsAtPos(pos, side = 1) {
|
|
4679
|
+
return coordsAtPos(this, pos, side);
|
|
4680
|
+
}
|
|
4681
|
+
/**
|
|
4682
|
+
Find the DOM position that corresponds to the given document
|
|
4683
|
+
position. When `side` is negative, find the position as close as
|
|
4684
|
+
possible to the content before the position. When positive,
|
|
4685
|
+
prefer positions close to the content after the position. When
|
|
4686
|
+
zero, prefer as shallow a position as possible.
|
|
4687
|
+
|
|
4688
|
+
Note that you should **not** mutate the editor's internal DOM,
|
|
4689
|
+
only inspect it (and even that is usually not necessary).
|
|
4690
|
+
*/
|
|
4691
|
+
domAtPos(pos, side = 0) {
|
|
4692
|
+
return this.docView.domFromPos(pos, side);
|
|
4693
|
+
}
|
|
4694
|
+
/**
|
|
4695
|
+
Find the DOM node that represents the document node after the
|
|
4696
|
+
given position. May return `null` when the position doesn't point
|
|
4697
|
+
in front of a node or if the node is inside an opaque node view.
|
|
4698
|
+
|
|
4699
|
+
This is intended to be able to call things like
|
|
4700
|
+
`getBoundingClientRect` on that DOM node. Do **not** mutate the
|
|
4701
|
+
editor DOM directly, or add styling this way, since that will be
|
|
4702
|
+
immediately overriden by the editor as it redraws the node.
|
|
4703
|
+
*/
|
|
4704
|
+
nodeDOM(pos) {
|
|
4705
|
+
let desc = this.docView.descAt(pos);
|
|
4706
|
+
return desc ? desc.nodeDOM : null;
|
|
4707
|
+
}
|
|
4708
|
+
/**
|
|
4709
|
+
Find the document position that corresponds to a given DOM
|
|
4710
|
+
position. (Whenever possible, it is preferable to inspect the
|
|
4711
|
+
document structure directly, rather than poking around in the
|
|
4712
|
+
DOM, but sometimes—for example when interpreting an event
|
|
4713
|
+
target—you don't have a choice.)
|
|
4714
|
+
|
|
4715
|
+
The `bias` parameter can be used to influence which side of a DOM
|
|
4716
|
+
node to use when the position is inside a leaf node.
|
|
4717
|
+
*/
|
|
4718
|
+
posAtDOM(node, offset, bias = -1) {
|
|
4719
|
+
let pos = this.docView.posFromDOM(node, offset, bias);
|
|
4720
|
+
if (pos == null)
|
|
4721
|
+
throw new RangeError("DOM position not inside the editor");
|
|
4722
|
+
return pos;
|
|
4723
|
+
}
|
|
4724
|
+
/**
|
|
4725
|
+
Find out whether the selection is at the end of a textblock when
|
|
4726
|
+
moving in a given direction. When, for example, given `"left"`,
|
|
4727
|
+
it will return true if moving left from the current cursor
|
|
4728
|
+
position would leave that position's parent textblock. Will apply
|
|
4729
|
+
to the view's current state by default, but it is possible to
|
|
4730
|
+
pass a different state.
|
|
4731
|
+
*/
|
|
4732
|
+
endOfTextblock(dir, state) {
|
|
4733
|
+
return endOfTextblock(this, state || this.state, dir);
|
|
4734
|
+
}
|
|
4735
|
+
/**
|
|
4736
|
+
Run the editor's paste logic with the given HTML string. The
|
|
4737
|
+
`event`, if given, will be passed to the
|
|
4738
|
+
[`handlePaste`](https://prosemirror.net/docs/ref/#view.EditorProps.handlePaste) hook.
|
|
4739
|
+
*/
|
|
4740
|
+
pasteHTML(html, event) {
|
|
4741
|
+
return doPaste(this, "", html, false, event || new ClipboardEvent("paste"));
|
|
4742
|
+
}
|
|
4743
|
+
/**
|
|
4744
|
+
Run the editor's paste logic with the given plain-text input.
|
|
4745
|
+
*/
|
|
4746
|
+
pasteText(text, event) {
|
|
4747
|
+
return doPaste(this, text, null, true, event || new ClipboardEvent("paste"));
|
|
4748
|
+
}
|
|
4749
|
+
/**
|
|
4750
|
+
Removes the editor from the DOM and destroys all [node
|
|
4751
|
+
views](https://prosemirror.net/docs/ref/#view.NodeView).
|
|
4752
|
+
*/
|
|
4753
|
+
destroy() {
|
|
4754
|
+
if (!this.docView)
|
|
4755
|
+
return;
|
|
4756
|
+
destroyInput(this);
|
|
4757
|
+
this.destroyPluginViews();
|
|
4758
|
+
if (this.mounted) {
|
|
4759
|
+
this.docView.update(this.state.doc, [], viewDecorations(this), this);
|
|
4760
|
+
this.dom.textContent = "";
|
|
4761
|
+
} else if (this.dom.parentNode) {
|
|
4762
|
+
this.dom.parentNode.removeChild(this.dom);
|
|
4763
|
+
}
|
|
4764
|
+
this.docView.destroy();
|
|
4765
|
+
this.docView = null;
|
|
4766
|
+
}
|
|
4767
|
+
/**
|
|
4768
|
+
This is true when the view has been
|
|
4769
|
+
[destroyed](https://prosemirror.net/docs/ref/#view.EditorView.destroy) (and thus should not be
|
|
4770
|
+
used anymore).
|
|
4771
|
+
*/
|
|
4772
|
+
get isDestroyed() {
|
|
4773
|
+
return this.docView == null;
|
|
4774
|
+
}
|
|
4775
|
+
/**
|
|
4776
|
+
Used for testing.
|
|
4777
|
+
*/
|
|
4778
|
+
dispatchEvent(event) {
|
|
4779
|
+
return dispatchEvent(this, event);
|
|
4780
|
+
}
|
|
4781
|
+
/**
|
|
4782
|
+
Dispatch a transaction. Will call
|
|
4783
|
+
[`dispatchTransaction`](https://prosemirror.net/docs/ref/#view.DirectEditorProps.dispatchTransaction)
|
|
4784
|
+
when given, and otherwise defaults to applying the transaction to
|
|
4785
|
+
the current state and calling
|
|
4786
|
+
[`updateState`](https://prosemirror.net/docs/ref/#view.EditorView.updateState) with the result.
|
|
4787
|
+
This method is bound to the view instance, so that it can be
|
|
4788
|
+
easily passed around.
|
|
4789
|
+
*/
|
|
4790
|
+
dispatch(tr) {
|
|
4791
|
+
let dispatchTransaction = this._props.dispatchTransaction;
|
|
4792
|
+
if (dispatchTransaction)
|
|
4793
|
+
dispatchTransaction.call(this, tr);
|
|
4794
|
+
else
|
|
4795
|
+
this.updateState(this.state.apply(tr));
|
|
4796
|
+
}
|
|
4797
|
+
/**
|
|
4798
|
+
@internal
|
|
4799
|
+
*/
|
|
4800
|
+
domSelectionRange() {
|
|
4801
|
+
return safari && this.root.nodeType === 11 && deepActiveElement(this.dom.ownerDocument) == this.dom ? safariShadowSelectionRange(this) : this.domSelection();
|
|
4802
|
+
}
|
|
4803
|
+
/**
|
|
4804
|
+
@internal
|
|
4805
|
+
*/
|
|
4806
|
+
domSelection() {
|
|
4807
|
+
return this.root.getSelection();
|
|
4808
|
+
}
|
|
4809
|
+
};
|
|
4810
|
+
function computeDocDeco(view) {
|
|
4811
|
+
let attrs = /* @__PURE__ */ Object.create(null);
|
|
4812
|
+
attrs.class = "ProseMirror";
|
|
4813
|
+
attrs.contenteditable = String(view.editable);
|
|
4814
|
+
view.someProp("attributes", (value) => {
|
|
4815
|
+
if (typeof value == "function")
|
|
4816
|
+
value = value(view.state);
|
|
4817
|
+
if (value)
|
|
4818
|
+
for (let attr in value) {
|
|
4819
|
+
if (attr == "class")
|
|
4820
|
+
attrs.class += " " + value[attr];
|
|
4821
|
+
else if (attr == "style")
|
|
4822
|
+
attrs.style = (attrs.style ? attrs.style + ";" : "") + value[attr];
|
|
4823
|
+
else if (!attrs[attr] && attr != "contenteditable" && attr != "nodeName")
|
|
4824
|
+
attrs[attr] = String(value[attr]);
|
|
4825
|
+
}
|
|
4826
|
+
});
|
|
4827
|
+
if (!attrs.translate)
|
|
4828
|
+
attrs.translate = "no";
|
|
4829
|
+
return [Decoration.node(0, view.state.doc.content.size, attrs)];
|
|
4830
|
+
}
|
|
4831
|
+
function updateCursorWrapper(view) {
|
|
4832
|
+
if (view.markCursor) {
|
|
4833
|
+
let dom = document.createElement("img");
|
|
4834
|
+
dom.className = "ProseMirror-separator";
|
|
4835
|
+
dom.setAttribute("mark-placeholder", "true");
|
|
4836
|
+
dom.setAttribute("alt", "");
|
|
4837
|
+
view.cursorWrapper = { dom, deco: Decoration.widget(view.state.selection.head, dom, { raw: true, marks: view.markCursor }) };
|
|
4838
|
+
} else {
|
|
4839
|
+
view.cursorWrapper = null;
|
|
4840
|
+
}
|
|
4841
|
+
}
|
|
4842
|
+
function getEditable(view) {
|
|
4843
|
+
return !view.someProp("editable", (value) => value(view.state) === false);
|
|
4844
|
+
}
|
|
4845
|
+
function selectionContextChanged(sel1, sel2) {
|
|
4846
|
+
let depth = Math.min(sel1.$anchor.sharedDepth(sel1.head), sel2.$anchor.sharedDepth(sel2.head));
|
|
4847
|
+
return sel1.$anchor.start(depth) != sel2.$anchor.start(depth);
|
|
4848
|
+
}
|
|
4849
|
+
function buildNodeViews(view) {
|
|
4850
|
+
let result = /* @__PURE__ */ Object.create(null);
|
|
4851
|
+
function add(obj) {
|
|
4852
|
+
for (let prop in obj)
|
|
4853
|
+
if (!Object.prototype.hasOwnProperty.call(result, prop))
|
|
4854
|
+
result[prop] = obj[prop];
|
|
4855
|
+
}
|
|
4856
|
+
view.someProp("nodeViews", add);
|
|
4857
|
+
view.someProp("markViews", add);
|
|
4858
|
+
return result;
|
|
4859
|
+
}
|
|
4860
|
+
function changedNodeViews(a, b) {
|
|
4861
|
+
let nA = 0, nB = 0;
|
|
4862
|
+
for (let prop in a) {
|
|
4863
|
+
if (a[prop] != b[prop])
|
|
4864
|
+
return true;
|
|
4865
|
+
nA++;
|
|
4866
|
+
}
|
|
4867
|
+
for (let _ in b)
|
|
4868
|
+
nB++;
|
|
4869
|
+
return nA != nB;
|
|
4870
|
+
}
|
|
4871
|
+
function checkStateComponent(plugin) {
|
|
4872
|
+
if (plugin.spec.state || plugin.spec.filterTransaction || plugin.spec.appendTransaction)
|
|
4873
|
+
throw new RangeError("Plugins passed directly to the view must not have a state component");
|
|
4874
|
+
}
|
|
4875
|
+
|
|
4876
|
+
export {
|
|
4877
|
+
Decoration,
|
|
4878
|
+
DecorationSet,
|
|
4879
|
+
__serializeForClipboard,
|
|
4880
|
+
__parseFromClipboard,
|
|
4881
|
+
__endComposition,
|
|
4882
|
+
EditorView
|
|
4883
|
+
};
|