DEV Community

DevSecBBS
DevSecBBS

Posted on

Code highlight plugin for suneditor

Image description

Hello dear

Am developing a Django blog where am using suneditor for my post editor. & I need a simple plugin where the user can highlight code from the toolbar of the suneditor. Am gonna use prismjs. But, that's super simple even if that doesn't highlight the code in the editor. But just add the language like <pre><code class="language-python"></pre> than later on you have to render the code in the posting page as you want according to prismjs instructions. But, there was a problem when I saved the post in my database & later when retrieved the data it was in <code> save the code using <br> for a new line. which acts as the code. That's why I have to remove extra <br> by this function in the post page & highlight the code

//Highlight code syntax by prismjs
function highlight_code(){
    $('code').each(function(){
        var data = $(this).html()
        data = data.replace(/<br>/g,'\n')
        $(this).html(data)
    })
    Prism.highlightAll()
}
Enter fullscreen mode Exit fullscreen mode

that's just in my case. You have to do what you want to do yourself. I don't know how.
& Here is the plugin.

// ex) A code highlight plugin that appends the contents of the input element to the editor
var plugin_codehighlight = {
    // @Required @Unique
    // plugin name
    name: 'custom_plugin_codehighlight',

    // @Required
    // data display
    display: 'submenu',

    // @Options
    title: 'Code syntax highlight',
    buttonClass: '', 
    innerHTML: '<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="#000000"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <title>language_json</title> <rect width="24" height="24" fill="none"></rect> <path d="M5,3H7V5H5v5a2,2,0,0,1-2,2,2,2,0,0,1,2,2v5H7v2H5c-1.07-.27-2-.9-2-2V15a2,2,0,0,0-2-2H0V11H1A2,2,0,0,0,3,9V5A2,2,0,0,1,5,3M19,3a2,2,0,0,1,2,2V9a2,2,0,0,0,2,2h1v2H23a2,2,0,0,0-2,2v4a2,2,0,0,1-2,2H17V19h2V14a2,2,0,0,1,2-2,2,2,0,0,1-2-2V5H17V3h2M12,15a1,1,0,1,1-1,1,1,1,0,0,1,1-1M8,15a1,1,0,1,1-1,1,1,1,0,0,1,1-1m8,0a1,1,0,1,1-1,1A1,1,0,0,1,16,15Z"></path> </g></svg>',

    // @Required
    // add function - It is called only once when the plugin is first run.
    // This function generates HTML to append and register the event.
    // arguments - (core : core object, targetElement : clicked button element)
    add: function (core, targetElement) {

        // @Required
        // Registering a namespace for caching as a plugin name in the context object
        const context = core.context;
        context.customSubmenu = {
            targetButton: targetElement,
            textElement: null,
            currentSpan: null
        };

        // Generate submenu HTML
        // Always bind "core" when calling a plugin function
        let listDiv = this.setSubmenu(core);

        // Input tag caching
        context.customSubmenu.textElement = listDiv.querySelector('input');

        // You must bind "core" object when registering an event.
        /** add event listeners */
        listDiv.querySelector('.se-btn-primary').addEventListener('click', this.onClick.bind(core));

        // @Required
        // You must add the "submenu" element using the "core.initMenuTarget" method.
        /** append target button menu */
        core.initMenuTarget(this.name, targetElement, listDiv);
    },

    setSubmenu: function (core) {
        const listDiv = core.util.createElement('DIV');
        // @Required
        // A "se-submenu" class is required for the top level element.
        listDiv.className = 'se-menu-container se-submenu se-list-layer';
        listDiv.innerHTML = '' +
            '<div class="se-list-inner">' +
                '<ul class="se-list-basic" style="width: 230px;">' +
                    '<li>' +
                        '<div class="se-form-group">' +
                            '<input class="se-input-form" type="text" placeholder="language python,java" style="border: 1px solid #CCC;" />' +
                            '<button type="button" class="se-btn-primary se-tooltip">' +
                                '<strong>Add</strong>' +
                                '<span class="se-tooltip-inner">' +
                                    '<span class="se-tooltip-text">Append code block</span>' +
                                '</span>' +
                            '</button>' +
                        '</div>' +
                    '</li>' +
                '</ul>' +
            '</div>';

        return listDiv;
    },

    // @Override core
    // Plugins with active methods load immediately when the editor loads.
    // Called each time the selection is moved.
    active: function (element) {
        // If no tag matches, the "element" argument is called with a null value.
        if (!element) {
            this.util.removeClass(this.context.customSubmenu.targetButton, 'active');
            this.context.customSubmenu.textElement.value = '';
            this.context.customSubmenu.currentSpan = null;
        } else if (this.util.hasClass(element, 'se-custom-tag')) {
            this.util.addClass(this.context.customSubmenu.targetButton, 'active');
            this.context.customSubmenu.textElement.value = element.textContent;
            this.context.customSubmenu.currentSpan = element;
            return true;
        }

        return false;
    },

    // @Override submenu
    // Called after the submenu has been rendered
    on: function () {
        this.context.customSubmenu.textElement.focus();
    },


    onClick: function () {
        const value = this.context.customSubmenu.textElement.value.trim();
        if (!value) return;

        const span = this.context.customSubmenu.currentSpan;
        if (span) {
            span.textContent = value;
            this.setRange(span, 1, span, 1);
        } else {
            this.functions.insertHTML('<pre><code class="language-'+value+'">' + 'Write your '+ value +' code' + '</code></pre>', true);
            this.context.customSubmenu.textElement.value = '';
        }
        this.submenuOff();
    }
};
Enter fullscreen mode Exit fullscreen mode

how to set up this. okay.
Step 1. Add plugins: [plugin_codehighlight] in your editor option like

SUNEDITOR.create('post_editor', {
        plugins: [plugin_codehighlight],
        display: 'block',
    ......
}
Enter fullscreen mode Exit fullscreen mode

Step 2. Add ['custom_plugin_codehighlight'] in the buttonlist like

buttonList: [
            // default
            ['undo', 'redo'],
            ['custom_plugin_codehighlight'],
         ......
]
Enter fullscreen mode Exit fullscreen mode

Step 3. That's okay. I don't know javascript.
Please go & know about prismjs,suneditor/plugin & than go ahead.
Thanks for your time...

Top comments (0)