//
you're reading...
General, Syntax Highlighter

Syntax Highlighter take 2

Thanks to liberal application of some regular expressions I was able to write my own syntax highlighter and it is now used on this site.

I based some of the ideas off of Beautifier but all of the code is mine except for the keyword list which was pulled from the Beautifier language defs.

Best of all, the code is fairly clean; without tons of hacks added in just to make it work with some code I didn’t write.

Download Syntax Highlighter 2 (23.2Kb) for WordPress, including language files for C++, C++/CLI, C#, HTML, and CSS. More may be added later or you can make your own by following the pattern set by the 4 included.

Installation is simple, extract to your WordPress directory, then login and enable the Syntax Highlighter 2 plugin. It takes care of the rest from there. Adding syntax highlighting to your posts is simple:

<pre lang=[cpp|cppcli|cs|html|css]>
// your code here
</pre>

Next add the following CSS classes to your .css file to get the same coloring I use here

pre .comment {
  color: green;
}

pre .keyword {
  color: blue;
}

pre .string {
  color: #990000;
}

pre .number {
  color: red;
}

Enjoy!

Update: Added samples of each of the formats below, use the more link to see them. Also added support for PHP, XML, and XSL

In the next version I plan to add support for line numbering, and I might even get that done tonight.

Update: It figures, the one thing I didn’t test in all off the new languages is broken. Comments might not work in HTML, XML, or XSL. I’ll update again as soon as its working again

Update: Comments in HTML, XML, and XSL are working again; the problem was in how I was keeping track of each match. Originally I was using an associative array where the key to the array was the index into the original string where the match occurred. But what happens when you have two matches start at the same index? The second match overwrites the first one.

Now the array isn’t associative and the array index has no bearing on the actual position in the string. I then sort it with my own sorting function so that it is arranged in index order with comments taking precedence over the other types of matches.

C++/CLI

value class Student
{
public:
    String^ strStudentname;
};

// Adding a comment for the hell of it

interface class IHello
{
    void SayHello(Student student);
};

ref class Hello : public IHello
{
public:
    Hello()
    {
        Console::WriteLine("Hello from C++/CLI");
    }
    void SayHello(Student student)
    {
        Console::WriteLine("Hello {0}",
            student->strStudentname);
    }
};

C#

public Instance this [Template template, int index]
{
  get
  {
    List<Instance> list = this [template];

    if( list == null )
      return Instance.default;

    if( list.Count > index )
      return Instance.default;

    return list [index];
  }
}

public void Stuff() 
{
  TemplateCollection<ItemTemplate, Item> items = 
    new TemplateCollection<ItemTemplate, Item>();

  // Add new item to room
  items.Add( itemTemplate, itemTemplate.CreateInstance() );
}

PHP

function syntax_highlighter_two( $content )
{
  return preg_replace_callback( 
    "/<pre([^>]*)>(.*?)</pre>/is", 
    'language_highlight', $content );
}

function language_highlight( $preBlockMatches )
{
  global $langDefs;

  $preAtts = $preBlockMatches[1];
  $code = $preBlockMatches[2];

  $lang = get_pre_lang( $preAtts );

  if( $lang == '' )
    $lang = 'default';

  if( isset( $langDefs[ $lang ] ) )
    $langClass = $langDefs[ $lang ];
  else
    $langClass = $langDefs[ 'default' ];
  // Need to add some comments 
  if( $langClass != '' )
  {
    $langClass = 'SH_' . $langClass;
    require_once( 'langs/' . $langClass . '.php' );

    $languageDef = new $langClass();
  }
  /*  don't allow this to happen
     $languageDef = null;
  */
}

XML

<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0" > 
	<xsl:output method = "xml" indent = "yes" /> 

<!--
A comment
-->
	<xsl:template match = "/" > 
		<xsl:element name = "QQQ" > 
			<xsl:element name = "{//BBB}" > 
				<xsl:element name = "{//CCC}" > 
					<XXX /> 
				</xsl:element> 
			</xsl:element> 
		</xsl:element> 
	</xsl:template> 
</xsl:stylesheet>

XSL

<xsl:stylesheet xmlns:xsl = "http://www.w3.org/1999/XSL/Transform" version = "1.0" > 
	<xsl:output method = "xml" indent = "yes" /> 
<!--
  a comment
-->
	<xsl:template match = "/" > 
		<xsl:element name = "QQQ" > 
			<xsl:element name = "{//BBB}" > 
				<xsl:element name = "{//CCC}" > 
					<XXX /> 
				</xsl:element> 
			</xsl:element> 
		</xsl:element> 
	</xsl:template> 
</xsl:stylesheet>

HTML

<div class="feedback"> 
  <a href="example.org/the-url#comments">Comments (0)</a> 
</div>

<!--
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
    xmlns:dc="http://purl.org/dc/elements/1.1/"
    xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <rdf:Description rdf:about="example.org/the-url"
    dc:identifier="example.org/the-url"
    dc:title="I'm in love with generics"
    trackback:ping="example.org/the-url" />
</rdf:RDF>  
-->

</div>
Advertisements

About James

I am a Senior Developer/Consultant for InfoPlanIT, LLC. I previously spent over 7 years as a Product Manager for what eventually became ComponentOne, a division of GrapeCity. While there, I helped to create ActiveReports 7, GrapeCity ActiveAnalysis, and Data Dynamics Reports.

Discussion

No comments yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Archive

%d bloggers like this: