Jay Harris is Cpt. LoadTest

a .net developers blog on improving user experience of humans and coders
Home | About | Speaking | Contact | Archives | RSS
 
Filed under: Blogging | JavaScript | Programming | Reviews | Tools

Google Syntax Highlighter is a simple tool that allows bloggers to easily display code in a format that is familiar end users. The tool renders the code in a very consumable fashion that includes colored syntax highlighting, line highlighting, and line numbers.

/*
This is an example of how Google
Syntax Highlighter can highlight and display syntax
to you, the end user
*/
public void HelloWorld()
{
  // I have some comments
  Console.WriteLine("Hello, World!");
}

It is purely a client-side tool, as all of the processing is done strictly within the browser through JavaScript. There is no server-side processing. Since it is all JavaScript, you don't need special Copy/Paste plugins and macros installed to your favorite IDE or your blog authoring tool. (I am leery of random plugins and installing them into the software that I use to feed my family.) To including code in your blog post, copy your code from Visual Studio, Notepad, Flash, Firebug, or any tool that displays text, and paste it in to your post. As of v1.5.1, Google Syntax Highlighter supports C, C++, C#, CSS, Delphi, HTML, Java, JavaScript, PHP, Pascal, Python, Ruby, SQL, VB, VB.NET, XML, XSLT, and all of this is just what comes out of the box.

Setting Up Syntax Highlighter

To get Syntax Highlighter running on your blog, download the latest version of the RAR archive and extract the code. The archive contains a parent folder, dp.SyntaxHighlighter, with three child folders:

dp.SyntaxHighlighter
  \Scripts         //Production-ready (Compressed) scripts
  \Styles          //CSS
  \Uncompressed    //Human-readable (Uncompressed/Debug) scripts

Once the archive is extracted, upload dp.SyntaxHighlighter to your blog. Feel free to rename the folder if you like, though I did not. It is not necessary to upload the Uncompressed folder and its files; they are best used for debugging or for viewing the code, as the files in the Scripts folder have been compressed to reduce bandwidth by having most of their whitespace removed.

After you have uploaded the files, you will need to add script and style references to your site's HTML. This is code is not for your posts, but rather for your blog template. In DasBlog, I place this code in the <HEAD> block of my homeTemplate.blogtemplate file. Remember to change the file paths to match the path to where you uploaded the code.

<link type="text/css" rel="stylesheet"
  href="dp.SyntaxHighlighter/Styles/SyntaxHighlighter.css"></link>
<script language="javascript" src="dp.SyntaxHighlighter/Scripts/shCore.js"></script>
<script language="javascript" src="dp.SyntaxHighlighter/Scripts/shBrushCSharp.js"></script>
<script language="javascript" src="dp.SyntaxHighlighter/Scripts/shBrushXml.js"></script>
<script language="javascript">
window.onload = function () {
  dp.SyntaxHighlighter.ClipboardSwf = 'dp.SyntaxHighlighter/Scripts/clipboard.swf';
  dp.SyntaxHighlighter.HighlightAll('code');
}
</script>

To make the tool most efficient, including minimizing the code download by the client browser, highlighting is only enabled for the languages that you specify. The highlighting rules for each language is available through a file referred to as a Brush. The code sample above enables only C# and XML/HTML by including the core file, shCore.js, the C# brush, shBrushCSharp.js and the XML/HTML brush, shBrushXml.js. A unique brush file is available for each of the supported languages, and only the core file is required. These brushes are located in your Scripts directory (the human-readable version is in the Uncompressed folder). Include only the brushes that you like; if you forgot a language brush, the code will still display on your page, but as unformatted text.

<!-- Unformatted HTML Code / No Brush -->
<p id="greeting">Hi, mom & dad!</p>
<!-- Formatted HTML Code -->
<p id="greeting">Hi, mom & dad!</p>

Making Syntax Highlighter Go

Now that the application is deployed to the site, how does it get applied to a post? Paste the code into the HTML view of your post, inside of a <PRE> tag. Create a name attribute on your tag with a value of code, and a class attribute set to the language and options you are using.

<pre name="code" class="c-sharp">
  public void HelloWorld()
  {
    Console.WriteLine("Hello, World!");
  }
</pre>

