Modifications to WP-Syntax for better ActionScript Code Highlighting Functionality

Posted on March 10, 2009 by:
Robert M. Hall, II in Flash
I finally got around to implementing a decent Syntax highlighter for code on my site. I looked at a number of different projects, and none of them had exactly all the features I wanted, so I went with WP-Syntax by Ryan McGeary available here: http://ryan.mcgeary.org/wp-syntax/ which in turn is based on GeSHi (Generic Syntax Highlighter) available here: http://qbnz.com/highlighter/
I liked how Ryan handled the line numbering on the left, but it was missing a nice way to quickly view the code in plain text, copy the code to your clipboard, or save it directly as a download. Several of the other solutions had features like that in the top header of the code, and I liked that, so I quickly hacked in support for that. The show in plain text icon simply leverages the built in thickbox.js built into WordPress and some JavaScript to get that done I quickly shoehorned that in. The other two icons for copy to clipboard and download and save were done through Flash. I leveraged the System.setClipboard() function to quickly push the code onto the users clipboard, as well as externalInterface to pass back a success notification to the browser and end user.
For the file download and save code, I was going to use AS3 and the filereference.download feature, and javascript to parse the code out of the page, and then download it directly to the users system with a standard OS dialog – but it was late and I didn’t feel like spending the time to parse the innerHTML with JS before passing it in to Flash – so I cheated and just pass it all in as a urlencoded Flashvar, and then do a roundtrip to my server with the code as POST data, and then leverage the filereference.download feature of Flash 8 AS 2.0 to accomplish what looks like the identical behavior. I’ll probably go back and clean this up and redo it the right way with AS3 so I don’t have to make that server trip, but I’ll save that for another day. The current version is smart enough to know when ActionScript is the language and automatically set the default filename extension to .as – and it also broadcasts a little download complete to the browser via externalInterface when things are complete, so its 99% of what I wanted and also nearly 100% compatible with most users installs of Flash. The tiny nature of the size of the SWF doesn’t lend itself to even using the Express Install feature of Flash 6+ to upgrade to 9, so think this was a good compromise, although I already have a workaround for that as well, with a self-resizing DIV and SWF combo.
I would also like to clean things up a bit more including making some more XHTML friendly changes to the html output and then submit my changes to Ryan for inclusion in a future version, as it would probably be too much ongoing work to make and then maintain a plugin that patches his plugin. Anyway, below is a quick sample of the output with a handy little contrain/resizing function I use often. Including some basic CSS adjustments to give alternating background colors on the lines (it looks decent in Safari at default text settings, but I have to put in some conditional CSS tweaks for other browsers to get the alternating line colors to line up better) – at least I now have a solution I like for posting code snippets. If anyone wants to get the source for this and hack away at it yourself, let me know and maybe I’ll bundle things up as they stand now and someone else can refine things a bit further, its really only some changes to the main wp-synax.php file, a dependency on SWFObject 2.1, and the custom little Flash widget I put together.
// AS3 example function to constrain an object's width/height proportionally with a given objects new targeted dimensions with optional rounding
function reSize (originalSize:Object, targetConstraints:Object, round:Boolean):Object {
var scaleFactor:Number = Math.min( (targetConstraints.width / originalSize.width), (targetConstraints.height / originalSize.height) );
var newSize:Object = new Object ;
newSize.width = round ? Math.round(scaleFactor * originalSize.width) : (scaleFactor * originalSize.width);
newSize.height = round ? Math.round(scaleFactor * originalSize.height) : (scaleFactor * originalSize.height);
return newSize;
}
var obj = new Object;
obj.width = 800;
obj.height = 600;
var newObj = new Object;
newObj.width = 640;
newObj.height = 500;
var objTarg:Object = reSize(obj, newObj, true);
trace (objTarg.width+"x"+objTarg.height);