@hackage pandoc-utils0.4.0

Utility functions to work with Pandoc in Haskell applications.

pandoc-utils

This package contains some useful functions for writing Pandoc filters and integrating Pandoc into Haskell applications such as Hakyll. It provides a composable wrapper for filters acting on nodes of the Pandoc AST.

Filter conversion/composition

As an example, let us look at the behead and delink filter from Pandoc's tutorial.

behead :: Block -> Block
behead (Header n _ xs) | n >= 2 = Para [Emph xs]
behead x = x

delink :: Inline -> [Inline]
delink (Link _ txt _) = txt
delink x = [x]

Since behead has type Block -> Block, while delink has type Inline -> [Inline], they are not naturally composable. However, this package provides a utility function mkFilter to convert them into a PandocFilter.

import Text.Pandoc.Filter.Utils

beheadFilter :: PandocFilter
beheadFilter = mkFilter behead

delinkFilter :: PandocFilter
delinkFilter = mkFilter delink

PandocFilter is an alias for PartialFilter Pandoc, so you can also have PartialFilter Inline, etc. There is also a monadic version called PartialFilterM for encapsulating monadic filters.

The PandocFilter is a monoid so you can do something like,

myFilter :: PandocFilter
myFilter = beheadFilter <> delinkFilter

where myFilter would apply beheadFilter first, then the delinkFilter. You can apply the filter using applyFilter,

import Text.Pandoc
import Data.Default (def)

mdToHtml
  :: Text                    -- ^ Input markdown string
  -> Either PandocError Text -- ^ Html string or error
mdToHtml md = runPure $ do
  doc <- readMarkdown def md
  let doc' = applyFilter myFilter doc
  writeHtml5String def doc'

or get an unwrapped Pandoc -> Pandoc filter using getFilter (this function is also capable of doing implicit conversion from PartialFilter a to b -> b).

myPandocFilter :: Pandoc -> Pandoc
myPandocFilter = getFilter myFilter

For applying multiple filters, there is also a function called applyFilters, which takes a list of filters and apply it to a Pandoc document (or subnode) sequentially, from left to right.

myFilters :: [PandocFilter]
myFilters =
  [ beheadFilter
  , delinkFilter
  ]

mdToHtml'
  :: Text                    -- ^ Input markdown string
  -> Either PandocError Text -- ^ Html string or error
mdToHtml' md = runPure $ do
  doc <- readMarkdown def md
  let doc' = applyFilters myFilters doc
  writeHtml5String def doc'

Attribute builder

pandoc-utils also provides an attribute builder for handling attributes. You can create a new attributes by

ghci> import Text.Pandoc.Filter.Utils.AttrBuilder
ghci> import Text.Pandoc.Definition
ghci> nullAttr `setId` "id" `addClass` "class" `addKVPair` ("key","value")
("id",["class"],[("key","value")])

or modifying an existing attributes by

ghci> attr = ("id",[],[])
ghci> attr `setId` "newId"
("newId",[],[])

For more examples, please read the spec.