You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

54 lines
1.6 KiB

import {Fragment, Slice, Node, Schema} from "prosemirror-model"
import {Step, StepResult} from "./step"
import {StepMap, Mappable} from "./map"
/// Update an attribute in a specific node.
export class AttrStep extends Step {
/// Construct an attribute step.
constructor(
/// The position of the target node.
readonly pos: number,
/// The attribute to set.
readonly attr: string,
// The attribute's new value.
readonly value: any
) {
super()
}
apply(doc: Node) {
let node = doc.nodeAt(this.pos)
if (!node) return StepResult.fail("No node at attribute step's position")
let attrs = Object.create(null)
for (let name in node.attrs) attrs[name] = node.attrs[name]
attrs[this.attr] = this.value
let updated = node.type.create(attrs, null, node.marks)
return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment.from(updated), 0, node.isLeaf ? 0 : 1))
}
getMap() {
return StepMap.empty
}
invert(doc: Node) {
return new AttrStep(this.pos, this.attr, doc.nodeAt(this.pos)!.attrs[this.attr])
}
map(mapping: Mappable) {
let pos = mapping.mapResult(this.pos, 1)
return pos.deletedAfter ? null : new AttrStep(pos.pos, this.attr, this.value)
}
toJSON(): any {
return {stepType: "attr", pos: this.pos, attr: this.attr, value: this.value}
}
static fromJSON(schema: Schema, json: any) {
if (typeof json.pos != "number" || typeof json.attr != "string")
throw new RangeError("Invalid input for AttrStep.fromJSON")
return new AttrStep(json.pos, json.attr, json.value)
}
}
Step.jsonID("attr", AttrStep)