Wednesday, October 9, 2024

How to Create a Custom Brush for SyntaxHighlighter

In the Guide to the SyntaxHighlighter JavaScript Library, I introduced Alex Gorbatchev’s popular SyntaxHighlighter library. As the name suggests, it’s purpose is to display source code or specially formatted text in color-coded schemes to highlight key syntactical elements. The code that determines which elements get assigned what color are called brushes. In this article, we’re going to create our own custom brush and add it to the SyntaxHighlighter library.

Brush Choices

SyntaxHighlighter already includes brushes for most common programming, scripting, markup, and data transport languages. The SyntaxHighlighter 3.0.83 site lists all of the brushes that come bundled with the library. If you don’t find what you want there, the Under My Hat blog maintains a much more comprehensive list of all the available brushes from third-party contributors for version 2.0 of SyntaxHighlighter and above. It also includes a wish list of brushes that have been requested and/or are in the works. You used to be able to submit requests in the SyntaxHighlighter forums but they now appear to be disabled due to spam. Needless to say, I don’t like spam!

 

The Easy Part: Creating the Brush Class

For the purpose of this exercise, we’ll write up a brush script for a fictional language called Pickle (imagine Cucumber but a little tipsy!).

The SyntaxHighlighter library organizes each brush within its own .js file, so that they are completely independent of each other and interchangeable. Brush scripts follow the naming convention of “shBrush.js”. Within each file, there are three components which make up the brush:

  • The brush class, which is appended to the SyntaxHighlighter.brushes object.
  • The brush class’s prototype property, which points to a new SyntaxHighlighter.Highlighter.
  • The aliases that will be used in the target HTML source to identify our brush.
SyntaxHighlighter.brushes.Pickle = function() 
{ 
  this.regexList = []; 
}; 
SyntaxHighlighter.brushes.Pickle.prototype = new SyntaxHighlighter.Highlighter();  
SyntaxHighlighter.brushes.Pickle.aliases   = ['pickle', 'pkl', 'pic'];  

The Slightly More Difficult Part: Writing the Brush Class Code

This requires more thinking on our part because only we know what words our brush will highlight.

Keywords are those words that should stand out. I chose some obvious ones from Java because I didn’t really want to design a whole new language! To define the keywords, we have to include them in a space delimited string and assign it to a variable called “keywords”. To parse them from the source code, we need create a regular expression object and seed it with our keywords. The getKeywords() function takes the string of keywords and tokenizes them for the RegExp object. Hence, the following code:

  1. Assigns a string of keywords to the “keywords” variable.
  2. Parses the string via the this.getKeywords() method.
  3. Passes the parsed keywords to a new RexExp.
  4. Adds the regular expression to the regexList array of object literals.
SyntaxHighlighter.brushes.Pickle = function() 
{ 
  var keywords = 'break case catch continue public void '
               + 'default delete do else throws '
               + 'for function if in instanceof '
               + 'new null return super switch '
               + 'this throw try typeof var while with ';
  this.regexList = [{ regex: new RegExp(this.getKeywords(keywords), 'gmi'), css: 'keyword' }]; 
}; 

In addition to the regex, the object literal also contains a property for the associated css color class. The pre-defined “keyword” class is the obvious choice here.

Including Our Brush in the Page

Our brush, though basic, is now fully functional. As with all SyntaxHighlighter brushes, you need to include the CSS theme tag, as well as the shCore.js and our shBrushPickle.js scripts in the host page. Any code snippets that you want to highlight using our brush must be placed within

 tags with a class set to "brush: pickle;" - of course, our 'pkl' and 'pic' aliases would work equally well. Finally, a script at the bottom of the page calls SyntaxHighlighter.all() to perform the highlighting:
Pickle Brush Tests


 

 

Pickle Brush Tests

public double negotiate(double anOffer) throws Exception {
  double newOffer = anOffer * 1.05;
  if (anOffer >= 0) {
  	System.out.println("Hmmm ... I don't think so " + "... how about "
  			          + newOffer + "?");
  }
  else {
  	throw new Exception("Offer can't be negative.");
  }
  return newOffer;
}

 

 

 

Want to see what that looks like? Here’s the same code again with highlighting.

public double negotiate(double anOffer) throws Exception {
		double newOffer = anOffer * 1.05;
		if (anOffer >= 0) {
			System.out.println("Hmmm ... I don't think so " + "... how about "
					          + newOffer + "?");
		}
		else {
			throw new Exception("Offer can't be negative.");
		}
		return newOffer;
}
 

Conclusion

That’s a good start, but there’s a lot more we can do, such as matching comments and strings, using predefined regular expressions, and assigning colors to keywords, functions, and operators. We’ll cover all that next time.



Rob Gravelle
Rob Gravelle
Rob Gravelle resides in Ottawa, Canada, and has been an IT guru for over 20 years. In that time, Rob has built systems for intelligence-related organizations such as Canada Border Services and various commercial businesses. In his spare time, Rob has become an accomplished music artist with several CDs and digital releases to his credit.

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Popular Articles

Featured