### One Thing Led to Another …

#### Update (2/15/2007):

My branch of Instiki has its own website, now.I was entering some of the notes, into the wiki, of the discussions with my collaborators, when Instiki more-or-less ground to a halt. Turns out that Ruby is *really slow* at string-manipulation and Regexp-based BlueCloth just can’t handle any remotely complicated input. I wrote a rant about it and a commenter suggested Maruku as an alternative Markdown implementation.

So I wrote the author, asking if he would make some changes that would be required to integrate itex2MML with Maruku. He was more than eager and, over the course of a few days, made all the changes I asked for, *and then some*.

He implemented automatic equation-numbering and cross-referencing, a quite serviceable LaTeX output and lots of other goodies.

All I had to do was roll his work in with my tweaks to Instiki. You can see the result in my BZR repository, or just download the tarball, follow the instructions in my previous entry and have a MathML-enabled Wiki up and running in minutes. My BZR repository is a branch of the main Instiki BZR repository. We’re talking bleeding-edge software^{1}. Still, it’s the version I’m using, and it seems pretty solid^{2}. I’ve included the latest development version of Maruku, so the only external dependency is the itex2MML Ruby bindings.

The result is pretty fast (Maruku parses the input, and relies on REXML, rather than string manipulation.) And Maruku incorporates some very nice extensions to the standard Markdown syntax. For instance, here’s the table that caused BlueCloth to cough up a hairball, redone in the extended Markdown table syntax:

{:r: scope="row"}

$j$|$0$|$1$|$2$|$3$|$4$|$5$|$6$|$7$|$8$ --:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:| {:r}$C\ell_{j}^-$|$\mathbb{R}$|$\mathbb{C}$|$\mathbb{H}$|$\mathbb{H}\oplus\mathbb{H}$|$\mathbb{H}(2)$|$\mathbb{C}(4)$|$\mathbb{R}(8)$|$\mathbb{R}(8)\oplus\mathbb{R}(8)$|$\mathbb{R}(16)$ {:r}$C\ell_{j}^+$|$\mathbb{R}$|$\mathbb{R}\oplus\mathbb{R}$|$\mathbb{R}(2)$|$\mathbb{C}(2)$|$\mathbb{H}(2)$|$\mathbb{H}(2)\oplus\mathbb{H}(2)$|$\mathbb{H}(4)$|$\mathbb{C}(8)$|$\mathbb{R}(16)$ {: class="plaintable" style="text-align:center;margin-left:0;" summary="The Clifford Algebras"}

Here’s the XHTML+MathML output:

$j$ | $0$ | $1$ | $2$ | $3$ | $4$ | $5$ | $6$ | $7$ | $8$ |
---|---|---|---|---|---|---|---|---|---|

$C{\ell}_{j}^{-}$ | $\mathbb{R}$ | $\u2102$ | $\mathbb{H}$ | $\mathbb{H}\oplus \mathbb{H}$ | $\mathbb{H}(2)$ | $\u2102(4)$ | $\mathbb{R}(8)$ | $\mathbb{R}(8)\oplus \mathbb{R}(8)$ | $\mathbb{R}(16)$ |

$C{\ell}_{j}^{+}$ | $\mathbb{R}$ | $\mathbb{R}\oplus \mathbb{R}$ | $\mathbb{R}(2)$ | $\u2102(2)$ | $\mathbb{H}(2)$ | $\mathbb{H}(2)\oplus \mathbb{H}(2)$ | $\mathbb{H}(4)$ | $\u2102(8)$ | $\mathbb{R}(16)$ |

and here’s the LaTeX output

