@kapouer, @rsaccon I just implemented a very rudimentary mechanism to handle unique IDs using appendTransaction and thought I’d share it here. This mechanism assumes that the attribute with the unique ID is set to null by default.
This can probably be optimized and maybe there’s a better way to implement this, but it’s what I came up with for now and hope that it’s helpful to others.
import {Plugin} from 'prosemirror-state'
// :: (?Object) → Plugin
//
// config::
//
// key:: string
// The name of the attributes which store unique ids.
//
// generateId:: (Node) -> string
// The function which should be used to generate new ids.
export function uniqueIds(config) {
return new Plugin({
state: {
init() { return null },
apply() { return null },
},
appendTransaction(transactions, oldState, newState) {
const ids = {}
const tr = newState.tr
let modified = false
newState.doc.descendants((node, pos) => {
const {[config.key]: id, ...rest} = node.attrs
if (typeof id != 'undefined') {
if (id == null || ids[id]) {
// Id is not set or already taken => generate and set a new id
const newId = config.generateId(node)
tr.setNodeMarkup(pos, null, {[config.key]: newId, ...rest})
ids[newId] = true
modified = true
}
else
ids[id] = true
}
})
if (modified)
return tr
},
})
}
An example of using the Plugin would look like this:
EditorState.create({
schema,
plugins: [
uniqueIds({
key: 'guid',
generateId(node) { return uuidV4() }
})
]
})