attr_step.ts (2674B)
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) 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)