pluginsckeditorbolt-cms

Why is CKEditor refusing my custom tag?


With a custom CKEditor plugin I am trying to insert a custom HTML tag, but the tag gets removed as soon as it is inserted into the editor. My plugin.js file:

CKEDITOR.plugins.add( 'tweet', {
    icons: 'tweet',
    init: function( editor ) {
        editor.addCommand( 'insertTweet', {
            allowedContent: 'tweet[:id]',
            requiredContent: 'tweet',
            exec: function( editor ) {
                console.log('inserting');  
                editor.insertHtml( '<tweet :id="\'123\'" />' );  // also tried <tweet />
                // editor.insertHtml( '[tweet :id="\'123\'" /]' ); // this works
            }
        });

        editor.ui.addButton( 'tweet', {
            label: 'Insert tweet',
            command: 'insertTweet',
            toolbar: 'insert,0'
        });
    }
});

The way I am adding the plugin for Bolt CMS backend:

function run() {
    var extrasAdded = false;

    if (typeof(CKEDITOR) == 'undefined') return;

    CKEDITOR.plugins.addExternal('tweet', '/assets/plugins/tweet/plugin.js', '');

    CKEDITOR.on('instanceReady', function (event, instance) {

        if (extrasAdded === true) return;

        var config = event.editor.config;

        config.toolbar.push(
            { name: 'insert', items: [ 'tweet' ] }
        );
        config.extraPlugins += (config.extraPlugins ? ',' : '') + 'tweet';
        config.extraAllowedContent = 'tweet';  // also tried 'tweet[:id]'

        CKEDITOR.instances['body'].destroy();
        CKEDITOR.replace('body', config);

        extrasAdded = true;
    });
}

if (document.readyState!='loading') run();
else document.addEventListener('DOMContentLoaded', run);

Can someone smart see why my tag is rejected?


Solution

  • So it turns out that we don't need the allowedContent or requiredContent properties in the plugin.js script. What did the trick was to tweak the editor's HTML DTD rules. In my case I got a reference to the editor in the instanceReady callback and tweeked it like this:

    // name = 'tweet'
    editor.filter.allow(name + "[!*]", name, true);
    
    CKEDITOR.dtd[name] = CKEDITOR.dtd;
    CKEDITOR.dtd.$empty[name] = 1; // allow self-closing tag
    CKEDITOR.dtd.$blockLimit[name] = 1;
    CKEDITOR.dtd.$nonEditable[name] = 1;
    CKEDITOR.dtd.$object[name] = 1;
    CKEDITOR.dtd.$inline[name] = 1; // $block won't work!
    

    You can also see a full gist of it.