\begin{tabular}{r|c|c|c|c|c|c|c|c|c} $j$&$0$&$1$&$2$&$3$&$4$&$5$&$6$&$7$&$8$\\ \hline $C\ell_{j}^-$&$\mathbb{R}$&$\mathbb{C}$&$\mathbb{H}$&$\mathbb{H}\oplus\mathbb{H}$&$\mathbb{H}(2)$&$\mathbb{C}(4)$&$\mathbb{R}(8)$&$\mathbb{R}(8)\oplus\mathbb{R}(8)$&$\mathbb{R}(16)$\\ $C\ell_{j}^+$&$\mathbb{R}$&$\mathbb{R}\oplus\mathbb{R}$&$\mathbb{R}(2)$&$\mathbb{C}(2)$&$\mathbb{H}(2)$&$\mathbb{H}(2)\oplus\mathbb{H}(2)$&$\mathbb{H}(4)$&$\mathbb{C}(8)$&$\mathbb{R}(16)$\\ \end{tabular}

Nifty, huh?

But the automatic equation-numbering and cross-referencing really got to me. I wanted it **here**, too. So I revised the MovableType itex2MML plugin to provide it.

As before, $$…$$ produces an un-numbered equation. Previously, \[…\] was synonymous with $$…$$. Now, it produces consecutively numbered equations. Optionally, you can supply a label, \[…\label{foo}…\], and then refer to the equation as (eq:foo) or \eqref{foo}. These automagically becomes hyperlinks to the equation.

The effect is achieved by a little preprocessing before handing the content off to the itex2MML binary.

So here’s the new version of the plugin, which I’ve now bundled with the Textile+itex2MML/Markdown+itex2MML plugin.

To get the equation hyperlinking to work in comments, I needed a one-character tweak to `lib/MT/Sanitize.pm`

`--- lib/MT/Sanitize.pm.orig 2006-09-21 20:26:59.000000000 -0500 +++ lib/MT/Sanitize.pm 2007-01-15 17:06:57.000000000 -0600 @@ -112,7 +112,7 @@ if ((my $prot) = $dec_val =~ m/^(.+?):/) { next if $prot =~ m/[\r\n\t]/; $prot =~ s/\s+//gs; - next if $prot =~ m/[^a-zA-Z0-9\+]/; + next if $prot =~ m/[^a-zA-Z0-9\+#]/; next if $prot =~ m/script$/i; next if $prot =~ m/&#/; }`

Oh yeah, then I had to go and revise the corresponding plugins for ecto…

#### Update (1/22/2007): Internet Explorer

Today, I quite innocently created a Wiki page for my class. Much to my bemusement, I discovered that UT Business School students don’t *all* use Firefox (or some other modern browser). It seemed that I would have to do some content-negotiation instead of sending `application/xhtml+xml`

to *everyone*.

Rails 1.1.x has support for content-negotiation^{3}. So I created a new BZR branch, based on the current Instiki SVN. This branch (and the corresponding tarball) is the one I’m going to try to maintain. It now does content-negotiation.

The branch based on the moribund Instiki BZR repository will remain for historical interest.

#### Update (2/9/2007): XHTMLDiff

The “Show Changes” function, which is supposed to generate a redline document, marking up changes between successive versions of a wiki page was more-or-less brain-dead. I replaced it with xhtmldiff, which generates well-formed XHTML redline documents.

^{1} Hmmm. Well, maybe not *quite* bleeding edge. Instiki’s BZR Branches no longer seem to be synced with their SVN repository.

^{2} If you want to play around with it, I’d suggest setting yourself up with BZR. Even if you don’t think you want tinker with the software, doing a `bzr pull`

is an easy way to get incremental updates.

^{3} Support, but broken support. The solution is to override the default behaviour

`module Mime # Fix HTML #HTML = Type.new "text/html", :html, %w( application/xhtml+xml ) HTML = Type.new "text/html", :html`

# Add XHTML XHTML = Type.new "application/xhtml+xml", :xhtml

# Fix xhtml and html lookups LOOKUP["text/html"] = HTML LOOKUP["application/xhtml+xml"] = XHTML end

and then write things like

`if @request.env['HTTP_USER_AGENT'] =~ /MathPlayer|Validator/ or Mime::Type.parse(@request.env["HTTP_ACCEPT"]).include?(Mime::XHTML) ... else ... end`

## Re: One Thing Led to Another …

Shiny!