How to create syntax highlighter using jQuery


Today I am going to show you how to create a basic code highlighter for website. This UI is actually inspired by sixrevisions.com. I have added functionality of showing line numbers.
Following things will be covered
  • How to add line numbers
  • How to highlight single line comments i.e. those lines which starts with //
  • How to highlight comment blocks i.e. those lines which are enclosed within /* */

Live Demo     Download Code

To use this code highlighter you have to wrap your code inside <pre> tags. Really there is nothing new in it. It is the same traditional old method. <code> tag is another way of adding code into your post. However there is a difference between <pre> and <code> tag. To give analogy of their working I would give example of <div> and <span> respectively. This means <pre> is a block tag and <code> tag can be used inline.
One important thing we need to consider is, in WordPress if you want to post HTML code then you have to escape it (if you are not using visual editor). This can be done easily by using freeformatter.com or htmlescape.net or a tool of accessify.com.

This can also be done with a line using jQuery by passing output of .html() function to .text() function of jQuery as follows:
jQuery( 'selector' ).text( jQuery( 'selector' ).html() );
Now let’s see how our code formatter can be created. First we need simple styling as follows:
pre.syntaxHighlight {
    border: 1px solid #e1e1e1;
    background-color: #ebebeb;
    font-size: 12px;
    padding: 10px;
    margin-top: 10px;
    margin-bottom: 10px;
    overflow: auto;
}
Now in your post when you add following snippet
<pre class="syntaxHighlight">
//test
var stage = new Kinetic.Stage({
 container: 'canvasArea',
 width: 500,
 height: 500,
 draggable: false
}),

layer = new Kinetic.Layer({
 name: 'layer'
}),

tmpLayer = new Kinetic.Layer({
 name: 'tmpLayer'
});
</pre>

You will see output like this:
//test
var stage = new Kinetic.Stage({
 container: 'canvasArea',
 width: 500,
 height: 500,
 draggable: false
}),

layer = new Kinetic.Layer({
 name: 'layer'
}),

tmpLayer = new Kinetic.Layer({
 name: 'tmpLayer'
});

As you can see there is no HTML code present in above example, so it worked without any problem. If you have added HTML code it would have been interpreted as a normal HTML code as we discussed above. Also we have discussed that we can escape it by two means, using online escape tools mentioned above or using one line of jQuery.
When I created this tool, I wanted a little sophistication of highlighting single line of comments and block comments. Also I wanted to show line numbers.
Therefore in our css code we need to add following two classes:
pre.syntaxHighlight span.digTSyntax {
     font-weight: bold;
     color: #096;
}
pre.syntaxHighlight span.lineNumber {
    color: #096;
    margin-right: 5px;
}
And now if we write markup as:
<pre class="syntaxHighlight">
<div id="test"></div>
//test
var stage = new Kinetic.Stage({
 container: 'canvasArea',
 width: 500,
 height: 500,
 draggable: false
}),

layer = new Kinetic.Layer({
 name: 'layer'
}),

tmpLayer = new Kinetic.Layer({
 name: 'tmpLayer'
});
</pre>
Following one line of jQuery will escape HTML code
jQuery('pre.syntaxHighlight').text( jQuery('pre.syntaxHighlight').html() );
Output will be
<div id="test"></div>
//test
var stage = new Kinetic.Stage({
 container: 'canvasArea',
 width: 500,
 height: 500,
 draggable: false
}),

layer = new Kinetic.Layer({
 name: 'layer'
}),

tmpLayer = new Kinetic.Layer({
 name: 'tmpLayer'
});
But something is wrong here. There are no line numbers in it.
To bring line numbers in it we have to prepend line number <span> to start of line, something like below:
var line = 1;
var htmlText = jQuery(this).html().replace(/\</g,'&lt;').replace(/\>/g,'&gt;');
htmlText = htmlText.replace(/(^)/gim, function(_, group){
  return group + '<span class="lineNumber">'+(line++)+'</span>';
});
We have taken code inside <pre> into “htmlText” variable and in next line we replaced start of line with start of line and <span class=”lineNumber”>. There is a little regular expression is used here which will give matching group (^) and in second argument of replace we have added a function of which 2nd argument will be start of line character. Also we have declared and initialized variable line to 1 which will be incremented with each line.
Next we want to highlight single line comments. For that we need to find each // and until end of line and color it to green.
var line = 1;
var htmlText = jQuery(this).html().replace(/\</g,'&lt;').replace(/\>/g,'&gt;');
htmlText = htmlText.replace(/(^)/gim, function(_, group){
  return group + '<span class="lineNumber">'+(line++)+'</span>';
}).replace(/(\/\/.*)/ig, function(_, group){
   return '<span class="digTSyntax">'+group+'</span>';
});
Similar to above now we want to highlight block of comment
var line = 1;
var htmlText = jQuery(this).html().replace(/\</g,'&lt;').replace(/\>/g,'&gt;');
htmlText = htmlText.replace(/(^)/gim, function(_, group){
  return group + '<span class="lineNumber">'+(line++)+'</span>';
}).replace(/(\/\/.*)/ig, function(_, group){
   return '<span class="digTSyntax">'+group+'</span>';
}).replace(/(\/\*[\s\S]+?\*\/)/igm, function(_, group){
   return '<span class="digTSyntax">'+group+'</span>';
});
Putting it all together
jQuery('pre.syntaxHighlight').each(function(){

 var line=1;
 var htmlText = jQuery(this).html().replace(/\n$/,'');
  
 htmlText = htmlText
 .replace(/\</g,'&lt;')
 .replace(/\>/g,'&gt;')
 .replace(/(^)/gim, function(_, group){
   return group + '<span class="lineNumber">'+(line++)+'</span>';
 }).replace(/(\/\/.*)/ig, function(_, group){
   return '<span class="digTSyntax">'+group+'</span>';
 }).replace(/(\/\*[\s\S]+?\*\/)/igm, function(_, group){
   return '<span class="digTSyntax">'+group+'</span>';
 });
  
 $(this).html(htmlText);  
});
This is just a basic mechanism. Of course there is a scope for improvement.

Comments

Popular posts from this blog

Step by step Cordova calabash-ios automation

How to get local time from UTC using Moment.JS

Measure the height of keyboard on PhoneGap app using jQuery