How do you spell hilighter? Hiliter, highlighter, hiliter? Anyway, after setting up the Google syntax hilighter, and running it on a few snippets I realized that 1) it’s the best looking, most functional highlighter 2) it can only highlight about 50 lines of code before it goes off into hilighter land never to return. Some of my snippets are a few hundred lines long – I had to have something better.
I looked around for a better hiliter. I found a decent review page. Unfortunately, about 1/2 these use the Google hiliter and the others didn’t fill my needs (serverside, not enough langs supported, etc.). I came across SHJS. It’s fast, themed, and supports 30 languages with easy language addition. But no line numbers. In the end, I decided to write a plugin to wrap SHJS, add line numbers, and allow me to provide links to the raw code for easy copy and paste. I really like the CnP functionality of the Google hiliter – but time is of the essence and the “Open In New Window” solution works for all browsers.
Installation
Download The Plugin
- Copy the SHJSSyntaxHiliter directory into /wp-content/plugins. Do not rename the directory when you copy it into your /wp-content/plugins directory as SHJSSyntaxHiliter is hardcoded in a few spots.
- Open your WordPress admin and go to the Plugins page. Find SHJSSyntaxHiliter in the list and click the “activate” link.
- Select the theme you want to use on the SHJS Syntax Hiliter configuration page. Themes can be previewed on SHJS. I tried to integrate the theme preview into the options page, but ran out of time – maybe next version.
Usage
Technique 1
In your post include your code in <pre name="code" class="sh_java"></pre> tags as you would normally use SHJS.
Technique 2
- Copy your code into a file on the server
- In your posts pass the webroot relative path and language like this: [SyntaxHilite:/path/relative/to/site/root/myfile.java,java]. This will result in the code being displayed as the code in this article is below. The supported languages, etc. are detailed on the Settings->SHJS Syntax Hiliter page.
A Bit About The Code
The Plugin Pieces
- SHJSSyntaxHiliter.php Core WordPress plugin code
- options.php Options page
- shjss directory The SHJS binary distribution available from SHJS
The Plugin Core Code
The core code contains two hooks: the_content and wp_footer. The the_content callback performs a regex replace on the article, inserting the code and html wherever [SyntaxHilite:…] has been used. The wp_footer callback performs a regex to gather which languages to include, and outputs the script to load the languages, syntax hilite, and insert line numbers.
Open Unformatted Code In New Window
<?php
/* Copyright 2009 R-Link Research and Consulting, Inc. (email : zach@rlinkconsulting.com)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
Plugin Name: SHJS Syntax Hilighter
Plugin URI: http://www.codezach.com
Description: Syntax hilighter using SHJS. See http://shjs.sourceforge.net for more info on SHJS.
Version: 0.1
Author: R-Link Research and Consulting, Inc.
Author URI: http://www.codezach.com
*/
//**************************************************************
// Globals
//**************************************************************
$webroot = dirname(dirname(dirname(dirname(__FILE__))));
$pluginroot = dirname(__FILE__);
$languages;
//**************************************************************
// Includes
//**************************************************************
$include = $pluginroot . '/options.php';
require_once $include;
//**************************************************************
// Initialize
//**************************************************************
add_filter('the_content', 'syntax_hilite');
add_action('wp_footer', 'do_hilite');
//**************************************************************
// Core hilite function
//**************************************************************
function syntax_hilite($content)
{
global $languages;
$theme = get_option('shjs_theme');
$ret = '<script type="text/javascript" src="/wp-content/plugins/SHJSSyntaxHiliter/shjs/sh_main.js"></script>';
$ret .= '<link type="text/css" rel="stylesheet" href="/wp-content/plugins/SHJSSyntaxHiliter/shjs/css/sh_' . $theme . '.css">';
$ret .= preg_replace_callback( "/(?<!`)\[SyntaxHilite:(([^]]+))]/i","hilite_cb", $content );
if(isset($languages))
{
// Include the scripts for the langs we loaded
//**************************************************************
foreach($languages as $lang => $val)
{
$ret .= '<script type="text/javascript" src="/wp-content/plugins/SHJSSyntaxHiliter/shjs/lang/sh_' . $lang . '.js"></script>';
}
}
return $ret;
}
//**************************************************************
// footer_class_tag_cb - fill global $languages
//**************************************************************
function footer_class_tag_cb($matches)
{
global $languages;
$match = $matches[0];
$parts = explode('"', $match);
$lang = $parts[1];
$languages[$lang] = true;
return $match;
}
//**************************************************************
// do_hilite() - include lang files, execute
//**************************************************************
function do_hilite()
{
global $languages;
$content = get_the_content();
preg_replace_callback('/class+\s*=\s*"sh_[^"]*"/', "footer_class_tag_cb", $content);
if(count($languages) < 1)
{
return;
}
foreach($languages as $lang => $val)
{
echo '<script type="text/javascript" src="/wp-content/plugins/SHJSSyntaxHiliter/shjs/lang/' . $lang . '.js"></script>';
}
?>
<p>Languages: <?php echo count($languages) ?></p>
<script type="text/javascript">
syntaxHilite();
function syntaxHilite()
{
var tab = " ";
var codes = document.getElementsByTagName("pre");
sh_highlightDocument();
for(var i = 0; i < codes.length; i++)
{
if(codes[i].getAttribute("name") != "code")
{
continue;
}
var orig = codes[i].innerHTML;
var nextline = "";
var output = "";
var lineBeginning = true;
for(var j = 0; j < orig.length; j++)
{
var nextChar = orig.charAt(j);
if(nextChar == '\r'|| nextChar == '\n')
{
if(nextChar == '\r' && (j + 1) <= orig.length && orig.charAt(j + 1) == '\n')
{
j++;
}
if(nextline.length < 1)
{
nextline = " ";
}
output += '<li>' + nextline + '</li>';
nextline = "";
lineBeginning = true;
}
else
{
if(nextChar == '\t')
{
nextline += tab;
}
else if(nextChar == ' ' && lineBeginning == true)
{
nextline += " ";
}
else
{
lineBeginning = false;
nextline += nextChar;
}
}
}
output = "<ol>" + output + '</ol>';
codes[i].innerHTML = output;
}
}
</script>
<?php
}
//**************************************************************
// Match callback - replaces the match with the
// <pre>...code...</pre>, etc.
//**************************************************************
function hilite_cb($matches)
{
global $webroot;
global $replacementCount;
global $languages;
$args = explode(',', $matches[2]);
$lang = $args[1];
$languages[$lang] = true;
$filename = $args[0];
$code = htmlentities(file_get_contents($webroot . $filename));
ob_start();
?>
<p><a target="_blank" href="<?php echo $filename ?>">Open Unformatted Code In New Window</a></p>
<pre name="code" class="sh_<?php echo $lang ?>">
<?php echo $code; ?>
</pre>
<?php
$ret = ob_get_contents();
ob_end_clean();
$replacementCount++;
return $ret;
}
?>
Syntax Hilite
The call to the SHJS function sh_highlightDocument(); on line 122 transforms our plain code in the pre tags into marked up hilited code. Notice this is in the footer callback – it must occur exactly once!
Line Numbers
After the call to sh_highlightDocument(); we can insert line numbers. The loop starts on line 124 and wraps the lines in <li> tags. It also replaces tab characters with spaces. This is a browser issue as some browsers (IE) will trim the spaces from the lines once they are added as list items. Non-breaking spaces are not stripped…
Conclusion
Well, that should be enough to help you get started syntax hiliting your WordPress blogs. And Hopefully, you can use my code as a starting point for your own plugins ![]()

June 6th, 2009 2:15 am
привет ! ничё беспричинный у тебя блог )) почитаешь мой? я любитель акуры Разве который заходи и почитай, бывает пишу информацию , которой не покажу в книгах и чём то подобном