I’m trying to build a feature that inserts “snippets” into the document. These are predefined structures that contain a mix of placeholders and predefined (but still editable!) content.
I’m struggling with correctly setting the selection in some cases.
A case that works:
structure to insert:
const nodeToInsert = schema.node(
'title',
{ __rdfaId: uuid() },
schema.node(
'paragraph',
null,
schema.node('placeholder', {
placeholderText,
})
)
);
A case that doesn’t work:
structure to insert:
const nodeToInsert = schema.node('motivering', {__rdfaId: uuid()}, [
schema.node('heading', {level: 5}, schema.text('Bevoegdheid')),
schema.node(
'paragraph',
null,
schema.node('placeholder', {
placeholderText: 'motivation',
})
)
]);
In each case, I’m trying to nodeselect the placeholder node. This is a node of our own making, with the following spec:
export const placeholder: NodeSpec = {
attrs: { placeholderText: { default: 'placeholder' } },
inline: true,
group: 'inline',
selectable: true,
draggable: false,
atom: true,
defining: false,
toDOM(node) {
return [
'span',
{ class: PLACEHOLDER_CLASS, ...node.attrs, contenteditable: false },
node.attrs.placeholderText,
];
},
leafText(node) {
return node.attrs.placeholderText as string;
},
parseDOM: [
{
tag: 'span',
getAttrs(node: HTMLElement) {
if (node.classList.contains(PLACEHOLDER_CLASS)) {
return { placeholderText: node.innerText };
}
return false;
},
},
],
};
In each case, after insertion, I’m simply making a new NodeSelection with NodeSelection.create(tr.doc, insertionPos + hardcodedOffset)
. In case 1, that offset is 2, in case 2, that offset is 15.
In case 2, the heading gets nodeselected instead of the placeholder. I’ve confirmed that the hardcoded offset is correct, and tried all manner of +1s and -1s, as wel as using NodeSelection.near
and family. In no way can I get it to select the placeholder, whereas in case 1 (and another similar case) it worked like a charm. I also have another broken case, where the offset is 4. In each case, the inner structure is the same: a paragraph with a single placeholder node.
While writing this out, I realized we can simply use a block-level placeholder node in these cases. However, to me the fact I cannot nodeselect an inline atom consistently still merits discussion.
Clicking manually on the placeholder works as expected, triggering the special node-selection styling we have for it. I have a gut feeling I’m bumping into some less-than-fully-supported combinations of nodespec properties here, but maybe I’m missing something.