Skip to content

Code Blocks with Highlighting: Adding Editor Buttons

Posted in Plugin Development, and WP Plugins

Hello, and welcome to our fourth installment of our Code Blocks with Highlighting tutorial! At this point, you should have completed at least section one and two of this ongoing series. Section three was optional, but provided some interesting insights into problems you might run in to while building plugins like this, and some possible solutions and pitfalls. In case you missed them, here are the previous sections:

Adding Editor Buttons

If you attempted the shortcodes in set three, you noticed that we ran into several issues relating to whitespace and the Visual and Text editors. While we can always use the <pre> and <code> tags with the classes defined in the first two parts, we still would prefer a more elegant solution. This can be found in the form of buttons added to both the Text editor, and the Visual editor. Essentially, when we highlight text and select these buttons they are about to create, they will wrap the text automatically in the <pre> and <code> tags with all appropriate classes.

Step 1: Text Editor Button

We’ll begin by adding a button to the Text editor. This will be the more simplistic of our buttons, since it will only have the one option. Using the Text editor for entering code blocks is ideal if you have lots of specialized tabs and whitespace.

We can do this with one function and action in our main plugin file, prism-js.php. We are looking to use WordPress text editor’s Quick Tags API to add our button, and a custom javascript function to handle the text. Just add this after the existing content:

//Adds a button to the text editor tab
//The button wraps selected text in prism pre and code tags
//Uses default settings, and converts < and > to html entities
function prism_js_button_script() 
{
    if(wp_script_is("quicktags"))
    {
        ?>
            <script type="text/javascript">
                
                //this function is used to retrieve the selected text from the text editor
                function getSel()
                {
                    var txtarea = document.getElementById("content");
                    var start = txtarea.selectionStart;
                    var finish = txtarea.selectionEnd;
                    return txtarea.value.substring(start, finish);
                }

                QTags.addButton( 
                    "prism_defaults", 
                    "Prism", 
                    callback
                );

                function callback()
                {
                    var selected_text = getSel();
				//replaces < ,>, and & with html entities to prevent stripping and display properly
				selected_text = selected_text.replace(/&/g, "&amp;").replace(/>/g, "&gt;").replace(/</g, "&lt;");

				//wraps the content with the tags
                    QTags.insertContent("<pre class=\"language-php line-numbers copytoclipboard\"><code class=\"language-php\">" +  selected_text + "</code></pre>");
                }
            </script>
        <?php
    }
}

add_action("admin_print_footer_scripts", "prism_js_button_script");

Let’s break this down. Line 6 first checks if the page is loading the quicktags api script. Once this is true, we start with our javascript.

The function getSel() just returns the text that we have highlighted when we push our button that we are creating.

QTags.addButton() does exactly what it sounds like: creates our button. The text “Prism” will be shown on our button, and callback is the function that will be run.

The function callback() assigns the text we selected, using the function getSel(), and saves it to a variable called selected_text. Once we have this text, we use .replace() to replace <, >, and & with their html friendly counterparts, preventing the browser from attempting to display these as tags on the page (the Visual editor does this automatically, when you type or paste these symbols). After all of these have been replaced, we return the selected_text, surrounded by <pre> and <code> tags with our most commonly used classes. I use php most often, but feel free to replace that with another language if you desire.

That’s it, for this step! Save, and give it a shot. Paste some code in the Text tab, select it, and click your button. If you need a different language highlighted, then you just have to edit that class manually, and replace language-php in the Text editor with language-###, the language of your choice.

Step 2: Visual Editor Button

Now that we’ve created a button for the Text editor, we’ll hop over to the Visual editor tab to do the same. This will give us the flexibility to create or edit our content in whichever editor we choose. And unlike the shortcodes from the last article, these will transition between editors with no issues at all.

The WordPress Visual editor is an implementation of TinyMCE. A full explanation of the workings of TinyMCE is beyond the scope of this article, so for now, we’ll just add a simple button, similar to the text button we added earlier.

Due to the way TinyMCE works, our button must be created first as a javascript file, and then added to the TinyMCE setup array. Let’s start by creating a file in our /js/ folder called prism-visual-edit.js. The contents of the file should be as follows:

(function() {
    tinymce.create("tinymce.plugins.prism_button_plugin", {

        //url argument holds the absolute url of our plugin directory
        init : function(ed, url) {

            //add new button     
            ed.addButton("prism", {
                title : "Prism Default Tags",
                cmd : "prism_command",
                image : url+"/crystal.png"
            });

            //button functionality.
            ed.addCommand("prism_command", function() {
                var selected_text = ed.selection.getContent({format : "text"});
                var return_text = "<pre class=\"language-php line-numbers copytoclipboard\"><code class=\"language-php\">" + selected_text + "</code></pre>";
                ed.execCommand("mceInsertContent", 0, return_text);
            });

        },

        createControl : function(n, cm) {
            return null;
        },

        getInfo : function() {
            return {
                longname : "PrismJS Default Tag Insertion",
                author : "Dan Dulaney",
                version : "1"
            };
        }
    });

    tinymce.PluginManager.add("prism_button_plugin", tinymce.plugins.prism_button_plugin);
})();

Much of this should look similar to the code above. For the icon we used (crystal.png), you can download it here, by opening and saving as crystal.png, with a lowercase c, in the /prism-js/js/ directory. This must be the same folder as the script that references it.

We are again getting our text, and returning it wrapped in <pre> and <code> tags with the default classes (php in this case). We no longer need to replace <, >, and & since the Visual editor handles these automatically. I will not go much more into the javascript file itself, although if you want to learn more about TinyMCE plugins, you can find some good information here: TinyMCE in WordPress and Creating A TinyMCE Plugin

Now that we’ve created our TinyMCE javascript file, it’s time to add it to our plugin. We’re going back now to edit prism-js.php, with the following functions and filters:

function enqueue_plugin_scripts($plugin_array)
{
    //enqueue TinyMCE plugin script with its ID.
    $plugin_array["prism_button_plugin"] =  plugin_dir_url(__FILE__) . "js/prism-visual-edit-mod.js";
    return $plugin_array;
}

add_filter("mce_external_plugins", "enqueue_plugin_scripts");

function register_buttons_editor($buttons)
{
    //register buttons with their id.
    array_push($buttons, "prism");
    return $buttons;
}

add_filter("mce_buttons", "register_buttons_editor");

The first function and filter register our newly created javascript file, and the second add the button to our toolbar in the Visual editor. We’re now ready to test it out! Save everything, clear your cache / force a refresh if you’re using Autoptimize, and head over to the Visual editor. Paste some code, select, and click the Prism / Diamond icon. If you want to check, head over to the Text editor to see that the classes and tags were all added.

Wrap Up

You’ve done it! You now have a pretty solid code highlighting plugin. We will have one more article coming up, discussing more advanced customization of the TinyMCE Visual editor button, but as it is, you have a fully functional plugin. There’s still quite a few things left to expand on, if you so choose. You could look into automatic language detection (quite a feat), integrating more of the PrismJS plugins from the official page, and more.

If you come up with any cool ideas, tweaks, or modifications of your own, I’d love to hear them! Just leave a comment below, with a link if you so desire. Thanks again, and if you want to take a further plunge into the Visual Editor buttons, join us next time as we add a dropdown for our most commonly used languages (instead of defaulting to PHP every time).

Sources:

Next in Series: Code Blocks with Highlighting: Extended TinyMCE Options