prosemirror-transform 1.7.5 → 1.9.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 +18 -0
- package/dist/index.cjs +233 -476
- package/dist/index.d.cts +31 -1
- package/dist/index.d.ts +31 -1
- package/dist/index.js +91 -5
- package/package.json +2 -2
- package/src/README.md +1 -0
- package/src/attr_step.ts +45 -0
- package/src/index.ts +1 -1
- package/src/mark.ts +4 -2
- package/src/replace_step.ts +2 -1
- package/src/structure.ts +31 -1
- package/src/transform.ts +9 -1
package/dist/index.d.cts
CHANGED
|
@@ -414,9 +414,15 @@ declare class Transform {
|
|
|
414
414
|
setNodeMarkup(pos: number, type?: NodeType | null, attrs?: Attrs | null, marks?: readonly Mark[]): this;
|
|
415
415
|
/**
|
|
416
416
|
Set a single attribute on a given node to a new value.
|
|
417
|
+
The `pos` addresses the document content. Use `setDocAttribute`
|
|
418
|
+
to set attributes on the document itself.
|
|
417
419
|
*/
|
|
418
420
|
setNodeAttribute(pos: number, attr: string, value: any): this;
|
|
419
421
|
/**
|
|
422
|
+
Set a single attribute on the document to a new value.
|
|
423
|
+
*/
|
|
424
|
+
setDocAttribute(attr: string, value: any): this;
|
|
425
|
+
/**
|
|
420
426
|
Add a mark to the node at position `pos`.
|
|
421
427
|
*/
|
|
422
428
|
addNodeMark(pos: number, mark: Mark): this;
|
|
@@ -797,6 +803,30 @@ declare class AttrStep extends Step {
|
|
|
797
803
|
toJSON(): any;
|
|
798
804
|
static fromJSON(schema: Schema, json: any): AttrStep;
|
|
799
805
|
}
|
|
806
|
+
/**
|
|
807
|
+
Update an attribute in the doc node.
|
|
808
|
+
*/
|
|
809
|
+
declare class DocAttrStep extends Step {
|
|
810
|
+
/**
|
|
811
|
+
The attribute to set.
|
|
812
|
+
*/
|
|
813
|
+
readonly attr: string;
|
|
814
|
+
readonly value: any;
|
|
815
|
+
/**
|
|
816
|
+
Construct an attribute step.
|
|
817
|
+
*/
|
|
818
|
+
constructor(
|
|
819
|
+
/**
|
|
820
|
+
The attribute to set.
|
|
821
|
+
*/
|
|
822
|
+
attr: string, value: any);
|
|
823
|
+
apply(doc: Node): StepResult;
|
|
824
|
+
getMap(): StepMap;
|
|
825
|
+
invert(doc: Node): DocAttrStep;
|
|
826
|
+
map(mapping: Mappable): this;
|
|
827
|
+
toJSON(): any;
|
|
828
|
+
static fromJSON(schema: Schema, json: any): DocAttrStep;
|
|
829
|
+
}
|
|
800
830
|
|
|
801
831
|
/**
|
|
802
832
|
‘Fit’ a slice into a given position in the document, producing a
|
|
@@ -806,4 +836,4 @@ would be a no-op (an empty slice over an empty range).
|
|
|
806
836
|
*/
|
|
807
837
|
declare function replaceStep(doc: Node, from: number, to?: number, slice?: Slice): Step | null;
|
|
808
838
|
|
|
809
|
-
export { AddMarkStep, AddNodeMarkStep, AttrStep, 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
|
@@ -414,9 +414,15 @@ declare class Transform {
|
|
|
414
414
|
setNodeMarkup(pos: number, type?: NodeType | null, attrs?: Attrs | null, marks?: readonly Mark[]): this;
|
|
415
415
|
/**
|
|
416
416
|
Set a single attribute on a given node to a new value.
|
|
417
|
+
The `pos` addresses the document content. Use `setDocAttribute`
|
|
418
|
+
to set attributes on the document itself.
|
|
417
419
|
*/
|
|
418
420
|
setNodeAttribute(pos: number, attr: string, value: any): this;
|
|
419
421
|
/**
|
|
422
|
+
Set a single attribute on the document to a new value.
|
|
423
|
+
*/
|
|
424
|
+
setDocAttribute(attr: string, value: any): this;
|
|
425
|
+
/**
|
|
420
426
|
Add a mark to the node at position `pos`.
|
|
421
427
|
*/
|
|
422
428
|
addNodeMark(pos: number, mark: Mark): this;
|
|
@@ -797,6 +803,30 @@ declare class AttrStep extends Step {
|
|
|
797
803
|
toJSON(): any;
|
|
798
804
|
static fromJSON(schema: Schema, json: any): AttrStep;
|
|
799
805
|
}
|
|
806
|
+
/**
|
|
807
|
+
Update an attribute in the doc node.
|
|
808
|
+
*/
|
|
809
|
+
declare class DocAttrStep extends Step {
|
|
810
|
+
/**
|
|
811
|
+
The attribute to set.
|
|
812
|
+
*/
|
|
813
|
+
readonly attr: string;
|
|
814
|
+
readonly value: any;
|
|
815
|
+
/**
|
|
816
|
+
Construct an attribute step.
|
|
817
|
+
*/
|
|
818
|
+
constructor(
|
|
819
|
+
/**
|
|
820
|
+
The attribute to set.
|
|
821
|
+
*/
|
|
822
|
+
attr: string, value: any);
|
|
823
|
+
apply(doc: Node): StepResult;
|
|
824
|
+
getMap(): StepMap;
|
|
825
|
+
invert(doc: Node): DocAttrStep;
|
|
826
|
+
map(mapping: Mappable): this;
|
|
827
|
+
toJSON(): any;
|
|
828
|
+
static fromJSON(schema: Schema, json: any): DocAttrStep;
|
|
829
|
+
}
|
|
800
830
|
|
|
801
831
|
/**
|
|
802
832
|
‘Fit’ a slice into a given position in the document, producing a
|
|
@@ -806,4 +836,4 @@ would be a no-op (an empty slice over an empty range).
|
|
|
806
836
|
*/
|
|
807
837
|
declare function replaceStep(doc: Node, from: number, to?: number, slice?: Slice): Step | null;
|
|
808
838
|
|
|
809
|
-
export { AddMarkStep, AddNodeMarkStep, AttrStep, 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)
|
|
@@ -1075,15 +1076,46 @@ function setBlockType(tr, from, to, type, attrs) {
|
|
|
1075
1076
|
let mapFrom = tr.steps.length;
|
|
1076
1077
|
tr.doc.nodesBetween(from, to, (node, pos) => {
|
|
1077
1078
|
if (node.isTextblock && !node.hasMarkup(type, attrs) && canChangeType(tr.doc, tr.mapping.slice(mapFrom).map(pos), type)) {
|
|
1079
|
+
let convertNewlines = null;
|
|
1080
|
+
if (type.schema.linebreakReplacement) {
|
|
1081
|
+
let pre = type.whitespace == "pre", supportLinebreak = !!type.contentMatch.matchType(type.schema.linebreakReplacement);
|
|
1082
|
+
if (pre && !supportLinebreak)
|
|
1083
|
+
convertNewlines = false;
|
|
1084
|
+
else if (!pre && supportLinebreak)
|
|
1085
|
+
convertNewlines = true;
|
|
1086
|
+
}
|
|
1078
1087
|
// Ensure all markup that isn't allowed in the new node type is cleared
|
|
1079
|
-
|
|
1088
|
+
if (convertNewlines === false)
|
|
1089
|
+
replaceLinebreaks(tr, node, pos, mapFrom);
|
|
1090
|
+
clearIncompatible(tr, tr.mapping.slice(mapFrom).map(pos, 1), type, undefined, convertNewlines === null);
|
|
1080
1091
|
let mapping = tr.mapping.slice(mapFrom);
|
|
1081
1092
|
let startM = mapping.map(pos, 1), endM = mapping.map(pos + node.nodeSize, 1);
|
|
1082
1093
|
tr.step(new ReplaceAroundStep(startM, endM, startM + 1, endM - 1, new Slice(Fragment.from(type.create(attrs, null, node.marks)), 0, 0), 1, true));
|
|
1094
|
+
if (convertNewlines === true)
|
|
1095
|
+
replaceNewlines(tr, node, pos, mapFrom);
|
|
1083
1096
|
return false;
|
|
1084
1097
|
}
|
|
1085
1098
|
});
|
|
1086
1099
|
}
|
|
1100
|
+
function replaceNewlines(tr, node, pos, mapFrom) {
|
|
1101
|
+
node.forEach((child, offset) => {
|
|
1102
|
+
if (child.isText) {
|
|
1103
|
+
let m, newline = /\r?\n|\r/g;
|
|
1104
|
+
while (m = newline.exec(child.text)) {
|
|
1105
|
+
let start = tr.mapping.slice(mapFrom).map(pos + 1 + offset + m.index);
|
|
1106
|
+
tr.replaceWith(start, start + 1, node.type.schema.linebreakReplacement.create());
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
});
|
|
1110
|
+
}
|
|
1111
|
+
function replaceLinebreaks(tr, node, pos, mapFrom) {
|
|
1112
|
+
node.forEach((child, offset) => {
|
|
1113
|
+
if (child.type == child.type.schema.linebreakReplacement) {
|
|
1114
|
+
let start = tr.mapping.slice(mapFrom).map(pos + 1 + offset);
|
|
1115
|
+
tr.replaceWith(start, start + 1, node.type.schema.text("\n"));
|
|
1116
|
+
}
|
|
1117
|
+
});
|
|
1118
|
+
}
|
|
1087
1119
|
function canChangeType(doc, pos, type) {
|
|
1088
1120
|
let $pos = doc.resolve(pos), index = $pos.index();
|
|
1089
1121
|
return $pos.parent.canReplaceWith(index, index + 1, type);
|
|
@@ -1746,6 +1778,51 @@ class AttrStep extends Step {
|
|
|
1746
1778
|
}
|
|
1747
1779
|
}
|
|
1748
1780
|
Step.jsonID("attr", AttrStep);
|
|
1781
|
+
/**
|
|
1782
|
+
Update an attribute in the doc node.
|
|
1783
|
+
*/
|
|
1784
|
+
class DocAttrStep extends Step {
|
|
1785
|
+
/**
|
|
1786
|
+
Construct an attribute step.
|
|
1787
|
+
*/
|
|
1788
|
+
constructor(
|
|
1789
|
+
/**
|
|
1790
|
+
The attribute to set.
|
|
1791
|
+
*/
|
|
1792
|
+
attr,
|
|
1793
|
+
// The attribute's new value.
|
|
1794
|
+
value) {
|
|
1795
|
+
super();
|
|
1796
|
+
this.attr = attr;
|
|
1797
|
+
this.value = value;
|
|
1798
|
+
}
|
|
1799
|
+
apply(doc) {
|
|
1800
|
+
let attrs = Object.create(null);
|
|
1801
|
+
for (let name in doc.attrs)
|
|
1802
|
+
attrs[name] = doc.attrs[name];
|
|
1803
|
+
attrs[this.attr] = this.value;
|
|
1804
|
+
let updated = doc.type.create(attrs, doc.content, doc.marks);
|
|
1805
|
+
return StepResult.ok(updated);
|
|
1806
|
+
}
|
|
1807
|
+
getMap() {
|
|
1808
|
+
return StepMap.empty;
|
|
1809
|
+
}
|
|
1810
|
+
invert(doc) {
|
|
1811
|
+
return new DocAttrStep(this.attr, doc.attrs[this.attr]);
|
|
1812
|
+
}
|
|
1813
|
+
map(mapping) {
|
|
1814
|
+
return this;
|
|
1815
|
+
}
|
|
1816
|
+
toJSON() {
|
|
1817
|
+
return { stepType: "docAttr", attr: this.attr, value: this.value };
|
|
1818
|
+
}
|
|
1819
|
+
static fromJSON(schema, json) {
|
|
1820
|
+
if (typeof json.attr != "string")
|
|
1821
|
+
throw new RangeError("Invalid input for DocAttrStep.fromJSON");
|
|
1822
|
+
return new DocAttrStep(json.attr, json.value);
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
Step.jsonID("docAttr", DocAttrStep);
|
|
1749
1826
|
|
|
1750
1827
|
/**
|
|
1751
1828
|
@internal
|
|
@@ -1950,12 +2027,21 @@ class Transform {
|
|
|
1950
2027
|
}
|
|
1951
2028
|
/**
|
|
1952
2029
|
Set a single attribute on a given node to a new value.
|
|
2030
|
+
The `pos` addresses the document content. Use `setDocAttribute`
|
|
2031
|
+
to set attributes on the document itself.
|
|
1953
2032
|
*/
|
|
1954
2033
|
setNodeAttribute(pos, attr, value) {
|
|
1955
2034
|
this.step(new AttrStep(pos, attr, value));
|
|
1956
2035
|
return this;
|
|
1957
2036
|
}
|
|
1958
2037
|
/**
|
|
2038
|
+
Set a single attribute on the document to a new value.
|
|
2039
|
+
*/
|
|
2040
|
+
setDocAttribute(attr, value) {
|
|
2041
|
+
this.step(new DocAttrStep(attr, value));
|
|
2042
|
+
return this;
|
|
2043
|
+
}
|
|
2044
|
+
/**
|
|
1959
2045
|
Add a mark to the node at position `pos`.
|
|
1960
2046
|
*/
|
|
1961
2047
|
addNodeMark(pos, mark) {
|
|
@@ -2018,4 +2104,4 @@ class Transform {
|
|
|
2018
2104
|
}
|
|
2019
2105
|
}
|
|
2020
2106
|
|
|
2021
|
-
export { AddMarkStep, AddNodeMarkStep, AttrStep, MapResult, Mapping, RemoveMarkStep, RemoveNodeMarkStep, ReplaceAroundStep, ReplaceStep, Step, StepMap, StepResult, Transform, TransformError, canJoin, canSplit, dropPoint, findWrapping, insertPoint, joinPoint, liftTarget, replaceStep };
|
|
2107
|
+
export { AddMarkStep, AddNodeMarkStep, AttrStep, DocAttrStep, MapResult, Mapping, RemoveMarkStep, RemoveNodeMarkStep, ReplaceAroundStep, ReplaceStep, Step, StepMap, StepResult, Transform, TransformError, canJoin, canSplit, dropPoint, findWrapping, insertPoint, joinPoint, liftTarget, replaceStep };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prosemirror-transform",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.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/README.md
CHANGED
package/src/attr_step.ts
CHANGED
|
@@ -51,3 +51,48 @@ export class AttrStep extends Step {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
Step.jsonID("attr", AttrStep)
|
|
54
|
+
|
|
55
|
+
/// Update an attribute in the doc node.
|
|
56
|
+
export class DocAttrStep extends Step {
|
|
57
|
+
/// Construct an attribute step.
|
|
58
|
+
constructor(
|
|
59
|
+
/// The attribute to set.
|
|
60
|
+
readonly attr: string,
|
|
61
|
+
// The attribute's new value.
|
|
62
|
+
readonly value: any
|
|
63
|
+
) {
|
|
64
|
+
super()
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
apply(doc: Node) {
|
|
68
|
+
let attrs = Object.create(null)
|
|
69
|
+
for (let name in doc.attrs) attrs[name] = doc.attrs[name]
|
|
70
|
+
attrs[this.attr] = this.value
|
|
71
|
+
let updated = doc.type.create(attrs, doc.content, doc.marks)
|
|
72
|
+
return StepResult.ok(updated)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
getMap() {
|
|
76
|
+
return StepMap.empty
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
invert(doc: Node) {
|
|
80
|
+
return new DocAttrStep(this.attr, doc.attrs[this.attr])
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
map(mapping: Mappable) {
|
|
84
|
+
return this
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
toJSON(): any {
|
|
88
|
+
return {stepType: "docAttr", attr: this.attr, value: this.value}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
static fromJSON(schema: Schema, json: any) {
|
|
92
|
+
if (typeof json.attr != "string")
|
|
93
|
+
throw new RangeError("Invalid input for DocAttrStep.fromJSON")
|
|
94
|
+
return new DocAttrStep(json.attr, json.value)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
Step.jsonID("docAttr", DocAttrStep)
|
package/src/index.ts
CHANGED
|
@@ -6,6 +6,6 @@ export {joinPoint, canJoin, canSplit, insertPoint, dropPoint, liftTarget, findWr
|
|
|
6
6
|
export {StepMap, MapResult, Mapping, Mappable} from "./map"
|
|
7
7
|
export {AddMarkStep, RemoveMarkStep, AddNodeMarkStep, RemoveNodeMarkStep} from "./mark_step"
|
|
8
8
|
export {ReplaceStep, ReplaceAroundStep} from "./replace_step"
|
|
9
|
-
export {AttrStep} from "./attr_step"
|
|
9
|
+
export {AttrStep, DocAttrStep} from "./attr_step"
|
|
10
10
|
import "./mark"
|
|
11
11
|
export {replaceStep} from "./replace"
|
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)) &&
|
|
@@ -116,17 +117,46 @@ export function setBlockType(tr: Transform, from: number, to: number, type: Node
|
|
|
116
117
|
let mapFrom = tr.steps.length
|
|
117
118
|
tr.doc.nodesBetween(from, to, (node, pos) => {
|
|
118
119
|
if (node.isTextblock && !node.hasMarkup(type, attrs) && canChangeType(tr.doc, tr.mapping.slice(mapFrom).map(pos), type)) {
|
|
120
|
+
let convertNewlines = null
|
|
121
|
+
if (type.schema.linebreakReplacement) {
|
|
122
|
+
let pre = type.whitespace == "pre", supportLinebreak = !!type.contentMatch.matchType(type.schema.linebreakReplacement)
|
|
123
|
+
if (pre && !supportLinebreak) convertNewlines = false
|
|
124
|
+
else if (!pre && supportLinebreak) convertNewlines = true
|
|
125
|
+
}
|
|
119
126
|
// Ensure all markup that isn't allowed in the new node type is cleared
|
|
120
|
-
|
|
127
|
+
if (convertNewlines === false) replaceLinebreaks(tr, node, pos, mapFrom)
|
|
128
|
+
clearIncompatible(tr, tr.mapping.slice(mapFrom).map(pos, 1), type, undefined, convertNewlines === null)
|
|
121
129
|
let mapping = tr.mapping.slice(mapFrom)
|
|
122
130
|
let startM = mapping.map(pos, 1), endM = mapping.map(pos + node.nodeSize, 1)
|
|
123
131
|
tr.step(new ReplaceAroundStep(startM, endM, startM + 1, endM - 1,
|
|
124
132
|
new Slice(Fragment.from(type.create(attrs, null, node.marks)), 0, 0), 1, true))
|
|
133
|
+
if (convertNewlines === true) replaceNewlines(tr, node, pos, mapFrom)
|
|
125
134
|
return false
|
|
126
135
|
}
|
|
127
136
|
})
|
|
128
137
|
}
|
|
129
138
|
|
|
139
|
+
function replaceNewlines(tr: Transform, node: Node, pos: number, mapFrom: number) {
|
|
140
|
+
node.forEach((child, offset) => {
|
|
141
|
+
if (child.isText) {
|
|
142
|
+
let m, newline = /\r?\n|\r/g
|
|
143
|
+
while (m = newline.exec(child.text!)) {
|
|
144
|
+
let start = tr.mapping.slice(mapFrom).map(pos + 1 + offset + m.index)
|
|
145
|
+
tr.replaceWith(start, start + 1, node.type.schema.linebreakReplacement!.create())
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function replaceLinebreaks(tr: Transform, node: Node, pos: number, mapFrom: number) {
|
|
152
|
+
node.forEach((child, offset) => {
|
|
153
|
+
if (child.type == child.type.schema.linebreakReplacement) {
|
|
154
|
+
let start = tr.mapping.slice(mapFrom).map(pos + 1 + offset)
|
|
155
|
+
tr.replaceWith(start, start + 1, node.type.schema.text("\n"))
|
|
156
|
+
}
|
|
157
|
+
})
|
|
158
|
+
}
|
|
159
|
+
|
|
130
160
|
function canChangeType(doc: Node, pos: number, type: NodeType) {
|
|
131
161
|
let $pos = doc.resolve(pos), index = $pos.index()
|
|
132
162
|
return $pos.parent.canReplaceWith(index, index + 1, type)
|
package/src/transform.ts
CHANGED
|
@@ -5,7 +5,7 @@ import {Step} from "./step"
|
|
|
5
5
|
import {addMark, removeMark, clearIncompatible} from "./mark"
|
|
6
6
|
import {replaceStep, replaceRange, replaceRangeWith, deleteRange} from "./replace"
|
|
7
7
|
import {lift, wrap, setBlockType, setNodeMarkup, split, join} from "./structure"
|
|
8
|
-
import {AttrStep} from "./attr_step"
|
|
8
|
+
import {AttrStep, DocAttrStep} from "./attr_step"
|
|
9
9
|
import {AddNodeMarkStep, RemoveNodeMarkStep} from "./mark_step"
|
|
10
10
|
|
|
11
11
|
/// @internal
|
|
@@ -179,11 +179,19 @@ export class Transform {
|
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
/// Set a single attribute on a given node to a new value.
|
|
182
|
+
/// The `pos` addresses the document content. Use `setDocAttribute`
|
|
183
|
+
/// to set attributes on the document itself.
|
|
182
184
|
setNodeAttribute(pos: number, attr: string, value: any): this {
|
|
183
185
|
this.step(new AttrStep(pos, attr, value))
|
|
184
186
|
return this
|
|
185
187
|
}
|
|
186
188
|
|
|
189
|
+
/// Set a single attribute on the document to a new value.
|
|
190
|
+
setDocAttribute(attr: string, value: any): this {
|
|
191
|
+
this.step(new DocAttrStep(attr, value))
|
|
192
|
+
return this
|
|
193
|
+
}
|
|
194
|
+
|
|
187
195
|
/// Add a mark to the node at position `pos`.
|
|
188
196
|
addNodeMark(pos: number, mark: Mark): this {
|
|
189
197
|
this.step(new AddNodeMarkStep(pos, mark))
|