prosemirror-transform 1.6.0 → 1.7.1
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/README.md +1 -1
- package/dist/index.cjs +270 -27
- package/dist/index.d.ts +105 -1
- package/dist/index.js +207 -4
- package/package.json +1 -1
- package/src/README.md +3 -0
- package/src/attr_step.ts +53 -0
- package/src/index.ts +2 -1
- package/src/mark_step.ts +96 -0
- package/src/replace.ts +12 -1
- package/src/structure.ts +1 -1
- package/src/transform.ts +28 -1
- package/dist/index.es.js +0 -1702
- package/dist/index.es.js.map +0 -1
- package/dist/index.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReplaceError, Slice, Fragment, MarkType } from 'prosemirror-model';
|
|
1
|
+
import { ReplaceError, Slice, Fragment, MarkType, Mark } from 'prosemirror-model';
|
|
2
2
|
|
|
3
3
|
// Recovery values encode a range index and an offset. They are
|
|
4
4
|
// represented as numbers, because tons of them will be created when
|
|
@@ -555,6 +555,113 @@ class RemoveMarkStep extends Step {
|
|
|
555
555
|
}
|
|
556
556
|
}
|
|
557
557
|
Step.jsonID("removeMark", RemoveMarkStep);
|
|
558
|
+
/**
|
|
559
|
+
Add a mark to a specific node.
|
|
560
|
+
*/
|
|
561
|
+
class AddNodeMarkStep extends Step {
|
|
562
|
+
/**
|
|
563
|
+
Create a node mark step.
|
|
564
|
+
*/
|
|
565
|
+
constructor(
|
|
566
|
+
/**
|
|
567
|
+
The position of the target node.
|
|
568
|
+
*/
|
|
569
|
+
pos,
|
|
570
|
+
/**
|
|
571
|
+
The mark to add.
|
|
572
|
+
*/
|
|
573
|
+
mark) {
|
|
574
|
+
super();
|
|
575
|
+
this.pos = pos;
|
|
576
|
+
this.mark = mark;
|
|
577
|
+
}
|
|
578
|
+
apply(doc) {
|
|
579
|
+
let node = doc.nodeAt(this.pos);
|
|
580
|
+
if (!node)
|
|
581
|
+
return StepResult.fail("No node at mark step's position");
|
|
582
|
+
let updated = node.type.create(node.attrs, null, this.mark.addToSet(node.marks));
|
|
583
|
+
return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment.from(updated), 0, node.isLeaf ? 0 : 1));
|
|
584
|
+
}
|
|
585
|
+
invert(doc) {
|
|
586
|
+
let node = doc.nodeAt(this.pos);
|
|
587
|
+
if (node) {
|
|
588
|
+
let newSet = this.mark.addToSet(node.marks);
|
|
589
|
+
if (newSet.length == node.marks.length) {
|
|
590
|
+
for (let i = 0; i < node.marks.length; i++)
|
|
591
|
+
if (!node.marks[i].isInSet(newSet))
|
|
592
|
+
return new AddNodeMarkStep(this.pos, node.marks[i]);
|
|
593
|
+
return new AddNodeMarkStep(this.pos, this.mark);
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
return new RemoveNodeMarkStep(this.pos, this.mark);
|
|
597
|
+
}
|
|
598
|
+
map(mapping) {
|
|
599
|
+
let pos = mapping.mapResult(this.pos, 1);
|
|
600
|
+
return pos.deletedAfter ? null : new AddNodeMarkStep(pos.pos, this.mark);
|
|
601
|
+
}
|
|
602
|
+
toJSON() {
|
|
603
|
+
return { stepType: "addNodeMark", pos: this.pos, mark: this.mark.toJSON() };
|
|
604
|
+
}
|
|
605
|
+
/**
|
|
606
|
+
@internal
|
|
607
|
+
*/
|
|
608
|
+
static fromJSON(schema, json) {
|
|
609
|
+
if (typeof json.pos != "number")
|
|
610
|
+
throw new RangeError("Invalid input for AddNodeMarkStep.fromJSON");
|
|
611
|
+
return new AddNodeMarkStep(json.pos, schema.markFromJSON(json.mark));
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
Step.jsonID("addNodeMark", AddNodeMarkStep);
|
|
615
|
+
/**
|
|
616
|
+
Remove a mark from a specific node.
|
|
617
|
+
*/
|
|
618
|
+
class RemoveNodeMarkStep extends Step {
|
|
619
|
+
/**
|
|
620
|
+
Create a mark-removing step.
|
|
621
|
+
*/
|
|
622
|
+
constructor(
|
|
623
|
+
/**
|
|
624
|
+
The position of the target node.
|
|
625
|
+
*/
|
|
626
|
+
pos,
|
|
627
|
+
/**
|
|
628
|
+
The mark to remove.
|
|
629
|
+
*/
|
|
630
|
+
mark) {
|
|
631
|
+
super();
|
|
632
|
+
this.pos = pos;
|
|
633
|
+
this.mark = mark;
|
|
634
|
+
}
|
|
635
|
+
apply(doc) {
|
|
636
|
+
let node = doc.nodeAt(this.pos);
|
|
637
|
+
if (!node)
|
|
638
|
+
return StepResult.fail("No node at mark step's position");
|
|
639
|
+
let updated = node.type.create(node.attrs, null, this.mark.removeFromSet(node.marks));
|
|
640
|
+
return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment.from(updated), 0, node.isLeaf ? 0 : 1));
|
|
641
|
+
}
|
|
642
|
+
invert(doc) {
|
|
643
|
+
let node = doc.nodeAt(this.pos);
|
|
644
|
+
if (!node || !this.mark.isInSet(node.marks))
|
|
645
|
+
return this;
|
|
646
|
+
return new AddNodeMarkStep(this.pos, this.mark);
|
|
647
|
+
}
|
|
648
|
+
map(mapping) {
|
|
649
|
+
let pos = mapping.mapResult(this.pos, 1);
|
|
650
|
+
return pos.deletedAfter ? null : new RemoveNodeMarkStep(pos.pos, this.mark);
|
|
651
|
+
}
|
|
652
|
+
toJSON() {
|
|
653
|
+
return { stepType: "removeNodeMark", pos: this.pos, mark: this.mark.toJSON() };
|
|
654
|
+
}
|
|
655
|
+
/**
|
|
656
|
+
@internal
|
|
657
|
+
*/
|
|
658
|
+
static fromJSON(schema, json) {
|
|
659
|
+
if (typeof json.pos != "number")
|
|
660
|
+
throw new RangeError("Invalid input for RemoveNodeMarkStep.fromJSON");
|
|
661
|
+
return new RemoveNodeMarkStep(json.pos, schema.markFromJSON(json.mark));
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
Step.jsonID("removeNodeMark", RemoveNodeMarkStep);
|
|
558
665
|
|
|
559
666
|
/**
|
|
560
667
|
Replace a part of the document with a slice of new content.
|
|
@@ -1225,10 +1332,21 @@ class Fitter {
|
|
|
1225
1332
|
// content that can be moved somewhere on the frontier. Returns two
|
|
1226
1333
|
// depths, one for the slice and one for the frontier.
|
|
1227
1334
|
findFittable() {
|
|
1335
|
+
let startDepth = this.unplaced.openStart;
|
|
1336
|
+
for (let cur = this.unplaced.content, d = 0, openEnd = this.unplaced.openEnd; d < startDepth; d++) {
|
|
1337
|
+
let node = cur.firstChild;
|
|
1338
|
+
if (cur.childCount > 1)
|
|
1339
|
+
openEnd = 0;
|
|
1340
|
+
if (node.type.spec.isolating && openEnd <= d) {
|
|
1341
|
+
startDepth = d;
|
|
1342
|
+
break;
|
|
1343
|
+
}
|
|
1344
|
+
cur = node.content;
|
|
1345
|
+
}
|
|
1228
1346
|
// Only try wrapping nodes (pass 2) after finding a place without
|
|
1229
1347
|
// wrapping failed.
|
|
1230
1348
|
for (let pass = 1; pass <= 2; pass++) {
|
|
1231
|
-
for (let sliceDepth = this.unplaced.openStart; sliceDepth >= 0; sliceDepth--) {
|
|
1349
|
+
for (let sliceDepth = pass == 1 ? startDepth : this.unplaced.openStart; sliceDepth >= 0; sliceDepth--) {
|
|
1232
1350
|
let fragment, parent = null;
|
|
1233
1351
|
if (sliceDepth) {
|
|
1234
1352
|
parent = contentAt(this.unplaced.content, sliceDepth - 1).firstChild;
|
|
@@ -1565,6 +1683,61 @@ function coveredDepths($from, $to) {
|
|
|
1565
1683
|
return result;
|
|
1566
1684
|
}
|
|
1567
1685
|
|
|
1686
|
+
/**
|
|
1687
|
+
Update an attribute in a specific node.
|
|
1688
|
+
*/
|
|
1689
|
+
class AttrStep extends Step {
|
|
1690
|
+
/**
|
|
1691
|
+
Construct an attribute step.
|
|
1692
|
+
*/
|
|
1693
|
+
constructor(
|
|
1694
|
+
/**
|
|
1695
|
+
The position of the target node.
|
|
1696
|
+
*/
|
|
1697
|
+
pos,
|
|
1698
|
+
/**
|
|
1699
|
+
The attribute to set.
|
|
1700
|
+
*/
|
|
1701
|
+
attr,
|
|
1702
|
+
// The attribute's new value.
|
|
1703
|
+
value) {
|
|
1704
|
+
super();
|
|
1705
|
+
this.pos = pos;
|
|
1706
|
+
this.attr = attr;
|
|
1707
|
+
this.value = value;
|
|
1708
|
+
}
|
|
1709
|
+
apply(doc) {
|
|
1710
|
+
let node = doc.nodeAt(this.pos);
|
|
1711
|
+
if (!node)
|
|
1712
|
+
return StepResult.fail("No node at attribute step's position");
|
|
1713
|
+
let attrs = Object.create(null);
|
|
1714
|
+
for (let name in node.attrs)
|
|
1715
|
+
attrs[name] = node.attrs[name];
|
|
1716
|
+
attrs[this.attr] = this.value;
|
|
1717
|
+
let updated = node.type.create(attrs, null, node.marks);
|
|
1718
|
+
return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment.from(updated), 0, node.isLeaf ? 0 : 1));
|
|
1719
|
+
}
|
|
1720
|
+
getMap() {
|
|
1721
|
+
return StepMap.empty;
|
|
1722
|
+
}
|
|
1723
|
+
invert(doc) {
|
|
1724
|
+
return new AttrStep(this.pos, this.attr, doc.nodeAt(this.pos).attrs[this.attr]);
|
|
1725
|
+
}
|
|
1726
|
+
map(mapping) {
|
|
1727
|
+
let pos = mapping.mapResult(this.pos, 1);
|
|
1728
|
+
return pos.deletedAfter ? null : new AttrStep(pos.pos, this.attr, this.value);
|
|
1729
|
+
}
|
|
1730
|
+
toJSON() {
|
|
1731
|
+
return { stepType: "attr", pos: this.pos, attr: this.attr, value: this.value };
|
|
1732
|
+
}
|
|
1733
|
+
static fromJSON(schema, json) {
|
|
1734
|
+
if (typeof json.pos != "number" || typeof json.attr != "string")
|
|
1735
|
+
throw new RangeError("Invalid input for AttrStep.fromJSON");
|
|
1736
|
+
return new AttrStep(json.pos, json.attr, json.value);
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
Step.jsonID("attr", AttrStep);
|
|
1740
|
+
|
|
1568
1741
|
/**
|
|
1569
1742
|
@internal
|
|
1570
1743
|
*/
|
|
@@ -1762,11 +1935,41 @@ class Transform {
|
|
|
1762
1935
|
Change the type, attributes, and/or marks of the node at `pos`.
|
|
1763
1936
|
When `type` isn't given, the existing node type is preserved,
|
|
1764
1937
|
*/
|
|
1765
|
-
setNodeMarkup(pos, type, attrs = null, marks
|
|
1938
|
+
setNodeMarkup(pos, type, attrs = null, marks) {
|
|
1766
1939
|
setNodeMarkup(this, pos, type, attrs, marks);
|
|
1767
1940
|
return this;
|
|
1768
1941
|
}
|
|
1769
1942
|
/**
|
|
1943
|
+
Set a single attribute on a given node to a new value.
|
|
1944
|
+
*/
|
|
1945
|
+
setNodeAttribute(pos, attr, value) {
|
|
1946
|
+
this.step(new AttrStep(pos, attr, value));
|
|
1947
|
+
return this;
|
|
1948
|
+
}
|
|
1949
|
+
/**
|
|
1950
|
+
Add a mark to the node at position `pos`.
|
|
1951
|
+
*/
|
|
1952
|
+
addNodeMark(pos, mark) {
|
|
1953
|
+
this.step(new AddNodeMarkStep(pos, mark));
|
|
1954
|
+
return this;
|
|
1955
|
+
}
|
|
1956
|
+
/**
|
|
1957
|
+
Remove a mark (or a mark of the given type) from the node at
|
|
1958
|
+
position `pos`.
|
|
1959
|
+
*/
|
|
1960
|
+
removeNodeMark(pos, mark) {
|
|
1961
|
+
if (!(mark instanceof Mark)) {
|
|
1962
|
+
let node = this.doc.nodeAt(pos);
|
|
1963
|
+
if (!node)
|
|
1964
|
+
throw new RangeError("No node at position " + pos);
|
|
1965
|
+
mark = mark.isInSet(node.marks);
|
|
1966
|
+
if (!mark)
|
|
1967
|
+
return this;
|
|
1968
|
+
}
|
|
1969
|
+
this.step(new RemoveNodeMarkStep(pos, mark));
|
|
1970
|
+
return this;
|
|
1971
|
+
}
|
|
1972
|
+
/**
|
|
1770
1973
|
Split the node at the given position, and optionally, if `depth` is
|
|
1771
1974
|
greater than one, any number of nodes above that. By default, the
|
|
1772
1975
|
parts split off will inherit the node type of the original node.
|
|
@@ -1806,4 +2009,4 @@ class Transform {
|
|
|
1806
2009
|
}
|
|
1807
2010
|
}
|
|
1808
2011
|
|
|
1809
|
-
export { AddMarkStep, MapResult, Mapping, RemoveMarkStep, ReplaceAroundStep, ReplaceStep, Step, StepMap, StepResult, Transform, TransformError, canJoin, canSplit, dropPoint, findWrapping, insertPoint, joinPoint, liftTarget, replaceStep };
|
|
2012
|
+
export { AddMarkStep, AddNodeMarkStep, AttrStep, MapResult, Mapping, RemoveMarkStep, RemoveNodeMarkStep, ReplaceAroundStep, ReplaceStep, Step, StepMap, StepResult, Transform, TransformError, canJoin, canSplit, dropPoint, findWrapping, insertPoint, joinPoint, liftTarget, replaceStep };
|
package/package.json
CHANGED
package/src/README.md
CHANGED
package/src/attr_step.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import {Fragment, Slice, Node, Schema} from "prosemirror-model"
|
|
2
|
+
import {Step, StepResult} from "./step"
|
|
3
|
+
import {StepMap, Mappable} from "./map"
|
|
4
|
+
|
|
5
|
+
/// Update an attribute in a specific node.
|
|
6
|
+
export class AttrStep extends Step {
|
|
7
|
+
/// Construct an attribute step.
|
|
8
|
+
constructor(
|
|
9
|
+
/// The position of the target node.
|
|
10
|
+
readonly pos: number,
|
|
11
|
+
/// The attribute to set.
|
|
12
|
+
readonly attr: string,
|
|
13
|
+
// The attribute's new value.
|
|
14
|
+
readonly value: any
|
|
15
|
+
) {
|
|
16
|
+
super()
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
apply(doc: Node) {
|
|
20
|
+
let node = doc.nodeAt(this.pos)
|
|
21
|
+
if (!node) return StepResult.fail("No node at attribute step's position")
|
|
22
|
+
let attrs = Object.create(null)
|
|
23
|
+
for (let name in node.attrs) attrs[name] = node.attrs[name]
|
|
24
|
+
attrs[this.attr] = this.value
|
|
25
|
+
let updated = node.type.create(attrs, null, node.marks)
|
|
26
|
+
return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment.from(updated), 0, node.isLeaf ? 0 : 1))
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
getMap() {
|
|
30
|
+
return StepMap.empty
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
invert(doc: Node) {
|
|
34
|
+
return new AttrStep(this.pos, this.attr, doc.nodeAt(this.pos)!.attrs[this.attr])
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
map(mapping: Mappable) {
|
|
38
|
+
let pos = mapping.mapResult(this.pos, 1)
|
|
39
|
+
return pos.deletedAfter ? null : new AttrStep(pos.pos, this.attr, this.value)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
toJSON(): any {
|
|
43
|
+
return {stepType: "attr", pos: this.pos, attr: this.attr, value: this.value}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
static fromJSON(schema: Schema, json: any) {
|
|
47
|
+
if (typeof json.pos != "number" || typeof json.attr != "string")
|
|
48
|
+
throw new RangeError("Invalid input for AttrStep.fromJSON")
|
|
49
|
+
return new AttrStep(json.pos, json.attr, json.value)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
Step.jsonID("attr", AttrStep)
|
package/src/index.ts
CHANGED
|
@@ -4,7 +4,8 @@ export {TransformError} from "./transform"
|
|
|
4
4
|
export {Step, StepResult} from "./step"
|
|
5
5
|
export {joinPoint, canJoin, canSplit, insertPoint, dropPoint, liftTarget, findWrapping} from "./structure"
|
|
6
6
|
export {StepMap, MapResult, Mapping, Mappable} from "./map"
|
|
7
|
-
export {AddMarkStep, RemoveMarkStep} from "./mark_step"
|
|
7
|
+
export {AddMarkStep, RemoveMarkStep, AddNodeMarkStep, RemoveNodeMarkStep} from "./mark_step"
|
|
8
8
|
export {ReplaceStep, ReplaceAroundStep} from "./replace_step"
|
|
9
|
+
export {AttrStep} from "./attr_step"
|
|
9
10
|
import "./mark"
|
|
10
11
|
export {replaceStep} from "./replace"
|
package/src/mark_step.ts
CHANGED
|
@@ -126,3 +126,99 @@ export class RemoveMarkStep extends Step {
|
|
|
126
126
|
}
|
|
127
127
|
|
|
128
128
|
Step.jsonID("removeMark", RemoveMarkStep)
|
|
129
|
+
|
|
130
|
+
/// Add a mark to a specific node.
|
|
131
|
+
export class AddNodeMarkStep extends Step {
|
|
132
|
+
/// Create a node mark step.
|
|
133
|
+
constructor(
|
|
134
|
+
/// The position of the target node.
|
|
135
|
+
readonly pos: number,
|
|
136
|
+
/// The mark to add.
|
|
137
|
+
readonly mark: Mark
|
|
138
|
+
) {
|
|
139
|
+
super()
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
apply(doc: Node) {
|
|
143
|
+
let node = doc.nodeAt(this.pos)
|
|
144
|
+
if (!node) return StepResult.fail("No node at mark step's position")
|
|
145
|
+
let updated = node.type.create(node.attrs, null, this.mark.addToSet(node.marks))
|
|
146
|
+
return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment.from(updated), 0, node.isLeaf ? 0 : 1))
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
invert(doc: Node): Step {
|
|
150
|
+
let node = doc.nodeAt(this.pos)
|
|
151
|
+
if (node) {
|
|
152
|
+
let newSet = this.mark.addToSet(node.marks)
|
|
153
|
+
if (newSet.length == node.marks.length) {
|
|
154
|
+
for (let i = 0; i < node.marks.length; i++)
|
|
155
|
+
if (!node.marks[i].isInSet(newSet))
|
|
156
|
+
return new AddNodeMarkStep(this.pos, node.marks[i])
|
|
157
|
+
return new AddNodeMarkStep(this.pos, this.mark)
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return new RemoveNodeMarkStep(this.pos, this.mark)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
map(mapping: Mappable): Step | null {
|
|
164
|
+
let pos = mapping.mapResult(this.pos, 1)
|
|
165
|
+
return pos.deletedAfter ? null : new AddNodeMarkStep(pos.pos, this.mark)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
toJSON(): any {
|
|
169
|
+
return {stepType: "addNodeMark", pos: this.pos, mark: this.mark.toJSON()}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/// @internal
|
|
173
|
+
static fromJSON(schema: Schema, json: any) {
|
|
174
|
+
if (typeof json.pos != "number")
|
|
175
|
+
throw new RangeError("Invalid input for AddNodeMarkStep.fromJSON")
|
|
176
|
+
return new AddNodeMarkStep(json.pos, schema.markFromJSON(json.mark))
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
Step.jsonID("addNodeMark", AddNodeMarkStep)
|
|
181
|
+
|
|
182
|
+
/// Remove a mark from a specific node.
|
|
183
|
+
export class RemoveNodeMarkStep extends Step {
|
|
184
|
+
/// Create a mark-removing step.
|
|
185
|
+
constructor(
|
|
186
|
+
/// The position of the target node.
|
|
187
|
+
readonly pos: number,
|
|
188
|
+
/// The mark to remove.
|
|
189
|
+
readonly mark: Mark
|
|
190
|
+
) {
|
|
191
|
+
super()
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
apply(doc: Node) {
|
|
195
|
+
let node = doc.nodeAt(this.pos)
|
|
196
|
+
if (!node) return StepResult.fail("No node at mark step's position")
|
|
197
|
+
let updated = node.type.create(node.attrs, null, this.mark.removeFromSet(node.marks))
|
|
198
|
+
return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment.from(updated), 0, node.isLeaf ? 0 : 1))
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
invert(doc: Node): Step {
|
|
202
|
+
let node = doc.nodeAt(this.pos)
|
|
203
|
+
if (!node || !this.mark.isInSet(node.marks)) return this
|
|
204
|
+
return new AddNodeMarkStep(this.pos, this.mark)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
map(mapping: Mappable): Step | null {
|
|
208
|
+
let pos = mapping.mapResult(this.pos, 1)
|
|
209
|
+
return pos.deletedAfter ? null : new RemoveNodeMarkStep(pos.pos, this.mark)
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
toJSON(): any {
|
|
213
|
+
return {stepType: "removeNodeMark", pos: this.pos, mark: this.mark.toJSON()}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/// @internal
|
|
217
|
+
static fromJSON(schema: Schema, json: any) {
|
|
218
|
+
if (typeof json.pos != "number")
|
|
219
|
+
throw new RangeError("Invalid input for RemoveNodeMarkStep.fromJSON")
|
|
220
|
+
return new RemoveNodeMarkStep(json.pos, schema.markFromJSON(json.mark))
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
Step.jsonID("removeNodeMark", RemoveNodeMarkStep)
|
package/src/replace.ts
CHANGED
|
@@ -110,10 +110,21 @@ class Fitter {
|
|
|
110
110
|
// content that can be moved somewhere on the frontier. Returns two
|
|
111
111
|
// depths, one for the slice and one for the frontier.
|
|
112
112
|
findFittable(): Fittable | undefined {
|
|
113
|
+
let startDepth = this.unplaced.openStart
|
|
114
|
+
for (let cur = this.unplaced.content, d = 0, openEnd = this.unplaced.openEnd; d < startDepth; d++) {
|
|
115
|
+
let node = cur.firstChild!
|
|
116
|
+
if (cur.childCount > 1) openEnd = 0
|
|
117
|
+
if (node.type.spec.isolating && openEnd <= d) {
|
|
118
|
+
startDepth = d
|
|
119
|
+
break
|
|
120
|
+
}
|
|
121
|
+
cur = node.content
|
|
122
|
+
}
|
|
123
|
+
|
|
113
124
|
// Only try wrapping nodes (pass 2) after finding a place without
|
|
114
125
|
// wrapping failed.
|
|
115
126
|
for (let pass = 1; pass <= 2; pass++) {
|
|
116
|
-
for (let sliceDepth = this.unplaced.openStart; sliceDepth >= 0; sliceDepth--) {
|
|
127
|
+
for (let sliceDepth = pass == 1 ? startDepth : this.unplaced.openStart; sliceDepth >= 0; sliceDepth--) {
|
|
117
128
|
let fragment, parent = null
|
|
118
129
|
if (sliceDepth) {
|
|
119
130
|
parent = contentAt(this.unplaced.content, sliceDepth - 1).firstChild
|
package/src/structure.ts
CHANGED
|
@@ -135,7 +135,7 @@ function canChangeType(doc: Node, pos: number, type: NodeType) {
|
|
|
135
135
|
/// Change the type, attributes, and/or marks of the node at `pos`.
|
|
136
136
|
/// When `type` isn't given, the existing node type is preserved,
|
|
137
137
|
export function setNodeMarkup(tr: Transform, pos: number, type: NodeType | undefined | null,
|
|
138
|
-
attrs: Attrs | null, marks: readonly Mark[]) {
|
|
138
|
+
attrs: Attrs | null, marks: readonly Mark[] | undefined) {
|
|
139
139
|
let node = tr.doc.nodeAt(pos)
|
|
140
140
|
if (!node) throw new RangeError("No node at given position")
|
|
141
141
|
if (!type) type = node.type
|
package/src/transform.ts
CHANGED
|
@@ -5,6 +5,8 @@ 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"
|
|
9
|
+
import {AddNodeMarkStep, RemoveNodeMarkStep} from "./mark_step"
|
|
8
10
|
|
|
9
11
|
/// @internal
|
|
10
12
|
export let TransformError = class extends Error {}
|
|
@@ -171,11 +173,36 @@ export class Transform {
|
|
|
171
173
|
|
|
172
174
|
/// Change the type, attributes, and/or marks of the node at `pos`.
|
|
173
175
|
/// When `type` isn't given, the existing node type is preserved,
|
|
174
|
-
setNodeMarkup(pos: number, type?: NodeType | null, attrs: Attrs | null = null, marks
|
|
176
|
+
setNodeMarkup(pos: number, type?: NodeType | null, attrs: Attrs | null = null, marks?: readonly Mark[]): this {
|
|
175
177
|
setNodeMarkup(this, pos, type, attrs, marks)
|
|
176
178
|
return this
|
|
177
179
|
}
|
|
178
180
|
|
|
181
|
+
/// Set a single attribute on a given node to a new value.
|
|
182
|
+
setNodeAttribute(pos: number, attr: string, value: any): this {
|
|
183
|
+
this.step(new AttrStep(pos, attr, value))
|
|
184
|
+
return this
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/// Add a mark to the node at position `pos`.
|
|
188
|
+
addNodeMark(pos: number, mark: Mark): this {
|
|
189
|
+
this.step(new AddNodeMarkStep(pos, mark))
|
|
190
|
+
return this
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/// Remove a mark (or a mark of the given type) from the node at
|
|
194
|
+
/// position `pos`.
|
|
195
|
+
removeNodeMark(pos: number, mark: Mark | MarkType): this {
|
|
196
|
+
if (!(mark instanceof Mark)) {
|
|
197
|
+
let node = this.doc.nodeAt(pos)
|
|
198
|
+
if (!node) throw new RangeError("No node at position " + pos)
|
|
199
|
+
mark = mark.isInSet(node.marks)!
|
|
200
|
+
if (!mark) return this
|
|
201
|
+
}
|
|
202
|
+
this.step(new RemoveNodeMarkStep(pos, mark))
|
|
203
|
+
return this
|
|
204
|
+
}
|
|
205
|
+
|
|
179
206
|
/// Split the node at the given position, and optionally, if `depth` is
|
|
180
207
|
/// greater than one, any number of nodes above that. By default, the
|
|
181
208
|
/// parts split off will inherit the node type of the original node.
|