prosemirror-transform 1.10.4 → 1.11.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 +12 -0
- package/dist/index.cjs +27 -4
- package/dist/index.d.cts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +28 -3
- package/package.json +1 -1
- package/src/replace.ts +1 -1
- package/src/structure.ts +4 -2
- package/src/transform.ts +21 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
## 1.11.0 (2026-01-21)
|
|
2
|
+
|
|
3
|
+
### New features
|
|
4
|
+
|
|
5
|
+
The new `Tranform.changedRange` method gives you a document range that includes all changes made by the transform/transaction.
|
|
6
|
+
|
|
7
|
+
## 1.10.5 (2025-11-11)
|
|
8
|
+
|
|
9
|
+
### Bug fixes
|
|
10
|
+
|
|
11
|
+
Fix a bug in `liftTarget` that caused it to fail to properly check content constraints when a lift would split a node.
|
|
12
|
+
|
|
1
13
|
## 1.10.4 (2025-04-22)
|
|
2
14
|
|
|
3
15
|
### Bug fixes
|
package/dist/index.cjs
CHANGED
|
@@ -853,12 +853,14 @@ function canCut(node, start, end) {
|
|
|
853
853
|
function liftTarget(range) {
|
|
854
854
|
var parent = range.parent;
|
|
855
855
|
var content = parent.content.cutByIndex(range.startIndex, range.endIndex);
|
|
856
|
-
for (var depth = range.depth;; --depth) {
|
|
856
|
+
for (var depth = range.depth, contentBefore = 0, contentAfter = 0;; --depth) {
|
|
857
857
|
var node = range.$from.node(depth);
|
|
858
|
-
var index = range.$from.index(depth),
|
|
859
|
-
endIndex = range.$to.indexAfter(depth);
|
|
858
|
+
var index = range.$from.index(depth) + contentBefore,
|
|
859
|
+
endIndex = range.$to.indexAfter(depth) - contentAfter;
|
|
860
860
|
if (depth < range.depth && node.canReplace(index, endIndex, content)) return depth;
|
|
861
861
|
if (depth == 0 || node.type.spec.isolating || !canCut(node, index, endIndex)) break;
|
|
862
|
+
if (index) contentBefore = 1;
|
|
863
|
+
if (endIndex < node.childCount) contentAfter = 1;
|
|
862
864
|
}
|
|
863
865
|
return null;
|
|
864
866
|
}
|
|
@@ -1434,7 +1436,7 @@ function _replaceRange(tr, from, to, slice) {
|
|
|
1434
1436
|
var $from = tr.doc.resolve(from),
|
|
1435
1437
|
$to = tr.doc.resolve(to);
|
|
1436
1438
|
if (fitsTrivially($from, $to, slice)) return tr.step(new ReplaceStep(from, to, slice));
|
|
1437
|
-
var targetDepths = coveredDepths($from,
|
|
1439
|
+
var targetDepths = coveredDepths($from, $to);
|
|
1438
1440
|
if (targetDepths[targetDepths.length - 1] == 0) targetDepths.pop();
|
|
1439
1441
|
var preferredTarget = -($from.depth + 1);
|
|
1440
1442
|
targetDepths.unshift(preferredTarget);
|
|
@@ -1689,6 +1691,27 @@ var Transform = function () {
|
|
|
1689
1691
|
get: function get() {
|
|
1690
1692
|
return this.steps.length > 0;
|
|
1691
1693
|
}
|
|
1694
|
+
}, {
|
|
1695
|
+
key: "changedRange",
|
|
1696
|
+
value: function changedRange() {
|
|
1697
|
+
var from = 1e9,
|
|
1698
|
+
to = -1e9;
|
|
1699
|
+
for (var i = 0; i < this.mapping.maps.length; i++) {
|
|
1700
|
+
var map = this.mapping.maps[i];
|
|
1701
|
+
if (i) {
|
|
1702
|
+
from = map.map(from, 1);
|
|
1703
|
+
to = map.map(to, -1);
|
|
1704
|
+
}
|
|
1705
|
+
map.forEach(function (_f, _t, fromB, toB) {
|
|
1706
|
+
from = Math.min(from, fromB);
|
|
1707
|
+
to = Math.max(to, toB);
|
|
1708
|
+
});
|
|
1709
|
+
}
|
|
1710
|
+
return from == 1e9 ? null : {
|
|
1711
|
+
from: from,
|
|
1712
|
+
to: to
|
|
1713
|
+
};
|
|
1714
|
+
}
|
|
1692
1715
|
}, {
|
|
1693
1716
|
key: "addStep",
|
|
1694
1717
|
value: function addStep(step, doc) {
|
package/dist/index.d.cts
CHANGED
|
@@ -326,6 +326,16 @@ declare class Transform {
|
|
|
326
326
|
*/
|
|
327
327
|
get docChanged(): boolean;
|
|
328
328
|
/**
|
|
329
|
+
Return a single range, in post-transform document positions,
|
|
330
|
+
that covers all content changed by this transform. Returns null
|
|
331
|
+
if no replacements are made. Note that this will ignore changes
|
|
332
|
+
that add/remove marks without replacing the underlying content.
|
|
333
|
+
*/
|
|
334
|
+
changedRange(): {
|
|
335
|
+
from: number;
|
|
336
|
+
to: number;
|
|
337
|
+
} | null;
|
|
338
|
+
/**
|
|
329
339
|
Replace the part of the document between `from` and `to` with the
|
|
330
340
|
given `slice`.
|
|
331
341
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -326,6 +326,16 @@ declare class Transform {
|
|
|
326
326
|
*/
|
|
327
327
|
get docChanged(): boolean;
|
|
328
328
|
/**
|
|
329
|
+
Return a single range, in post-transform document positions,
|
|
330
|
+
that covers all content changed by this transform. Returns null
|
|
331
|
+
if no replacements are made. Note that this will ignore changes
|
|
332
|
+
that add/remove marks without replacing the underlying content.
|
|
333
|
+
*/
|
|
334
|
+
changedRange(): {
|
|
335
|
+
from: number;
|
|
336
|
+
to: number;
|
|
337
|
+
} | null;
|
|
338
|
+
/**
|
|
329
339
|
Replace the part of the document between `from` and `to` with the
|
|
330
340
|
given `slice`.
|
|
331
341
|
*/
|
package/dist/index.js
CHANGED
|
@@ -982,13 +982,17 @@ can be lifted. Will not go across
|
|
|
982
982
|
function liftTarget(range) {
|
|
983
983
|
let parent = range.parent;
|
|
984
984
|
let content = parent.content.cutByIndex(range.startIndex, range.endIndex);
|
|
985
|
-
for (let depth = range.depth;; --depth) {
|
|
985
|
+
for (let depth = range.depth, contentBefore = 0, contentAfter = 0;; --depth) {
|
|
986
986
|
let node = range.$from.node(depth);
|
|
987
|
-
let index = range.$from.index(depth), endIndex = range.$to.indexAfter(depth);
|
|
987
|
+
let index = range.$from.index(depth) + contentBefore, endIndex = range.$to.indexAfter(depth) - contentAfter;
|
|
988
988
|
if (depth < range.depth && node.canReplace(index, endIndex, content))
|
|
989
989
|
return depth;
|
|
990
990
|
if (depth == 0 || node.type.spec.isolating || !canCut(node, index, endIndex))
|
|
991
991
|
break;
|
|
992
|
+
if (index)
|
|
993
|
+
contentBefore = 1;
|
|
994
|
+
if (endIndex < node.childCount)
|
|
995
|
+
contentAfter = 1;
|
|
992
996
|
}
|
|
993
997
|
return null;
|
|
994
998
|
}
|
|
@@ -1639,7 +1643,7 @@ function replaceRange(tr, from, to, slice) {
|
|
|
1639
1643
|
let $from = tr.doc.resolve(from), $to = tr.doc.resolve(to);
|
|
1640
1644
|
if (fitsTrivially($from, $to, slice))
|
|
1641
1645
|
return tr.step(new ReplaceStep(from, to, slice));
|
|
1642
|
-
let targetDepths = coveredDepths($from,
|
|
1646
|
+
let targetDepths = coveredDepths($from, $to);
|
|
1643
1647
|
// Can't replace the whole document, so remove 0 if it's present
|
|
1644
1648
|
if (targetDepths[targetDepths.length - 1] == 0)
|
|
1645
1649
|
targetDepths.pop();
|
|
@@ -1942,6 +1946,27 @@ class Transform {
|
|
|
1942
1946
|
return this.steps.length > 0;
|
|
1943
1947
|
}
|
|
1944
1948
|
/**
|
|
1949
|
+
Return a single range, in post-transform document positions,
|
|
1950
|
+
that covers all content changed by this transform. Returns null
|
|
1951
|
+
if no replacements are made. Note that this will ignore changes
|
|
1952
|
+
that add/remove marks without replacing the underlying content.
|
|
1953
|
+
*/
|
|
1954
|
+
changedRange() {
|
|
1955
|
+
let from = 1e9, to = -1e9;
|
|
1956
|
+
for (let i = 0; i < this.mapping.maps.length; i++) {
|
|
1957
|
+
let map = this.mapping.maps[i];
|
|
1958
|
+
if (i) {
|
|
1959
|
+
from = map.map(from, 1);
|
|
1960
|
+
to = map.map(to, -1);
|
|
1961
|
+
}
|
|
1962
|
+
map.forEach((_f, _t, fromB, toB) => {
|
|
1963
|
+
from = Math.min(from, fromB);
|
|
1964
|
+
to = Math.max(to, toB);
|
|
1965
|
+
});
|
|
1966
|
+
}
|
|
1967
|
+
return from == 1e9 ? null : { from, to };
|
|
1968
|
+
}
|
|
1969
|
+
/**
|
|
1945
1970
|
@internal
|
|
1946
1971
|
*/
|
|
1947
1972
|
addStep(step, doc) {
|
package/package.json
CHANGED
package/src/replace.ts
CHANGED
|
@@ -338,7 +338,7 @@ export function replaceRange(tr: Transform, from: number, to: number, slice: Sli
|
|
|
338
338
|
if (fitsTrivially($from, $to, slice))
|
|
339
339
|
return tr.step(new ReplaceStep(from, to, slice))
|
|
340
340
|
|
|
341
|
-
let targetDepths = coveredDepths($from,
|
|
341
|
+
let targetDepths = coveredDepths($from, $to)
|
|
342
342
|
// Can't replace the whole document, so remove 0 if it's present
|
|
343
343
|
if (targetDepths[targetDepths.length - 1] == 0) targetDepths.pop()
|
|
344
344
|
// Negative numbers represent not expansion over the whole node at
|
package/src/structure.ts
CHANGED
|
@@ -15,12 +15,14 @@ function canCut(node: Node, start: number, end: number) {
|
|
|
15
15
|
export function liftTarget(range: NodeRange): number | null {
|
|
16
16
|
let parent = range.parent
|
|
17
17
|
let content = parent.content.cutByIndex(range.startIndex, range.endIndex)
|
|
18
|
-
for (let depth = range.depth;; --depth) {
|
|
18
|
+
for (let depth = range.depth, contentBefore = 0, contentAfter = 0;; --depth) {
|
|
19
19
|
let node = range.$from.node(depth)
|
|
20
|
-
let index = range.$from.index(depth), endIndex = range.$to.indexAfter(depth)
|
|
20
|
+
let index = range.$from.index(depth) + contentBefore, endIndex = range.$to.indexAfter(depth) - contentAfter
|
|
21
21
|
if (depth < range.depth && node.canReplace(index, endIndex, content))
|
|
22
22
|
return depth
|
|
23
23
|
if (depth == 0 || node.type.spec.isolating || !canCut(node, index, endIndex)) break
|
|
24
|
+
if (index) contentBefore = 1
|
|
25
|
+
if (endIndex < node.childCount) contentAfter = 1
|
|
24
26
|
}
|
|
25
27
|
return null
|
|
26
28
|
}
|
package/src/transform.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import {Node, NodeType, Mark, MarkType, ContentMatch, Slice, Fragment, NodeRange, Attrs} from "prosemirror-model"
|
|
2
|
-
|
|
3
2
|
import {Mapping} from "./map"
|
|
4
3
|
import {Step} from "./step"
|
|
5
4
|
import {addMark, removeMark, clearIncompatible} from "./mark"
|
|
@@ -66,6 +65,26 @@ export class Transform {
|
|
|
66
65
|
return this.steps.length > 0
|
|
67
66
|
}
|
|
68
67
|
|
|
68
|
+
/// Return a single range, in post-transform document positions,
|
|
69
|
+
/// that covers all content changed by this transform. Returns null
|
|
70
|
+
/// if no replacements are made. Note that this will ignore changes
|
|
71
|
+
/// that add/remove marks without replacing the underlying content.
|
|
72
|
+
changedRange() {
|
|
73
|
+
let from = 1e9, to = -1e9
|
|
74
|
+
for (let i = 0; i < this.mapping.maps.length; i++) {
|
|
75
|
+
let map = this.mapping.maps[i]
|
|
76
|
+
if (i) {
|
|
77
|
+
from = map.map(from, 1)
|
|
78
|
+
to = map.map(to, -1)
|
|
79
|
+
}
|
|
80
|
+
map.forEach((_f, _t, fromB, toB) => {
|
|
81
|
+
from = Math.min(from, fromB)
|
|
82
|
+
to = Math.max(to, toB)
|
|
83
|
+
})
|
|
84
|
+
}
|
|
85
|
+
return from == 1e9 ? null : {from, to}
|
|
86
|
+
}
|
|
87
|
+
|
|
69
88
|
/// @internal
|
|
70
89
|
addStep(step: Step, doc: Node) {
|
|
71
90
|
this.docs.push(this.doc)
|
|
@@ -206,7 +225,7 @@ export class Transform {
|
|
|
206
225
|
if (mark instanceof Mark) {
|
|
207
226
|
if (mark.isInSet(node.marks)) this.step(new RemoveNodeMarkStep(pos, mark))
|
|
208
227
|
} else {
|
|
209
|
-
let set = node.marks, found, steps: Step[] = []
|
|
228
|
+
let set = node.marks, found: Mark | undefined, steps: Step[] = []
|
|
210
229
|
while (found = mark.isInSet(set)) {
|
|
211
230
|
steps.push(new RemoveNodeMarkStep(pos, found))
|
|
212
231
|
set = found.removeFromSet(set)
|