
On Sun, Feb 1, 2009 at 1:37 AM, John MacFarlane
Not too hard, I think. Here's code for something similar (for graphviz diagrams), derived from plugins/DotPlugin.hs in SVN pandoc.
transform :: Block -> IO Block transform (CodeBlock (id, classes, namevals) contents) | "dot" `elem` classes = do let (name, outfile) = case lookup "name" namevals of Just fn -> ([Str fn], fn ++ ".png") Nothing -> ([], uniqueName contents ++ ".png") result <- readProcess "dot" ["-Tpng"] contents writeFile outfile result return $ Para [Image name (outfile, "")] transform x = return x
-- | Generate a unique filename given the file's contents. uniqueName :: String -> String uniqueName = showDigest . sha1 . fromString
The 'transform' function will transform delimited code blocks such as
~~~ {.dot name="diagram1"} digraph G {Hello->World} ~~~
into images generated by running the contents through graphviz's dot. To lift this into a transformation of Pandoc documents, you can use syb:
convertGraphviz :: Pandoc -> IO Pandoc convertGraphviz = everywhereM (mkM transform)
With minimal modifications, the same technique should work for diagrams...
Best, John
This certainly does seem reasonable, but I don't think the sandboxing/interpretation question is addressed. In your GraphViz example, you dump out to the 'dot' executable and it does things which you read back. But with Diagrams, we're interested in running arbitrary Haskell code - that's what makes Diagrams so useful, that we can exploit the full power of Haskell in our expressions. Now, to implement it, I would probably say to myself, "well, we'll create a temporary file, we'll write some basic imports into it, then we'll write the user's expression into it as the definition of a function 'foo', and main will be defined as 'main = renderFile foo'. Then we use 'runhaskell' on the temporary file to create the picture, delete the temp file, and bob's your uncle." Except of course there's nothing to prevent DoS attacks or other exploits in the arbitrary code. So do we accept this and say that this is a plugin one uses at one's own risk? -- gwern