prosemirror-transform 1.6.0 → 1.7.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 +8 -0
- package/dist/index.cjs +254 -25
- package/dist/index.d.ts +105 -1
- package/dist/index.js +194 -2
- 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/transform.ts +27 -0
- package/dist/index.es.js +0 -1702
- package/dist/index.es.js.map +0 -1
- package/dist/index.js.map +0 -1
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/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 {}
|
|
@@ -176,6 +178,31 @@ export class Transform {
|
|
|
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.
|