I've written a couple articles for TidBITS since they started using John Gruber's Markdown format, and despite actually liking HTML as a writing format, I was impressed with Markdown's simplicity and efficiency (no <p>s are a big time savings!).

So I installed PHP Markdown Extra here on Extra Pepperoni, and got hooked on writing in Markdown. Unfortunately, there's no Markdown plug-in for plain Apache -- lots of ways to parse Markdown in your blogging software or wiki or CMS, but I want to be able to write a .text file and serve it up 'directly' from Apache on www.reppep.com.

Update: Markdown.cgi has been updated. Check my Markdown category for the latest.

Markdown is designed to run as a simple filter, so it's well suited to drop-in installation in a lot of places, without having to build customized versions for a particular application's APIs. There are several implementations -- the original Perl script, as well as versions in PHP (which I use in WordPress, slightly hacked), Python, Ruby, JavaScript, etc. http://markdown.infogami.com/ keeps a list.

Since I couldn't find an Apache handler (plug-in) or a CGI for Markdown, I wrote a very simple wrapper for Gruber's Markdown.pl. Conceptually, my wrapper spits out an HTML header, uses Markdown.pl to render the requested page as (X)HTML, and then appends an (X)HTML footer. The reality is slightly more complicated, due to the vagaries of figuring out the document's title, and conditionally inserting it back into the output as an <H1> tag. Even so, the whole thing is under 60 lines, mostly whitespace and comments.

Markdown.cgi also solves a problem which has wasted a significant amount of my time. BBEdit's built-in Preview tool can use Markdown.pl to generate HTML, which it then passes to WebKit for previewing in a formatted window. But if you put the pages on a real active website, BBEdit has another feature I really like, whereby it will actually calculate a live URL for the page to be previewed, request that URL from the web server, and preview that instead.

This is great, but if you're writing Markdown, BBEdit shows you the unrendered Markdown code (as served up by the web server), instead of rendering the Markdown file from disk. To make matters worse, BBEdit's Preview is live in real time, but continuously re-rendering a Markdown document as you type makes BBEdit stall badly on my 1.5GHz PBG4, so I've stopped using it as a live preview. I instead trained myself to use Markdown.pl as a UNIX script, which I manually trigger to generate a temporary HTML document. I then view this document in BBEdit's live Preview. Among other things, I frequently found myself editing the scratch HTML document, and having to copy my changes back to the Markdown source. Yuck.

Now that my web servers can serve up Markdown .text documents in HTML format, I can skip that whole mess, and go back to previewing .text documents (using Safari or BBEdit's live Preview) with server-side HTML conversion, seeing exactly what surfers see, as Siegel intended.

Tip: If you're reading about or trying out Markdown, don't read the syntax page -- skip to the simple crib sheet on the Dingus page. It's much simpler (and shorter!).


To implement this, I added some lines to my Apache httpd (1.3) configuration, inside the main vhost block:

Action markdown /cgi-bin/Markdown.cgi
AddHandler markdown .text
AddType text/html .text
ScriptAlias /cgi-bin/ /home/web/www.reppep.com/cgi-bin/
AddType text/html .pl

Here is Markdown.cgi, although I had to rename this copy Markdown.txt so you can download it:

#!/bin/sh
# Markdown v1.1.1 2007/05/24
# Build an HTML page (with headers) from Markdown.pl output.

INCLUDES=/home/web/www.reppep.com/include
TITLE=`head -1 $PATH_TRANSLATED | cut -f2`
echo "Content-type: text/html"
echo

cat $INCLUDES/head1.incl
echo $TITLE
cat $INCLUDES/head2.incl

# If we already have an H1, don't insert one.
if ! grep --silent '^# ' $PATH_TRANSLATED
 then
  echo -n '<h1>'
  echo -n $TITLE
  echo '</h1>'
  echo
fi

/usr/local/bin/Markdown.pl < $PATH_TRANSLATED

cat $INCLUDES/foot.incl

exit 0

# http://www.extrapepperoni.com/2007/05/24/markdowncgi-using-markdown-in-apache-httpd/
# http://daringfireball.net/projects/markdown/

# To use, copy Markdown.cgi (this wrapper, which you may have to rename
# from Markdown.txt) and Markdown.pl (from Daring Fireball) into your
# cgi-bin/ and make them executable
# ("chmod +x Markdown.cgi Markdown.pl"), set the correct path for
# INCLUDES below, and install head1.incl (HTML header up to <title>),
# head2.incl (HTML header starting with </title>), and foot.incl in
# that directory.

# Markdown.cgi reads the page's title from the first line, starting
# after the first tab and ending before the second.
# Your document's title should be inside an HTML comment, set off by tabs.
# The title line contains 5 parts:
# 1) the HTML comment open delimiter (less-bang-dash-dash)
# 2) a tab
# 3) the title text
# 4) a tab
# 5) the HTML comment close delimiter (dash-dash-greater)
# For example (not counting the # on the next line):
#<!--   Markdown.cgi: A Simple Wrapper for Markdown.pl  -->

# Add the following to your Apache httpd configuration
# (likely httpd.conf or a virtual host .conf file):
#   AddHandler markdown .text
#   Action markdown /cgi-bin/Markdown.cgi
#   AddType text/html .text
#   ScriptAlias /cgi-bin/ /home/web/www.reppep.com/cgi-bin/
#   AddType text/html .pl

My header and footer are dead simple, but easy to replace with something more sophisticated.

head1.incl:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>

head2.incl:

    </title>
    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
</head>
<body>

foot.incl:

<hr />

<p align="center"><small><a href="./">home</a></small></p>

</body>
</html>