Posting Syntax-Highlighted Code to the Web
Awhile back I noted some ways to copy syntax-highlighted text from TextMate to other applications like VoodooPad and MarsEdit. In some cases it was a simple procedure of two or three steps. But getting syntax-highlighted text into MarsEdit was comparatively tedious.
In all cases the procedure started with the Experimental -> View Document as HTML
bundle. This morning I finally got around to browsing that bundle's definition and lo! it's just a simple Perl script invocation.
Better yet, it can act on either a complete document or just the text you've selected within that document. So if you want to post a code snippet? No problem.
It's also easy to make a copy of the bundle which, instead of creating a new HTML document, creates a plaintext document containing the HTML mark-up. You can copy the contents of this document and paste it directly into MarsEdit. (With a few caveats, i.e. you need to modify the stylesheet to avoid affecting the appearance of your entire post.)
The steps are simple:
- Select
Bundles->Bundle Editor->Show Bundle Editor...
- Browse into
Experimental
and select theView Document as HTML
command - Click the "double-plus" button at the bottom of the window to make a copy of the command
- Drag the command to some other bundle. I like to keep custom snippets, commands and templates in an
@My Stuff
bundle, which won't get overwritten when I upgrade TextMate - Select the copied command. Rename it as you see fit, e.g.
Format as Raw HTML
- Change the
Output
popup menu's value fromShow as HTML
toCreate New Document
That's it! Now you can select some code which you want to post, select your new command from the Bundles menu, and get a window with (almost) ready-to-post HTML markup.
Next Steps
Keyboard Navigation
If you come from (X)Emacs and wish you could invoke the bundle without having to navigate through a menu hierarchy, you can. Just use Control-Command-T to bring up the
Select Bundle Item
command window. Then type in the name of your new command, and hit return.If you want to feel even more at home you can give your bundle a name which "feels like" an Emacs command. I've been trying single-word "command name" prefixes, like "rawhtml - Format as Raw HTML". The idea is to give your command both a quick-to-type "command" name, so you can get to it quickly in the command window, and a human-readable name so you can remember what it does :)
Limiting the Scope of the Styling
I haven't had time to do further customizations to the command. The next thing to tackle will be the stylesheet which it generates -- it's written to address an entire document, so it applies styles to e.g. the body element. I'd like to customize the generated HTML so it puts everything into a
<div>
with a unique timestamp for its id, and to modify the CSS so it applies only to that div. That'll make it easier to create markup that can be dumped directly into a blog regardless of what else might be on the blog page.Update:
Turns out it was easy to modify the generated styesheet, and to wrap the output in a timestamped div. I'm not sure how righteous it is to include a
<style>
block inside the body of a blog post, rather than the head, but it renders okay in WebKit and Firefox 2.Here's the source code for the command, as rendered by itself :)
#!/bin/sh
now=`date +'%Y%m%d%H%M%S'`
cat <<HTML
<style type="text/css">
.comment
.keyword
.string
.entity
.storage
.support
.constant, #source_$ .variable
</style>
HTML
perl -pe 's/<\/[^>]+>/<\/span>/g' \
| perl -pe 's/<([^\/.>]+)[^>]*>/<span class="$1">/g' \
| perl -pe 's/\t/ /g'
echo "</div></div>"