Here is a plugin taken from https://discuss.prosemirror.net/t/how-i-can-attach-attribute-with-dynamic-value-when-new-paragraph-is-inserted/751/3
new Plugin({
key: PLUGIN_KEY,
appendTransaction: (transactions, oldState, newState) => {
const tr = newState.tr
let modified = false
if (transactions.some(transaction => transaction.docChanged)) {
newState.doc.descendants((node, pos) => {
console.log(`${node.type.name}`)
const { uuid: id, ...rest } = node.attrs
if (!id) {
// Id is not set or already taken => generate and set a new id
const newId = uuid()
tr.setNodeMarkup(pos, null, { uuid: newId, ...rest })
modified = true
}
})
}
if (modified) return tr
}
})
But it says
Uncaught Error: NodeType.create can't construct text nodes
at NodeType.create (index.es.js:1965)
at Transaction.Transform.setNodeMarkup (index.es.js:765)
at index.ts:26
It seems that a text
type cannot create in setNodeMarkup
:
// :: (number, ?NodeType, ?Object, ?[Mark]) → this
// Change the type, attributes, and/or marks of the node at `pos`.
// When `type` isn't given, the existing node type is preserved,
Transform.prototype.setNodeMarkup = function(pos, type, attrs, marks) {
let node = this.doc.nodeAt(pos)
if (!node) throw new RangeError("No node at given position")
if (!type) type = node.type
let newNode = type.create(attrs, null, marks || node.marks)
if (node.isLeaf)
return this.replaceWith(pos, pos + node.nodeSize, newNode)
if (!type.validContent(node.content))
throw new RangeError("Invalid content for node type " + type.name)
return this.step(new ReplaceAroundStep(pos, pos + node.nodeSize, pos + 1, pos + node.nodeSize - 1,
new Slice(Fragment.from(newNode), 0, 0), 1, true))
}
// :: (?Object, ?union<Fragment, Node, [Node]>, ?[Mark]) → Node
// Create a `Node` of this type. The given attributes are
// checked and defaulted (you can pass `null` to use the type's
// defaults entirely, if no required attributes exist). `content`
// may be a `Fragment`, a node, an array of nodes, or
// `null`. Similarly `marks` may be `null` to default to the empty
// set of marks.
create(attrs, content, marks) {
if (this.isText) throw new Error("NodeType.create can't construct text nodes")
return new Node(this, this.computeAttrs(attrs), Fragment.from(content), Mark.setFrom(marks))
}