Struggling to replace the contents of a node

I have a custom node that is like a label for a paragraph for a custom app we’re writing. We’d like each paragraph to contain this label, or to have a hidden node exempting the paragraph from containing it.

const paragraphCategory: NodeSpec = {
  inline: true,
  // atom: true,
  attr: {
    unmarked: {
      default: null,
    },
  },
  group: 'inline',
  toDOM(node) {
    console.log('toDom')
    const text = `(${node.content.firstChild?.text}) `
    return [
      'paragraph-category',
      {
        class: 'paragraph-category cursor-pointer',
      },
      text,
    ]
  },
  parseDOM: [
    {
      tag: 'paragraph-category',
    },
  ],
}

I want to be able to default the value to UNSET and then toggle between some values when it’s clicked. We don’t want free-text.

I’m trying to write a plugin to set it, but we are struggling to find the exact position (start and finish) of the node, and to then change the value without destroying the node. I can get the size of the node, but am struggling to find the beginning of the node when it’s clicked on. And, when I replace the contents, it seems to not always update the editor. I’m attempting to dispatch a setSelection, followed by dispatch replaceSelectionWith, but it doesn’t seem to work the way I expect.

Can you help me with:

  • Find the exact start and end of a node when it’s clicked on
  • Replace content programmatically

Thanks

Firstly, if you’re storing the text as a child node, you’ll want to just include a 0 to mark its position in the output, and not read it from the child node and emit it, the way you’re doing.

If you’re using a handleClickOn function, that will pass you the node’s position. This is the position before the node, so if you want to range of it’s content that’s pos + 1 to pos + 1 + node.content.size.

To replace content, dispatch a transaction on which you called the replace or replaceWith method.