简体   繁体   中英

Tiptap (Prosemirror) collab schema error for mention tags

I needed some help implementing mentions into real-time collab server ( https://tiptap.dev/suggestions ). My code is modded version of this: https://glitch.com/edit/#?/tiptap-sockets.path=server.js%3A1%3A0

I am sending these steps to my socket server to be applied to the previous version of the doc

steps.forEach((step) => {
    const result = Step.fromJSON(schema, step).apply(doc)
    doc = result.doc
})

And using this schema to validate the mention:

mention: {
  attrs: {
    id: {},
    label: {},
  },
  group: 'inline',
  inline: true,
  selectable: false,
  atom: true,
  toDOM: node => [
    'span',
    {
      class: 'mention',
      'data-mention-id': node.attrs.id,
    },
    `@${node.attrs.label}`,
  ],
  parseDOM: [
    {
      tag: 'span[data-mention-id]',
      getAttrs: dom => {
        const id = dom.getAttribute('data-mention-id')
        const label = dom.innerText.split('@').join('')
        return { id, label }
      },
    },
  ],
},

The frontend sends the following steps when I enter @Philip Isik,

step 1: @philip Isik

step 2: " "

These are the above steps in JSON form that the server receives:

    [ 
        '{"stepType":"replace","from":1,"to":2,"slice":{"content":[{"type":"mention","attrs":{"id":4,"label":"Philip Isik"},"content":[{"type":"text","text":"@Philip Isik"}]}]}}',
        
        '{"stepType":"replace","from":15,"to":15,"slice":{"content":[{"type":"text","text":" "}]}}' 
    ]

After step 1, the loop fails and throws

RangeError: Position 15 out of range

So I checked the content length after step one, it said it was of length 3 when it should be of length 12 (length of @Philip Isik)

Does anyone know why this is happening? been at it for 2 days now. Any help is greatly appreciated!

TLDR:

  1. So I'm sending a @Name to the server to be applied to the current version of the doc.

  2. The server receives the mentioned step @Name

  3. Now when it sends the next step, the step being sent is for location 6 (@Name is of length 5, so 5+1th=6th pos)

  4. Here is the problem, according to tiptap/prose object, @ Name is of length 2, not 5

  5. Therefore, it throws a 'Position-out-of-range error'

Try adding trim() to parseDOM to remove whitespace as I see the issue may be related trailing space being present ( "text": " " ).

'{"stepType":"replace","from":15,"to":15,"slice":{"content":[{"type":"text","text":" "}]}}'

When tested in Chrome browser, simple HTML like this with some new-lines and spaces:

<span data-mention-id="test">
  @Test mention
</span>

returned dom.innerText with a trailing space at the end @Test mention .

Here's updated schema with trim added to parseDOM :

mention: {
  attrs: {
    id: {},
    label: {},
  },
  group: 'inline',
  inline: true,
  selectable: false,
  atom: true,
  toDOM: node => [
    'span',
    {
      class: 'mention',
      'data-mention-id': node.attrs.id,
    },
    `@${node.attrs.label}`,
  ],
  parseDOM: [
    {
      tag: 'span[data-mention-id]',
      getAttrs: dom => {
        const id = dom.getAttribute('data-mention-id')
        const label = dom.innerText.trim().split('@').join('') // trim removes white space around text
        return { id, label }
      },
    },
  ],
},

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM