My latest plugin is a simple piece of code that replicates the `code in backticks` function used in the wp.org support forums
. It works in posts and comments, although it’s mainly intended for the comments section (because there are already many, many, many plugins for pasting code into posts).
(If you use it in posts, you must use the code view–it will not work in the visual editor, I assure you. By that, I mean that you need to have the visual editor disabled in your profile. Otherwise, when you go back later to edit the post, it will try to open in the visual editor first, and it will get screwy.)
So now when folks are asking me questions about my plugins, they can just insert an error message or a piece of code right into their comment with no difficulty at all. How lovely.
Appropriately enough, I’ll post version 0.1 of the code right here using my plugin as a demo.
Important: The code pasted below is version 0.1. The current version of the plugin can be downloaded here
.
Here goes:
<?php
/*
Plugin Name: KB Backtick Comments
Plugin URI: http://adambrown.info/b/widgets/category/kb-backtick-comments/
Description: Include code in posts or comments by putting it in `backticks`
Author: Adam Brown
Author URI: http://adambrown.info/
Version: 0.1
*/
// OPTIONAL SETTINGS
// To control how this plugin's code blocks look, modify the style declarations at the very end of this file. If all you want to change is the colors, though,
// you can do that here.
define('KB_BACKTICK_BG', '#e3e3ff'); // what background color will code blocks have? (Affects BOTH code blocks AND inline code.)
define('KB_BACKTICK_BORDER', '#88a'); // what border color will code blocks have? (Does not affect inline code--code blocks only.)
/*
WHAT DOES THIS DO?
Allows your commenters to paste code in their comments by enclosing it in `backticks`, like in the wp.org support forums.
Also works in posts, but only if you have the visual editor disabled (in your profile).
TIPS
* If you need to include backticks in the code you paste, escape them with a backslash: \`
* If, for some odd reason, you need to include a \` in what you post, double escape it (two backslashes): \\`
LICENSE
THIS IS BETA SOFTWARE. I have only tested it on my platform under limited circumstances. In other words, I wrote this to do something specific on my site. I hope
it works for you too, but I don't promise anything. You use this entirely at your own risk. You are welcome to modify this code, but please refer people to my site
(or WP.org if it gets listed there) to download the plugin rather than redistributing it from your own site. I mean really, I gave this to you for free, so the least you
can do is let me have a shot at getting some advertising revenue by sending people to my site to get the code.
DEV NOTES
This plugin works in three stages.
1) Before a comment/post gets saved, we look for `...` and replace it with `<code>htmlspecialchars(...)</code>` (preserving the backticks, as you see, to make the block
of code recognizable to later stages of the plugin)
2) Before a comment/post gets displayed, we remove the backticks and, if the code is a separate paragraph, wrap it in <pre> tags. (This is a distinct stage
from the first one because <pre> tags aren't allowed in comments. An earlier version of this would add <pre> to the allowed list of tags, but that was buggy.)
3) When a comment/post gets opened for editing, we look for `<code>...</code>`, remove the <code> tags, and apply htmlspecialchars_decode() to the contents.
SOMETHING WEIRD
WP will not let you post a comment that contains certain HTML entities, including '. So we strip all entities in stage 1 and reformat them as __abENT__###; (where
### is the entity code), then in stages 2 and 3 we turn that back into &###; for display.
*/
// STAGE 1 FILTERS: BEFORE A COMMENT/POST GETS SAVED
$ab_bslash = '\\'; // makes life easier when you're trying to tell \ from \\. (This is a single backslash.)
// looks for code blocks (in backticks), sends to callback
function ab_backtickFilter($content){
if (false===strpos($content,'`')) // save CPU resources
return $content;
global $ab_bslash;
// check for special problems:
// on the offchance that somebody's code contains '__abENT__' in it, we should replace the underscores with entity #95 (makes posting this file possible, for example):
$content = str_replace('__abENT__', '__abENT__#95;__abENT__#95;abENT__abENT__#95;__abENT__#95;', $content);
// allow for escaped backticks. Remember that posting vars adds slashes, so we check for two slashes, not just one:
$content = str_replace($ab_bslash.$ab_bslash.'`', '__abENT__#96;', $content);
// but just in case, we'll also look for just one slash:
$content = str_replace($ab_bslash.'`', '__abENT__#96;', $content);
// do it
$content = preg_replace_callback( '|`([^`]+)`|Us', 'ab_backtickCallback', $content );
return $content;
}
function ab_backtickCallback($matches){ // callback
$r = trim($matches[1]);
$r = stripslashes($r); // do this before converting any backslashes to entities (see below)
$r = htmlspecialchars($r);
// inexplicably, if $r contains ' the comment won't post, so we can't use htmlspecialchars(...,ENT_QUOTES). (More broadly, this is why we have that ab_removeEnts() function.)
// But we also can't just leave the apostrophes untouched, or WP texturizes them into "friendly" apostrophes. So we turn them into ' even though '
// isn't recognized by IE. We'll turn the ' back into ' with our stage 2 filters.
$r = str_replace( "'", ''', $r );
// some other cleanup:
global $ab_bslash;
$r = str_replace( $ab_bslash, '\', $r ); // convert backslashes to entities (lest WP have problems)
$r = str_replace( '.', '.', $r ); // lest WP turn ... into an elipses entity
$r = str_replace( '/', '⁄', $r ); // break links in the code (lest WP underline them) by replacing slashes with fraction entities (which are similar to slashes)
// wrap in tags:
$r = '`<code>' . nl2br($r) . '</code>`';
// remove all entities, lest WP refuse to post the comment (not necessary for posts, but very necessary for comments)
$r = ab_removeEnts($r);
return $r;
}
// Our hooks. Do it early, so kses and wp_texturize haven't hit yet--priority of 5
add_filter('content_save_pre', 'ab_backtickFilter', 5);
add_filter('pre_comment_content', 'ab_backtickFilter', 5);
// STAGE 2 FILTERS: BEFORE DISPLAYING A COMMENT/POST:
function ab_backtickStage2($content){
if (false==strpos($content,'`<code>')) // save CPU resources
return $content;
// first we look for blocks of code and apply <pre> tags:
$content = preg_replace_callback('|<p>`<code>(.*)</code>`</p>|Us', 'ab_backtickCallback2', $content );
// then we look for inline code and remove the backticks:
$content = preg_replace('|`<code>(.*)</code>`|Us', '<code class="backtick">$1</code>', $content );
// fix the entities that we destroyed in stage 1
$content = ab_restoreEnts($content);
// fix our apostrophes (see notes in ab_backtickCallback())
$content = str_replace( ''', "'", $content );
// fix our slashes (see notes in ab_backtickFilter())
$content = str_replace( '⁄', '/', $content );
return $content;
}
function ab_backtickCallback2($matches){
// change paragraph tags to <pre> tags
$r = '<pre class="backtick"><code>'.$matches[1].'</code></pre>';
// if this is a multi-line block of code, there might be </p><p> inside it. Let's get rid of those. Also, WP likes to turn newlines into <br />, so let's kill those too.
$find = array('<p>', '</p>', '<br />');
$replace = array("\n", '', '');
$r = str_replace($find, $replace, $r);
return $r;
}
// Our hooks. Do it late in the game (after WP is done texturizing) with a very high priority:
add_filter('comment_text', 'ab_backtickStage2', 1001);
add_filter('the_content', 'ab_backtickStage2', 1001);
// STAGE 3 FILTERS: BEFORE OPENING A COMMENT/POST FOR EDITING:
// we undo everything in the stage 1 filter (and in the opposite order)
function ab_backtickStage3($content){
if (false===strpos($content,'`')) // save CPU resources
return $content;
$content = ab_restoreEnts($content);
$content = preg_replace_callback( '|`<code>(.*)</code>`|Us', 'ab_backtickCallback3', $content );
// check for escaped backticks outside the code blocks:
$content = str_replace('`', '\`', $content );
return $content;
}
function ab_backtickCallback3($matches){
$r = $matches[1];
// WP likes to convert newlines in code blocks into <br />. Let's kill them all (the <pre> tag only needs newlines)
$r = str_replace( '<br />', '', $r );
// undo stage 1:
// fix: slashes, backslashes, apostrophes, (escaped) backticks, periods
$find = array( '⁄', '\', ''', '`', '.' );
$replace = array('/', '\\', "'", '\`', '.');
$r = str_replace( $find, $replace, $r );
$r = htmlspecialchars_decode($r);
$r = '`'.$r.'`'; // restore backticks
return $r;
}
add_filter('format_to_edit', 'ab_backtickStage3', 5); // one hook for both comments and posts
// OTHER STUFF
// used to remove and restore the HTML entities, which WP doesn't like to see in comments:
function ab_removeEnts($s){ // reformat all entities so WP won't screw with them
return preg_replace('|&([0-9a-zA-Z#]{1,5});|', '__abENT__$1;', $s);
}
function ab_restoreEnts($s){ // fix all the entities
return preg_replace('|__abENT__([0-9a-zA-Z#]{1,5});|', '&$1;', $s);
}
// Replicate a PHP 5 function for all those PHP 4 types out there:
if (!function_exists("htmlspecialchars_decode")){
function htmlspecialchars_decode($string, $quote_style = ENT_COMPAT){
return strtr($string, array_flip(get_html_translation_table(HTML_SPECIALCHARS, $quote_style)));
}
}
// OPTIONAL.
// You'll want this in your style, or something like it, so that code blocks look good. I've made it easy to change the settings via an option at the top of
// this file, or you can just edit this function directly.
function ab_backtickStyles(){
// inline code looks like this: <p>blah blah blah <code class="backtick">code code code</code> blah blah blah</p>
// blocks of code like like this: <pre class="backtick"><code>code code code code</code></pre>
echo '
<style type="text/css"><!--
.backtick{background:'.KB_BACKTICK_BG.';color:#000;}
pre.backtick{overflow:auto;max-height:30em;padding:1em;background:'.KB_BACKTICK_BG.';border:'.KB_BACKTICK_BORDER.' 1px solid;}
// -->
</style>
';
}
add_action('wp_head', 'ab_backtickStyles');
?>Important note: This is very, very pre-beta. I’ll be testing it as people use it here on my site. It might mess things up in the code. If you notice that it does mess something up, please let me know, although I don’t know whether I’ll have time to fix it. (Patches are much more appreciated than bug reports, although bug reports are also helpful.)

5 Comments
A quick demo. Put code in backticks in your comments. You can do it inline or as a block. Either way, it gets wrapped in
<code>tags, but if it’s a block, it also gets<pre>tags.Example of
<?php // look, I'm inline ?>inline code.Easy as that. The code can be in any language, and it can be very long, as this example shows (my stylesheet):
Very neat! Useful for posting code in different tutorials :)
Hi,
I’m using this plugin for my website, but it looks like something is giong wrong when there is some text before or after the code…
Something like this doen’t work on my website :
text
code in backtickstext
If I let a white line after the text, it’s ok… Like this is working:
text
code in backtickstext
Do you think that you can fix easylly this problem
Oddly enough, you can see that it worked both ways in your comment. Maybe it’s only a problem in posts, not comments?
I’m swamped right now with my real work, but I’ll take a look at this next time I update the plugin. Don’t know how soon that will be.
Nice plugin. If you are curious, I struggled with the same single quote problem in a plugin of mine, and discovered why WordPress chokes on single quotes. It is because the “blacklist” check doesn’t allow any ASCII entities below 128, except for the ampersand, marking them as spam. (I went through my blog database and discovered hundreds of comments that I had never seen because of that.)
This code happens in wp-includes/comment.php:
Anyway, your solution to the single quote problem is great, and I “borrowed” it for my plugin.