I was writing my first technical post (about asp.net MVC) and I realized that I had no way to display code snippets properly. It's inadmissible for a programming blog to not have that kind of feature. I started looking for a tool and I quickly found SyntaxHighlighter, an open-source product written in javascript and widely used on the Net. Documentation is clear and installation seems simple. It has been a little more complex that advertised but I've been able to integrate it in BE.Net with a little work.
Download SyntaxHighlighter
By going to the "official" site, we can download version 1.5. But, on the author personal site, we can download the new 2.0 version. I choose this one. The package contains some css and javascripts required for that tool to work properly. To get the formatting, you just have to wrap your code in a <PRE> tag with a class corresponding to the language to display. Ex :
<pre class="brush: html;">
<b>bold text</b>
</pre>
The scripts work very well, it's when you try to include it in BE.NET that the fun begins ! BE.Net use many URL rewriting rules, so it's difficult to refer the script relatively to the current page so we must do the reference to the application root. The first replex is to put runat="server" on the scripts and to use tilde (˜) to translate to the application root. Unfortunately, it doesn't work because with that tag, the javascript code is evaluated by the compiler and some of the code in SH have errors (or at least, synx that VS2008 doesn't like. I also tried to integrate so code into the markup (ex: <%= SiteRoot() %>/Scripts/shcore.js) but it doesn't work either because BE.Net tried to add Meta tags at runtime, throwing this exception.
I finally rely on the ScriptManager, that help for 2 things : I can refer my scripts using the tilde (˜) now that it's a server control and I can at the same time combine my scripts for better performance.
<asp:ScriptManager ID="ScriptManager1" runat="server">
<CompositeScript>
<Scripts>
<asp:ScriptReference Path="~/Scripts/shCore.js"/>
<asp:ScriptReference Path="~/Scripts/shBrushBash.js"/>
<asp:ScriptReference Path="~/Scripts/shBrushCpp.js"/>
<asp:ScriptReference Path="~/Scripts/shBrushCSharp.js"/>
<asp:ScriptReference Path="~/Scripts/shBrushCss.js"/>
<asp:ScriptReference Path="~/Scripts/shBrushDelphi.js"/>
<asp:ScriptReference Path="~/Scripts/shBrushDiff.js"/>
<asp:ScriptReference Path="~/Scripts/shBrushJava.js"/>
<asp:ScriptReference Path="~/Scripts/shBrushJScript.js"/>
<asp:ScriptReference Path="~/Scripts/shBrushPlain.js"/>
<asp:ScriptReference Path="~/Scripts/shBrushPython.js"/>
<asp:ScriptReference Path="~/Scripts/shBrushRuby.js"/>
<asp:ScriptReference Path="~/Scripts/shBrushPerl.js"/>
<asp:ScriptReference Path="~/Scripts/shBrushSql.js"/>
<asp:ScriptReference Path="~/Scripts/shBrushVb.js"/>
<asp:ScriptReference Path="~/Scripts/shBrushXml.js"/>
<asp:ScriptReference Path="~/Scripts/shBrushJavaFX.js"/>
<asp:ScriptReference Path="~/Scripts/shBrushPowerShell.js"/>
</Scripts>
</CompositeScript>
</asp:ScriptManager>
The drawback of using the ScriptManager is that my implementation of BE.Net isn't totally comptible with .Net 2.0 anymore but how cares, .Net 4 is about to be release so we must live in the present so welcome .Net 3.5 !
Integration into the blog editor
BE.Net 1.5 useTinyMCE 3 to edit blog posts. The editor has a WYSIWYG mode but also an HTML mode. It's possible to generate the required markup to integrate code into posts but somes opertions still highly manual and error prone like convert special characters, configuring options, etc. So I ask Google and I found someone has already solve that problem and developped a plugin SyntaxHighlighter for Tiny MCE. It wasn't working at first but just a little tweeking and we're done ! Also, the character encoding wasn't done properly but a little search in StackOverflow and everything is all right.
function Save_Button_onclick() {
var lang = document.getElementById("ProgrammingLanguages").value;
var code = WrapCode(lang);
code = code + HtmlEncode(document.getElementById("CodeArea").value);
code = code + "</pre> "
if (document.getElementById("CodeArea").value == '') {
tinyMCEPopup.close();
return false;
}
tinyMCEPopup.execCommand('mceInsertContent', false, code);
tinyMCEPopup.close();
}
function HtmlEncode(s) {
var el = document.createElement("div");
el.innerText = el.textContent = s;
s = el.innerHTML;
delete el;
return s;
}
Good ! Eveything works and now that I finishing reading Professional ASP.NET MVC 1.0, I've many ideas to explore and share with you.
See you next time