Skip to content

Add IDs to headings and make "isActive" state work #621

@git-mischa

Description

@git-mischa

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions