October 17, 2009

Implementing Syntax Highlighting on your blog / website

One of things that has always been missing on my blog as a techie and programmer (and you can judge that from older posts) was a Language / Script Syntax Highlighter. Sometime last week I finally decided to work on a solution for this. Before I continue, credits where they are due (no need to re-invent the wheel if it's already been done, right?):

  • Loading external Javascript files: depending on your situation, you might need to load all the Javascript files that you require from an external server. For example, if you are exclusively using the Blogger platform like I am, you may need to load your files externally as you cannot per-say upload them to the blogger server for use in your scripts. In order to do this, I found a very useful script here: Snipplr LoadScript Function.
  • SyntaxHighlighter: This is a fully functional self-contained code syntax highlighter developed in Javascript by Alex Gorbatchev.
After a bit of Googling, I found my perfect solution. It's called SyntaxHighlighter and has been around for quite a while (since 2004). However, when you Google for it, the first links that show up are that of older versions. SyntaxHighlighter is a work in progress and is already on version 2.x.x. So let's dive straight into the code. The first step you'd like to take loading the style sheets that you'd like to use for your code listing. There is the essential / core one which is shCore.css. Once that's loaded, you should have a look at the various available themes to see which one you'd like to use. Head over here. I personally prefer the default theme as it fits with the white and plain color scheme of my blog. Once all the decisions above have been made, you should go ahead and add the following lines of code to the "head" tag of your blog:

<link href='http://alexgorbatchev.com/pub/sh/2.0.320/styles/shCore.css' rel='stylesheet' type='text/css'/>
<link href='http://alexgorbatchev.com/pub/sh/2.0.320/styles/shThemeDefault.css' rel='stylesheet' type='text/css'/>

Note that you can replace the default theme by looking at the available files available here. Once you're satisfied with the styling, you can move on to the first interesting section of the implementation.

First, add in the script that's needed to load external Javascript files. Also, you'd like to define a URI variable that will be used to refer to the main URI where your files will be loaded from. In the script below, the variable loadURI has been created just for that purpose. As per the reference above, we will use the loadScript function. Right under the previous CSS links we created, add the following lines of code:

<script type="text/javascript">
//<![CDATA[
// let's define a variable for the URL, making it easier to change
// should the case arise
var loadURI = 'http://alexgorbatchev.com/pub/sh/2.0.320/scripts/';

// reference: http://snipplr.com/view/18756/loadscript/
function loadScript(url, callback){

 var script = document.createElement("script")
 script.type = "text/javascript";

 if (script.readyState){  //IE
  script.onreadystatechange = function(){
   if (script.readyState == "loaded" || script.readyState == "complete") {
     script.onreadystatechange = null;
     callback();
   }
  };
 } else {  //Others
  script.onload = function(){
   callback();
  };
 }

 script.src = url;
 document.getElementsByTagName("head")[0].appendChild(script);
}
//]]>
</script>

The script above will allow you to load all the subsequent Javascript files you'd like to use from the external server. As specified before, this is very useful if you are not able to host the files on your blogging platform. It's time to use the script above. Assuming that you'd like to load the scripts straight from the servers where they're published (cautionary note: you should not be doing this), you'd add the following lines to the script above:

loadScript(loadURI + 'shCore.js', function(){
 loadScript(loadURI + 'shBrushCss.js', function(){});
 loadScript(loadURI + 'shBrushSql.js', function(){});
 loadScript(loadURI + 'shBrushPhp.js', function(){});
 loadScript(loadURI + 'shBrushJava.js', function(){});
 loadScript(loadURI + 'shBrushJScript.js', function(){});
 loadScript(loadURI + 'shBrushBash.js', function(){});
 loadScript(loadURI + 'shBrushXml.js', function(){});
 initSyntaxHighlighter();
});

As you can see, the scripts that I've added are those for the languages I'd like to support on my blog. Basically, with the above, the following languages will be automatically supported: CSS, SQL, PHP, Java, Javascript, Bash. Obviously, we all have different needs. In order to see what fits your needs, you should have a look at the following page: Bundled Syntaxes. Head over here to see what the concrete names of the files are. Once you've decided on the scripts that you need, all you have to do is to make sure they're loaded in the main template of your blog / website or you could write some script that would load them dynamically on demand. One essential point to note is that the shCore.js definitely needs to be the first one to be included as per my example above. Once loaded, we use the callback functionality of the loadScript function to load the remaining scripts. This ensures that shCore.js is all loaded into the browser before downloading the other script files. Not doing it this way (as I have learned) would results in Reference Errors in WebKit (engine behind Safari, Opera, Google Chrome, etc...). After all the loadScript calls, there is an aditional function initSyntaxHighlighter() call, which will be explained further down the line. All in all the full script should now be looking like this:

<script type="text/javascript">
//<![CDATA[
// reference: http://snipplr.com/view/18756/loadscript/
function loadScript(url, callback){

 var script = document.createElement("script")
 script.type = "text/javascript";

 if (script.readyState){  //IE
  script.onreadystatechange = function(){
   if (script.readyState == "loaded" || script.readyState == "complete") {
     script.onreadystatechange = null;
     callback();
   }
  };
 } else {  //Others
  script.onload = function(){
   callback();
  };
 }

 script.src = url;
 document.getElementsByTagName("head")[0].appendChild(script);
}

// load the scripts for the language we'd like 
// to have syntax highlighting for on our blog / website
loadScript(loadURI + 'shCore.js', function(){
 loadScript(loadURI + 'shBrushCss.js', function(){});
 loadScript(loadURI + 'shBrushSql.js', function(){});
 loadScript(loadURI + 'shBrushPhp.js', function(){});
 loadScript(loadURI + 'shBrushJava.js', function(){});
 loadScript(loadURI + 'shBrushJScript.js', function(){});
 loadScript(loadURI + 'shBrushBash.js', function(){});
 loadScript(loadURI + 'shBrushXml.js', function(){});
 initSyntaxHighlighter();
});

//]]>
</script> 


The SyntaxHighlighter is almost setup. The next step will be to have a look at how you'd like to configure it. My own configuration is very basic. For more info on all the options as far as the configuration of the script is concerned, you should check the SyntaxHighliter Configuration wiki page. For a very simple and basic configuration, append the following lines of code to the previous one:

function initSyntaxHighlighter()
 {
  SyntaxHighlighter.bloggerMode = true; // set to false or remove if not on blogger platform
  SyntaxHighlighter.stripBrs = false;
  SyntaxHighlighter.clipboardSwf = loadURI + 'clipboard.swf';
  SyntaxHighlighter.all();
 }

Pay attention to the name of this function. It's the same function we call in the loadScript callback of shCore.js. We call it at that stage for the same reason as earlier: avoiding variable or class name Reference Errors in WebKit.

What you may notice here is that I have set the bloggerMode to true. This is because I am hosting my configuration on the blogger platform. If you're hosting on a non-blogger platform, make sure to set that configuration parameter to false or remove that line of code altogether. Once you're happy with the configuration above, you should go ahead and test it. To use see results of all the hard work above, you'd use CSS classes related to the syntax highlighting languages you've included. An example of using it for a bash script for example would be as follows

<pre class="brush: bash;">
  !#/bin/bash
  echo "hello world!"
  export $path:/something/somewhere
</pre>

You will notice the use of "brush" in the class. That's just how you'd use it. So, if you were to need a Javascript syntax highlight, all you'd have to do is to use the "pre" tag or any other tag that you'd specify although "pre" is pretty convenient and add the class as follows: class="brush: html;". This works almost the same way as when adding the style attribute to your tags.

Here's a screenshot of what you will get if everything got properly setup:



Hope this helps anyone else who is looking for a way to have syntax highlighting on their websites or blogs. I find it extremely useful and it's first usage on my blog has been for this post.

Note:I have added all of the sample code above in a one example HTML file which can be downloaded here: Sample Demo File.

Update:You should also download the following PNG files and make sure that they are in the same directory as the CSS files you've linked above. The files are:

No comments:

Post a Comment