prosemirror-view 1.31.7 → 1.32.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 +22 -0
- package/dist/index.cjs +61 -38
- package/dist/index.d.cts +16 -9
- package/dist/index.d.ts +16 -9
- package/dist/index.js +66 -31
- package/package.json +1 -1
- package/src/capturekeys.ts +16 -12
- package/src/decoration.ts +13 -8
- package/src/domcoords.ts +5 -0
- package/src/index.ts +6 -0
- package/src/viewdesc.ts +22 -13
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,25 @@
|
|
|
1
|
+
## 1.32.0 (2023-09-27)
|
|
2
|
+
|
|
3
|
+
### Bug fixes
|
|
4
|
+
|
|
5
|
+
Work around an issue on Chrome where, when clicking above the right side of an uneditable node, the cursor would be put after the node.
|
|
6
|
+
|
|
7
|
+
Fix a bug that could corrupt the composition when it occurs next to text identical to the composed characters.
|
|
8
|
+
|
|
9
|
+
### New features
|
|
10
|
+
|
|
11
|
+
The new `EditorView.updateRoot` method can be used to make the editor update its DOM root when it is moved to a new document or shadow tree.
|
|
12
|
+
|
|
13
|
+
## 1.31.8 (2023-09-12)
|
|
14
|
+
|
|
15
|
+
### Bug fixes
|
|
16
|
+
|
|
17
|
+
Fix a bug that broke arrow motion near uneditable nodes on Chrome in some situations.
|
|
18
|
+
|
|
19
|
+
Fix an issue that broke backspace at the end of a textblock that ended in a newline on Chrome.
|
|
20
|
+
|
|
21
|
+
Fix a crash in the way inline decorations that ended right after a node end position were drawn.
|
|
22
|
+
|
|
1
23
|
## 1.31.7 (2023-07-28)
|
|
2
24
|
|
|
3
25
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -32,10 +32,6 @@ function _defineProperties(target, props) { for (var i = 0; i < props.length; i+
|
|
|
32
32
|
|
|
33
33
|
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
|
|
34
34
|
|
|
35
|
-
Object.defineProperty(exports, '__esModule', {
|
|
36
|
-
value: true
|
|
37
|
-
});
|
|
38
|
-
|
|
39
35
|
var prosemirrorState = require('prosemirror-state');
|
|
40
36
|
|
|
41
37
|
var prosemirrorModel = require('prosemirror-model');
|
|
@@ -517,6 +513,8 @@ function _posAtCoords(view, coords) {
|
|
|
517
513
|
}
|
|
518
514
|
}
|
|
519
515
|
|
|
516
|
+
var prev;
|
|
517
|
+
if (webkit && offset && node.nodeType == 1 && (prev = node.childNodes[offset - 1]).nodeType == 1 && prev.contentEditable == "false" && prev.getBoundingClientRect().top >= coords.top) offset--;
|
|
520
518
|
if (node == view.dom && offset == node.childNodes.length - 1 && node.lastChild.nodeType == 1 && coords.top > node.lastChild.getBoundingClientRect().bottom) pos = view.state.doc.content.size;else if (offset == 0 || node.nodeType != 1 || node.childNodes[offset - 1].nodeName != "BR") pos = posFromCaret(view, node, offset, coords);
|
|
521
519
|
}
|
|
522
520
|
|
|
@@ -2190,9 +2188,13 @@ var ViewTreeUpdater = function () {
|
|
|
2190
2188
|
return true;
|
|
2191
2189
|
} else if (!locked && (updated = this.recreateWrapper(next, node, outerDeco, innerDeco, view, pos))) {
|
|
2192
2190
|
this.top.children[this.index] = updated;
|
|
2193
|
-
|
|
2194
|
-
updated.
|
|
2195
|
-
|
|
2191
|
+
|
|
2192
|
+
if (updated.contentDOM) {
|
|
2193
|
+
updated.dirty = CONTENT_DIRTY;
|
|
2194
|
+
updated.updateChildren(view, pos + 1);
|
|
2195
|
+
updated.dirty = NOT_DIRTY;
|
|
2196
|
+
}
|
|
2197
|
+
|
|
2196
2198
|
this.changed = true;
|
|
2197
2199
|
this.index++;
|
|
2198
2200
|
return true;
|
|
@@ -2209,25 +2211,27 @@ var ViewTreeUpdater = function () {
|
|
|
2209
2211
|
value: function recreateWrapper(next, node, outerDeco, innerDeco, view, pos) {
|
|
2210
2212
|
if (next.dirty || node.isAtom || !next.children.length || !next.node.content.eq(node.content)) return null;
|
|
2211
2213
|
var wrapper = NodeViewDesc.create(this.top, node, outerDeco, innerDeco, view, pos);
|
|
2212
|
-
if (!wrapper.contentDOM) return null;
|
|
2213
|
-
wrapper.children = next.children;
|
|
2214
|
-
next.children = [];
|
|
2215
|
-
next.destroy();
|
|
2216
2214
|
|
|
2217
|
-
|
|
2218
|
-
|
|
2215
|
+
if (wrapper.contentDOM) {
|
|
2216
|
+
wrapper.children = next.children;
|
|
2217
|
+
next.children = [];
|
|
2219
2218
|
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2219
|
+
var _iterator = _createForOfIteratorHelper(wrapper.children),
|
|
2220
|
+
_step;
|
|
2221
|
+
|
|
2222
|
+
try {
|
|
2223
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
2224
|
+
var ch = _step.value;
|
|
2225
|
+
ch.parent = wrapper;
|
|
2226
|
+
}
|
|
2227
|
+
} catch (err) {
|
|
2228
|
+
_iterator.e(err);
|
|
2229
|
+
} finally {
|
|
2230
|
+
_iterator.f();
|
|
2224
2231
|
}
|
|
2225
|
-
} catch (err) {
|
|
2226
|
-
_iterator.e(err);
|
|
2227
|
-
} finally {
|
|
2228
|
-
_iterator.f();
|
|
2229
2232
|
}
|
|
2230
2233
|
|
|
2234
|
+
next.destroy();
|
|
2231
2235
|
return wrapper;
|
|
2232
2236
|
}
|
|
2233
2237
|
}, {
|
|
@@ -2364,14 +2368,18 @@ function iterDeco(parent, deco, onWidget, onNode) {
|
|
|
2364
2368
|
restNode = null;
|
|
2365
2369
|
|
|
2366
2370
|
for (var parentIndex = 0;;) {
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2371
|
+
var widget = void 0,
|
|
2372
|
+
widgets = void 0;
|
|
2373
|
+
|
|
2374
|
+
while (decoIndex < locals.length && locals[decoIndex].to == offset) {
|
|
2375
|
+
var next = locals[decoIndex++];
|
|
2370
2376
|
|
|
2371
|
-
|
|
2372
|
-
(widgets || (widgets = [widget])).push(
|
|
2377
|
+
if (next.widget) {
|
|
2378
|
+
if (!widget) widget = next;else (widgets || (widgets = [widget])).push(next);
|
|
2373
2379
|
}
|
|
2380
|
+
}
|
|
2374
2381
|
|
|
2382
|
+
if (widget) {
|
|
2375
2383
|
if (widgets) {
|
|
2376
2384
|
widgets.sort(compareSide);
|
|
2377
2385
|
|
|
@@ -2473,6 +2481,7 @@ function findTextInFragment(frag, text, from, to) {
|
|
|
2473
2481
|
}
|
|
2474
2482
|
|
|
2475
2483
|
if (pos >= from) {
|
|
2484
|
+
if (pos >= to && str.slice(to - text.length - childStart, to - childStart) == text) return to - text.length;
|
|
2476
2485
|
var found = childStart < to ? str.lastIndexOf(text, to - childStart - 1) : -1;
|
|
2477
2486
|
if (found >= 0 && found + text.length + childStart >= from) return childStart + found;
|
|
2478
2487
|
if (from == to && str.length >= to + text.length - childStart && str.slice(to - childStart, to - childStart + text.length) == text) return to;
|
|
@@ -2773,10 +2782,10 @@ function nodeLen(node) {
|
|
|
2773
2782
|
return node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length;
|
|
2774
2783
|
}
|
|
2775
2784
|
|
|
2776
|
-
function isIgnorable(dom) {
|
|
2785
|
+
function isIgnorable(dom, dir) {
|
|
2777
2786
|
if (dom.contentEditable == "false") return true;
|
|
2778
2787
|
var desc = dom.pmViewDesc;
|
|
2779
|
-
return desc && desc.size == 0 && (dom.nextSibling || dom.nodeName != "BR");
|
|
2788
|
+
return desc && desc.size == 0 && (dir < 0 || dom.nextSibling || dom.nodeName != "BR");
|
|
2780
2789
|
}
|
|
2781
2790
|
|
|
2782
2791
|
function skipIgnoredNodes(view, dir) {
|
|
@@ -2791,7 +2800,7 @@ function skipIgnoredNodesBefore(view) {
|
|
|
2791
2800
|
var moveNode,
|
|
2792
2801
|
moveOffset,
|
|
2793
2802
|
force = false;
|
|
2794
|
-
if (gecko && node.nodeType == 1 && offset < nodeLen(node) && isIgnorable(node.childNodes[offset])) force = true;
|
|
2803
|
+
if (gecko && node.nodeType == 1 && offset < nodeLen(node) && isIgnorable(node.childNodes[offset], -1)) force = true;
|
|
2795
2804
|
|
|
2796
2805
|
for (;;) {
|
|
2797
2806
|
if (offset > 0) {
|
|
@@ -2800,7 +2809,7 @@ function skipIgnoredNodesBefore(view) {
|
|
|
2800
2809
|
} else {
|
|
2801
2810
|
var before = node.childNodes[offset - 1];
|
|
2802
2811
|
|
|
2803
|
-
if (isIgnorable(before)) {
|
|
2812
|
+
if (isIgnorable(before, -1)) {
|
|
2804
2813
|
moveNode = node;
|
|
2805
2814
|
moveOffset = --offset;
|
|
2806
2815
|
} else if (before.nodeType == 3) {
|
|
@@ -2813,7 +2822,7 @@ function skipIgnoredNodesBefore(view) {
|
|
|
2813
2822
|
} else {
|
|
2814
2823
|
var prev = node.previousSibling;
|
|
2815
2824
|
|
|
2816
|
-
while (prev && isIgnorable(prev)) {
|
|
2825
|
+
while (prev && isIgnorable(prev, -1)) {
|
|
2817
2826
|
moveNode = node.parentNode;
|
|
2818
2827
|
moveOffset = domIndex(prev);
|
|
2819
2828
|
prev = prev.previousSibling;
|
|
@@ -2846,7 +2855,7 @@ function skipIgnoredNodesAfter(view) {
|
|
|
2846
2855
|
if (node.nodeType != 1) break;
|
|
2847
2856
|
var after = node.childNodes[offset];
|
|
2848
2857
|
|
|
2849
|
-
if (isIgnorable(after)) {
|
|
2858
|
+
if (isIgnorable(after, 1)) {
|
|
2850
2859
|
moveNode = node;
|
|
2851
2860
|
moveOffset = ++offset;
|
|
2852
2861
|
} else break;
|
|
@@ -2855,7 +2864,7 @@ function skipIgnoredNodesAfter(view) {
|
|
|
2855
2864
|
} else {
|
|
2856
2865
|
var next = node.nextSibling;
|
|
2857
2866
|
|
|
2858
|
-
while (next && isIgnorable(next)) {
|
|
2867
|
+
while (next && isIgnorable(next, 1)) {
|
|
2859
2868
|
moveNode = next.parentNode;
|
|
2860
2869
|
moveOffset = domIndex(next) + 1;
|
|
2861
2870
|
next = next.nextSibling;
|
|
@@ -2888,8 +2897,10 @@ function textNodeAfter(node, offset) {
|
|
|
2888
2897
|
}
|
|
2889
2898
|
|
|
2890
2899
|
while (node && offset < node.childNodes.length) {
|
|
2891
|
-
|
|
2892
|
-
if (
|
|
2900
|
+
var next = node.childNodes[offset];
|
|
2901
|
+
if (next.nodeType == 3) return next;
|
|
2902
|
+
if (next.nodeType == 1 && next.contentEditable == "false") break;
|
|
2903
|
+
node = next;
|
|
2893
2904
|
offset = 0;
|
|
2894
2905
|
}
|
|
2895
2906
|
}
|
|
@@ -2901,8 +2912,10 @@ function textNodeBefore(node, offset) {
|
|
|
2901
2912
|
}
|
|
2902
2913
|
|
|
2903
2914
|
while (node && offset) {
|
|
2904
|
-
|
|
2905
|
-
if (
|
|
2915
|
+
var next = node.childNodes[offset - 1];
|
|
2916
|
+
if (next.nodeType == 3) return next;
|
|
2917
|
+
if (next.nodeType == 1 && next.contentEditable == "false") break;
|
|
2918
|
+
node = next;
|
|
2906
2919
|
offset = node.childNodes.length;
|
|
2907
2920
|
}
|
|
2908
2921
|
}
|
|
@@ -3059,7 +3072,7 @@ function captureKeyDown(view, event) {
|
|
|
3059
3072
|
} else if (code == 38 || mac && code == 80 && mods == "c") {
|
|
3060
3073
|
return selectVertically(view, -1, mods) || skipIgnoredNodes(view, -1);
|
|
3061
3074
|
} else if (code == 40 || mac && code == 78 && mods == "c") {
|
|
3062
|
-
return safariDownArrowBug(view) || selectVertically(view, 1, mods) ||
|
|
3075
|
+
return safariDownArrowBug(view) || selectVertically(view, 1, mods) || skipIgnoredNodes(view, 1);
|
|
3063
3076
|
} else if (mods == (mac ? "m" : "c") && (code == 66 || code == 73 || code == 89 || code == 90)) {
|
|
3064
3077
|
return true;
|
|
3065
3078
|
}
|
|
@@ -4296,6 +4309,11 @@ var Decoration = function () {
|
|
|
4296
4309
|
get: function get() {
|
|
4297
4310
|
return this.type instanceof InlineType;
|
|
4298
4311
|
}
|
|
4312
|
+
}, {
|
|
4313
|
+
key: "widget",
|
|
4314
|
+
get: function get() {
|
|
4315
|
+
return this.type instanceof WidgetType;
|
|
4316
|
+
}
|
|
4299
4317
|
}], [{
|
|
4300
4318
|
key: "widget",
|
|
4301
4319
|
value: function widget(pos, toDOM, spec) {
|
|
@@ -5928,6 +5946,11 @@ var EditorView = function () {
|
|
|
5928
5946
|
|
|
5929
5947
|
return cached || document;
|
|
5930
5948
|
}
|
|
5949
|
+
}, {
|
|
5950
|
+
key: "updateRoot",
|
|
5951
|
+
value: function updateRoot() {
|
|
5952
|
+
this._root = null;
|
|
5953
|
+
}
|
|
5931
5954
|
}, {
|
|
5932
5955
|
key: "posAtCoords",
|
|
5933
5956
|
value: function posAtCoords(coords) {
|
package/dist/index.d.cts
CHANGED
|
@@ -2,9 +2,9 @@ import { EditorState, Transaction, Selection, Plugin } from 'prosemirror-state';
|
|
|
2
2
|
import { Mark, Node, ParseRule, Slice, ResolvedPos, DOMParser, DOMSerializer } from 'prosemirror-model';
|
|
3
3
|
import { Mapping } from 'prosemirror-transform';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
type DOMNode = InstanceType<typeof window.Node>;
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
type WidgetConstructor = ((view: EditorView, getPos: () => number | undefined) => DOMNode) | DOMNode;
|
|
8
8
|
/**
|
|
9
9
|
Decoration objects can be provided to the view through the
|
|
10
10
|
[`decorations` prop](https://prosemirror.net/docs/ref/#view.EditorProps.decorations). They come in
|
|
@@ -125,7 +125,7 @@ A set of attributes to add to a decorated node. Most properties
|
|
|
125
125
|
simply directly correspond to DOM attributes of the same name,
|
|
126
126
|
which will be set to the property's value. These are exceptions:
|
|
127
127
|
*/
|
|
128
|
-
|
|
128
|
+
type DecorationAttrs = {
|
|
129
129
|
/**
|
|
130
130
|
When non-null, the target node is wrapped in a DOM element of
|
|
131
131
|
this type (and the other attributes are applied to this element).
|
|
@@ -166,7 +166,8 @@ updates create a new value.
|
|
|
166
166
|
declare class DecorationSet implements DecorationSource {
|
|
167
167
|
/**
|
|
168
168
|
Create a set of decorations, using the structure of the given
|
|
169
|
-
document.
|
|
169
|
+
document. This will consume (modify) the `decorations` array, so
|
|
170
|
+
you must make a copy if you want need to preserve that.
|
|
170
171
|
*/
|
|
171
172
|
static create(doc: Node, decorations: Decoration[]): DecorationSet;
|
|
172
173
|
/**
|
|
@@ -193,8 +194,9 @@ declare class DecorationSet implements DecorationSource {
|
|
|
193
194
|
}): DecorationSet;
|
|
194
195
|
/**
|
|
195
196
|
Add the given array of decorations to the ones in the set,
|
|
196
|
-
producing a new set.
|
|
197
|
-
create the appropriate tree
|
|
197
|
+
producing a new set. Consumes the `decorations` array. Needs
|
|
198
|
+
access to the current document to create the appropriate tree
|
|
199
|
+
structure.
|
|
198
200
|
*/
|
|
199
201
|
add(doc: Node, decorations: Decoration[]): DecorationSet;
|
|
200
202
|
private addInner;
|
|
@@ -356,7 +358,7 @@ declare class NodeViewDesc extends ViewDesc {
|
|
|
356
358
|
parseRule(): ParseRule | null;
|
|
357
359
|
matchesNode(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource): boolean;
|
|
358
360
|
get size(): number;
|
|
359
|
-
get border():
|
|
361
|
+
get border(): 0 | 1;
|
|
360
362
|
updateChildren(view: EditorView, pos: number): void;
|
|
361
363
|
localCompositionInfo(view: EditorView, pos: number): {
|
|
362
364
|
node: Text;
|
|
@@ -490,6 +492,11 @@ declare class EditorView {
|
|
|
490
492
|
*/
|
|
491
493
|
get root(): Document | ShadowRoot;
|
|
492
494
|
/**
|
|
495
|
+
When an existing editor view is moved to a new document or
|
|
496
|
+
shadow tree, call this to make it recompute its root.
|
|
497
|
+
*/
|
|
498
|
+
updateRoot(): void;
|
|
499
|
+
/**
|
|
493
500
|
Given a pair of viewport coordinates, return the document
|
|
494
501
|
position that corresponds to them. May return null if the given
|
|
495
502
|
coordinates aren't inside of the editor. When an object is
|
|
@@ -604,12 +611,12 @@ declare class EditorView {
|
|
|
604
611
|
The type of function [provided](https://prosemirror.net/docs/ref/#view.EditorProps.nodeViews) to
|
|
605
612
|
create [node views](https://prosemirror.net/docs/ref/#view.NodeView).
|
|
606
613
|
*/
|
|
607
|
-
|
|
614
|
+
type NodeViewConstructor = (node: Node, view: EditorView, getPos: () => number | undefined, decorations: readonly Decoration[], innerDecorations: DecorationSource) => NodeView;
|
|
608
615
|
/**
|
|
609
616
|
The function types [used](https://prosemirror.net/docs/ref/#view.EditorProps.markViews) to create
|
|
610
617
|
mark views.
|
|
611
618
|
*/
|
|
612
|
-
|
|
619
|
+
type MarkViewConstructor = (mark: Mark, view: EditorView, inline: boolean) => {
|
|
613
620
|
dom: HTMLElement;
|
|
614
621
|
contentDOM?: HTMLElement;
|
|
615
622
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -2,9 +2,9 @@ import { EditorState, Transaction, Selection, Plugin } from 'prosemirror-state';
|
|
|
2
2
|
import { Mark, Node, ParseRule, Slice, ResolvedPos, DOMParser, DOMSerializer } from 'prosemirror-model';
|
|
3
3
|
import { Mapping } from 'prosemirror-transform';
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
type DOMNode = InstanceType<typeof window.Node>;
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
type WidgetConstructor = ((view: EditorView, getPos: () => number | undefined) => DOMNode) | DOMNode;
|
|
8
8
|
/**
|
|
9
9
|
Decoration objects can be provided to the view through the
|
|
10
10
|
[`decorations` prop](https://prosemirror.net/docs/ref/#view.EditorProps.decorations). They come in
|
|
@@ -125,7 +125,7 @@ A set of attributes to add to a decorated node. Most properties
|
|
|
125
125
|
simply directly correspond to DOM attributes of the same name,
|
|
126
126
|
which will be set to the property's value. These are exceptions:
|
|
127
127
|
*/
|
|
128
|
-
|
|
128
|
+
type DecorationAttrs = {
|
|
129
129
|
/**
|
|
130
130
|
When non-null, the target node is wrapped in a DOM element of
|
|
131
131
|
this type (and the other attributes are applied to this element).
|
|
@@ -166,7 +166,8 @@ updates create a new value.
|
|
|
166
166
|
declare class DecorationSet implements DecorationSource {
|
|
167
167
|
/**
|
|
168
168
|
Create a set of decorations, using the structure of the given
|
|
169
|
-
document.
|
|
169
|
+
document. This will consume (modify) the `decorations` array, so
|
|
170
|
+
you must make a copy if you want need to preserve that.
|
|
170
171
|
*/
|
|
171
172
|
static create(doc: Node, decorations: Decoration[]): DecorationSet;
|
|
172
173
|
/**
|
|
@@ -193,8 +194,9 @@ declare class DecorationSet implements DecorationSource {
|
|
|
193
194
|
}): DecorationSet;
|
|
194
195
|
/**
|
|
195
196
|
Add the given array of decorations to the ones in the set,
|
|
196
|
-
producing a new set.
|
|
197
|
-
create the appropriate tree
|
|
197
|
+
producing a new set. Consumes the `decorations` array. Needs
|
|
198
|
+
access to the current document to create the appropriate tree
|
|
199
|
+
structure.
|
|
198
200
|
*/
|
|
199
201
|
add(doc: Node, decorations: Decoration[]): DecorationSet;
|
|
200
202
|
private addInner;
|
|
@@ -356,7 +358,7 @@ declare class NodeViewDesc extends ViewDesc {
|
|
|
356
358
|
parseRule(): ParseRule | null;
|
|
357
359
|
matchesNode(node: Node, outerDeco: readonly Decoration[], innerDeco: DecorationSource): boolean;
|
|
358
360
|
get size(): number;
|
|
359
|
-
get border():
|
|
361
|
+
get border(): 0 | 1;
|
|
360
362
|
updateChildren(view: EditorView, pos: number): void;
|
|
361
363
|
localCompositionInfo(view: EditorView, pos: number): {
|
|
362
364
|
node: Text;
|
|
@@ -490,6 +492,11 @@ declare class EditorView {
|
|
|
490
492
|
*/
|
|
491
493
|
get root(): Document | ShadowRoot;
|
|
492
494
|
/**
|
|
495
|
+
When an existing editor view is moved to a new document or
|
|
496
|
+
shadow tree, call this to make it recompute its root.
|
|
497
|
+
*/
|
|
498
|
+
updateRoot(): void;
|
|
499
|
+
/**
|
|
493
500
|
Given a pair of viewport coordinates, return the document
|
|
494
501
|
position that corresponds to them. May return null if the given
|
|
495
502
|
coordinates aren't inside of the editor. When an object is
|
|
@@ -604,12 +611,12 @@ declare class EditorView {
|
|
|
604
611
|
The type of function [provided](https://prosemirror.net/docs/ref/#view.EditorProps.nodeViews) to
|
|
605
612
|
create [node views](https://prosemirror.net/docs/ref/#view.NodeView).
|
|
606
613
|
*/
|
|
607
|
-
|
|
614
|
+
type NodeViewConstructor = (node: Node, view: EditorView, getPos: () => number | undefined, decorations: readonly Decoration[], innerDecorations: DecorationSource) => NodeView;
|
|
608
615
|
/**
|
|
609
616
|
The function types [used](https://prosemirror.net/docs/ref/#view.EditorProps.markViews) to create
|
|
610
617
|
mark views.
|
|
611
618
|
*/
|
|
612
|
-
|
|
619
|
+
type MarkViewConstructor = (mark: Mark, view: EditorView, inline: boolean) => {
|
|
613
620
|
dom: HTMLElement;
|
|
614
621
|
contentDOM?: HTMLElement;
|
|
615
622
|
};
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TextSelection, NodeSelection,
|
|
1
|
+
import { TextSelection, NodeSelection, AllSelection, Selection } from 'prosemirror-state';
|
|
2
2
|
import { DOMSerializer, Fragment, Mark, Slice, DOMParser } from 'prosemirror-model';
|
|
3
3
|
import { dropPoint } from 'prosemirror-transform';
|
|
4
4
|
|
|
@@ -426,6 +426,11 @@ function posAtCoords(view, coords) {
|
|
|
426
426
|
offset++;
|
|
427
427
|
}
|
|
428
428
|
}
|
|
429
|
+
let prev;
|
|
430
|
+
// When clicking above the right side of an uneditable node, Chrome will report a cursor position after that node.
|
|
431
|
+
if (webkit && offset && node.nodeType == 1 && (prev = node.childNodes[offset - 1]).nodeType == 1 &&
|
|
432
|
+
prev.contentEditable == "false" && prev.getBoundingClientRect().top >= coords.top)
|
|
433
|
+
offset--;
|
|
429
434
|
// Suspiciously specific kludge to work around caret*FromPoint
|
|
430
435
|
// never returning a position at the end of the document
|
|
431
436
|
if (node == view.dom && offset == node.childNodes.length - 1 && node.lastChild.nodeType == 1 &&
|
|
@@ -1810,9 +1815,11 @@ class ViewTreeUpdater {
|
|
|
1810
1815
|
}
|
|
1811
1816
|
else if (!locked && (updated = this.recreateWrapper(next, node, outerDeco, innerDeco, view, pos))) {
|
|
1812
1817
|
this.top.children[this.index] = updated;
|
|
1813
|
-
updated.
|
|
1814
|
-
|
|
1815
|
-
|
|
1818
|
+
if (updated.contentDOM) {
|
|
1819
|
+
updated.dirty = CONTENT_DIRTY;
|
|
1820
|
+
updated.updateChildren(view, pos + 1);
|
|
1821
|
+
updated.dirty = NOT_DIRTY;
|
|
1822
|
+
}
|
|
1816
1823
|
this.changed = true;
|
|
1817
1824
|
this.index++;
|
|
1818
1825
|
return true;
|
|
@@ -1829,13 +1836,13 @@ class ViewTreeUpdater {
|
|
|
1829
1836
|
!next.node.content.eq(node.content))
|
|
1830
1837
|
return null;
|
|
1831
1838
|
let wrapper = NodeViewDesc.create(this.top, node, outerDeco, innerDeco, view, pos);
|
|
1832
|
-
if (
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1839
|
+
if (wrapper.contentDOM) {
|
|
1840
|
+
wrapper.children = next.children;
|
|
1841
|
+
next.children = [];
|
|
1842
|
+
for (let ch of wrapper.children)
|
|
1843
|
+
ch.parent = wrapper;
|
|
1844
|
+
}
|
|
1836
1845
|
next.destroy();
|
|
1837
|
-
for (let ch of wrapper.children)
|
|
1838
|
-
ch.parent = wrapper;
|
|
1839
1846
|
return wrapper;
|
|
1840
1847
|
}
|
|
1841
1848
|
// Insert the node as a newly created node desc.
|
|
@@ -1963,10 +1970,17 @@ function iterDeco(parent, deco, onWidget, onNode) {
|
|
|
1963
1970
|
}
|
|
1964
1971
|
let decoIndex = 0, active = [], restNode = null;
|
|
1965
1972
|
for (let parentIndex = 0;;) {
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1973
|
+
let widget, widgets;
|
|
1974
|
+
while (decoIndex < locals.length && locals[decoIndex].to == offset) {
|
|
1975
|
+
let next = locals[decoIndex++];
|
|
1976
|
+
if (next.widget) {
|
|
1977
|
+
if (!widget)
|
|
1978
|
+
widget = next;
|
|
1979
|
+
else
|
|
1980
|
+
(widgets || (widgets = [widget])).push(next);
|
|
1981
|
+
}
|
|
1982
|
+
}
|
|
1983
|
+
if (widget) {
|
|
1970
1984
|
if (widgets) {
|
|
1971
1985
|
widgets.sort(compareSide);
|
|
1972
1986
|
for (let i = 0; i < widgets.length; i++)
|
|
@@ -2059,6 +2073,8 @@ function findTextInFragment(frag, text, from, to) {
|
|
|
2059
2073
|
str += next.text;
|
|
2060
2074
|
}
|
|
2061
2075
|
if (pos >= from) {
|
|
2076
|
+
if (pos >= to && str.slice(to - text.length - childStart, to - childStart) == text)
|
|
2077
|
+
return to - text.length;
|
|
2062
2078
|
let found = childStart < to ? str.lastIndexOf(text, to - childStart - 1) : -1;
|
|
2063
2079
|
if (found >= 0 && found + text.length + childStart >= from)
|
|
2064
2080
|
return childStart + found;
|
|
@@ -2355,11 +2371,11 @@ function selectHorizontally(view, dir, mods) {
|
|
|
2355
2371
|
function nodeLen(node) {
|
|
2356
2372
|
return node.nodeType == 3 ? node.nodeValue.length : node.childNodes.length;
|
|
2357
2373
|
}
|
|
2358
|
-
function isIgnorable(dom) {
|
|
2374
|
+
function isIgnorable(dom, dir) {
|
|
2359
2375
|
if (dom.contentEditable == "false")
|
|
2360
2376
|
return true;
|
|
2361
2377
|
let desc = dom.pmViewDesc;
|
|
2362
|
-
return desc && desc.size == 0 && (dom.nextSibling || dom.nodeName != "BR");
|
|
2378
|
+
return desc && desc.size == 0 && (dir < 0 || dom.nextSibling || dom.nodeName != "BR");
|
|
2363
2379
|
}
|
|
2364
2380
|
function skipIgnoredNodes(view, dir) {
|
|
2365
2381
|
return dir < 0 ? skipIgnoredNodesBefore(view) : skipIgnoredNodesAfter(view);
|
|
@@ -2375,7 +2391,7 @@ function skipIgnoredNodesBefore(view) {
|
|
|
2375
2391
|
// Gecko will do odd things when the selection is directly in front
|
|
2376
2392
|
// of a non-editable node, so in that case, move it into the next
|
|
2377
2393
|
// node if possible. Issue prosemirror/prosemirror#832.
|
|
2378
|
-
if (gecko && node.nodeType == 1 && offset < nodeLen(node) && isIgnorable(node.childNodes[offset]))
|
|
2394
|
+
if (gecko && node.nodeType == 1 && offset < nodeLen(node) && isIgnorable(node.childNodes[offset], -1))
|
|
2379
2395
|
force = true;
|
|
2380
2396
|
for (;;) {
|
|
2381
2397
|
if (offset > 0) {
|
|
@@ -2384,7 +2400,7 @@ function skipIgnoredNodesBefore(view) {
|
|
|
2384
2400
|
}
|
|
2385
2401
|
else {
|
|
2386
2402
|
let before = node.childNodes[offset - 1];
|
|
2387
|
-
if (isIgnorable(before)) {
|
|
2403
|
+
if (isIgnorable(before, -1)) {
|
|
2388
2404
|
moveNode = node;
|
|
2389
2405
|
moveOffset = --offset;
|
|
2390
2406
|
}
|
|
@@ -2401,7 +2417,7 @@ function skipIgnoredNodesBefore(view) {
|
|
|
2401
2417
|
}
|
|
2402
2418
|
else {
|
|
2403
2419
|
let prev = node.previousSibling;
|
|
2404
|
-
while (prev && isIgnorable(prev)) {
|
|
2420
|
+
while (prev && isIgnorable(prev, -1)) {
|
|
2405
2421
|
moveNode = node.parentNode;
|
|
2406
2422
|
moveOffset = domIndex(prev);
|
|
2407
2423
|
prev = prev.previousSibling;
|
|
@@ -2437,7 +2453,7 @@ function skipIgnoredNodesAfter(view) {
|
|
|
2437
2453
|
if (node.nodeType != 1)
|
|
2438
2454
|
break;
|
|
2439
2455
|
let after = node.childNodes[offset];
|
|
2440
|
-
if (isIgnorable(after)) {
|
|
2456
|
+
if (isIgnorable(after, 1)) {
|
|
2441
2457
|
moveNode = node;
|
|
2442
2458
|
moveOffset = ++offset;
|
|
2443
2459
|
}
|
|
@@ -2449,7 +2465,7 @@ function skipIgnoredNodesAfter(view) {
|
|
|
2449
2465
|
}
|
|
2450
2466
|
else {
|
|
2451
2467
|
let next = node.nextSibling;
|
|
2452
|
-
while (next && isIgnorable(next)) {
|
|
2468
|
+
while (next && isIgnorable(next, 1)) {
|
|
2453
2469
|
moveNode = next.parentNode;
|
|
2454
2470
|
moveOffset = domIndex(next) + 1;
|
|
2455
2471
|
next = next.nextSibling;
|
|
@@ -2480,9 +2496,12 @@ function textNodeAfter(node, offset) {
|
|
|
2480
2496
|
node = node.parentNode;
|
|
2481
2497
|
}
|
|
2482
2498
|
while (node && offset < node.childNodes.length) {
|
|
2483
|
-
|
|
2484
|
-
if (
|
|
2485
|
-
return
|
|
2499
|
+
let next = node.childNodes[offset];
|
|
2500
|
+
if (next.nodeType == 3)
|
|
2501
|
+
return next;
|
|
2502
|
+
if (next.nodeType == 1 && next.contentEditable == "false")
|
|
2503
|
+
break;
|
|
2504
|
+
node = next;
|
|
2486
2505
|
offset = 0;
|
|
2487
2506
|
}
|
|
2488
2507
|
}
|
|
@@ -2492,9 +2511,12 @@ function textNodeBefore(node, offset) {
|
|
|
2492
2511
|
node = node.parentNode;
|
|
2493
2512
|
}
|
|
2494
2513
|
while (node && offset) {
|
|
2495
|
-
|
|
2496
|
-
if (
|
|
2497
|
-
return
|
|
2514
|
+
let next = node.childNodes[offset - 1];
|
|
2515
|
+
if (next.nodeType == 3)
|
|
2516
|
+
return next;
|
|
2517
|
+
if (next.nodeType == 1 && next.contentEditable == "false")
|
|
2518
|
+
break;
|
|
2519
|
+
node = next;
|
|
2498
2520
|
offset = node.childNodes.length;
|
|
2499
2521
|
}
|
|
2500
2522
|
}
|
|
@@ -2656,7 +2678,7 @@ function captureKeyDown(view, event) {
|
|
|
2656
2678
|
return selectVertically(view, -1, mods) || skipIgnoredNodes(view, -1);
|
|
2657
2679
|
}
|
|
2658
2680
|
else if (code == 40 || (mac && code == 78 && mods == "c")) { // Down arrow, Ctrl-n on Mac
|
|
2659
|
-
return safariDownArrowBug(view) || selectVertically(view, 1, mods) ||
|
|
2681
|
+
return safariDownArrowBug(view) || selectVertically(view, 1, mods) || skipIgnoredNodes(view, 1);
|
|
2660
2682
|
}
|
|
2661
2683
|
else if (mods == (mac ? "m" : "c") &&
|
|
2662
2684
|
(code == 66 || code == 73 || code == 89 || code == 90)) { // Mod-[biyz]
|
|
@@ -3814,6 +3836,10 @@ class Decoration {
|
|
|
3814
3836
|
@internal
|
|
3815
3837
|
*/
|
|
3816
3838
|
get inline() { return this.type instanceof InlineType; }
|
|
3839
|
+
/**
|
|
3840
|
+
@internal
|
|
3841
|
+
*/
|
|
3842
|
+
get widget() { return this.type instanceof WidgetType; }
|
|
3817
3843
|
}
|
|
3818
3844
|
const none = [], noSpec = {};
|
|
3819
3845
|
/**
|
|
@@ -3832,7 +3858,8 @@ class DecorationSet {
|
|
|
3832
3858
|
}
|
|
3833
3859
|
/**
|
|
3834
3860
|
Create a set of decorations, using the structure of the given
|
|
3835
|
-
document.
|
|
3861
|
+
document. This will consume (modify) the `decorations` array, so
|
|
3862
|
+
you must make a copy if you want need to preserve that.
|
|
3836
3863
|
*/
|
|
3837
3864
|
static create(doc, decorations) {
|
|
3838
3865
|
return decorations.length ? buildTree(decorations, doc, 0, noSpec) : empty;
|
|
@@ -3891,8 +3918,9 @@ class DecorationSet {
|
|
|
3891
3918
|
}
|
|
3892
3919
|
/**
|
|
3893
3920
|
Add the given array of decorations to the ones in the set,
|
|
3894
|
-
producing a new set.
|
|
3895
|
-
create the appropriate tree
|
|
3921
|
+
producing a new set. Consumes the `decorations` array. Needs
|
|
3922
|
+
access to the current document to create the appropriate tree
|
|
3923
|
+
structure.
|
|
3896
3924
|
*/
|
|
3897
3925
|
add(doc, decorations) {
|
|
3898
3926
|
if (!decorations.length)
|
|
@@ -5333,6 +5361,13 @@ class EditorView {
|
|
|
5333
5361
|
return cached || document;
|
|
5334
5362
|
}
|
|
5335
5363
|
/**
|
|
5364
|
+
When an existing editor view is moved to a new document or
|
|
5365
|
+
shadow tree, call this to make it recompute its root.
|
|
5366
|
+
*/
|
|
5367
|
+
updateRoot() {
|
|
5368
|
+
this._root = null;
|
|
5369
|
+
}
|
|
5370
|
+
/**
|
|
5336
5371
|
Given a pair of viewport coordinates, return the document
|
|
5337
5372
|
position that corresponds to them. May return null if the given
|
|
5338
5373
|
coordinates aren't inside of the editor. When an object is
|
package/package.json
CHANGED
package/src/capturekeys.ts
CHANGED
|
@@ -54,10 +54,10 @@ function nodeLen(node: Node) {
|
|
|
54
54
|
return node.nodeType == 3 ? node.nodeValue!.length : node.childNodes.length
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
function isIgnorable(dom: Node) {
|
|
57
|
+
function isIgnorable(dom: Node, dir: number) {
|
|
58
58
|
if ((dom as HTMLElement).contentEditable == "false") return true
|
|
59
59
|
let desc = dom.pmViewDesc
|
|
60
|
-
return desc && desc.size == 0 && (dom.nextSibling || dom.nodeName != "BR")
|
|
60
|
+
return desc && desc.size == 0 && (dir < 0 || dom.nextSibling || dom.nodeName != "BR")
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
function skipIgnoredNodes(view: EditorView, dir: number) {
|
|
@@ -74,14 +74,14 @@ function skipIgnoredNodesBefore(view: EditorView) {
|
|
|
74
74
|
// Gecko will do odd things when the selection is directly in front
|
|
75
75
|
// of a non-editable node, so in that case, move it into the next
|
|
76
76
|
// node if possible. Issue prosemirror/prosemirror#832.
|
|
77
|
-
if (browser.gecko && node.nodeType == 1 && offset < nodeLen(node) && isIgnorable(node.childNodes[offset])) force = true
|
|
77
|
+
if (browser.gecko && node.nodeType == 1 && offset < nodeLen(node) && isIgnorable(node.childNodes[offset], -1)) force = true
|
|
78
78
|
for (;;) {
|
|
79
79
|
if (offset > 0) {
|
|
80
80
|
if (node.nodeType != 1) {
|
|
81
81
|
break
|
|
82
82
|
} else {
|
|
83
83
|
let before = node.childNodes[offset - 1]
|
|
84
|
-
if (isIgnorable(before)) {
|
|
84
|
+
if (isIgnorable(before, -1)) {
|
|
85
85
|
moveNode = node
|
|
86
86
|
moveOffset = --offset
|
|
87
87
|
} else if (before.nodeType == 3) {
|
|
@@ -93,7 +93,7 @@ function skipIgnoredNodesBefore(view: EditorView) {
|
|
|
93
93
|
break
|
|
94
94
|
} else {
|
|
95
95
|
let prev = node.previousSibling
|
|
96
|
-
while (prev && isIgnorable(prev)) {
|
|
96
|
+
while (prev && isIgnorable(prev, -1)) {
|
|
97
97
|
moveNode = node.parentNode
|
|
98
98
|
moveOffset = domIndex(prev)
|
|
99
99
|
prev = prev.previousSibling
|
|
@@ -124,7 +124,7 @@ function skipIgnoredNodesAfter(view: EditorView) {
|
|
|
124
124
|
if (offset < len) {
|
|
125
125
|
if (node.nodeType != 1) break
|
|
126
126
|
let after = node.childNodes[offset]
|
|
127
|
-
if (isIgnorable(after)) {
|
|
127
|
+
if (isIgnorable(after, 1)) {
|
|
128
128
|
moveNode = node
|
|
129
129
|
moveOffset = ++offset
|
|
130
130
|
}
|
|
@@ -133,7 +133,7 @@ function skipIgnoredNodesAfter(view: EditorView) {
|
|
|
133
133
|
break
|
|
134
134
|
} else {
|
|
135
135
|
let next = node.nextSibling
|
|
136
|
-
while (next && isIgnorable(next)) {
|
|
136
|
+
while (next && isIgnorable(next, 1)) {
|
|
137
137
|
moveNode = next.parentNode
|
|
138
138
|
moveOffset = domIndex(next) + 1
|
|
139
139
|
next = next.nextSibling
|
|
@@ -163,8 +163,10 @@ function textNodeAfter(node: Node | null, offset: number): Text | undefined {
|
|
|
163
163
|
node = node.parentNode
|
|
164
164
|
}
|
|
165
165
|
while (node && offset < node.childNodes.length) {
|
|
166
|
-
|
|
167
|
-
if (
|
|
166
|
+
let next = node.childNodes[offset]
|
|
167
|
+
if (next.nodeType == 3) return next as Text
|
|
168
|
+
if (next.nodeType == 1 && (next as HTMLElement).contentEditable == "false") break
|
|
169
|
+
node = next
|
|
168
170
|
offset = 0
|
|
169
171
|
}
|
|
170
172
|
}
|
|
@@ -175,8 +177,10 @@ function textNodeBefore(node: Node | null, offset: number): Text | undefined {
|
|
|
175
177
|
node = node.parentNode
|
|
176
178
|
}
|
|
177
179
|
while (node && offset) {
|
|
178
|
-
|
|
179
|
-
if (
|
|
180
|
+
let next = node.childNodes[offset - 1]
|
|
181
|
+
if (next.nodeType == 3) return next as Text
|
|
182
|
+
if (next.nodeType == 1 && (next as HTMLElement).contentEditable == "false") break
|
|
183
|
+
node = next
|
|
180
184
|
offset = node.childNodes.length
|
|
181
185
|
}
|
|
182
186
|
}
|
|
@@ -327,7 +331,7 @@ export function captureKeyDown(view: EditorView, event: KeyboardEvent) {
|
|
|
327
331
|
} else if (code == 38 || (browser.mac && code == 80 && mods == "c")) { // Up arrow, Ctrl-p on Mac
|
|
328
332
|
return selectVertically(view, -1, mods) || skipIgnoredNodes(view, -1)
|
|
329
333
|
} else if (code == 40 || (browser.mac && code == 78 && mods == "c")) { // Down arrow, Ctrl-n on Mac
|
|
330
|
-
return safariDownArrowBug(view) || selectVertically(view, 1, mods) ||
|
|
334
|
+
return safariDownArrowBug(view) || selectVertically(view, 1, mods) || skipIgnoredNodes(view, 1)
|
|
331
335
|
} else if (mods == (browser.mac ? "m" : "c") &&
|
|
332
336
|
(code == 66 || code == 73 || code == 89 || code == 90)) { // Mod-[biyz]
|
|
333
337
|
return true
|
package/src/decoration.ts
CHANGED
|
@@ -223,6 +223,9 @@ export class Decoration {
|
|
|
223
223
|
|
|
224
224
|
/// @internal
|
|
225
225
|
get inline() { return this.type instanceof InlineType }
|
|
226
|
+
|
|
227
|
+
/// @internal
|
|
228
|
+
get widget() { return this.type instanceof WidgetType }
|
|
226
229
|
}
|
|
227
230
|
|
|
228
231
|
/// A set of attributes to add to a decorated node. Most properties
|
|
@@ -278,7 +281,8 @@ export class DecorationSet implements DecorationSource {
|
|
|
278
281
|
}
|
|
279
282
|
|
|
280
283
|
/// Create a set of decorations, using the structure of the given
|
|
281
|
-
/// document.
|
|
284
|
+
/// document. This will consume (modify) the `decorations` array, so
|
|
285
|
+
/// you must make a copy if you want need to preserve that.
|
|
282
286
|
static create(doc: Node, decorations: Decoration[]) {
|
|
283
287
|
return decorations.length ? buildTree(decorations, doc, 0, noSpec) : empty
|
|
284
288
|
}
|
|
@@ -302,7 +306,7 @@ export class DecorationSet implements DecorationSource {
|
|
|
302
306
|
result.push(span.copy(span.from + offset, span.to + offset))
|
|
303
307
|
}
|
|
304
308
|
for (let i = 0; i < this.children.length; i += 3) {
|
|
305
|
-
if (this.children[i] < end && this.children[i + 1] > start) {
|
|
309
|
+
if ((this.children[i] as number) < end && (this.children[i + 1] as number) > start) {
|
|
306
310
|
let childOff = (this.children[i] as number) + 1
|
|
307
311
|
;(this.children[i + 2] as DecorationSet).findInner(start - childOff, end - childOff,
|
|
308
312
|
result, offset + childOff, predicate)
|
|
@@ -340,8 +344,9 @@ export class DecorationSet implements DecorationSource {
|
|
|
340
344
|
}
|
|
341
345
|
|
|
342
346
|
/// Add the given array of decorations to the ones in the set,
|
|
343
|
-
/// producing a new set.
|
|
344
|
-
/// create the appropriate tree
|
|
347
|
+
/// producing a new set. Consumes the `decorations` array. Needs
|
|
348
|
+
/// access to the current document to create the appropriate tree
|
|
349
|
+
/// structure.
|
|
345
350
|
add(doc: Node, decorations: Decoration[]) {
|
|
346
351
|
if (!decorations.length) return this
|
|
347
352
|
if (this == empty) return DecorationSet.create(doc, decorations)
|
|
@@ -355,7 +360,7 @@ export class DecorationSet implements DecorationSource {
|
|
|
355
360
|
if (!(found = takeSpansForNode(decorations, childNode, baseOffset))) return
|
|
356
361
|
|
|
357
362
|
if (!children) children = this.children.slice()
|
|
358
|
-
while (childIndex < children.length && children[childIndex] < childOffset) childIndex += 3
|
|
363
|
+
while (childIndex < children.length && (children[childIndex] as number) < childOffset) childIndex += 3
|
|
359
364
|
if (children[childIndex] == childOffset)
|
|
360
365
|
children[childIndex + 2] = (children[childIndex + 2] as DecorationSet).addInner(childNode, found, baseOffset + 1)
|
|
361
366
|
else
|
|
@@ -414,7 +419,7 @@ export class DecorationSet implements DecorationSource {
|
|
|
414
419
|
if (node.isLeaf) return DecorationSet.empty
|
|
415
420
|
|
|
416
421
|
let child, local: Decoration[] | undefined
|
|
417
|
-
for (let i = 0; i < this.children.length; i += 3) if (this.children[i] >= offset) {
|
|
422
|
+
for (let i = 0; i < this.children.length; i += 3) if ((this.children[i] as number) >= offset) {
|
|
418
423
|
if (this.children[i] == offset) child = this.children[i + 2] as DecorationSet
|
|
419
424
|
break
|
|
420
425
|
}
|
|
@@ -576,7 +581,7 @@ function mapChildren(
|
|
|
576
581
|
// Find the child nodes that still correspond to a single node,
|
|
577
582
|
// recursively call mapInner on them and update their positions.
|
|
578
583
|
let mustRebuild = false
|
|
579
|
-
for (let i = 0; i < children.length; i += 3) if (children[i + 1] < 0) { // Touched nodes
|
|
584
|
+
for (let i = 0; i < children.length; i += 3) if ((children[i + 1] as number) < 0) { // Touched nodes
|
|
580
585
|
if (children[i + 1] == -2) {
|
|
581
586
|
mustRebuild = true
|
|
582
587
|
children[i + 1] = -1
|
|
@@ -613,7 +618,7 @@ function mapChildren(
|
|
|
613
618
|
offset, oldOffset, options)
|
|
614
619
|
let built = buildTree(decorations, node, 0, options)
|
|
615
620
|
newLocal = built.local as Decoration[]
|
|
616
|
-
for (let i = 0; i < children.length; i += 3) if (children[i + 1] < 0) {
|
|
621
|
+
for (let i = 0; i < children.length; i += 3) if ((children[i + 1] as number) < 0) {
|
|
617
622
|
children.splice(i, 3)
|
|
618
623
|
i -= 3
|
|
619
624
|
}
|
package/src/domcoords.ts
CHANGED
|
@@ -294,6 +294,11 @@ export function posAtCoords(view: EditorView, coords: {top: number, left: number
|
|
|
294
294
|
offset++
|
|
295
295
|
}
|
|
296
296
|
}
|
|
297
|
+
let prev
|
|
298
|
+
// When clicking above the right side of an uneditable node, Chrome will report a cursor position after that node.
|
|
299
|
+
if (browser.webkit && offset && node.nodeType == 1 && (prev = node.childNodes[offset - 1]).nodeType == 1 &&
|
|
300
|
+
(prev as HTMLElement).contentEditable == "false" && (prev as HTMLElement).getBoundingClientRect().top >= coords.top)
|
|
301
|
+
offset--
|
|
297
302
|
// Suspiciously specific kludge to work around caret*FromPoint
|
|
298
303
|
// never returning a position at the end of the document
|
|
299
304
|
if (node == view.dom && offset == node.childNodes.length - 1 && node.lastChild!.nodeType == 1 &&
|
package/src/index.ts
CHANGED
|
@@ -339,6 +339,12 @@ export class EditorView {
|
|
|
339
339
|
return cached || document
|
|
340
340
|
}
|
|
341
341
|
|
|
342
|
+
/// When an existing editor view is moved to a new document or
|
|
343
|
+
/// shadow tree, call this to make it recompute its root.
|
|
344
|
+
updateRoot() {
|
|
345
|
+
this._root = null
|
|
346
|
+
}
|
|
347
|
+
|
|
342
348
|
/// Given a pair of viewport coordinates, return the document
|
|
343
349
|
/// position that corresponds to them. May return null if the given
|
|
344
350
|
/// coordinates aren't inside of the editor. When an object is
|
package/src/viewdesc.ts
CHANGED
|
@@ -387,7 +387,7 @@ export class ViewDesc {
|
|
|
387
387
|
brKludge = !!(offset && node.nodeValue![offset - 1] == "\n")
|
|
388
388
|
// Issue #1128
|
|
389
389
|
if (brKludge && offset == node.nodeValue!.length) {
|
|
390
|
-
|
|
390
|
+
for (let scan: DOMNode | null = node, after; scan; scan = scan.parentNode) {
|
|
391
391
|
if (after = scan.nextSibling) {
|
|
392
392
|
if (after.nodeName == "BR")
|
|
393
393
|
anchorDOM = headDOM = {node: after.parentNode!, offset: domIndex(after) + 1}
|
|
@@ -1244,9 +1244,11 @@ class ViewTreeUpdater {
|
|
|
1244
1244
|
return true
|
|
1245
1245
|
} else if (!locked && (updated = this.recreateWrapper(next, node, outerDeco, innerDeco, view, pos))) {
|
|
1246
1246
|
this.top.children[this.index] = updated
|
|
1247
|
-
updated.
|
|
1248
|
-
|
|
1249
|
-
|
|
1247
|
+
if (updated.contentDOM) {
|
|
1248
|
+
updated.dirty = CONTENT_DIRTY
|
|
1249
|
+
updated.updateChildren(view, pos + 1)
|
|
1250
|
+
updated.dirty = NOT_DIRTY
|
|
1251
|
+
}
|
|
1250
1252
|
this.changed = true
|
|
1251
1253
|
this.index++
|
|
1252
1254
|
return true
|
|
@@ -1264,12 +1266,12 @@ class ViewTreeUpdater {
|
|
|
1264
1266
|
if (next.dirty || node.isAtom || !next.children.length ||
|
|
1265
1267
|
!next.node.content.eq(node.content)) return null
|
|
1266
1268
|
let wrapper = NodeViewDesc.create(this.top, node, outerDeco, innerDeco, view, pos)
|
|
1267
|
-
if (
|
|
1268
|
-
|
|
1269
|
-
|
|
1269
|
+
if (wrapper.contentDOM) {
|
|
1270
|
+
wrapper.children = next.children
|
|
1271
|
+
next.children = []
|
|
1272
|
+
for (let ch of wrapper.children) ch.parent = wrapper
|
|
1273
|
+
}
|
|
1270
1274
|
next.destroy()
|
|
1271
|
-
for (let ch of wrapper.children) ch.parent = wrapper
|
|
1272
|
-
|
|
1273
1275
|
return wrapper
|
|
1274
1276
|
}
|
|
1275
1277
|
|
|
@@ -1403,10 +1405,15 @@ function iterDeco(
|
|
|
1403
1405
|
|
|
1404
1406
|
let decoIndex = 0, active = [], restNode = null
|
|
1405
1407
|
for (let parentIndex = 0;;) {
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1408
|
+
let widget, widgets
|
|
1409
|
+
while (decoIndex < locals.length && locals[decoIndex].to == offset) {
|
|
1410
|
+
let next = locals[decoIndex++]
|
|
1411
|
+
if (next.widget) {
|
|
1412
|
+
if (!widget) widget = next
|
|
1413
|
+
else (widgets || (widgets = [widget])).push(next)
|
|
1414
|
+
}
|
|
1415
|
+
}
|
|
1416
|
+
if (widget) {
|
|
1410
1417
|
if (widgets) {
|
|
1411
1418
|
widgets.sort(compareSide)
|
|
1412
1419
|
for (let i = 0; i < widgets.length; i++) onWidget(widgets[i], parentIndex, !!restNode)
|
|
@@ -1492,6 +1499,8 @@ function findTextInFragment(frag: Fragment, text: string, from: number, to: numb
|
|
|
1492
1499
|
str += next.text
|
|
1493
1500
|
}
|
|
1494
1501
|
if (pos >= from) {
|
|
1502
|
+
if (pos >= to && str.slice(to - text.length - childStart, to - childStart) == text)
|
|
1503
|
+
return to - text.length
|
|
1495
1504
|
let found = childStart < to ? str.lastIndexOf(text, to - childStart - 1) : -1
|
|
1496
1505
|
if (found >= 0 && found + text.length + childStart >= from)
|
|
1497
1506
|
return childStart + found
|