I will try to be short:
- I have a custom inline node which can be a part of a paragraph and it can hold a text
export const noteGenerationSchema = new Schema({
nodes: {
doc: {
content: 'paragraph+'
},
text: {
group: 'inline'
},
paragraph: {
...baseSchema.spec.nodes.get('paragraph'),
content: 'inline*',
group: 'block',
parseDOM: [{ tag: 'p' }],
toDOM() {
return ['p', 0];
}
},
addedContent: {
inline: true, // It's an inline node
group: 'inline', // Can be used inside inline content like text
content: 'text*', // It can have text inside it
toDOM() {
return ['span', { class: 'added-content highlight' }, 0];
},
parseDOM: [
{
tag: 'span.added-content'
}
]
}
},
});
- I have a nodeView constructor for
addedContent
which applies clickEvent on it and tries to replace this node with simple text node
export class WithCustomEventsNodeViewBuilder implements NodeView {
public dom: HTMLElement;
public contentDOM: HTMLElement | undefined;
public actualNode: Node;
public actualPos: number | undefined;
constructor(
public node: Node,
public view: EditorView,
public getPos: () => number | undefined,
) {
this.actualNode = node;
const { dom, contentDOM } = DOMSerializer.renderSpec(document, node.type.spec.toDOM!(node), null);
this.dom = dom as HTMLElement;
this.contentDOM = contentDOM;
this.dom.addEventListener('click', () => {
const props = {
dom: this.dom,
node: this.node,
actualPosition: this.getPos() || 0,
view: this.view
}
//get raw text of a clicked node
const nodeText = props.node.textContent;
//create a text node
const textNode = props.view.state.schema.text(nodeText)
//get actual size of a clicked node
const actualSize = this.node.nodeSize;
const tr = this.view.state.tr;
tr.replaceRangeWith(props.actualPosition, (props.actualPosition) + actualSize, textNode);
this.view.dispatch(tr);
});
}
public update(node: Node): boolean {
this.actualNode = node;
return true;
}
}
- It works fine in cases when `addedContent’ is surrounded by text node or when it’s located in the end of a paragraph
- However it doesn’t work fine when `addedContent’ node is. a) In the beginning of a paragraph. b) occupies entire paragraph. c) in the end but goes right after another ‘addedContent’ which reaches the left edge of a paragraph
My observation show next:
- Line get’s empty but when I try to get a state I see that it is in a correct format: Paragraph contains just a text with a content
- On the html paragraph contains a span with
added-content
class - Trying to delete(from,to) then tr.insert(from, textNode) or any sorts of method didn’t result to success
- Just delete(from, to) works as expected in all cases
- If I put a 0ms timer and then do tr.insert(from, textNode) it will work fine and no issues will be there
Please check out screenshots and stackblits example
Pic 1. Before actions
Pic 2. After clicking, State in the console: