liamoc / latex-formulae

Libraries and tools for rendering math to images using real LaTeX, from Haskell, Pandoc and Hakyll
BSD 3-Clause "New" or "Revised" License
56 stars 6 forks source link

[[https://travis-ci.org/liamoc/latex-formulae][file:https://travis-ci.org/liamoc/latex-formulae.svg]] [[http://haskell.org][file:https://img.shields.io/badge/language-Haskell-blue.svg]] [[https://github.com/liamoc/latex-formulae/blob/master/LICENSE][file:http://img.shields.io/badge/license-BSD3-brightgreen.svg]]

This is a suite of tools and libraries to make rendering LaTeX equations to images easy from Haskell and Pandoc. For an example of what they're capable of, take a look at [[http://liamoc.net/posts/2013-11-13-imperativereasoning.html][articles on my blog]].

It contains three parts,

These libraries also give you precise control over the output DPI and over the dimensions of the image in the HTML output, so it can be configured to give crisp images even on high DPI displays, like Retina displays.

Because they use just regular LaTeX, any of the packages available to your system LaTeX installation are also available in these formulae. Just add the necessary ~usepackage~ invocations to the preamble inside your ~FormulaOptions~ value.

** Requirements

You must have a LaTeX installation available, which includes ~latex~ and ~dvips~. ImageMagick's ~convert~ is also required, and must be able to understand PostScript (for example, using ~gs~). Most recent binary distributions of LaTeX and ImageMagick satisfy these dependencies.

** Building/Installing

If you're using ~stack~, it should just be a matter of ~stack build~, and ~stack install~ if you want to use the example pandoc filter, ~latex-formulae-filter~.

Users of ~cabal~ will have to build each package using the usual ~cabal~ ceremony:

+BEGIN_SRC sh

cabal update cabal configure cabal build cabal install

+END_SRC

** Using

As always, see the Haddocks for more thorough details. Here are some simple example usages.

*** As a library

**** ~latex-formulae-image~

The ~latex-formulae-image~ package really only has one major function, ~imageForFormula~. You can use it like so:

+BEGIN_SRC haskell

import Image.LaTeX.Render (imageForFormula, defaultEnv, displaymath) import Codec.Picture (writeDynamicPng) -- JuicyPixels

main = do x <- imageforFormula defaultEnv displaymath "y = mx + b" case x of Left e -> return () Right (baseline, img) -> do _ <- writeDynamicPng "image.png" img return ()

+END_SRC

Settings such as where to find LaTeX etc. can be set by altering the ~EnvironmentOptions~ value, in this case we just use ~defaultEnv~ defaults. Settings such as the LaTeX environment to use, the preamble, and the DPI can be set in the ~FormulaOptions~ value, in this case we use the ~displaymath~ defaults.

**** ~latex-formulae-pandoc~

If you want to integrate with ~pandoc~ programmatically, you can use the ~latex-formulae-pandoc~ package. This package includes functions that allow you to transform ~pandoc~ documents. If you're happy to embed the images directly inside the HTML, then ~convertAllFormulaeDataURI~ is easiest:

+BEGIN_SRC haskell

imagesForFormulae :: Pandoc -> IO Pandoc imagesForFormulae doc = convertAllFormulaeDataURI defaultEnv defaultPandocFormulaOptions doc

+END_SRC

The above example function can be inserted between any ~Pandoc~ reader and an HTML writer, producing embedded images inside the HTML output using data URIs.

If you would rather they be stored as separate PNG images in a directory called ~static~, ~convertAllFormulaeFiles~ can be used:

+BEGIN_SRC haskell

imagesForFormulae :: Pandoc -> IO Pandoc imagesForFormulae doc = do ns <- newNameSupply convertAllFormulaeFiles ns "static" defaultEnv defaultPandocFormulaOptions doc

+END_SRC

There are also more general versions of the ~convertFormula~ functions, named `convertFormulaWith`, which allow the actual function that does the rendering of formulae to be altered. This is so that you can insert image caching or other image postprocessing into the renderer.

**** ~latex-formulae-hakyll~

Currently only Data URI embedding is supported for Hakyll, but using it should be as simple as the following minimal example:

+BEGIN_SRC haskell

main = do renderFormulae <- initFormulaCompilerDataURI 1000 defaultEnv hakyll $ match "posts/*.markdown" $ do route $ setExtension "html" compile $ pandocCompilerWithTransformM defaultHakyllReaderOptions defaultHakyllWriterOptions $ renderFormulae defaultPandocFormulaOptions

+END_SRC

If for whatever reason you don't want to have formula caching for @watch@ servers, you can just use this simpler form:

+BEGIN_SRC haskell

main = hakyll $ match "posts/*.markdown" $ do route $ setExtension "html" compile $ pandocCompilerWithTransformM defaultHakyllReaderOptions defaultHakyllWriterOptions $ compileFormulaeDataURI defaultEnv defaultPandocFormulaOptions

+END_SRC

*** As a pandoc filter

The ~latex-formulae-pandoc~ library comes with a simple example filter executable, called ~latex-formulae-filter~. If you ~stack install~ or ~cabal install~ it to your ~$PATH~, you can use it with ~pandoc~ like so:

+BEGIN_SRC sh

pandoc -s --filter=latex-formulae-filter -o output.html input.html

+END_SRC sh

The source code for this program is very simple:

+BEGIN_SRC haskell

import Image.LaTeX.Render.Pandoc import Image.LaTeX.Render import Text.Pandoc.JSON

main :: IO () main = toJSONFilter $ convertFormulaDataURI defaultEnv defaultPandocFormulaOptions

+END_SRC haskell

This filter embeds the images with data URIs. To use files, follow the same routine as above:

+BEGIN_SRC haskell

import Image.LaTeX.Render.Pandoc import Image.LaTeX.Render import Text.Pandoc.JSON

main :: IO () main = do ns <- newNameSupply toJSONFilter $ convertFormulaFiles ns "static" defaultEnv defaultPandocFormulaOptions

+END_SRC haskell

Adjust the various options by altering the ~defaultPandocFormulaOptions~ and ~defaultEnv~ terms in this program, as described in the Haddock documentation.

** Example/Demo

Writing the following markdown:

+BEGIN_SRC markdown

Lines (that is, $f(x) = mx + b$) are of degree 1, whereas quadratics (that is, $f(x) = ax^2 + bx + c$) are of degree 2. Solve quadratics with the quadratic formula:

$$x=\frac{-b\pm\sqrt{b^2-4ac}}{2a}$$

Enough high school algebra for now!

+END_SRC

Leads to [[https://htmlpreview.github.io/?https://github.com/liamoc/latex-formulae/blob/master/example.html][this output]]! Pretty nifty :)

** Future work

I would like to add files support for Hakyll websites, but it's not clear how this would interact with Hakyll's compiler system.