prosemirror-transform 1.8.0 → 1.10.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 +16 -0
- package/dist/index.cjs +174 -489
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +40 -6
- package/package.json +2 -2
- package/src/mark.ts +4 -2
- package/src/replace_step.ts +2 -1
- package/src/structure.ts +37 -4
- package/src/transform.ts +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -406,7 +406,7 @@ declare class Transform {
|
|
|
406
406
|
Set the type of all textblocks (partly) between `from` and `to` to
|
|
407
407
|
the given node type with the given attributes.
|
|
408
408
|
*/
|
|
409
|
-
setBlockType(from: number, to: number | undefined, type: NodeType, attrs?: Attrs | null): this;
|
|
409
|
+
setBlockType(from: number, to: number | undefined, type: NodeType, attrs?: Attrs | null | ((oldNode: Node) => Attrs)): this;
|
|
410
410
|
/**
|
|
411
411
|
Change the type, attributes, and/or marks of the node at `pos`.
|
|
412
412
|
When `type` isn't given, the existing node type is preserved,
|
|
@@ -836,4 +836,4 @@ would be a no-op (an empty slice over an empty range).
|
|
|
836
836
|
*/
|
|
837
837
|
declare function replaceStep(doc: Node, from: number, to?: number, slice?: Slice): Step | null;
|
|
838
838
|
|
|
839
|
-
export { AddMarkStep, AddNodeMarkStep, AttrStep, DocAttrStep, MapResult, Mappable, Mapping, RemoveMarkStep, RemoveNodeMarkStep, ReplaceAroundStep, ReplaceStep, Step, StepMap, StepResult, Transform, canJoin, canSplit, dropPoint, findWrapping, insertPoint, joinPoint, liftTarget, replaceStep };
|
|
839
|
+
export { AddMarkStep, AddNodeMarkStep, AttrStep, DocAttrStep, MapResult, type Mappable, Mapping, RemoveMarkStep, RemoveNodeMarkStep, ReplaceAroundStep, ReplaceStep, Step, StepMap, StepResult, Transform, canJoin, canSplit, dropPoint, findWrapping, insertPoint, joinPoint, liftTarget, replaceStep };
|
package/dist/index.d.ts
CHANGED
|
@@ -406,7 +406,7 @@ declare class Transform {
|
|
|
406
406
|
Set the type of all textblocks (partly) between `from` and `to` to
|
|
407
407
|
the given node type with the given attributes.
|
|
408
408
|
*/
|
|
409
|
-
setBlockType(from: number, to: number | undefined, type: NodeType, attrs?: Attrs | null): this;
|
|
409
|
+
setBlockType(from: number, to: number | undefined, type: NodeType, attrs?: Attrs | null | ((oldNode: Node) => Attrs)): this;
|
|
410
410
|
/**
|
|
411
411
|
Change the type, attributes, and/or marks of the node at `pos`.
|
|
412
412
|
When `type` isn't given, the existing node type is preserved,
|
|
@@ -836,4 +836,4 @@ would be a no-op (an empty slice over an empty range).
|
|
|
836
836
|
*/
|
|
837
837
|
declare function replaceStep(doc: Node, from: number, to?: number, slice?: Slice): Step | null;
|
|
838
838
|
|
|
839
|
-
export { AddMarkStep, AddNodeMarkStep, AttrStep, DocAttrStep, MapResult, Mappable, Mapping, RemoveMarkStep, RemoveNodeMarkStep, ReplaceAroundStep, ReplaceStep, Step, StepMap, StepResult, Transform, canJoin, canSplit, dropPoint, findWrapping, insertPoint, joinPoint, liftTarget, replaceStep };
|
|
839
|
+
export { AddMarkStep, AddNodeMarkStep, AttrStep, DocAttrStep, MapResult, type Mappable, Mapping, RemoveMarkStep, RemoveNodeMarkStep, ReplaceAroundStep, ReplaceStep, Step, StepMap, StepResult, Transform, canJoin, canSplit, dropPoint, findWrapping, insertPoint, joinPoint, liftTarget, replaceStep };
|
package/dist/index.js
CHANGED
|
@@ -824,7 +824,8 @@ class ReplaceAroundStep extends Step {
|
|
|
824
824
|
}
|
|
825
825
|
map(mapping) {
|
|
826
826
|
let from = mapping.mapResult(this.from, 1), to = mapping.mapResult(this.to, -1);
|
|
827
|
-
let gapFrom =
|
|
827
|
+
let gapFrom = this.from == this.gapFrom ? from.pos : mapping.map(this.gapFrom, -1);
|
|
828
|
+
let gapTo = this.to == this.gapTo ? to.pos : mapping.map(this.gapTo, 1);
|
|
828
829
|
if ((from.deletedAcross && to.deletedAcross) || gapFrom < from.pos || gapTo > to.pos)
|
|
829
830
|
return null;
|
|
830
831
|
return new ReplaceAroundStep(from.pos, to.pos, gapFrom, gapTo, this.slice, this.insert, this.structure);
|
|
@@ -936,7 +937,7 @@ function removeMark(tr, from, to, mark) {
|
|
|
936
937
|
});
|
|
937
938
|
matched.forEach(m => tr.step(new RemoveMarkStep(m.from, m.to, m.style)));
|
|
938
939
|
}
|
|
939
|
-
function clearIncompatible(tr, pos, parentType, match = parentType.contentMatch) {
|
|
940
|
+
function clearIncompatible(tr, pos, parentType, match = parentType.contentMatch, clearNewlines = true) {
|
|
940
941
|
let node = tr.doc.nodeAt(pos);
|
|
941
942
|
let replSteps = [], cur = pos + 1;
|
|
942
943
|
for (let i = 0; i < node.childCount; i++) {
|
|
@@ -950,7 +951,7 @@ function clearIncompatible(tr, pos, parentType, match = parentType.contentMatch)
|
|
|
950
951
|
for (let j = 0; j < child.marks.length; j++)
|
|
951
952
|
if (!parentType.allowsMarkType(child.marks[j].type))
|
|
952
953
|
tr.step(new RemoveMarkStep(cur, end, child.marks[j]));
|
|
953
|
-
if (child.isText &&
|
|
954
|
+
if (clearNewlines && child.isText && parentType.whitespace != "pre") {
|
|
954
955
|
let m, newline = /\r?\n|\r/g, slice;
|
|
955
956
|
while (m = newline.exec(child.text)) {
|
|
956
957
|
if (!slice)
|
|
@@ -1074,16 +1075,49 @@ function setBlockType(tr, from, to, type, attrs) {
|
|
|
1074
1075
|
throw new RangeError("Type given to setBlockType should be a textblock");
|
|
1075
1076
|
let mapFrom = tr.steps.length;
|
|
1076
1077
|
tr.doc.nodesBetween(from, to, (node, pos) => {
|
|
1077
|
-
|
|
1078
|
+
let attrsHere = typeof attrs == "function" ? attrs(node) : attrs;
|
|
1079
|
+
if (node.isTextblock && !node.hasMarkup(type, attrsHere) &&
|
|
1080
|
+
canChangeType(tr.doc, tr.mapping.slice(mapFrom).map(pos), type)) {
|
|
1081
|
+
let convertNewlines = null;
|
|
1082
|
+
if (type.schema.linebreakReplacement) {
|
|
1083
|
+
let pre = type.whitespace == "pre", supportLinebreak = !!type.contentMatch.matchType(type.schema.linebreakReplacement);
|
|
1084
|
+
if (pre && !supportLinebreak)
|
|
1085
|
+
convertNewlines = false;
|
|
1086
|
+
else if (!pre && supportLinebreak)
|
|
1087
|
+
convertNewlines = true;
|
|
1088
|
+
}
|
|
1078
1089
|
// Ensure all markup that isn't allowed in the new node type is cleared
|
|
1079
|
-
|
|
1090
|
+
if (convertNewlines === false)
|
|
1091
|
+
replaceLinebreaks(tr, node, pos, mapFrom);
|
|
1092
|
+
clearIncompatible(tr, tr.mapping.slice(mapFrom).map(pos, 1), type, undefined, convertNewlines === null);
|
|
1080
1093
|
let mapping = tr.mapping.slice(mapFrom);
|
|
1081
1094
|
let startM = mapping.map(pos, 1), endM = mapping.map(pos + node.nodeSize, 1);
|
|
1082
|
-
tr.step(new ReplaceAroundStep(startM, endM, startM + 1, endM - 1, new Slice(Fragment.from(type.create(
|
|
1095
|
+
tr.step(new ReplaceAroundStep(startM, endM, startM + 1, endM - 1, new Slice(Fragment.from(type.create(attrsHere, null, node.marks)), 0, 0), 1, true));
|
|
1096
|
+
if (convertNewlines === true)
|
|
1097
|
+
replaceNewlines(tr, node, pos, mapFrom);
|
|
1083
1098
|
return false;
|
|
1084
1099
|
}
|
|
1085
1100
|
});
|
|
1086
1101
|
}
|
|
1102
|
+
function replaceNewlines(tr, node, pos, mapFrom) {
|
|
1103
|
+
node.forEach((child, offset) => {
|
|
1104
|
+
if (child.isText) {
|
|
1105
|
+
let m, newline = /\r?\n|\r/g;
|
|
1106
|
+
while (m = newline.exec(child.text)) {
|
|
1107
|
+
let start = tr.mapping.slice(mapFrom).map(pos + 1 + offset + m.index);
|
|
1108
|
+
tr.replaceWith(start, start + 1, node.type.schema.linebreakReplacement.create());
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
});
|
|
1112
|
+
}
|
|
1113
|
+
function replaceLinebreaks(tr, node, pos, mapFrom) {
|
|
1114
|
+
node.forEach((child, offset) => {
|
|
1115
|
+
if (child.type == child.type.schema.linebreakReplacement) {
|
|
1116
|
+
let start = tr.mapping.slice(mapFrom).map(pos + 1 + offset);
|
|
1117
|
+
tr.replaceWith(start, start + 1, node.type.schema.text("\n"));
|
|
1118
|
+
}
|
|
1119
|
+
});
|
|
1120
|
+
}
|
|
1087
1121
|
function canChangeType(doc, pos, type) {
|
|
1088
1122
|
let $pos = doc.resolve(pos), index = $pos.index();
|
|
1089
1123
|
return $pos.parent.canReplaceWith(index, index + 1, type);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prosemirror-transform",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.10.0",
|
|
4
4
|
"description": "ProseMirror document transformations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"url": "git://github.com/prosemirror/prosemirror-transform.git"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"prosemirror-model": "^1.
|
|
27
|
+
"prosemirror-model": "^1.21.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"@prosemirror/buildhelper": "^0.1.5",
|
package/src/mark.ts
CHANGED
|
@@ -72,7 +72,9 @@ export function removeMark(tr: Transform, from: number, to: number, mark?: Mark
|
|
|
72
72
|
matched.forEach(m => tr.step(new RemoveMarkStep(m.from, m.to, m.style)))
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
export function clearIncompatible(tr: Transform, pos: number, parentType: NodeType,
|
|
75
|
+
export function clearIncompatible(tr: Transform, pos: number, parentType: NodeType,
|
|
76
|
+
match = parentType.contentMatch,
|
|
77
|
+
clearNewlines = true) {
|
|
76
78
|
let node = tr.doc.nodeAt(pos)!
|
|
77
79
|
let replSteps: Step[] = [], cur = pos + 1
|
|
78
80
|
for (let i = 0; i < node.childCount; i++) {
|
|
@@ -85,7 +87,7 @@ export function clearIncompatible(tr: Transform, pos: number, parentType: NodeTy
|
|
|
85
87
|
for (let j = 0; j < child.marks.length; j++) if (!parentType.allowsMarkType(child.marks[j].type))
|
|
86
88
|
tr.step(new RemoveMarkStep(cur, end, child.marks[j]))
|
|
87
89
|
|
|
88
|
-
if (child.isText &&
|
|
90
|
+
if (clearNewlines && child.isText && parentType.whitespace != "pre") {
|
|
89
91
|
let m, newline = /\r?\n|\r/g, slice
|
|
90
92
|
while (m = newline.exec(child.text!)) {
|
|
91
93
|
if (!slice) slice = new Slice(Fragment.from(parentType.schema.text(" ", parentType.allowedMarks(child.marks))),
|
package/src/replace_step.ts
CHANGED
|
@@ -134,7 +134,8 @@ export class ReplaceAroundStep extends Step {
|
|
|
134
134
|
|
|
135
135
|
map(mapping: Mappable) {
|
|
136
136
|
let from = mapping.mapResult(this.from, 1), to = mapping.mapResult(this.to, -1)
|
|
137
|
-
let gapFrom =
|
|
137
|
+
let gapFrom = this.from == this.gapFrom ? from.pos : mapping.map(this.gapFrom, -1)
|
|
138
|
+
let gapTo = this.to == this.gapTo ? to.pos : mapping.map(this.gapTo, 1)
|
|
138
139
|
if ((from.deletedAcross && to.deletedAcross) || gapFrom < from.pos || gapTo > to.pos) return null
|
|
139
140
|
return new ReplaceAroundStep(from.pos, to.pos, gapFrom, gapTo, this.slice, this.insert, this.structure)
|
|
140
141
|
}
|
package/src/structure.ts
CHANGED
|
@@ -2,6 +2,7 @@ import {Slice, Fragment, NodeRange, NodeType, Node, Mark, Attrs, ContentMatch} f
|
|
|
2
2
|
|
|
3
3
|
import {Transform} from "./transform"
|
|
4
4
|
import {ReplaceStep, ReplaceAroundStep} from "./replace_step"
|
|
5
|
+
import {clearIncompatible} from "./mark"
|
|
5
6
|
|
|
6
7
|
function canCut(node: Node, start: number, end: number) {
|
|
7
8
|
return (start == 0 || node.canReplace(start, node.childCount)) &&
|
|
@@ -111,22 +112,54 @@ export function wrap(tr: Transform, range: NodeRange, wrappers: readonly {type:
|
|
|
111
112
|
tr.step(new ReplaceAroundStep(start, end, start, end, new Slice(content, 0, 0), wrappers.length, true))
|
|
112
113
|
}
|
|
113
114
|
|
|
114
|
-
export function setBlockType(tr: Transform, from: number, to: number,
|
|
115
|
+
export function setBlockType(tr: Transform, from: number, to: number,
|
|
116
|
+
type: NodeType, attrs: Attrs | null | ((oldNode: Node) => Attrs)) {
|
|
115
117
|
if (!type.isTextblock) throw new RangeError("Type given to setBlockType should be a textblock")
|
|
116
118
|
let mapFrom = tr.steps.length
|
|
117
119
|
tr.doc.nodesBetween(from, to, (node, pos) => {
|
|
118
|
-
|
|
120
|
+
let attrsHere = typeof attrs == "function" ? attrs(node) : attrs
|
|
121
|
+
if (node.isTextblock && !node.hasMarkup(type, attrsHere) &&
|
|
122
|
+
canChangeType(tr.doc, tr.mapping.slice(mapFrom).map(pos), type)) {
|
|
123
|
+
let convertNewlines = null
|
|
124
|
+
if (type.schema.linebreakReplacement) {
|
|
125
|
+
let pre = type.whitespace == "pre", supportLinebreak = !!type.contentMatch.matchType(type.schema.linebreakReplacement)
|
|
126
|
+
if (pre && !supportLinebreak) convertNewlines = false
|
|
127
|
+
else if (!pre && supportLinebreak) convertNewlines = true
|
|
128
|
+
}
|
|
119
129
|
// Ensure all markup that isn't allowed in the new node type is cleared
|
|
120
|
-
|
|
130
|
+
if (convertNewlines === false) replaceLinebreaks(tr, node, pos, mapFrom)
|
|
131
|
+
clearIncompatible(tr, tr.mapping.slice(mapFrom).map(pos, 1), type, undefined, convertNewlines === null)
|
|
121
132
|
let mapping = tr.mapping.slice(mapFrom)
|
|
122
133
|
let startM = mapping.map(pos, 1), endM = mapping.map(pos + node.nodeSize, 1)
|
|
123
134
|
tr.step(new ReplaceAroundStep(startM, endM, startM + 1, endM - 1,
|
|
124
|
-
new Slice(Fragment.from(type.create(
|
|
135
|
+
new Slice(Fragment.from(type.create(attrsHere, null, node.marks)), 0, 0), 1, true))
|
|
136
|
+
if (convertNewlines === true) replaceNewlines(tr, node, pos, mapFrom)
|
|
125
137
|
return false
|
|
126
138
|
}
|
|
127
139
|
})
|
|
128
140
|
}
|
|
129
141
|
|
|
142
|
+
function replaceNewlines(tr: Transform, node: Node, pos: number, mapFrom: number) {
|
|
143
|
+
node.forEach((child, offset) => {
|
|
144
|
+
if (child.isText) {
|
|
145
|
+
let m, newline = /\r?\n|\r/g
|
|
146
|
+
while (m = newline.exec(child.text!)) {
|
|
147
|
+
let start = tr.mapping.slice(mapFrom).map(pos + 1 + offset + m.index)
|
|
148
|
+
tr.replaceWith(start, start + 1, node.type.schema.linebreakReplacement!.create())
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
})
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function replaceLinebreaks(tr: Transform, node: Node, pos: number, mapFrom: number) {
|
|
155
|
+
node.forEach((child, offset) => {
|
|
156
|
+
if (child.type == child.type.schema.linebreakReplacement) {
|
|
157
|
+
let start = tr.mapping.slice(mapFrom).map(pos + 1 + offset)
|
|
158
|
+
tr.replaceWith(start, start + 1, node.type.schema.text("\n"))
|
|
159
|
+
}
|
|
160
|
+
})
|
|
161
|
+
}
|
|
162
|
+
|
|
130
163
|
function canChangeType(doc: Node, pos: number, type: NodeType) {
|
|
131
164
|
let $pos = doc.resolve(pos), index = $pos.index()
|
|
132
165
|
return $pos.parent.canReplaceWith(index, index + 1, type)
|
package/src/transform.ts
CHANGED
|
@@ -166,7 +166,7 @@ export class Transform {
|
|
|
166
166
|
|
|
167
167
|
/// Set the type of all textblocks (partly) between `from` and `to` to
|
|
168
168
|
/// the given node type with the given attributes.
|
|
169
|
-
setBlockType(from: number, to = from, type: NodeType, attrs: Attrs | null = null): this {
|
|
169
|
+
setBlockType(from: number, to = from, type: NodeType, attrs: Attrs | null | ((oldNode: Node) => Attrs) = null): this {
|
|
170
170
|
setBlockType(this, from, to, type, attrs)
|
|
171
171
|
return this
|
|
172
172
|
}
|