Extending RedCloth
[latex]\LaTeX{}[/latex] is the permier typesetting tool of the engineering and math world. It allows you to create beautifully typeset mathematical documents with a minimal learning curve. So why would you care about this on the web? Well for one, there really is no way to typset math in a browser. Sure there is MathML but that is supported by only a few browsers nativly, most will require a plugin (if even available).
So how should one go about doing this, ensuring that the math formulas will be seen by the widest possible auidence? Use images! Every browser can render an image, so if we are able to take the LaTeX and render it as an image, we will be set. This is exactly the approach taked by LatexRender, a set of scripts for rendering LaTeX in php programs. Unfortunatly, as far as I know, there is not drop in solution for Ruby.
However, there were a few projects that pointed me in the right direction. Most noteable was redsymbols l2p Perl script and the afformentioned LatexRender. I have already done the hard stuff for you and put it up on my GitHub repository.
$> git clone git://github.com/mpetnuch/latex-renderer.git vendor/plugins/latex_render
You also need to make sure that you have the RedCloth Ruby Gem and a LaTeX package for the Latex Render plugin installed. Next we need to write our own custom RedCloth. I am going to call it Washcloth since it is cleaning up the site. Create a new file called washcloth.rb in your projects lib directory with the following contents:
class Washcloth < RedCloth LATEX_START_CODE = /\[latex\]/i LATEX_END_CODE = /\[\/latex\]/i LATEX_RE = /\[latex\](.*)\[\/latex\]/i RULES = [:block_textile_table, :block_textile_lists, :block_textile_prefix, :inline_textile_image, :inline_latex, :inline_textile_link, :inline_textile_code, :inline_textile_span, :glyphs_textile] def inline_latex( text ) # Don't do anything unless we have same number of start/end tags if text.scan(LATEX_START_CODE).size == text.scan(LATEX_END_CODE).size text.gsub!( LATEX_RE ) do |m| latex = LatexRenderer.new latex.formula = $1 begin filename = latex.process md5 = latex.md5hash # if the processing was successful we just display the rendered image sprintf '<img src="%s" alt="latex image" />', filename.gsub(/.*?\/images/, '/images') rescue => e sprintf('%s', latex.formula) end end end end def to_html super(*RULES) end end
Let’s test it out. Fire up the console:
>> latex = '[latex]x^2 + y^2 = z^2[/latex]' => "[latex]x^2 + y^2 = z^2[/latex]" >> r = WashCloth.new latex => "[latex]x^2 + y^2 = z^2[/latex]" >> r.to_html => "<p><img src="/images/latex/image.png" /></p>"
So we see that our [latex]\LaTeX{}[/latex] is replaced with a link to a rendered image of the code. All that is left is to replace any instance of RedCloth in your program with WashCloth and it will automatically render the LaTeX in your views. What if you use something like Err the Blog’s acts_as_textiled? You going to have to edit the plugins source and change RedCloth to WashCloth, but that’s it! So what have we accomplished? We can now render latex commands inline with our Textiled HTML. For instance, the following command:
[latex]
$$\Gamma(s) \zeta(s) =
\int_0^{\infty} \frac{x^{s-1}e^{-x}}{1-e^{-x}}\,dx$$
[/latex]
Will render as: [latex]$$\Gamma(s) \zeta(s) = \int_0^{\infty} \frac{x^{s-1}e^{-x}}{1-e^{-x}}\,dx$$[/latex]


