prosemirror-view 1.35.0 → 1.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/dist/index.cjs +28 -13
- package/dist/index.d.cts +52 -21
- package/dist/index.d.ts +52 -21
- package/dist/index.js +27 -14
- package/package.json +1 -1
- package/src/README.md +4 -0
- package/src/clipboard.ts +4 -1
- package/src/domobserver.ts +2 -2
- package/src/index.ts +3 -3
- package/src/selection.ts +1 -1
- package/src/viewdesc.ts +68 -33
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
## 1.37.0 (2024-11-23)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Fix an issue on Safari where the (incorrect) top-level selection was used, instead of the workaround that also works inside shadow roots.
|
|
6
|
+
|
|
7
|
+
### New features
|
|
8
|
+
|
|
9
|
+
Mark views can now provide an `ignoreMutation` method. Add ViewMutationRecord to doc template
|
|
10
|
+
|
|
11
|
+
## 1.36.0 (2024-11-05)
|
|
12
|
+
|
|
13
|
+
### Bug fixes
|
|
14
|
+
|
|
15
|
+
Don't recreated `TrustedTypePolicy` objects for every paste.
|
|
16
|
+
|
|
17
|
+
### New features
|
|
18
|
+
|
|
19
|
+
Add support for a `destroy` method on custom mark views. Add MarkView to the doc template
|
|
20
|
+
|
|
1
21
|
## 1.35.0 (2024-10-29)
|
|
2
22
|
|
|
3
23
|
### New features
|
package/dist/index.cjs
CHANGED
|
@@ -935,19 +935,20 @@ var ViewDesc = function () {
|
|
|
935
935
|
}
|
|
936
936
|
}, {
|
|
937
937
|
key: "setSelection",
|
|
938
|
-
value: function setSelection(anchor, head,
|
|
938
|
+
value: function setSelection(anchor, head, view) {
|
|
939
939
|
var force = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
|
|
940
940
|
var from = Math.min(anchor, head),
|
|
941
941
|
to = Math.max(anchor, head);
|
|
942
942
|
for (var i = 0, offset = 0; i < this.children.length; i++) {
|
|
943
943
|
var child = this.children[i],
|
|
944
944
|
end = offset + child.size;
|
|
945
|
-
if (from > offset && to < end) return child.setSelection(anchor - offset - child.border, head - offset - child.border,
|
|
945
|
+
if (from > offset && to < end) return child.setSelection(anchor - offset - child.border, head - offset - child.border, view, force);
|
|
946
946
|
offset = end;
|
|
947
947
|
}
|
|
948
948
|
var anchorDOM = this.domFromPos(anchor, anchor ? -1 : 1);
|
|
949
949
|
var headDOM = head == anchor ? anchorDOM : this.domFromPos(head, head ? -1 : 1);
|
|
950
|
-
var domSel = root.getSelection();
|
|
950
|
+
var domSel = view.root.getSelection();
|
|
951
|
+
var selRange = view.domSelectionRange();
|
|
951
952
|
var brKludge = false;
|
|
952
953
|
if ((gecko || safari) && anchor == head) {
|
|
953
954
|
var _anchorDOM = anchorDOM,
|
|
@@ -973,11 +974,11 @@ var ViewDesc = function () {
|
|
|
973
974
|
brKludge = prev && (prev.nodeName == "BR" || prev.contentEditable == "false");
|
|
974
975
|
}
|
|
975
976
|
}
|
|
976
|
-
if (gecko &&
|
|
977
|
-
var _after2 =
|
|
977
|
+
if (gecko && selRange.focusNode && selRange.focusNode != headDOM.node && selRange.focusNode.nodeType == 1) {
|
|
978
|
+
var _after2 = selRange.focusNode.childNodes[selRange.focusOffset];
|
|
978
979
|
if (_after2 && _after2.contentEditable == "false") force = true;
|
|
979
980
|
}
|
|
980
|
-
if (!(force || brKludge && safari) && isEquivalentPosition(anchorDOM.node, anchorDOM.offset,
|
|
981
|
+
if (!(force || brKludge && safari) && isEquivalentPosition(anchorDOM.node, anchorDOM.offset, selRange.anchorNode, selRange.anchorOffset) && isEquivalentPosition(headDOM.node, headDOM.offset, selRange.focusNode, selRange.focusOffset)) return;
|
|
981
982
|
var domSelExtended = false;
|
|
982
983
|
if ((domSel.extend || anchor == head) && !brKludge) {
|
|
983
984
|
domSel.collapse(anchorDOM.node, anchorDOM.offset);
|
|
@@ -1167,11 +1168,12 @@ var CompositionViewDesc = function (_ViewDesc2) {
|
|
|
1167
1168
|
var MarkViewDesc = function (_ViewDesc3) {
|
|
1168
1169
|
_inherits(MarkViewDesc, _ViewDesc3);
|
|
1169
1170
|
var _super3 = _createSuper(MarkViewDesc);
|
|
1170
|
-
function MarkViewDesc(parent, mark, dom, contentDOM) {
|
|
1171
|
+
function MarkViewDesc(parent, mark, dom, contentDOM, spec) {
|
|
1171
1172
|
var _this3;
|
|
1172
1173
|
_classCallCheck(this, MarkViewDesc);
|
|
1173
1174
|
_this3 = _super3.call(this, parent, [], dom, contentDOM);
|
|
1174
1175
|
_this3.mark = mark;
|
|
1176
|
+
_this3.spec = spec;
|
|
1175
1177
|
return _this3;
|
|
1176
1178
|
}
|
|
1177
1179
|
_createClass(MarkViewDesc, [{
|
|
@@ -1212,13 +1214,24 @@ var MarkViewDesc = function (_ViewDesc3) {
|
|
|
1212
1214
|
copy.children = nodes;
|
|
1213
1215
|
return copy;
|
|
1214
1216
|
}
|
|
1217
|
+
}, {
|
|
1218
|
+
key: "ignoreMutation",
|
|
1219
|
+
value: function ignoreMutation(mutation) {
|
|
1220
|
+
return this.spec.ignoreMutation ? this.spec.ignoreMutation(mutation) : _get(_getPrototypeOf(MarkViewDesc.prototype), "ignoreMutation", this).call(this, mutation);
|
|
1221
|
+
}
|
|
1222
|
+
}, {
|
|
1223
|
+
key: "destroy",
|
|
1224
|
+
value: function destroy() {
|
|
1225
|
+
if (this.spec.destroy) this.spec.destroy();
|
|
1226
|
+
_get(_getPrototypeOf(MarkViewDesc.prototype), "destroy", this).call(this);
|
|
1227
|
+
}
|
|
1215
1228
|
}], [{
|
|
1216
1229
|
key: "create",
|
|
1217
1230
|
value: function create(parent, mark, inline, view) {
|
|
1218
1231
|
var custom = view.nodeViews[mark.type.name];
|
|
1219
1232
|
var spec = custom && custom(mark, view, inline);
|
|
1220
1233
|
if (!spec || !spec.dom) spec = prosemirrorModel.DOMSerializer.renderSpec(document, mark.type.spec.toDOM(mark, inline), null, mark.attrs);
|
|
1221
|
-
return new MarkViewDesc(parent, mark, spec.dom, spec.contentDOM || spec.dom);
|
|
1234
|
+
return new MarkViewDesc(parent, mark, spec.dom, spec.contentDOM || spec.dom, spec);
|
|
1222
1235
|
}
|
|
1223
1236
|
}]);
|
|
1224
1237
|
return MarkViewDesc;
|
|
@@ -1586,8 +1599,8 @@ var CustomNodeViewDesc = function (_NodeViewDesc2) {
|
|
|
1586
1599
|
}
|
|
1587
1600
|
}, {
|
|
1588
1601
|
key: "setSelection",
|
|
1589
|
-
value: function setSelection(anchor, head,
|
|
1590
|
-
this.spec.setSelection ? this.spec.setSelection(anchor, head, root) : _get(_getPrototypeOf(CustomNodeViewDesc.prototype), "setSelection", this).call(this, anchor, head,
|
|
1602
|
+
value: function setSelection(anchor, head, view, force) {
|
|
1603
|
+
this.spec.setSelection ? this.spec.setSelection(anchor, head, view.root) : _get(_getPrototypeOf(CustomNodeViewDesc.prototype), "setSelection", this).call(this, anchor, head, view, force);
|
|
1591
1604
|
}
|
|
1592
1605
|
}, {
|
|
1593
1606
|
key: "destroy",
|
|
@@ -2172,7 +2185,7 @@ function selectionToDOM(view) {
|
|
|
2172
2185
|
if (!sel.$from.parent.inlineContent) resetEditableFrom = temporarilyEditableNear(view, sel.from);
|
|
2173
2186
|
if (!sel.empty && !sel.$from.parent.inlineContent) resetEditableTo = temporarilyEditableNear(view, sel.to);
|
|
2174
2187
|
}
|
|
2175
|
-
view.docView.setSelection(anchor, head, view
|
|
2188
|
+
view.docView.setSelection(anchor, head, view, force);
|
|
2176
2189
|
if (brokenSelectBetweenUneditable) {
|
|
2177
2190
|
if (resetEditableFrom) resetEditable(resetEditableFrom);
|
|
2178
2191
|
if (resetEditableTo) resetEditable(resetEditableTo);
|
|
@@ -2783,14 +2796,16 @@ var _detachedDoc = null;
|
|
|
2783
2796
|
function detachedDoc() {
|
|
2784
2797
|
return _detachedDoc || (_detachedDoc = document.implementation.createHTMLDocument("title"));
|
|
2785
2798
|
}
|
|
2799
|
+
var _policy = null;
|
|
2786
2800
|
function maybeWrapTrusted(html) {
|
|
2787
2801
|
var trustedTypes = window.trustedTypes;
|
|
2788
2802
|
if (!trustedTypes) return html;
|
|
2789
|
-
|
|
2803
|
+
if (!_policy) _policy = trustedTypes.createPolicy("ProseMirrorClipboard", {
|
|
2790
2804
|
createHTML: function createHTML(s) {
|
|
2791
2805
|
return s;
|
|
2792
2806
|
}
|
|
2793
|
-
})
|
|
2807
|
+
});
|
|
2808
|
+
return _policy.createHTML(html);
|
|
2794
2809
|
}
|
|
2795
2810
|
function readHTML(html) {
|
|
2796
2811
|
var metas = /^(\s*<meta [^>]*>)*/.exec(html);
|
package/dist/index.d.cts
CHANGED
|
@@ -238,6 +238,17 @@ declare global {
|
|
|
238
238
|
}
|
|
239
239
|
}
|
|
240
240
|
/**
|
|
241
|
+
A ViewMutationRecord represents a DOM
|
|
242
|
+
[mutation](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver)
|
|
243
|
+
or a selection change happens within the view. When the change is
|
|
244
|
+
a selection change, the record will have a `type` property of
|
|
245
|
+
`"selection"` (which doesn't occur for native mutation records).
|
|
246
|
+
*/
|
|
247
|
+
type ViewMutationRecord = MutationRecord | {
|
|
248
|
+
type: "selection";
|
|
249
|
+
target: DOMNode;
|
|
250
|
+
};
|
|
251
|
+
/**
|
|
241
252
|
By default, document nodes are rendered using the result of the
|
|
242
253
|
[`toDOM`](https://prosemirror.net/docs/ref/#model.NodeSpec.toDOM) method of their spec, and managed
|
|
243
254
|
entirely by the editor. For some use cases, such as embedded
|
|
@@ -245,9 +256,6 @@ node-specific editing interfaces, you want more control over
|
|
|
245
256
|
the behavior of a node's in-editor representation, and need to
|
|
246
257
|
[define](https://prosemirror.net/docs/ref/#view.EditorProps.nodeViews) a custom node view.
|
|
247
258
|
|
|
248
|
-
Mark views only support `dom` and `contentDOM`, and don't support
|
|
249
|
-
any of the node view methods.
|
|
250
|
-
|
|
251
259
|
Objects returned as node views must conform to this interface.
|
|
252
260
|
*/
|
|
253
261
|
interface NodeView {
|
|
@@ -311,19 +319,45 @@ interface NodeView {
|
|
|
311
319
|
*/
|
|
312
320
|
stopEvent?: (event: Event) => boolean;
|
|
313
321
|
/**
|
|
314
|
-
Called when a
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
a selection change, the record will have a `type` property of
|
|
318
|
-
`"selection"` (which doesn't occur for native mutation records).
|
|
319
|
-
Return false if the editor should re-read the selection or
|
|
320
|
-
re-parse the range around the mutation, true if it can safely be
|
|
321
|
-
ignored.
|
|
322
|
+
Called when a [mutation](https://prosemirror.net/docs/ref/#view.ViewMutationRecord) happens within the
|
|
323
|
+
view. Return false if the editor should re-read the selection or re-parse
|
|
324
|
+
the range around the mutation, true if it can safely be ignored.
|
|
322
325
|
*/
|
|
323
|
-
ignoreMutation?: (mutation:
|
|
326
|
+
ignoreMutation?: (mutation: ViewMutationRecord) => boolean;
|
|
324
327
|
/**
|
|
325
328
|
Called when the node view is removed from the editor or the whole
|
|
326
|
-
editor is destroyed.
|
|
329
|
+
editor is destroyed.
|
|
330
|
+
*/
|
|
331
|
+
destroy?: () => void;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
By default, document marks are rendered using the result of the
|
|
335
|
+
[`toDOM`](https://prosemirror.net/docs/ref/#model.MarkSpec.toDOM) method of their spec, and managed entirely
|
|
336
|
+
by the editor. For some use cases, you want more control over the behavior
|
|
337
|
+
of a mark's in-editor representation, and need to
|
|
338
|
+
[define](https://prosemirror.net/docs/ref/#view.EditorProps.markViews) a custom mark view.
|
|
339
|
+
|
|
340
|
+
Objects returned as mark views must conform to this interface.
|
|
341
|
+
*/
|
|
342
|
+
interface MarkView {
|
|
343
|
+
/**
|
|
344
|
+
The outer DOM node that represents the document node.
|
|
345
|
+
*/
|
|
346
|
+
dom: DOMNode;
|
|
347
|
+
/**
|
|
348
|
+
The DOM node that should hold the mark's content. When this is not
|
|
349
|
+
present, the `dom` property is used as the content DOM.
|
|
350
|
+
*/
|
|
351
|
+
contentDOM?: HTMLElement | null;
|
|
352
|
+
/**
|
|
353
|
+
Called when a [mutation](https://prosemirror.net/docs/ref/#view.ViewMutationRecord) happens within the
|
|
354
|
+
view. Return false if the editor should re-read the selection or re-parse
|
|
355
|
+
the range around the mutation, true if it can safely be ignored.
|
|
356
|
+
*/
|
|
357
|
+
ignoreMutation?: (mutation: ViewMutationRecord) => boolean;
|
|
358
|
+
/**
|
|
359
|
+
Called when the mark view is removed from the editor or the whole
|
|
360
|
+
editor is destroyed.
|
|
327
361
|
*/
|
|
328
362
|
destroy?: () => void;
|
|
329
363
|
}
|
|
@@ -369,8 +403,8 @@ declare class ViewDesc {
|
|
|
369
403
|
};
|
|
370
404
|
emptyChildAt(side: number): boolean;
|
|
371
405
|
domAfterPos(pos: number): DOMNode;
|
|
372
|
-
setSelection(anchor: number, head: number,
|
|
373
|
-
ignoreMutation(mutation:
|
|
406
|
+
setSelection(anchor: number, head: number, view: EditorView, force?: boolean): void;
|
|
407
|
+
ignoreMutation(mutation: ViewMutationRecord): boolean;
|
|
374
408
|
get contentLost(): boolean | null;
|
|
375
409
|
markDirty(from: number, to: number): void;
|
|
376
410
|
markParentsDirty(): void;
|
|
@@ -419,7 +453,7 @@ declare class TextViewDesc extends NodeViewDesc {
|
|
|
419
453
|
offset: number;
|
|
420
454
|
};
|
|
421
455
|
localPosFromDOM(dom: DOMNode, offset: number, bias: number): number;
|
|
422
|
-
ignoreMutation(mutation:
|
|
456
|
+
ignoreMutation(mutation: ViewMutationRecord): boolean;
|
|
423
457
|
slice(from: number, to: number, view: EditorView): TextViewDesc;
|
|
424
458
|
markDirty(from: number, to: number): void;
|
|
425
459
|
get domAtom(): boolean;
|
|
@@ -650,10 +684,7 @@ type NodeViewConstructor = (node: Node, view: EditorView, getPos: () => number |
|
|
|
650
684
|
The function types [used](https://prosemirror.net/docs/ref/#view.EditorProps.markViews) to create
|
|
651
685
|
mark views.
|
|
652
686
|
*/
|
|
653
|
-
type MarkViewConstructor = (mark: Mark, view: EditorView, inline: boolean) =>
|
|
654
|
-
dom: HTMLElement;
|
|
655
|
-
contentDOM?: HTMLElement;
|
|
656
|
-
};
|
|
687
|
+
type MarkViewConstructor = (mark: Mark, view: EditorView, inline: boolean) => MarkView;
|
|
657
688
|
/**
|
|
658
689
|
Helper type that maps event names to event object types, but
|
|
659
690
|
includes events that TypeScript's HTMLElementEventMap doesn't know
|
|
@@ -936,4 +967,4 @@ interface DirectEditorProps extends EditorProps {
|
|
|
936
967
|
dispatchTransaction?: (tr: Transaction) => void;
|
|
937
968
|
}
|
|
938
969
|
|
|
939
|
-
export { type DOMEventMap, Decoration, type DecorationAttrs, DecorationSet, type DecorationSource, type DirectEditorProps, type EditorProps, EditorView, type MarkViewConstructor, type NodeView, type NodeViewConstructor };
|
|
970
|
+
export { type DOMEventMap, Decoration, type DecorationAttrs, DecorationSet, type DecorationSource, type DirectEditorProps, type EditorProps, EditorView, type MarkView, type MarkViewConstructor, type NodeView, type NodeViewConstructor, type ViewMutationRecord };
|
package/dist/index.d.ts
CHANGED
|
@@ -238,6 +238,17 @@ declare global {
|
|
|
238
238
|
}
|
|
239
239
|
}
|
|
240
240
|
/**
|
|
241
|
+
A ViewMutationRecord represents a DOM
|
|
242
|
+
[mutation](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver)
|
|
243
|
+
or a selection change happens within the view. When the change is
|
|
244
|
+
a selection change, the record will have a `type` property of
|
|
245
|
+
`"selection"` (which doesn't occur for native mutation records).
|
|
246
|
+
*/
|
|
247
|
+
type ViewMutationRecord = MutationRecord | {
|
|
248
|
+
type: "selection";
|
|
249
|
+
target: DOMNode;
|
|
250
|
+
};
|
|
251
|
+
/**
|
|
241
252
|
By default, document nodes are rendered using the result of the
|
|
242
253
|
[`toDOM`](https://prosemirror.net/docs/ref/#model.NodeSpec.toDOM) method of their spec, and managed
|
|
243
254
|
entirely by the editor. For some use cases, such as embedded
|
|
@@ -245,9 +256,6 @@ node-specific editing interfaces, you want more control over
|
|
|
245
256
|
the behavior of a node's in-editor representation, and need to
|
|
246
257
|
[define](https://prosemirror.net/docs/ref/#view.EditorProps.nodeViews) a custom node view.
|
|
247
258
|
|
|
248
|
-
Mark views only support `dom` and `contentDOM`, and don't support
|
|
249
|
-
any of the node view methods.
|
|
250
|
-
|
|
251
259
|
Objects returned as node views must conform to this interface.
|
|
252
260
|
*/
|
|
253
261
|
interface NodeView {
|
|
@@ -311,19 +319,45 @@ interface NodeView {
|
|
|
311
319
|
*/
|
|
312
320
|
stopEvent?: (event: Event) => boolean;
|
|
313
321
|
/**
|
|
314
|
-
Called when a
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
a selection change, the record will have a `type` property of
|
|
318
|
-
`"selection"` (which doesn't occur for native mutation records).
|
|
319
|
-
Return false if the editor should re-read the selection or
|
|
320
|
-
re-parse the range around the mutation, true if it can safely be
|
|
321
|
-
ignored.
|
|
322
|
+
Called when a [mutation](https://prosemirror.net/docs/ref/#view.ViewMutationRecord) happens within the
|
|
323
|
+
view. Return false if the editor should re-read the selection or re-parse
|
|
324
|
+
the range around the mutation, true if it can safely be ignored.
|
|
322
325
|
*/
|
|
323
|
-
ignoreMutation?: (mutation:
|
|
326
|
+
ignoreMutation?: (mutation: ViewMutationRecord) => boolean;
|
|
324
327
|
/**
|
|
325
328
|
Called when the node view is removed from the editor or the whole
|
|
326
|
-
editor is destroyed.
|
|
329
|
+
editor is destroyed.
|
|
330
|
+
*/
|
|
331
|
+
destroy?: () => void;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
By default, document marks are rendered using the result of the
|
|
335
|
+
[`toDOM`](https://prosemirror.net/docs/ref/#model.MarkSpec.toDOM) method of their spec, and managed entirely
|
|
336
|
+
by the editor. For some use cases, you want more control over the behavior
|
|
337
|
+
of a mark's in-editor representation, and need to
|
|
338
|
+
[define](https://prosemirror.net/docs/ref/#view.EditorProps.markViews) a custom mark view.
|
|
339
|
+
|
|
340
|
+
Objects returned as mark views must conform to this interface.
|
|
341
|
+
*/
|
|
342
|
+
interface MarkView {
|
|
343
|
+
/**
|
|
344
|
+
The outer DOM node that represents the document node.
|
|
345
|
+
*/
|
|
346
|
+
dom: DOMNode;
|
|
347
|
+
/**
|
|
348
|
+
The DOM node that should hold the mark's content. When this is not
|
|
349
|
+
present, the `dom` property is used as the content DOM.
|
|
350
|
+
*/
|
|
351
|
+
contentDOM?: HTMLElement | null;
|
|
352
|
+
/**
|
|
353
|
+
Called when a [mutation](https://prosemirror.net/docs/ref/#view.ViewMutationRecord) happens within the
|
|
354
|
+
view. Return false if the editor should re-read the selection or re-parse
|
|
355
|
+
the range around the mutation, true if it can safely be ignored.
|
|
356
|
+
*/
|
|
357
|
+
ignoreMutation?: (mutation: ViewMutationRecord) => boolean;
|
|
358
|
+
/**
|
|
359
|
+
Called when the mark view is removed from the editor or the whole
|
|
360
|
+
editor is destroyed.
|
|
327
361
|
*/
|
|
328
362
|
destroy?: () => void;
|
|
329
363
|
}
|
|
@@ -369,8 +403,8 @@ declare class ViewDesc {
|
|
|
369
403
|
};
|
|
370
404
|
emptyChildAt(side: number): boolean;
|
|
371
405
|
domAfterPos(pos: number): DOMNode;
|
|
372
|
-
setSelection(anchor: number, head: number,
|
|
373
|
-
ignoreMutation(mutation:
|
|
406
|
+
setSelection(anchor: number, head: number, view: EditorView, force?: boolean): void;
|
|
407
|
+
ignoreMutation(mutation: ViewMutationRecord): boolean;
|
|
374
408
|
get contentLost(): boolean | null;
|
|
375
409
|
markDirty(from: number, to: number): void;
|
|
376
410
|
markParentsDirty(): void;
|
|
@@ -419,7 +453,7 @@ declare class TextViewDesc extends NodeViewDesc {
|
|
|
419
453
|
offset: number;
|
|
420
454
|
};
|
|
421
455
|
localPosFromDOM(dom: DOMNode, offset: number, bias: number): number;
|
|
422
|
-
ignoreMutation(mutation:
|
|
456
|
+
ignoreMutation(mutation: ViewMutationRecord): boolean;
|
|
423
457
|
slice(from: number, to: number, view: EditorView): TextViewDesc;
|
|
424
458
|
markDirty(from: number, to: number): void;
|
|
425
459
|
get domAtom(): boolean;
|
|
@@ -650,10 +684,7 @@ type NodeViewConstructor = (node: Node, view: EditorView, getPos: () => number |
|
|
|
650
684
|
The function types [used](https://prosemirror.net/docs/ref/#view.EditorProps.markViews) to create
|
|
651
685
|
mark views.
|
|
652
686
|
*/
|
|
653
|
-
type MarkViewConstructor = (mark: Mark, view: EditorView, inline: boolean) =>
|
|
654
|
-
dom: HTMLElement;
|
|
655
|
-
contentDOM?: HTMLElement;
|
|
656
|
-
};
|
|
687
|
+
type MarkViewConstructor = (mark: Mark, view: EditorView, inline: boolean) => MarkView;
|
|
657
688
|
/**
|
|
658
689
|
Helper type that maps event names to event object types, but
|
|
659
690
|
includes events that TypeScript's HTMLElementEventMap doesn't know
|
|
@@ -936,4 +967,4 @@ interface DirectEditorProps extends EditorProps {
|
|
|
936
967
|
dispatchTransaction?: (tr: Transaction) => void;
|
|
937
968
|
}
|
|
938
969
|
|
|
939
|
-
export { type DOMEventMap, Decoration, type DecorationAttrs, DecorationSet, type DecorationSource, type DirectEditorProps, type EditorProps, EditorView, type MarkViewConstructor, type NodeView, type NodeViewConstructor };
|
|
970
|
+
export { type DOMEventMap, Decoration, type DecorationAttrs, DecorationSet, type DecorationSource, type DirectEditorProps, type EditorProps, EditorView, type MarkView, type MarkViewConstructor, type NodeView, type NodeViewConstructor, type ViewMutationRecord };
|
package/dist/index.js
CHANGED
|
@@ -996,18 +996,19 @@ class ViewDesc {
|
|
|
996
996
|
// custom things with the selection. Note that this falls apart when
|
|
997
997
|
// a selection starts in such a node and ends in another, in which
|
|
998
998
|
// case we just use whatever domFromPos produces as a best effort.
|
|
999
|
-
setSelection(anchor, head,
|
|
999
|
+
setSelection(anchor, head, view, force = false) {
|
|
1000
1000
|
// If the selection falls entirely in a child, give it to that child
|
|
1001
1001
|
let from = Math.min(anchor, head), to = Math.max(anchor, head);
|
|
1002
1002
|
for (let i = 0, offset = 0; i < this.children.length; i++) {
|
|
1003
1003
|
let child = this.children[i], end = offset + child.size;
|
|
1004
1004
|
if (from > offset && to < end)
|
|
1005
|
-
return child.setSelection(anchor - offset - child.border, head - offset - child.border,
|
|
1005
|
+
return child.setSelection(anchor - offset - child.border, head - offset - child.border, view, force);
|
|
1006
1006
|
offset = end;
|
|
1007
1007
|
}
|
|
1008
1008
|
let anchorDOM = this.domFromPos(anchor, anchor ? -1 : 1);
|
|
1009
1009
|
let headDOM = head == anchor ? anchorDOM : this.domFromPos(head, head ? -1 : 1);
|
|
1010
|
-
let domSel = root.getSelection();
|
|
1010
|
+
let domSel = view.root.getSelection();
|
|
1011
|
+
let selRange = view.domSelectionRange();
|
|
1011
1012
|
let brKludge = false;
|
|
1012
1013
|
// On Firefox, using Selection.collapse to put the cursor after a
|
|
1013
1014
|
// BR node for some reason doesn't always work (#1073). On Safari,
|
|
@@ -1038,14 +1039,14 @@ class ViewDesc {
|
|
|
1038
1039
|
}
|
|
1039
1040
|
// Firefox can act strangely when the selection is in front of an
|
|
1040
1041
|
// uneditable node. See #1163 and https://bugzilla.mozilla.org/show_bug.cgi?id=1709536
|
|
1041
|
-
if (gecko &&
|
|
1042
|
-
let after =
|
|
1042
|
+
if (gecko && selRange.focusNode && selRange.focusNode != headDOM.node && selRange.focusNode.nodeType == 1) {
|
|
1043
|
+
let after = selRange.focusNode.childNodes[selRange.focusOffset];
|
|
1043
1044
|
if (after && after.contentEditable == "false")
|
|
1044
1045
|
force = true;
|
|
1045
1046
|
}
|
|
1046
1047
|
if (!(force || brKludge && safari) &&
|
|
1047
|
-
isEquivalentPosition(anchorDOM.node, anchorDOM.offset,
|
|
1048
|
-
isEquivalentPosition(headDOM.node, headDOM.offset,
|
|
1048
|
+
isEquivalentPosition(anchorDOM.node, anchorDOM.offset, selRange.anchorNode, selRange.anchorOffset) &&
|
|
1049
|
+
isEquivalentPosition(headDOM.node, headDOM.offset, selRange.focusNode, selRange.focusOffset))
|
|
1049
1050
|
return;
|
|
1050
1051
|
// Selection.extend can be used to create an 'inverted' selection
|
|
1051
1052
|
// (one where the focus is before the anchor), but not all
|
|
@@ -1192,16 +1193,17 @@ class CompositionViewDesc extends ViewDesc {
|
|
|
1192
1193
|
// some cases they will be split more often than would appear
|
|
1193
1194
|
// necessary.
|
|
1194
1195
|
class MarkViewDesc extends ViewDesc {
|
|
1195
|
-
constructor(parent, mark, dom, contentDOM) {
|
|
1196
|
+
constructor(parent, mark, dom, contentDOM, spec) {
|
|
1196
1197
|
super(parent, [], dom, contentDOM);
|
|
1197
1198
|
this.mark = mark;
|
|
1199
|
+
this.spec = spec;
|
|
1198
1200
|
}
|
|
1199
1201
|
static create(parent, mark, inline, view) {
|
|
1200
1202
|
let custom = view.nodeViews[mark.type.name];
|
|
1201
1203
|
let spec = custom && custom(mark, view, inline);
|
|
1202
1204
|
if (!spec || !spec.dom)
|
|
1203
1205
|
spec = DOMSerializer.renderSpec(document, mark.type.spec.toDOM(mark, inline), null, mark.attrs);
|
|
1204
|
-
return new MarkViewDesc(parent, mark, spec.dom, spec.contentDOM || spec.dom);
|
|
1206
|
+
return new MarkViewDesc(parent, mark, spec.dom, spec.contentDOM || spec.dom, spec);
|
|
1205
1207
|
}
|
|
1206
1208
|
parseRule() {
|
|
1207
1209
|
if ((this.dirty & NODE_DIRTY) || this.mark.type.spec.reparseInView)
|
|
@@ -1233,6 +1235,14 @@ class MarkViewDesc extends ViewDesc {
|
|
|
1233
1235
|
copy.children = nodes;
|
|
1234
1236
|
return copy;
|
|
1235
1237
|
}
|
|
1238
|
+
ignoreMutation(mutation) {
|
|
1239
|
+
return this.spec.ignoreMutation ? this.spec.ignoreMutation(mutation) : super.ignoreMutation(mutation);
|
|
1240
|
+
}
|
|
1241
|
+
destroy() {
|
|
1242
|
+
if (this.spec.destroy)
|
|
1243
|
+
this.spec.destroy();
|
|
1244
|
+
super.destroy();
|
|
1245
|
+
}
|
|
1236
1246
|
}
|
|
1237
1247
|
// Node view descs are the main, most common type of view desc, and
|
|
1238
1248
|
// correspond to an actual node in the document. Unlike mark descs,
|
|
@@ -1571,9 +1581,9 @@ class CustomNodeViewDesc extends NodeViewDesc {
|
|
|
1571
1581
|
deselectNode() {
|
|
1572
1582
|
this.spec.deselectNode ? this.spec.deselectNode() : super.deselectNode();
|
|
1573
1583
|
}
|
|
1574
|
-
setSelection(anchor, head,
|
|
1575
|
-
this.spec.setSelection ? this.spec.setSelection(anchor, head, root)
|
|
1576
|
-
: super.setSelection(anchor, head,
|
|
1584
|
+
setSelection(anchor, head, view, force) {
|
|
1585
|
+
this.spec.setSelection ? this.spec.setSelection(anchor, head, view.root)
|
|
1586
|
+
: super.setSelection(anchor, head, view, force);
|
|
1577
1587
|
}
|
|
1578
1588
|
destroy() {
|
|
1579
1589
|
if (this.spec.destroy)
|
|
@@ -2233,7 +2243,7 @@ function selectionToDOM(view, force = false) {
|
|
|
2233
2243
|
if (!sel.empty && !sel.$from.parent.inlineContent)
|
|
2234
2244
|
resetEditableTo = temporarilyEditableNear(view, sel.to);
|
|
2235
2245
|
}
|
|
2236
|
-
view.docView.setSelection(anchor, head, view
|
|
2246
|
+
view.docView.setSelection(anchor, head, view, force);
|
|
2237
2247
|
if (brokenSelectBetweenUneditable) {
|
|
2238
2248
|
if (resetEditableFrom)
|
|
2239
2249
|
resetEditable(resetEditableFrom);
|
|
@@ -2953,6 +2963,7 @@ let _detachedDoc = null;
|
|
|
2953
2963
|
function detachedDoc() {
|
|
2954
2964
|
return _detachedDoc || (_detachedDoc = document.implementation.createHTMLDocument("title"));
|
|
2955
2965
|
}
|
|
2966
|
+
let _policy = null;
|
|
2956
2967
|
function maybeWrapTrusted(html) {
|
|
2957
2968
|
let trustedTypes = window.trustedTypes;
|
|
2958
2969
|
if (!trustedTypes)
|
|
@@ -2960,7 +2971,9 @@ function maybeWrapTrusted(html) {
|
|
|
2960
2971
|
// With the require-trusted-types-for CSP, Chrome will block
|
|
2961
2972
|
// innerHTML, even on a detached document. This wraps the string in
|
|
2962
2973
|
// a way that makes the browser allow us to use its parser again.
|
|
2963
|
-
|
|
2974
|
+
if (!_policy)
|
|
2975
|
+
_policy = trustedTypes.createPolicy("ProseMirrorClipboard", { createHTML: (s) => s });
|
|
2976
|
+
return _policy.createHTML(html);
|
|
2964
2977
|
}
|
|
2965
2978
|
function readHTML(html) {
|
|
2966
2979
|
let metas = /^(\s*<meta [^>]*>)*/.exec(html);
|
package/package.json
CHANGED
package/src/README.md
CHANGED
package/src/clipboard.ts
CHANGED
|
@@ -204,13 +204,16 @@ function detachedDoc() {
|
|
|
204
204
|
return _detachedDoc || (_detachedDoc = document.implementation.createHTMLDocument("title"))
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
+
let _policy: any = null
|
|
208
|
+
|
|
207
209
|
function maybeWrapTrusted(html: string): string {
|
|
208
210
|
let trustedTypes = (window as any).trustedTypes
|
|
209
211
|
if (!trustedTypes) return html
|
|
210
212
|
// With the require-trusted-types-for CSP, Chrome will block
|
|
211
213
|
// innerHTML, even on a detached document. This wraps the string in
|
|
212
214
|
// a way that makes the browser allow us to use its parser again.
|
|
213
|
-
|
|
215
|
+
if (!_policy) _policy = trustedTypes.createPolicy("ProseMirrorClipboard", {createHTML: (s: string) => s})
|
|
216
|
+
return _policy.createHTML(html)
|
|
214
217
|
}
|
|
215
218
|
|
|
216
219
|
function readHTML(html: string) {
|
package/src/domobserver.ts
CHANGED
|
@@ -151,8 +151,8 @@ export class DOMObserver {
|
|
|
151
151
|
let desc = container && this.view.docView.nearestDesc(container)
|
|
152
152
|
if (desc && desc.ignoreMutation({
|
|
153
153
|
type: "selection",
|
|
154
|
-
target: container!.nodeType == 3 ? container!.parentNode : container
|
|
155
|
-
}
|
|
154
|
+
target: container!.nodeType == 3 ? container!.parentNode! : container!
|
|
155
|
+
})) {
|
|
156
156
|
this.setCurSelection()
|
|
157
157
|
return true
|
|
158
158
|
}
|
package/src/index.ts
CHANGED
|
@@ -3,7 +3,7 @@ import {Slice, ResolvedPos, DOMParser, DOMSerializer, Node, Mark} from "prosemir
|
|
|
3
3
|
|
|
4
4
|
import {scrollRectIntoView, posAtCoords, coordsAtPos, endOfTextblock, storeScrollPos,
|
|
5
5
|
resetScrollPos, focusPreventScroll} from "./domcoords"
|
|
6
|
-
import {docViewDesc, ViewDesc, NodeView, NodeViewDesc} from "./viewdesc"
|
|
6
|
+
import {docViewDesc, ViewDesc, NodeView, NodeViewDesc, MarkView} from "./viewdesc"
|
|
7
7
|
import {initInput, destroyInput, dispatchEvent, ensureListeners, clearComposition,
|
|
8
8
|
InputState, doPaste, Dragging, findCompositionNode} from "./input"
|
|
9
9
|
import {selectionToDOM, anchorInRightPlace, syncNodeSelection} from "./selection"
|
|
@@ -14,7 +14,7 @@ import {DOMSelection, DOMNode, DOMSelectionRange, deepActiveElement, clearReused
|
|
|
14
14
|
import * as browser from "./browser"
|
|
15
15
|
|
|
16
16
|
export {Decoration, DecorationSet, DecorationAttrs, DecorationSource} from "./decoration"
|
|
17
|
-
export {NodeView} from "./viewdesc"
|
|
17
|
+
export {NodeView, MarkView, ViewMutationRecord} from "./viewdesc"
|
|
18
18
|
|
|
19
19
|
// Exported for testing
|
|
20
20
|
import {serializeForClipboard, parseFromClipboard} from "./clipboard"
|
|
@@ -576,7 +576,7 @@ export type NodeViewConstructor = (node: Node, view: EditorView, getPos: () => n
|
|
|
576
576
|
|
|
577
577
|
/// The function types [used](#view.EditorProps.markViews) to create
|
|
578
578
|
/// mark views.
|
|
579
|
-
export type MarkViewConstructor = (mark: Mark, view: EditorView, inline: boolean) =>
|
|
579
|
+
export type MarkViewConstructor = (mark: Mark, view: EditorView, inline: boolean) => MarkView
|
|
580
580
|
|
|
581
581
|
type NodeViewSet = {[name: string]: NodeViewConstructor | MarkViewConstructor}
|
|
582
582
|
|
package/src/selection.ts
CHANGED
|
@@ -84,7 +84,7 @@ export function selectionToDOM(view: EditorView, force = false) {
|
|
|
84
84
|
if (!sel.empty && !sel.$from.parent.inlineContent)
|
|
85
85
|
resetEditableTo = temporarilyEditableNear(view, sel.to)
|
|
86
86
|
}
|
|
87
|
-
view.docView.setSelection(anchor, head, view
|
|
87
|
+
view.docView.setSelection(anchor, head, view, force)
|
|
88
88
|
if (brokenSelectBetweenUneditable) {
|
|
89
89
|
if (resetEditableFrom) resetEditable(resetEditableFrom)
|
|
90
90
|
if (resetEditableTo) resetEditable(resetEditableTo)
|
package/src/viewdesc.ts
CHANGED
|
@@ -10,6 +10,13 @@ declare global {
|
|
|
10
10
|
interface Node { pmViewDesc?: ViewDesc }
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
/// A ViewMutationRecord represents a DOM
|
|
14
|
+
/// [mutation](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver)
|
|
15
|
+
/// or a selection change happens within the view. When the change is
|
|
16
|
+
/// a selection change, the record will have a `type` property of
|
|
17
|
+
/// `"selection"` (which doesn't occur for native mutation records).
|
|
18
|
+
export type ViewMutationRecord = MutationRecord | { type: "selection", target: DOMNode }
|
|
19
|
+
|
|
13
20
|
/// By default, document nodes are rendered using the result of the
|
|
14
21
|
/// [`toDOM`](#model.NodeSpec.toDOM) method of their spec, and managed
|
|
15
22
|
/// entirely by the editor. For some use cases, such as embedded
|
|
@@ -17,9 +24,6 @@ declare global {
|
|
|
17
24
|
/// the behavior of a node's in-editor representation, and need to
|
|
18
25
|
/// [define](#view.EditorProps.nodeViews) a custom node view.
|
|
19
26
|
///
|
|
20
|
-
/// Mark views only support `dom` and `contentDOM`, and don't support
|
|
21
|
-
/// any of the node view methods.
|
|
22
|
-
///
|
|
23
27
|
/// Objects returned as node views must conform to this interface.
|
|
24
28
|
export interface NodeView {
|
|
25
29
|
/// The outer DOM node that represents the document node.
|
|
@@ -73,18 +77,39 @@ export interface NodeView {
|
|
|
73
77
|
/// which this returns true are not handled by the editor.
|
|
74
78
|
stopEvent?: (event: Event) => boolean
|
|
75
79
|
|
|
76
|
-
/// Called when a
|
|
77
|
-
///
|
|
78
|
-
///
|
|
79
|
-
|
|
80
|
-
/// `"selection"` (which doesn't occur for native mutation records).
|
|
81
|
-
/// Return false if the editor should re-read the selection or
|
|
82
|
-
/// re-parse the range around the mutation, true if it can safely be
|
|
83
|
-
/// ignored.
|
|
84
|
-
ignoreMutation?: (mutation: MutationRecord) => boolean
|
|
80
|
+
/// Called when a [mutation](#view.ViewMutationRecord) happens within the
|
|
81
|
+
/// view. Return false if the editor should re-read the selection or re-parse
|
|
82
|
+
/// the range around the mutation, true if it can safely be ignored.
|
|
83
|
+
ignoreMutation?: (mutation: ViewMutationRecord) => boolean
|
|
85
84
|
|
|
86
85
|
/// Called when the node view is removed from the editor or the whole
|
|
87
|
-
/// editor is destroyed.
|
|
86
|
+
/// editor is destroyed.
|
|
87
|
+
destroy?: () => void
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/// By default, document marks are rendered using the result of the
|
|
91
|
+
/// [`toDOM`](#model.MarkSpec.toDOM) method of their spec, and managed entirely
|
|
92
|
+
/// by the editor. For some use cases, you want more control over the behavior
|
|
93
|
+
/// of a mark's in-editor representation, and need to
|
|
94
|
+
/// [define](#view.EditorProps.markViews) a custom mark view.
|
|
95
|
+
///
|
|
96
|
+
/// Objects returned as mark views must conform to this interface.
|
|
97
|
+
export interface MarkView {
|
|
98
|
+
/// The outer DOM node that represents the document node.
|
|
99
|
+
dom: DOMNode
|
|
100
|
+
|
|
101
|
+
/// The DOM node that should hold the mark's content. When this is not
|
|
102
|
+
/// present, the `dom` property is used as the content DOM.
|
|
103
|
+
contentDOM?: HTMLElement | null
|
|
104
|
+
|
|
105
|
+
/// Called when a [mutation](#view.ViewMutationRecord) happens within the
|
|
106
|
+
/// view. Return false if the editor should re-read the selection or re-parse
|
|
107
|
+
/// the range around the mutation, true if it can safely be ignored.
|
|
108
|
+
ignoreMutation?: (mutation: ViewMutationRecord) => boolean
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
/// Called when the mark view is removed from the editor or the whole
|
|
112
|
+
/// editor is destroyed.
|
|
88
113
|
destroy?: () => void
|
|
89
114
|
}
|
|
90
115
|
|
|
@@ -370,19 +395,20 @@ export class ViewDesc {
|
|
|
370
395
|
// custom things with the selection. Note that this falls apart when
|
|
371
396
|
// a selection starts in such a node and ends in another, in which
|
|
372
397
|
// case we just use whatever domFromPos produces as a best effort.
|
|
373
|
-
setSelection(anchor: number, head: number,
|
|
398
|
+
setSelection(anchor: number, head: number, view: EditorView, force = false): void {
|
|
374
399
|
// If the selection falls entirely in a child, give it to that child
|
|
375
400
|
let from = Math.min(anchor, head), to = Math.max(anchor, head)
|
|
376
401
|
for (let i = 0, offset = 0; i < this.children.length; i++) {
|
|
377
402
|
let child = this.children[i], end = offset + child.size
|
|
378
403
|
if (from > offset && to < end)
|
|
379
|
-
return child.setSelection(anchor - offset - child.border, head - offset - child.border,
|
|
404
|
+
return child.setSelection(anchor - offset - child.border, head - offset - child.border, view, force)
|
|
380
405
|
offset = end
|
|
381
406
|
}
|
|
382
407
|
|
|
383
408
|
let anchorDOM = this.domFromPos(anchor, anchor ? -1 : 1)
|
|
384
409
|
let headDOM = head == anchor ? anchorDOM : this.domFromPos(head, head ? -1 : 1)
|
|
385
|
-
let domSel = (root as Document).getSelection()!
|
|
410
|
+
let domSel = (view.root as Document).getSelection()!
|
|
411
|
+
let selRange = view.domSelectionRange()
|
|
386
412
|
|
|
387
413
|
let brKludge = false
|
|
388
414
|
// On Firefox, using Selection.collapse to put the cursor after a
|
|
@@ -412,14 +438,14 @@ export class ViewDesc {
|
|
|
412
438
|
}
|
|
413
439
|
// Firefox can act strangely when the selection is in front of an
|
|
414
440
|
// uneditable node. See #1163 and https://bugzilla.mozilla.org/show_bug.cgi?id=1709536
|
|
415
|
-
if (browser.gecko &&
|
|
416
|
-
let after =
|
|
441
|
+
if (browser.gecko && selRange.focusNode && selRange.focusNode != headDOM.node && selRange.focusNode.nodeType == 1) {
|
|
442
|
+
let after = selRange.focusNode.childNodes[selRange.focusOffset]
|
|
417
443
|
if (after && (after as HTMLElement).contentEditable == "false") force = true
|
|
418
444
|
}
|
|
419
445
|
|
|
420
446
|
if (!(force || brKludge && browser.safari) &&
|
|
421
|
-
isEquivalentPosition(anchorDOM.node, anchorDOM.offset,
|
|
422
|
-
isEquivalentPosition(headDOM.node, headDOM.offset,
|
|
447
|
+
isEquivalentPosition(anchorDOM.node, anchorDOM.offset, selRange.anchorNode!, selRange.anchorOffset) &&
|
|
448
|
+
isEquivalentPosition(headDOM.node, headDOM.offset, selRange.focusNode!, selRange.focusOffset))
|
|
423
449
|
return
|
|
424
450
|
|
|
425
451
|
// Selection.extend can be used to create an 'inverted' selection
|
|
@@ -451,8 +477,8 @@ export class ViewDesc {
|
|
|
451
477
|
}
|
|
452
478
|
}
|
|
453
479
|
|
|
454
|
-
ignoreMutation(mutation:
|
|
455
|
-
return !this.contentDOM &&
|
|
480
|
+
ignoreMutation(mutation: ViewMutationRecord): boolean {
|
|
481
|
+
return !this.contentDOM && mutation.type != "selection"
|
|
456
482
|
}
|
|
457
483
|
|
|
458
484
|
get contentLost() {
|
|
@@ -531,8 +557,8 @@ class WidgetViewDesc extends ViewDesc {
|
|
|
531
557
|
return stop ? stop(event) : false
|
|
532
558
|
}
|
|
533
559
|
|
|
534
|
-
ignoreMutation(mutation:
|
|
535
|
-
return
|
|
560
|
+
ignoreMutation(mutation: ViewMutationRecord) {
|
|
561
|
+
return mutation.type != "selection" || this.widget.spec.ignoreSelection
|
|
536
562
|
}
|
|
537
563
|
|
|
538
564
|
destroy() {
|
|
@@ -561,7 +587,7 @@ class CompositionViewDesc extends ViewDesc {
|
|
|
561
587
|
return {node: this.textDOM, offset: pos}
|
|
562
588
|
}
|
|
563
589
|
|
|
564
|
-
ignoreMutation(mut:
|
|
590
|
+
ignoreMutation(mut: ViewMutationRecord) {
|
|
565
591
|
return mut.type === 'characterData' && mut.target.nodeValue == mut.oldValue
|
|
566
592
|
}
|
|
567
593
|
}
|
|
@@ -572,7 +598,7 @@ class CompositionViewDesc extends ViewDesc {
|
|
|
572
598
|
// some cases they will be split more often than would appear
|
|
573
599
|
// necessary.
|
|
574
600
|
class MarkViewDesc extends ViewDesc {
|
|
575
|
-
constructor(parent: ViewDesc, readonly mark: Mark, dom: DOMNode, contentDOM: HTMLElement) {
|
|
601
|
+
constructor(parent: ViewDesc, readonly mark: Mark, dom: DOMNode, contentDOM: HTMLElement, readonly spec: MarkView) {
|
|
576
602
|
super(parent, [], dom, contentDOM)
|
|
577
603
|
}
|
|
578
604
|
|
|
@@ -581,7 +607,7 @@ class MarkViewDesc extends ViewDesc {
|
|
|
581
607
|
let spec: {dom: HTMLElement, contentDOM?: HTMLElement} = custom && (custom as any)(mark, view, inline)
|
|
582
608
|
if (!spec || !spec.dom)
|
|
583
609
|
spec = (DOMSerializer.renderSpec as any)(document, mark.type.spec.toDOM!(mark, inline), null, mark.attrs) as any
|
|
584
|
-
return new MarkViewDesc(parent, mark, spec.dom, spec.contentDOM || spec.dom as HTMLElement)
|
|
610
|
+
return new MarkViewDesc(parent, mark, spec.dom, spec.contentDOM || spec.dom as HTMLElement, spec)
|
|
585
611
|
}
|
|
586
612
|
|
|
587
613
|
parseRule() {
|
|
@@ -611,6 +637,15 @@ class MarkViewDesc extends ViewDesc {
|
|
|
611
637
|
copy.children = nodes
|
|
612
638
|
return copy
|
|
613
639
|
}
|
|
640
|
+
|
|
641
|
+
ignoreMutation(mutation: ViewMutationRecord) {
|
|
642
|
+
return this.spec.ignoreMutation ? this.spec.ignoreMutation(mutation) : super.ignoreMutation(mutation)
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
destroy() {
|
|
646
|
+
if (this.spec.destroy) this.spec.destroy()
|
|
647
|
+
super.destroy()
|
|
648
|
+
}
|
|
614
649
|
}
|
|
615
650
|
|
|
616
651
|
// Node view descs are the main, most common type of view desc, and
|
|
@@ -902,8 +937,8 @@ class TextViewDesc extends NodeViewDesc {
|
|
|
902
937
|
return super.localPosFromDOM(dom, offset, bias)
|
|
903
938
|
}
|
|
904
939
|
|
|
905
|
-
ignoreMutation(mutation:
|
|
906
|
-
return mutation.type != "characterData" &&
|
|
940
|
+
ignoreMutation(mutation: ViewMutationRecord) {
|
|
941
|
+
return mutation.type != "characterData" && mutation.type != "selection"
|
|
907
942
|
}
|
|
908
943
|
|
|
909
944
|
slice(from: number, to: number, view: EditorView) {
|
|
@@ -965,9 +1000,9 @@ class CustomNodeViewDesc extends NodeViewDesc {
|
|
|
965
1000
|
this.spec.deselectNode ? this.spec.deselectNode() : super.deselectNode()
|
|
966
1001
|
}
|
|
967
1002
|
|
|
968
|
-
setSelection(anchor: number, head: number,
|
|
969
|
-
this.spec.setSelection ? this.spec.setSelection(anchor, head, root)
|
|
970
|
-
: super.setSelection(anchor, head,
|
|
1003
|
+
setSelection(anchor: number, head: number, view: EditorView, force: boolean) {
|
|
1004
|
+
this.spec.setSelection ? this.spec.setSelection(anchor, head, view.root)
|
|
1005
|
+
: super.setSelection(anchor, head, view, force)
|
|
971
1006
|
}
|
|
972
1007
|
|
|
973
1008
|
destroy() {
|
|
@@ -979,7 +1014,7 @@ class CustomNodeViewDesc extends NodeViewDesc {
|
|
|
979
1014
|
return this.spec.stopEvent ? this.spec.stopEvent(event) : false
|
|
980
1015
|
}
|
|
981
1016
|
|
|
982
|
-
ignoreMutation(mutation:
|
|
1017
|
+
ignoreMutation(mutation: ViewMutationRecord) {
|
|
983
1018
|
return this.spec.ignoreMutation ? this.spec.ignoreMutation(mutation) : super.ignoreMutation(mutation)
|
|
984
1019
|
}
|
|
985
1020
|
}
|