The diagrams-haddock package

[Tags: bsd3, library, program]

diagrams-haddock is a tool for compiling embedded inline diagrams code in Haddock documentation, for an easy way to spice up your documentation with diagrams. Just create some diagrams code using special markup, run diagrams-haddock, and ensure the resulting image files are installed along with your documentation. For complete documentation and examples, see

For a good example of a package making use of diagrams-haddock, see the diagrams-contrib package (

[Skip to ReadMe]


Versions0.1.0.0,,,,,, 0.2, 0.2.1,,,,,,, 0.2.2,,,,,,,,,,,,,,, 0.3,,,,,,,
Dependenciesansi-terminal (>=0.5 && <0.7), base (>=4.4 && <4.9), base64-bytestring (>=1 && <1.1), bytestring (>=0.9 && <0.11), Cabal (>=1.14 && <1.23), cautious-file (==1.0.*), cmdargs (>=0.8 && <0.11), containers (>=0.4 && <0.6), cpphs (>=1.15), diagrams-builder (>=0.5 && <0.8), diagrams-haddock, diagrams-lib (>=0.6 && <1.4), diagrams-svg (>= && <1.4), directory, filepath, haskell-src-exts (==1.16.*), lens (>=3.8 && <4.14), linear (>=1.10 && <1.21), lucid-svg (==0.5.*), mtl (>=2.0 && <2.3), parsec (>=3), split (==0.2.*), strict (==0.3.*), text (>=0.11 && <1.3), uniplate (==1.6.*) [details]
AuthorBrent Yorgey
Home page
Bug tracker
Source repositoryhead: git clone git://
UploadedTue Sep 22 17:13:27 UTC 2015 by BrentYorgey
DistributionsLTSHaskell:, NixOS:, Stackage:
Downloads4757 total (302 in last 30 days)
0 []
StatusDocs available [build log]
Last success reported on 2015-09-22 [all 1 reports]




Maintainers' corner

For package maintainers and hackage trustees

Readme for diagrams-haddock-

Build Status


diagrams-haddock is a preprocessor which allows embedding images generated using the diagrams framework within Haddock documentation. The code to generate images is embedded directly within the source file itself (and the code can be included in the Haddock output or not, as you wish). diagrams-haddock takes care of generating SVG images and linking them into the Haddock output.


Just cabal install diagrams-haddock. If you have any trouble, ask in the #diagrams freenode IRC channel, or file a ticket on the bug tracker.

On the design of diagrams-haddock

Before getting into the details of using diagrams-haddock, it should be noted that diagrams-haddock has been carefully designed so that you only have to maintain a single copy of your source files. In particular, you do not have to maintain one copy of your source files with embedded diagrams code and another copy where the diagrams code has been replaced by images. If you find yourself scratching your head over the quirky ways that diagrams-haddock works, now you will know why.

An important caveat

diagrams-haddock modifies files in place! While we have worked hard to ensure that it cannot make catastrophic changes to your files, you would be wise to only run diagrams-haddock on files under version control so you can easily examine and (if necessary) undo the changes it makes. (Of course, being a conscientious developer, you would never work with source files not under version control, right?)

Adding diagrams to source files

Haddock supports inline links to images with the syntax <<URL>>. To indicate an image which should be automatically generated from some diagrams code, use the special syntax <<URL#diagram=name&key1=val1&key2=val2&...>>. The URL will be automatically filled in by diagrams-haddock, so when you first create an inline image placeholder you can simply omit it (or put any arbitrary text in its place). For example, you might write


indicating an image which should be generated using the definition of mySquare, with a maximum width of 200 and maximum height of 300. (Incidentally, this syntax is used because everything following the # symbol will be ignored by browsers.)

Continuing with the above example, you must also provide a definition of mySquare. You must provide it in a code block, which must be set off by bird tracks (that is, greater-than symbols followed by at least one space). For example,

-- > mySquare = square 1 # fc blue # myTransf
-- > myTransf = rotateBy (1/27)

In this case, mySquare has type Diagram SVG R2. Additionally, you may give identifiers of type IO (Diagram SVG R2); in that case the IO action will be run to determine the diagram to render. This can be useful, for example, when producing a diagram built from some external data or using randomness.

You can choose to have the code block included in the Haddock output or not, simply by putting it in a Haddock comment or not. Note that the code block defining mySquare can be anywhere in the same file; it does not have to be right before or right after the diagram URL referencing it.

Code block dependency analysis

diagrams-haddock does a simple dependency analysis to determine which code blocks should be in scope while compiling each diagram. First, it locates a code block containing a binding for the requested diagram name. Then, it pulls in any code blocks containing bindings for identifiers referenced by this code block, and so on transitively. (Note that this analysis is overly simplistic and does not take things like shadowing into account; this may sometimes cause additional code blocks to be included which would not be included with a more careful analysis.)

This has a few implications. First, code blocks containing irrelevant bindings will not be considered. It is common to have code blocks which are intended simply to show some example code---they may not even be valid Haskell. However, as long as such code blocks do not contain any bindings of names used by a diagram, they will be ignored. For example:

-- The algorithm works by doing the equivalent of
-- > rep = uncurry replicate
-- >
-- > algo = map rep . zip [1..]
-- as illustrated below:
-- <<#diagram=algoIllustration&width=400>>
-- > algoIllustration = ...

The first code block shown above (beginning rep = ...) contains some bindings, but none of those bindings are referenced by any diagram URLs, so the code block is ignored.

Another convenient implication is that supporting code can be put in separate code blocks and even shared between diagrams. For example:

-- > makeitblue d = d # fc blue # lc blue
-- Here is a blue circle:
-- <<#diagram=blueC&width=200>>
-- > blueC = circle 1 # makeitblue
-- And here is a blue square:
-- <<#diagram=blueS&width=200>>
-- > blueS = square 1 # makeitblue

This also means that diagrams are recompiled only when necessary. For example, if the definition of blueC is changed, only blueC will be recompiled. If the definition of makeitblue is changed, both blueC and blueS will be recompiled.

Invoking diagrams-haddock

Invoking the diagrams-haddock tool is simple: just give it a list of targets, like so:

diagrams-haddock foo.hs baz/bar.lhs ~/src/some-cabal-directory

Also, if you simply invoke diagrams-haddock with no targets, it will process the Cabal package in the current directory.

diagrams-haddock also takes a few command-line options which can be used to customize its behavior:

Workflow and Cabal setup

There are two ways one may include generated SVG images with your documentation: as data URIs, or as external images. The two options are discussed below, along with pros and cons of each. Note that in either case, consumers of your library (including Hackage itself) do not need to have diagrams-haddock installed in order to build your documentation.

Using data URIs

If you pass the --dataURIs option to diagrams-haddock, any generated images will be embedded directly in your source file (and hence also in the HTML ultimately produced by haddock) as data URIs. To use this method,

  1. Include inline diagrams code and URLs in your source code.
  2. Run diagrams-haddock --dataURIs.
  3. Commit the resulting URL changes to your source files.

The benefit of this scheme is that there are no extra files to deal with, and no need to alter your .cabal file in any way. The downside is that it significantly bloats your source code, and may make it extremely inconvenient to edit without some sort of tool support (e.g. an editor that can "collapse" certain sections of the source file).

Using external images

By default, diagrams-haddock generates external SVG image files. This makes for much less invasive changes to your source files, but requires some work to manage the extra files. To use this method,

  1. Include inline diagrams code and URLs in your source code.
  2. Run diagrams-haddock.
  3. Commit the resulting URL changes to your source files and the produced SVG files.
  4. Arrange to have the SVG files installed along with your package's Haddock documentation (more on this below).

The generated SVG files need to be copied in alongside the generated Haddock documentation. There are two ways to accomplish this:

  1. As of Cabal-1.18, the .cabal file format has acquired an extra-doc-files field, specifying files which should be copied in alongside generated Haddock documentation. So the preferred method is to add something like

    extra-source-files:,, diagrams/*.svg
    extra-doc-files: diagrams/*.svg

    to your .cabal file. Note that you must list the generated images in both the extra-source-files field (so they will be included in your package tarball) and the extra-doc-files field (so they will be copied alongside generated Haddock documentation). Hackage is now built on Cabal-1.18, so uploading a package using the extra-doc-files field in this way works just fine.

  2. If you need to make your documentation buildable with a pre-1.18 version of cabal-install, it is possible to take advantage of cabal's system of user hooks to manually copy the images right after the Haddock documentation is generated. Add something like

    build-type: Custom
    extra-source-files: diagrams/*.svg

    to your .cabal file, and then put something like the following in your Setup.hs:

    import           Data.List                 (isSuffixOf)
    import           Distribution.Simple
    import           Distribution.Simple.Setup (Flag (..), HaddockFlags,
    import           Distribution.Simple.Utils (copyFiles)
    import           Distribution.Text         (display)
    import           Distribution.Verbosity    (normal)
    import           System.Directory          (getDirectoryContents)
    import           System.FilePath           ((</>))
    -- Ugly hack, logic copied from Distribution.Simple.Haddock
    haddockOutputDir :: Package pkg => HaddockFlags -> pkg -> FilePath
    haddockOutputDir flags pkg = destDir
         baseDir = case haddockDistPref flags of
                          NoFlag -> "."
                          Flag x -> x
         destDir = baseDir </> "doc" </> "html" </> display (packageName pkg)
    diagramsDir = "diagrams"
    main :: IO ()
    main = defaultMainWithHooks simpleUserHooks
             { postHaddock = \args flags pkg lbi -> do
                 dias <- filter ("svg" `isSuffixOf`) `fmap` getDirectoryContents diagramsDir
                 copyFiles normal (haddockOutputDir flags pkg)
                   (map (\d -> ("", diagramsDir </> d)) dias)
                 postHaddock simpleUserHooks args flags pkg lbi

    It may not be pretty, but it works!

File encodings

For now, diagrams-haddock assumes that all .hs and .lhs files are encoded using UTF-8. If you would like to use it with source files stored using some other encoding, feel free to file a feature request.

The diagrams-haddock library

For most use cases, simply using the diagrams-haddock executable should get you what you want. Note, however, that the internals are also exposed as a library, making it possible to do all sorts of crazy stuff you might dream up. Let us know what you do with it!

Reporting bugs

Please report any bugs, feature requests, etc., on the github issue tracker.