Skip to content

Code Blocks with Highlighting: Adding Custom Shortcodes (Optional)

Posted in Plugin Development, and WP Plugins

Welcome back to our third installment of our guide to creating your own Code Highlighting plugin. In the first two sections, we created the base plugin using PrismJS and then added in a “Copy to Clipboard” button using ClipboardJS. If you haven’t completed both of these sections, you’ll want to head back and do those two first.

Note: This section is optional. Please make sure you read the caveat before you begin.

Adding Shortcodes and Attributes

So far, to use the code highlighter and copy to clipboard functionality, we’ve been forced to rely on the manual use of <pre> and <code> tags, as well as manually assigning the correct CSS classes. Today, we’re going to make our plugin more user friendly by replacing these tags with custom shortcodes, complete with attributes to allow all of the customization we’ve gotten used to previously. Before we begin, there is an important caveat that we need to discuss regarding the use of shortcodes in this manner:

Caveat: If you’re using a shortcode for a code block, you’re stuck with the Text editor.  This is the same for all similar plugins, not just this one. Switching to Visual and back will remove all of your tabs and whitespace, although we are going to mitigate this somewhat to preserve blank lines (you will still loose your tabs). If you write entirely in the Text editor, or do all of your Visual work first, and then switch to Text for your code blocks, you will be fine. This is due to a limitation of how the Visual Editor (TinyMCE) handles white space, and after several days of research, I have not found any good way around this.

You can still use the <pre><code> tags instead, which do preserve white space and tabs. In our next article, we’ll look at one possible solution for this, to let us more easily add code blocks without shortcodes. If using shortcodes in this manner does not appeal to you, you can skip this section and proceed to the next, Code Blocks with Highlighting: Adding Editor Buttons, as the next step will not depend on this one at all.

Step 1: Building The Empty Shortcode

We’re going to start by first working with the main plugin file, prism-js.php. So far, you should have your comments and your enqueues for your javascript and css. We’ll be working beneath this.

//shortcode function
function prism_js_wrapping_tags($atts, $content, $tag){


}
add_shortcode('prism_js','prism_js_wrapping_tags');

So far, we’ve declared a function (line 2) that will receive the shortcode attributes ($atts) that we set, and the text between the shortcodes in our post ($content).

On line 6, we register the function we just created to the shortcode prism_js.

Step 2: Handling Attributes and Defaults

Next, we’re going to build in the options that we want to allow our users to set via shortcode. Everything that we’ve set in the past two tutorials via classes can be set here. We’ll create attributes to control the pre tag’s id, the language for syntax highlighting, row highlighting, whether to show line numbers or not, and whether to display the copy to clipboard button. Let’s start by creating a random id to use for the <pre> block, and then choosing our default settings, until a user overrides them.

//shortcode function
function prism_js_wrapping_tags($atts, $content, $tag){
	
	$randpreid = 'a'.substr(md5(microtime()),rand(0,26),10);
	
	$atts = shortcode_atts(
        array(
			'lang' => 'php',
			'preid' => $randpreid,
			'copy' => 'yes',
			'numbers' => 'yes',
			'highlight' => 'none',
	   ), $atts, 'prism_js' );

	$language = $atts['lang'];
	$preid = $atts['preid'];
	$copy = $atts['copy'];
	$highlight = $atts['highlight'];
	$numbers = $atts['numbers'];

}
add_shortcode('prism_js','prism_js_wrapping_tags');

The defaults, are set intially via the shortcode_atts() function. Underneath this, we assign those attributes (both default, or if overwritten, the user selected) to variables to use.

Step 3: Building the Output

Now that we have all of our settings, we’ll need to build the output that will be displayed. We are going to be dynamically building our <pre> and <code> tags and then using $content to pass everything between our opening and closing prism_js tags. If you are not familiar with PHP if statements or concatenation, you should make sure you have a basic understanding of each first.

//shortcode function
function prism_js_wrapping_tags($atts, $content, $tag){
	
	$randpreid = 'a'.substr(md5(microtime()),rand(0,26),10);
	
	$atts = shortcode_atts(
        array(
			'lang' => 'php',
			'preid' => $randpreid,
			'copy' => 'yes',
			'numbers' => 'yes',
			'highlight' => 'none',
	   ), $atts, 'prism_js' );

	$language = $atts['lang'];
	$preid = $atts['preid'];
	$copy = $atts['copy'];
	$highlight = $atts['highlight'];
	$numbers = $atts['numbers'];

	$output = '<pre id="'.$preid.'" class="';

	if ($numbers=='yes') { $output .= 'line-numbers '; }

	$output.='language-'.$language; 

	if ($copy=='yes') { $output.=' copytoclipboard'; }

	$output.='"';

	if ($highlight != 'none') { $output.= ' data-line="'.$highlight.'"'; }

	$output.='><code class="language-'.$language.'">' . $content .		'</code></pre>';
 

	return $output;

}
add_shortcode('prism_js','prism_js_wrapping_tags');

Through this section, we are building a variable called $output, which will contain the $content of our shortcodes, between our custom built <pre> and <code> tags. When we finish, $output is returned, to be displayed on the page.

Step 4: Cleaning Up the Mess

As we saw earlier in the caveat posted at the beginning of this article, WordPress likes to do strange things with whitespaces. Specifically, it likes to strip out extra blank lines and whitespace, as well as performing some odd substitutions like replacing straight quotes with the curled ones, which do not display well in code. While we cannot fix the issue of tabs being stripped by switching between editors at this time, we can preserve blank lines and stop the straight quotes from being replaced.

All code from this section will be placed between the enqueue functions and the shortcode function.

Preventing straight quote replacement:

//prevents curly quotes
function prism_js_no_curly_quotes( $shortcodes ) {
    $shortcodes[] = 'prism_js';
    return $shortcodes;
}
add_filter( 'no_texturize_shortcodes', 'prism_js_no_curly_quotes' );

To prevent the stripping of blank lines, we’re going to have to look at a WordPress function known as wpautop(). This function, among other things, handles stripping of whitespace and <br> tags, and the automatic addition of <p> tags around blocks of text. While some advocate for disabling this function as a nuisance, many other users rely on it, so we are instead going to replace it with a similar function that selectively ignores code between your shortcodes.

To do this, we’ll be using a project called shortcode-wpautop-control, by Chiedo. Just download the main file, shortcode-wpautop-control.php, and add it to your plugin folder (prism_js) alongside your main plugin file.

//disables wpautop for this shortcode
include "shortcode-wpautop-control.php";
chiedolabs_shortcode_wpautop_control(array('prism_js'));

That’s it! You should now have working shortcodes! Give them a spin and try different settings for each of your attributes. Next time, we’ll look at an alternative to using shortcodes that will speed up your workflow without having the issues of lost whitespace.

Source(s): https://github.com/chiedolabs/shortcode-wpautop-control

Next in Series: Code Blocks with Highlighting: Adding Editor Buttons