Tiptap: Add IDs to headings and make "isActive" state work

Created on 2 Mar 2020  路  3Comments  路  Source: ueberdosis/tiptap

Hey guys,

so I'm trying to make my own heading node, which adds IDs to the headings, which I in return use to create jump marks in my editor environment. I can make it work as far as it correctly writes the HTML-tag and adds the ID. Also if the editor is loaded, already existing ID don't get overwritten but parsed correctly. Only problem is, that I somehow can't make it work, that the "isActive" state is computed within the button I use, which means that I can't toggle the heading on and off.

Here is the code, where I used the existing heading component as a basis and tried to add the capability for IDs:

import { Node } from 'tiptap'
import { setBlockType, textblockTypeInputRule, toggleBlockType } from 'tiptap-commands'

export default class Heading extends Node {

  get name () {
    return 'heading'
  }

  get defaultOptions () {
    return {
      levels: [1, 2, 3, 4, 5, 6]
    }
  }

  get schema () {
    return {
      attrs: {
        level: {
          default: 1,
        },
        id: {
          default: ''
        }
      },
      content: 'inline*',
      group: 'block',
      defining: true,
      draggable: false,
      parseDOM: this.options.levels
        .map(level => (
          {
            tag: `h${level}`,
            getAttrs: dom => ({
              level: level,
              id: dom.getAttribute('id')
            })
          })),
      toDOM: node => [`h${node.attrs.level}`,
        {
          class: 'anchor-heading',
          id: node.attrs.id || this.createId()
        }, 0]
    }
  }

  commands ({ type, schema }) {
    return attrs => toggleBlockType(type, schema.nodes.paragraph, attrs)
  }

  keys ({ type }) {
    return this.options.levels.reduce((items, level) => ({
      ...items,
      ...{
        [`Shift-Ctrl-${level}`]: setBlockType(type, { level })
      }
    }), {})
  }

  inputRules ({ type }) {
    return this.options.levels.map(level => {
      textblockTypeInputRule(
        new RegExp(`^(#{1,${level}})\\s$`),
        type,
        () => ({ level })
      )
    })
  }

  createId (length = 5) {
    return Math.round((Math.pow(36, length + 1) - Math.random() * Math.pow(36, length))).toString(36).slice(1)
  }
}

I am a 100% sure that I am missing some clue as how the active state is created and I tried to follow the steps in the library, but I can't make out what I'm missing.
Maybe someone can take a look at my code and guide me to the solution.

bug

Most helpful comment

This should be fixed with the latest update. (see https://github.com/scrumpy/tiptap/issues/666)

All 3 comments

same problems

Does anyone have an idea on how to solve this? I tried a few different approaches, but nothing really worked.

This should be fixed with the latest update. (see https://github.com/scrumpy/tiptap/issues/666)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

winterdedavid picture winterdedavid  路  3Comments

glavdir picture glavdir  路  3Comments

afwn90cj93201nixr2e1re picture afwn90cj93201nixr2e1re  路  3Comments

unikitty37 picture unikitty37  路  3Comments

dolbex picture dolbex  路  3Comments