One catch is the code must be first made HTML-safe. All angle-brackets, <tag>, must be converted to their HTML equivalent, &lt;tag&gt;, as well as ampersands, & to &amp;. I also find it helpful if your code-indentation uses two-spaces, rather than tabs.

<!-- Pre-converted code -->
<p>Hi, mom & dad!</p>
<!-- Converted code -->
<pre name="code" class="html">
  &lt;p&gt;Hi, mom &amp; dad!&lt;/p&gt;
</pre>

The class attribute is made up of both language and option aliases. These aliases consist of one language followed by your desired options, all in a colon delimited list.

class="language[:option[:option[:option]]]"

The value of language is any of Syntax Highlighter's defined language aliases, such as c#, csharp, or c-sharp for C#, or rb, ruby, rails, or ror for Ruby. See: full list of available languages.

Options allow for such things as turning off the plain text / copy / about controls (nocontrols), turning off the line number gutter (nogutter), or specifying the number of the first line (firstline[n]). A JavaScript code block with no controls header, and starting the line numbering at 34 would have a class attribute value of class="js:nocontrols:linenumber[34]". See: full list of available options.

Extending Syntax Highlighter

Because Google Syntax Highlighter is entirely in JavaScript, you have access to all of the code. Edit it however you like to suit your needs. Additionally, brushes are very easy to create, and include little more than a list of a highlighted language's keywords in a string and an array of language aliases. Creating a brush for ActionScript or QBasic would not take much time. Language brushes exist in the wild for Perl, DOS Batch, and ColdFusion.

In a future post I plan on discussing Brush Creation in depth through creating a brush for ActionScript.

Comparing Syntax Highlighter to Others

I am a fan of this tool, though that should be obvious considering it is what I use on this blog. I like how readable the code is, how extendable it is, and how easy it is to use. I don't like its compatibility--or lack thereof--with RSS; since all of the work is done in JavaScript, and RSS doesn't do JavaScript, there is no syntax highlighting, numbers, or options within a feed, though the code formatting is still maintained. Other tools, like the CopySourceAsHtml plugin for Visual Studio or Insert Code Snippet for Windows Live Writer convert your code into formatted HTML, where all of the syntax highlighting is applied through HTML attributes and embedded CSS. Their methods are much easier than Syntax Highlighter, since there are no stylesheets or JavaScript files to include in your HTML, and you don't have to worry about making your code HTML-safe. Also, their method works in RSS feeds. However, there isn't the same level of control. Through Syntax Highlighter's extendibility, I can theme my code views, such as if I wanted them to look like my personal Visual Studio theme. Through Syntax Highlighter, I can also make changes at a later time, and those changes will immediately reflected in all past posts, whereas making modifications to the HTML/embedded CSS pattern is much more difficult.

Final Thoughts

I like CopySourceAsHtml in Visual Studio. I used it for years on this blog. But I code in more languages than VB.Net or C#, and the plugin isn't available within the Flash or LoadRunner IDE. I was also frustrated with pasting my code in, only to find that it was too wide for my blog theme's margins, and would have to go back to Visual Studio, change my line endings, and repeat the process. I'm sticking with Google Syntax Highlighter. It works for all of my languages (as soon as I finish writing my ActionScript brush), and when my line endings are too long, I simply change my HTML. And in my HTML, my code still looks like code, rather than a mess of embedded style. I have to sacrifice RSS formatting, but as a presentation developer that is very particular about his HTML, I am glad for the customization and control.

Monday, 24 November 2008 10:41:50 (Eastern Standard Time, UTC-05:00)  #    Comments [9] - Trackback

Filed under: ASP.Net | Programming

A few months ago I switched my blogging engine from WordPress to DasBlog, and was left with a pile of broken post links. The WordPress format of formatting URLs, such as cptloadtest.com/?p=56, no longer applied; DasBlog has its own way of building the URL: cptloadtest.com/2006/05/31/VSNetMacroCollapseAll.aspx. Other people, with links to my posts on their own blogs, and search engines, with search results pointing to the old format, no longer directed people to the proper page. Fortunately, the old WordPress way directed users to the domain root, so they saw the main page instead of a 404, but what I really needed was a way to get users to the content they came for. But, I wanted a way that didn't involve customizing DasBlog code.

