Setup

Generally, the default setup of rhino-editor should be enough. However, in the interest of leveraging the underlying rich text editor, let’s look at how we can add, modify, or remove extensions and extend the underlying web component.

Adding functionality to an existing editor

The easiest way to modify an editor is by listening to the rhino-before-initialize event and modifying it’s options.

Heres a simple example to remove galleries and add all heading levels.

JavaScript
function modifyEditor (e) {
  const editor = e.target
  editor.starterKitOptions = {
    ...editor.starterKitOptions,
    heading: {
      // Enable all heading levels. This only allows the editor to support it.
      // this doesn't provide any UI.
      levels: [1, 2, 3, 4, 5, 6],
    },
    // Disables the gallery for attachments.
    rhinoGallery: false
  }
}

document.addEventListener("rhino-before-initialize", modifyEditor)

For more reading on other ways to modify an existing editor without extends the custom element class, check out this reference documentation on modifying the editor.

Extending the base class

If you plan to do the same thing across the entire app and may have many instances of RhinoEditor running, it may be worth extending the RhinoEditor base class and adding your additional functionality.

JavaScript
import "rhino-editor/exports/styles/trix.css"
import { TipTapEditor } from "rhino-editor/exports/elements/tip-tap-editor.js"

You’ll notice we don’t want to auto-register the <rhino-editor> component. Instead, we want to extend it, then register it.

JavaScript
import "rhino-editor/exports/styles/trix.css"
import { TipTapEditor } from "rhino-editor/exports/elements/tip-tap-editor.js"

class MyEditor extends TipTapEditor {
  constructor () {
    super()
    this.starterKitOptions = {
      ...this.starterKitOptions,
      heading: {
        // Enable all heading levels
        levels: [1, 2, 3, 4, 5, 6],
      },
      // Remove the gallery, all images are always full size.
      rhinoGallery: false
    }
  }
}

MyEditor.define("my-editor")

Adding Extensions

Now let’s see how we would add extensions:

JavaScript
import { TipTapEditor } from "rhino-editor/exports/elements/tip-tap-editor.js"

// https://tiptap.dev/api/extensions/character-count
import CharacterCount from "@tiptap/extension-character-count"
import { html } from "lit"

class ExtendedEditor extends TipTapEditor {
  constructor () {
    super()
    this.characterCountLimit = 240

    this.extensions = [
      ...this.extensions,
      CharacterCount.configure({
        limit: this.characterCountLimit,
      })
    ]
  }


  render () {
    return html`
      ${super.render()}

      <p style="color: gray;">
        ${this.editor?.storage.characterCount.characters()}/${this.characterCountLimit} characters
        <br />
        ${this.editor?.storage.characterCount.words()} words
      </p>
    `
  }
}

ExtendedEditor.define("extended-rhino-editor")
HTML
<!-- index.html -->
<extended-rhino-editor></extended-rhino-editor>

The above will now have a character counter in place for the editor! This can be applied to any extensions. You could even wipe out all existing extensions and replace them all with your own if you wanted!

Character Count Example