Shape vaguely symbolizing an HTML tag.

Adding custom TinyMCE plugins to the HTML editor in Optimizely CMS


TinyMCE plugins allow you to extend the HTML editor in Optimizely CMS. In this example we'll look at adding a custom button to TinyMCE for formatting text with the <mark> element.

Estimated read time : 2 minutes

Jump to

Key takeaways

  • TinyMCE plugins are commonly just a single JavaScript file
  • Custom plugins are enabled through TinyMCE configuration in Startup class

The <mark> element

The <mark> element is used to highlight a piece of text, and most browsers by default display it with a yellow background like this.

Creating the TinyMCE plugin

The plugin itself has nothing Optimizely-specific in it, so everything on how to create a TinyMCE plugin from the official TinyMCE docs apply.

This sample is in TypeScript, but it can be turned into vanilla JavaScript with minor modifications:

import { PluginManager } from "tinymce"

declare var tinymce: any;

/**
 * Add plugin for surrounding text with <mark> element to highlight text, for example in blog posts
 */
PluginManager.add("markButton", (editor, url) => {

    editor.on('init', function () {

        // Register custom formatter which simply surrounds selected content with a <mark> tag
        editor.formatter.register('mark', {
            inline: 'mark'
        });
    });

    editor.addButton('markButton', {
        icon: 'backcolor',
        tooltip: "Highlight text",
        onclick: function (e) {
            // Add or remove <mark> tag around the selected content
            tinymce.activeEditor.formatter.toggle('mark');
        },
        onPostRender: function () {
            // When active node changes, highlight the toolbar button if on a <mark> element
            editor.on('NodeChange', function (e) {
                this.active(e.element.tagName === "MARK");
            }.bind(this));
        }
    });

    return {
        getMetadata: function () {
            return {
                name: 'Mark button',
                url: 'https://tedgustaf.com/blog'
            };
        }
    }
});

In our case, the TypeScript file is transpiled to a path like /dist/tinymce/markbutton.js, you'll see why this matters below.

Adding the custom plugin to TinyMCE

Next, we add some code to our TinyMCE configuration in Startup.cs to enable our custom plugin for all XhtmlString properties:

services.Configure<TinyMceConfiguration>(config =>
{
    config.Default()
          .AddEpiserverSupport()
          .AddExternalPlugin("markButton", "/dist/tinymce/markbutton.js")
          .AppendToolbar("markButton");
});

What it looks like

TinyMCE highlighting.gif