MultiMarkdown Apache handler.

| 1 Comment | 1 TrackBack

The "What?" and the "Why?"

I've been a fan of the MultiMarkdown for quite a while now. I keep all of my important notes in this format, which is easy to write with just a simple text editor.

I wanted to be able to copy or sync my *.mark files to my web server and have them automatically be rendered as XHTML. I looked into a couple of ways of doing this. One of which is the Text::MultiMarkdown::ApacheHandler Perl module Apache handler. The downside is that this handler doesn't work out of the box in Apache2.2.

Read on to see my solution. I've also seen a cgi based apache handler done by reppep as chronicled here. The only problem is that he's using the original Markdown. I've long been a fan of the extended syntax, and output formats I can get from MultiMarkdown. So I've build a similar script to what reppep has done.

The "How?"


You'll need at least these Perl modules installed on your system.

  • File::Slurp
  • CGI
  • Text::MultiMarkdown

You'll also need Apache and mod_cgi installed.

The script

The CGI script I use is pretty straightforward. Here it is in it's entirety:

use warnings;
use strict;
use CGI qw/:standard/;
use Text::MultiMarkdown qw/markdown/;
use File::Slurp qw/slurp/;

my $text = slurp($file);
my $mark;
if (param('_text')) {
  print header('text/plain');
  print $text;
} else {
  print header;
  $text .= "\n\n[See the Source](?_text=1)\n\n";
  if (param('_partial')) {
    ##TODO test for Format: complete header and warn
    my @lines = split /\n/, $text;
    if (@lines = grep (!/^([Ff][Oo][Rr][Mm][Aa][Tt]):\s*(.*)$/, @lines)) {
       print "<h4>Overriding metadata to generate partial XHTML</h4>\n";
    $text = join("\n",@lines);
    $mark = markdown($text);
  } else {
    $mark = markdown($text, {
      document_format => 'complete'
  print $mark;

=head1 Name


A simple cgi script which is used as an action handler for the Apache HTTP

=head1 USAGE

Place this file into your cgi-bin directory and add a stanza like this to

    Action markdown /cgi-bin/
    AddHandler markdown .mark
    AddType text/html .mark

Now any MultiMarkdown file you serve which has the extenstion .mark will
automatically get rendered as xhtml.

This script will honor all of the metadata you place in your markdown file
with the exception of the Format: header which is always assumed to be 


You can override the default actions of this script by passing some
parameters encoded into the URL.

=head2 TEXT

Pass a parameter of _text=1 to get the raw MultiMarkdown file.

=head2 PARTIAL

To override the default action of rendering an entire XHTML file, pass a
parameter of _partial=1 to get just the partial XHTML.

This will override any Format: headers in your source MultiMarkdown file.
And the default format of the handler (which is complete).

Place this script into your cgi-bin directory and make sure it's executable by your web server's process. I named mine Here's a downloadable link of

The config

To make your new script do exactly what you want it to (render *.mark files as XHTML to the browser), you'll need to modify your Apache config. I placed this config section into a file named /etc/httpd/conf.d/multimarkdown.conf

Action markdown /cgi-bin/
AddHandler markdown .mark
AddType text/html .mark


Make sure your Apache configs are proper by running the command apachectl configtest. If all checks ok, you should be good to restart your Apache server, upload a MultiMarkdown-formatted file to your web server with the extension of *.mark, and see it rendered in it's full XHTML glory.

You can see examples of how this MultiMarkdown handler works by clicking on the links below.

Presentation on presentations

After action report from my presentation

As you have probably noticed, there is a "See the source" link on each rendered page. This is part of the CGI script I created. Add the parameter _text=1 to the url and the handler passes the MultiMarkdown source file straight to the client without any rendering, like so.

I hope you enjoy the simplicity of editing decent web documents in a simple format.

Next time I'll share how I keep all of my files in sync using Bazaar-ng and bzr-push-and-update.

1 TrackBack

TrackBack URL:

Daringfireball Links from iLinkShare (Web 2.0 linksharing) on October 11, 2008 3:48 AM

Tagged your site as daringfireball at iLinkShare! Read More