Part 1 discusses some client-side options for redirecting traffic. As a developer, I would only need to add some quick JavaScript or HTML to my pages to reroute traffic, but I wanted a better way. I wanted Google's links to be updated, rather than just for the link to correctly route. I want a solution that worked without JavaScript. I wanted a solution that didn't download the page twice, as any client-side processor would do. I wanted the HTTP 301.

HTTP 301, Move Permanently, is a server-side redirection of traffic. No client-side processing is involved. And Google recognizes that this is a permanent redirect, as it's name implies, so the Google result link is updated to the new URL. But since this is a server-side process, and I don't have full access to IIS settings with my hosting provider, I needed some code.

response.StatusCode = 301;
response.AddHeader("Location", "http://www.cptloadtest.com");
response.End();

You may have noticed that, unlike the title of this blog post, I did not use a URL rewrite. HTTP 301 (and 302) redirects are HTTP Response Codes that are returned to the client browser, and the client then requests the new URL. A URL Rewrite leaves the original URL in place, and renders a different page instead, without visibility to the client browser or end-user. If I were to URL rewrite my blog from page1.aspx to page2.aspx, the URL in your address bar would still list page1.aspx, even though the content was from page2.aspx. The end-user (and the search engine) never know about the URL for page2.aspx. However, with a HTTP redirect, the content and the address bar would both be page2.aspx.

I ran through Google to see if anyone had solved this problem in the past. I came across a Scott Hanselman post on HTTP 301, which mentions a fantastic drop-in redirect module by Fritz Onion. I was elated when I found this module, and it was very easy to implement. Drop the assembly into your application's bin, add a few lines into the web.config, and enjoy redirection bliss. The module also supports both HTTP 302 and HTTP 301 redirects through the "permanent" attribute in the redirection rules.

<?xml version="1.0"?>
<configuration>
  <configSections>
    <section name="redirections"
      type="Pluralsight.Website.XmlSerializerSectionHandler, redirectmodule" />
  </configSections>
  <!-- Redirect Rules -->
  <redirections type="Pluralsight.Website.redirections, redirectmodule">
    <!-- Wordpress Post Redirects //-->
    <add targetUrl="/default\.aspx\?p=86"
      destinationUrl="/2007/09/22/ManagingMultipleEnvironmentConfigurationsThroughNAnt.aspx"
      permanent="true" />
    <add targetUrl="/default\.aspx\?p=74"
      destinationUrl="/2007/02/09/Flash8DepthManagerBaffledByThoseWithoutDepth.aspx"
      permanent="true" />
    <add targetUrl="/default\.aspx\?p=72"
      destinationUrl="/2006/10/20/IE7Released.aspx"
      permanent="true" />
    <add targetUrl="/default\.aspx\?p=70"
      destinationUrl="/2006/10/17/ClearingFlashIDEWSDLCache.aspx"
      permanent="true" />
    <add targetUrl="/default\.aspx\?p=69"
      destinationUrl="/2006/10/10/CruiseControlNetV11ReleasedOct1.aspx"
      permanent="true" />

    <!-- ...More Redirects -->
  </redirections>
  <system.web>
    <httpModules>
      <add name="RedirectModule"
        type="Pluralsight.Website.RedirectModule, redirectmodule" />
    </httpModules>
  </system.web>
</configuration>

The entire implementation took only a few minutes. It seemed like it took longer to upload the changes to the blog than it did to make the local edits. The solution is also very clean, as it required no modification to the existing application beyond integrating the configuration blocks into the web.config. Blog traffic will now seamlessly redirect from links that use the old WordPress URL to post that use the new DasBlog URL. Search Engines also update their links, and the page ranking for each post isn't lost into the ether just because the URL changed. All is well with the world, again.

Next up: Part 3. URL redirection also plays a role in Search Engine Optimization. In Part 3, I will go over some ways that you can use HTTP redirects to improve your search engine listings, as well as discuss some improvements I made to Fritz Onion's redirect module in the name of SEO.

URL Rewrite

Technorati Tags: ,,
Tuesday, 11 November 2008 12:36:34 (Eastern Standard Time, UTC-05:00)  #    Comments [0] - Trackback

Filed under: ASP.Net | Programming

A few months ago I switched my blogging engine from WordPress to DasBlog. Though I do feel that WordPress is a more mature engine, with a more robust feature set and a better plug-in community, I wanted a site that was built on .NET. Being a .NET developer, I wanted something I could tinker with,  modify, and adjust to my liking.

Redirecting WordPress URL Format to DasBlog

One of the pain points of the switch was with the differences in how the two blogging engines generated their URLs. As an example, my post on the Collapse All macro for the Visual Studio Solution Explorer, originally written in WordPress, went from a URL of cptloadtest.com/?p=56 to cptloadtest.com/2006/05/31/VSNetMacroCollapseAll.aspx. A few sites, such as Chinhdo.com, link to the post's old URL, which without effort to put a redirect in place would return HTTP 404: File Not Found under the new engine.

Enter URL redirects. I needed a way to translate one URL into another. More specifically, since WordPress retrieves all of its posts by query string (using the 'p' key), I needed to translate a specific query string key/value pair into a URL. But, I didn't want to have to recompile any code.

There are a view client-side redirecting options available:

Meta Refresh

<meta http-equiv="refresh" content="0;url=http://www.cptloadtest.com/">

The Old-School HTML way of redirecting a page. Nothing but HTML is needed. Only access to the base HTML page is required. Place the above HTML within your <HEAD> tag, reformatting the content value with "X;url=myURL", where X is the number of seconds to wait before initiating the redirect, and myURL is the destination URL. Any browsers will obey Meta-Refresh, regardless of JavaScript's enabled setting, but the simple implementation brings with it simple features. Meta-Refresh will redirect any request the page, regardless of the query string, and there is no simple way to enable it only for the specific key/value query string pair. Because all WordPress requests are to the domain root--a single page--and referenced by query string, this would not work for my needs. If the old request was instead to a unique former page, such as /post56.html, I could go create a new copy of post56.html as just a stub, and have each page Meta-Refresh to the post's new location. But even if this did apply, it's too much work to create 56 stub pages for 56 former posts.

JavaScript Redirect

<script type="text/javascript">
<!--
window.location = "http://www.cptloadtest.com/"
//-->
</script>

This one requires JavaScript to work. Since the query string is on the domain root, the request is serving up Default.aspx and applying the query string to it. DasBlog doesn't observe the "p" query string key, so it will not perform any action against it, but the query string is still available to client-side scripts. I can add JavaScript code to perform regular expression matches on the URL (window.location), and upon match rewrite the old URL to the new and redirect. It's relatively simple to create new match patterns for each of my 56 posts, and I can place all of my new client-side code atop Default.aspx.

var oldPath = "/?p=56";
var newPath = "/2006/05/31/VSNetMacroCollapseAll.aspx";
if (document.URL.indexOf(oldPath) > 0)
{
  window.location.replace(document.URL.replace(oldPath, newPath));
}

However, since the patterns are in client-side code, they are visible to end-users who view source. Users will also see page-flicker, as the Default.aspx is served up using the old URL, only to be redirected and refreshed under the new URL; a side-effect of downloading the page twice is that my bandwidth is also doubled for that single request, since users downloaded the page twice.

What it all means

All of the options above result in functionality similar a HTTP 302, otherwise known as a Temporary Redirect. This class of redirect is meant for simple forwarding or consolidation that is either of temporary nature or part of intended functional implementation. An example of where this would be used is if after one page is finished processing, another should be returned, such as if authentication is complete on a login page and the client should be redirected to a home page or landing page. With a 302, the original page is still a valid page, and users should still go to it in the future, but under certain scenarios there is an alternate page should be used.

The alternative to a 302 is a HTTP 301, otherwise known as Moved or a Permanent Redirect. The 301 is for files which have permanently changed locations and come with an implied "please update your links" notice. The HTTP 301 is ultimately what I was looking for. cptloadtest.com/?p=56 is a defunct URL that will never again see light of day; users, web sites, and (most importantly) search engines should update their references to the new DasBlog format of the post's URL. Client-side coding doesn't have the ability to create an HTTP 301, so it was beginning to look like I may either have to modify DasBlog code to get my 301s or live without. But, I found a way; this site now has all of the 301 goodness I craved, while keeping the DasBlog code pure.

It's all about HTTP Modules.

In Part 2, I will go over how to use HTTP Modules to implement both HTTP 301 and HTTP 302 redirects, all with simply dropping a file into your application bin and adding a new section to your web.config. No compile required.

URL Rewrite

Technorati Tags: ,
Thursday, 06 November 2008 10:01:33 (Eastern Standard Time, UTC-05:00)  #    Comments [1] - Trackback