diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -23,8 +23,10 @@
 [lpdf]: http://lierdakil.github.io/pandoc-crossref/output-listings.pdf
 
 
-Tested with Pandoc from 1.13.2 to 1.16.0.
+Tested with Pandoc 1.16.0.
 
+**NOTE**: pandoc-crossref versions 0.2.0 and up only support pandoc v1.16. You can still file issues with older versions, but please don't expect more than an occasional bugfix. Thank you for understanding.
+
 This work is inspired by [pandoc-fignos][1] and [pandoc-eqnos][2] by @tomduck.
 
 [1]: https://github.com/tomduck/pandoc-fignos
@@ -38,6 +40,14 @@
 
 pandoc-crossref uses metadata variable `header-includes` to add LaTeX definitions to output. However, Pandoc's command line option `--include-in-header`/`-H` overrides this variable. If you need to use `--include-in-header`, add pandoc-crossref-specific definitions as well. See [LaTeX customization](#latex-customization) for more information.
 
+### pandoc-citeproc and pandoc-crossref
+
+Since pandoc-crossref uses the same citation syntax as pandoc-citeproc, you *have* to run former *before* latter. For example:
+
+```
+pandoc -F pandoc-crossref -F pandoc-citeproc file.md -o file.html
+```
+
 ## Syntax
 
 Syntax is loosely based on discussion in <https://github.com/jgm/pandoc/issues/813>
@@ -54,6 +64,43 @@
 
 Image block and label *can not* be separated by spaces.
 
+#### Subfigures
+
+It's possible to group figures as subfigures. Basic syntax is as follows:
+
+```
+<div id="fig:figureRef">
+![subfigure 1 caption](image1.png){#fig:figureRefA}
+
+![subfigure 2 caption](image2.png){#fig:figureRefB}
+
+Caption of figure
+</div>
+```
+
+To sum up, subfigures are made with a div having a figure `id`. Contents of said div consist of several paragraphs. All but last paragraphs contain one subfigure each, with captions, images and (optionally) reference attributes. Last paragraph contains figure caption.
+
+Output is customizable, with metadata fields. See [Customization](#Customization) for more information.
+
+Default settings will produce the following equivalent Markdown from example above:
+
+```
+<div id="fig:figureRef" class="subfigures">
+
+![a](image1.png){#fig:figureRefA}
+
+![b](image2.png){#fig:figureRefB}
+
+Figure 1: Caption of figure. a — subfigure 1 caption, b — subfigure 2
+caption
+
+</div>
+```
+
+References to subfigures will be rendered as `figureNumber (subfigureNumber)`, e.g., in this particular example, `[@fig:figureRefA]` will produce `fig. 1 (a)`.
+
+You can add `nocaption` class to an image to suppress subfigure caption altogether. Note that it will still be counted.
+
 ### Equation labels
 
 ```markdown
@@ -215,7 +262,7 @@
 * `figureTitle`, default `Figure`: Word(s) to prepend to figure titles, e.g. `Figure 1: Description`
 * `tableTitle`, default `Table`: Word(s) to prepend to table titles, e.g. `Table 1: Description`
 * `listingTitle`, default `Listing`: Word(s) to prepend to listing titles, e.g. `Listing 1: Description`
-* `titleDelimiter`, default `:`: What to put between object number and caption text.
+* `titleDelim`, default `:`: What to put between object number and caption text.
 * `figPrefix`, default `fig.`, `figs.`: Prefix for references to figures, e.g. `figs. 1-3`
 * `eqnPrefix`, default `eq.`, `eqns.`: Prefix for references to equations, e.g. `eqns. 3,4`
 * `tblPrefix`, default `tbl.`, `tbls.`: Prefix for references to tables, e.g. `tbl. 2`
@@ -229,7 +276,18 @@
 * `lolTitle`, default `# List of Listings`: Title for list of listings (lol)
 * `figureTemplate`, default `\\[figureTitle\\] \\[i\\]\\[titleDelim\\] \\[t\\]`: template for figure captions, see [Templates](#templates)
 * `tableTemplate`, default `\\[tableTitle\\] \\[i\\]\\[titleDelim\\] \\[t\\]`: template for table captions, see [Templates](#templates)
-* `listingTemplate`, default `\\[tableTitle\\] \\[i\\]\\[titleDelim\\] \\[t\\]`: template for listing captions, see [Templates](#templates)
+* `listingTemplate`, default `\\[listingTitle\\] \\[i\\]\\[titleDelim\\] \\[t\\]`: template for listing captions, see [Templates](#templates)
+* `subfigureTemplate`, default `\\[figureTitle\\] \\[i\\]\\[titleDelim\\] \\[t\\]. \\[ccs\\]`: template for subfigure divs captions. See [Subfigures](#subfigures)
+* `subfigureChildTemplate`, default `\\[i\\]`: template for actual subfigure captions. See [Subfigures](#subfigures)
+* `ccsTemplate`, default `\\[i\\]\\[ccsLabelSep\\]\\[t\\]`: template for collected subfigure captions. See [Subfigures](#subfigures), [Templates](#templates)
+* `figLabels`, default unset: custom numbering scheme for figures. See [Custom Numbering Schemes](#custom-numbering-schemes)
+* `subfigLabels`, default `alpha a`: custom numbering scheme for subfigures. See [Custom Numbering Schemes](#custom-numbering-schemes)
+* `eqnLabels`, default unset: custom numbering scheme for equations. See [Custom Numbering Schemes](#custom-numbering-schemes)
+* `tblLabels`, default unset: custom numbering scheme for tables. See [Custom Numbering Schemes](#custom-numbering-schemes)
+* `lstLabels`, default unset: custom numbering scheme for listings. See [Custom Numbering Schemes](#custom-numbering-schemes)
+* `secLabels`, default unset: custom numbering scheme for sections. See [Custom Numbering Schemes](#custom-numbering-schemes)
+* `ccsDelim`, default `,&nbsp;`: delimiter for collected subfigure captions. See [Subfigures](#subfigures) and [Templates](#templates)
+* `ccsLabelSep`, default `&nbsp;—&nbsp;`: delimiter used between subfigure label and subfigure caption in collected captions. See [Subfigures](#subfigures) and [Templates](#templates)
 
 `figPrefix`, `eqnPrefix`, `tblPrefix`, `lstPrefix` can be YAML arrays. That way, value at index corresponds to total number of references in group, f.ex.
 
@@ -283,6 +341,7 @@
 
 * `i` -- object number, possibly with chapter number (if `chapter=True`)
 * `t` -- object caption, as given in source Markdown
+* `ccs` -- collected subfigure captions. Only applicable to `subfigureTemplate`. Collected captions will be separated by `ccsDelim` and individual captions will be printed with `ccsTemplate`. See [Subfigures](#subfigures)
 
 Please note that at the moment, templates are not supported with LaTeX/PDF output.
 
diff --git a/demo.md b/demo.md
--- a/demo.md
+++ b/demo.md
@@ -24,6 +24,8 @@
 
 You can also have custom chapter reference labels, like @sec:custlabs
 
+Subfigures are supported, see [@fig:subfigures; @fig:subfigureB]
+
 # Chapter 1. Figures {#sec:sec1}
 
 ![First figure](img1.jpg){#fig:figure1}
@@ -33,6 +35,14 @@
 ![Third figure](img3.jpg){#fig:figure3}
 
 ![Unlabelled image](img1.jpg)
+
+<div id="fig:subfigures">
+![Subfigure a](img1.jpg)
+
+![Subfigure b](img1.jpg){#fig:subfigureB}
+
+Subfigures caption
+</div>
 
 # Chapter 2. Equations {#sec:sec2}
 
diff --git a/lib/Text/Pandoc/CrossRef.hs b/lib/Text/Pandoc/CrossRef.hs
--- a/lib/Text/Pandoc/CrossRef.hs
+++ b/lib/Text/Pandoc/CrossRef.hs
@@ -62,12 +62,11 @@
 import Control.Monad.State
 import qualified Control.Monad.Reader as R
 import Text.Pandoc
-import Text.Pandoc.Walk
 import Data.Monoid ((<>))
 
 import Text.Pandoc.CrossRef.References
 import Text.Pandoc.CrossRef.Util.Settings
-import Text.Pandoc.CrossRef.Util.Options
+import Text.Pandoc.CrossRef.Util.Options as O
 import Text.Pandoc.CrossRef.Util.CodeBlockCaptions
 import Text.Pandoc.CrossRef.Util.ModifyMeta
 import Text.Pandoc.CrossRef.Util.Settings.Gen as SG
@@ -89,8 +88,8 @@
   opts <- R.asks creOptions
   let
     doWalk =
-      bottomUpM (codeBlockCaptions opts) (walk divBlocks blocks)
-      >>= walkM (replaceBlocks opts)
+      bottomUpM (mkCodeBlockCaptions opts) blocks
+      >>= replaceAll opts
       >>= bottomUpM (replaceRefs opts)
       >>= bottomUpM (listOf opts)
   return $ evalState doWalk def
diff --git a/lib/Text/Pandoc/CrossRef/References.hs b/lib/Text/Pandoc/CrossRef/References.hs
--- a/lib/Text/Pandoc/CrossRef/References.hs
+++ b/lib/Text/Pandoc/CrossRef/References.hs
@@ -1,7 +1,6 @@
 module Text.Pandoc.CrossRef.References ( module X ) where
 
-import Text.Pandoc.CrossRef.References.Accessors as X
 import Text.Pandoc.CrossRef.References.Types as X
-import Text.Pandoc.CrossRef.References.Blocks as X (divBlocks, replaceBlocks)
+import Text.Pandoc.CrossRef.References.Blocks as X (replaceAll)
 import Text.Pandoc.CrossRef.References.Refs as X
 import Text.Pandoc.CrossRef.References.List as X
diff --git a/lib/Text/Pandoc/CrossRef/References/Accessors.hs b/lib/Text/Pandoc/CrossRef/References/Accessors.hs
deleted file mode 100644
--- a/lib/Text/Pandoc/CrossRef/References/Accessors.hs
+++ /dev/null
@@ -1,35 +0,0 @@
-{-# LANGUAGE RecordWildCards #-}
-module Text.Pandoc.CrossRef.References.Accessors where
-
-import Text.Pandoc.CrossRef.References.Types
-import Data.Accessor
-
-imgRefs' :: Accessor References RefMap
-imgRefs' = accessor
-  (\References{..} -> imgRefs)
-  (\a r -> r{imgRefs=a})
-
-eqnRefs' :: Accessor References RefMap
-eqnRefs' = accessor
-  (\References{..} -> eqnRefs)
-  (\a r -> r{eqnRefs=a})
-
-tblRefs' :: Accessor References RefMap
-tblRefs' = accessor
-  (\References{..} -> tblRefs)
-  (\a r -> r{tblRefs=a})
-
-lstRefs' :: Accessor References RefMap
-lstRefs' = accessor
-  (\References{..} -> lstRefs)
-  (\a r -> r{lstRefs=a})
-
-secRefs' :: Accessor References RefMap
-secRefs' = accessor
-  (\References{..} -> secRefs)
-  (\a r -> r{secRefs=a})
-
-curChap' :: Accessor References Index
-curChap' = accessor
-  (\References{..} -> curChap)
-  (\a r -> r{curChap=a})
diff --git a/lib/Text/Pandoc/CrossRef/References/Blocks.hs b/lib/Text/Pandoc/CrossRef/References/Blocks.hs
--- a/lib/Text/Pandoc/CrossRef/References/Blocks.hs
+++ b/lib/Text/Pandoc/CrossRef/References/Blocks.hs
@@ -1,38 +1,45 @@
-{-# LANGUAGE CPP #-}
+{-# LANGUAGE CPP, Rank2Types, MultiWayIf #-}
 module Text.Pandoc.CrossRef.References.Blocks
-  ( divBlocks
-  , replaceBlocks
-  , spanInlines
-  , replaceInlines
+  ( replaceAll
   ) where
 
 import Text.Pandoc.Definition
-import Text.Pandoc.Generic
-import Text.Pandoc.Walk
 import Text.Pandoc.Builder (text, toList)
 import Text.Pandoc.Shared (stringify, normalizeSpaces)
 import Control.Monad.State hiding (get, modify)
 import Data.List
+import Data.Maybe
+import Data.Monoid
 import qualified Data.Map as M
 
 import Data.Accessor
 import Data.Accessor.Monad.Trans.State
 import Text.Pandoc.CrossRef.References.Types
-import Text.Pandoc.CrossRef.References.Accessors
 import Text.Pandoc.CrossRef.Util.Util
 import Text.Pandoc.CrossRef.Util.Options
 import Text.Pandoc.CrossRef.Util.Template
 import Control.Applicative
 import Prelude
+import Data.Default
 
+replaceAll :: Data a => Options -> a -> WS a
+replaceAll opts =
+    everywhereMBut' (mkQ False isSubfig) (mkM (replaceBlocks opts) `extM` replaceInlines opts)
+  . everywhere' (mkT divBlocks `extT` spanInlines)
+  where
+    isSubfig (Div (label,cls,_) _)
+      | "fig:" `isPrefixOf` label = True
+      | "crossref-stop" `elem` cls = True
+    isSubfig _ = False
+
 replaceBlocks :: Options -> Block -> WS Block
 replaceBlocks opts (Header n (label, cls, attrs) text')
   = do
-    let label' = if autoSecLab opts && not ("sec:" `isPrefixOf` label)
+    let label' = if autoSectionLabels opts && not ("sec:" `isPrefixOf` label)
                  then "sec:"++label
                  else label
     unless ("unnumbered" `elem` cls) $ do
-      modify curChap' $ \cc ->
+      modify curChap $ \cc ->
         let ln = length cc
             cl = lookup "label" attrs
             inc l = init l ++ [(fst (last l) + 1, cl)]
@@ -40,25 +47,66 @@
                 | ln == n = inc cc
                 | otherwise = cc ++ take (n-ln-1) (zip [1,1..] $ repeat Nothing) ++ [(1,cl)]
         in cc'
-      when ("sec:" `isPrefixOf` label') $ replaceAttrSec label' text' secRefs'
+      when ("sec:" `isPrefixOf` label') $ replaceAttrSec label' text' secRefs
     return $ Header n (label', cls, attrs) text'
-#if MIN_VERSION_pandoc(1,16,0)
-#else
-replaceBlocks opts (Div (label,_,attrs) [Plain [Image alt img]])
+-- subfigures
+replaceBlocks opts (Div (label,cls,attrs) images)
   | "fig:" `isPrefixOf` label
+  , all isImage (init images)
+  , Para caption <- last images
   = do
-    idxStr <- replaceAttr opts label (lookup "label" attrs) alt imgRefs'
-    let alt' = case outFormat opts of
+    idxStr <- replaceAttr opts label (lookup "label" attrs) caption imgRefs
+    let (cont, st) = runState (replaceAll opts' $ init images) (subFig ^= True $ def)
+        collectedCaptions =
+            intercalate (ccsDelim opts)
+          $ map snd
+          $ M.toList
+          $ M.map collectCaps
+          $ imgRefs_ st
+        collectCaps v =
+              applyTemplate
+                (chapPrefix (chapDelim opts) (refIndex v))
+                (refTitle v)
+                (ccsTemplate opts)
+        vars = M.fromDistinctAscList
+                  [ ("ccs", collectedCaptions)
+                  , ("i", idxStr)
+                  , ("t", caption)
+                  ]
+        capt = applyTemplate' vars $ subfigureTemplate opts
+    lastRef <- fromJust . M.lookup label <$> get imgRefs
+    modify imgRefs $ \old ->
+        M.union
+          old
+          (M.map (\v -> v{refIndex = refIndex lastRef, refSubfigure = Just $ refIndex v})
+          $ imgRefs_ st)
+    case outFormat opts of
           f | isFormat "latex" f ->
-            RawInline (Format "tex") ("\\label{"++label++"}") : alt
-          _  -> applyTemplate idxStr alt $ figureTemplate opts
-    return $ Para [Image alt' img]
-#endif
+            return $ Div stopAttr $
+              [ RawBlock (Format "tex") "\\begin{figure}" ]
+              ++ cont ++
+              [ Para [RawInline (Format "tex") "\\caption"
+                       , Span stopAttr caption]
+              , RawBlock (Format "tex") $ "\\label{"++label++"}"
+              , RawBlock (Format "tex") "\\end{figure}"]
+          _  -> return $ Div (label, "subfigures":cls, attrs) $ cont ++ [Para capt]
+  where
+    isImage (Para images') = all isImage' images'
+    isImage (Plain images') = all isImage' images'
+    isImage _ = False
+    isImage' (Image _ _ s) = "fig:" `isPrefixOf` snd s
+    isImage' Space = True
+    isImage' SoftBreak = True
+    isImage' _ = False
+    opts' = opts
+              { figureTemplate = subfigureChildTemplate opts
+              , customLabel = \r i -> customLabel opts ("sub"++r) i
+              }
 replaceBlocks opts (Div (label,_,attrs) [Table title align widths header cells])
   | not $ null title
   , "tbl:" `isPrefixOf` label
   = do
-    idxStr <- replaceAttr opts label (lookup "label" attrs) title tblRefs'
+    idxStr <- replaceAttr opts label (lookup "label" attrs) title tblRefs
     let title' =
           case outFormat opts of
               f | isFormat "latex" f ->
@@ -72,10 +120,10 @@
   = case outFormat opts of
       f
         --if used with listings package,nothing shoud be done
-        | isFormat "latex" f, useListings opts -> return cb
+        | isFormat "latex" f, listings opts -> return cb
         --if not using listings, however, wrap it in a codelisting environment
         | isFormat "latex" f ->
-          return $ Div nullAttr [
+          return $ Div stopAttr [
               RawBlock (Format "tex")
                 $ "\\begin{codelisting}\n\\caption{"++caption++"}"
             , cb
@@ -83,7 +131,7 @@
             ]
       _ -> do
         let cap = toList $ text caption
-        idxStr <- replaceAttr opts label (lookup "label" attrs) cap lstRefs'
+        idxStr <- replaceAttr opts label (lookup "label" attrs) cap lstRefs
         let caption' = applyTemplate idxStr cap $ listingTemplate opts
         return $ Div (label, "listing":classes, []) [
             Para caption'
@@ -97,28 +145,27 @@
   = case outFormat opts of
       f
         --if used with listings package, return code block with caption
-        | isFormat "latex" f, useListings opts ->
+        | isFormat "latex" f, listings opts ->
           return $ CodeBlock (label,classes,("caption",stringify caption):attrs) code
         --if not using listings, however, wrap it in a codelisting environment
         | isFormat "latex" f ->
-          return $ Div nullAttr [
+          return $ Div stopAttr [
               RawBlock (Format "tex") "\\begin{codelisting}"
             , Para [
-                RawInline (Format "tex") "\\caption{"
-              , Span nullAttr caption
-              , RawInline (Format "tex") "}"
+                RawInline (Format "tex") "\\caption"
+              , Span stopAttr caption
               ]
             , CodeBlock (label,classes,attrs) code
             , RawBlock (Format "tex") "\\end{codelisting}"
             ]
       _ -> do
-        idxStr <- replaceAttr opts label (lookup "label" attrs) caption lstRefs'
+        idxStr <- replaceAttr opts label (lookup "label" attrs) caption lstRefs
         let caption' = applyTemplate idxStr caption $ listingTemplate opts
         return $ Div (label, "listing":classes, []) [
             Para caption'
           , CodeBlock ([], classes, attrs) code
           ]
-replaceBlocks opts x = walkM (replaceInlines opts) x
+replaceBlocks _ x = return x
 
 replaceInlines :: Options -> Inline -> WS Inline
 replaceInlines opts (Span (label,_,attrs) [Math DisplayMath eq])
@@ -128,39 +175,42 @@
         let eqn = "\\begin{equation}"++eq++"\\label{"++label++"}\\end{equation}"
         in return $ RawInline (Format "tex") eqn
       _ -> do
-        idxStr <- replaceAttr opts label (lookup "label" attrs) [] eqnRefs'
+        idxStr <- replaceAttr opts label (lookup "label" attrs) [] eqnRefs
         let eq' = eq++"\\qquad("++stringify idxStr++")"
         return $ Math DisplayMath eq'
-#if MIN_VERSION_pandoc(1,16,0)
-replaceInlines opts x@(Image attr@(label,_,attrs) alt img)
-  | "fig:" `isPrefixOf` label, "fig:" `isPrefixOf` snd img
+replaceInlines opts x@(Image attr@(label,cls,attrs) alt img@(src, tit))
+  | "fig:" `isPrefixOf` snd img
   = do
-    hasLab <- M.member label <$> (get imgRefs')
-    if hasLab
-    then return x
-    else do
-      idxStr <- replaceAttr opts label (lookup "label" attrs) alt imgRefs'
-      let alt' = case outFormat opts of
-            f | isFormat "latex" f ->
-              RawInline (Format "tex") ("\\label{"++label++"}") : alt
-            _  -> applyTemplate idxStr alt $ figureTemplate opts
-      return $ Image attr alt' img
-#else
-#endif
+    sf <- get subFig
+    if | sf -> do
+        let label' | "fig:" `isPrefixOf` label = label
+                   | otherwise  = "fig:" ++ label
+        idxStr <- replaceAttr opts label' (lookup "label" attrs) alt imgRefs
+        case outFormat opts of
+          f | isFormat "latex" f ->
+            return $ latexSubFigure x label
+          _  ->
+            let alt' = applyTemplate idxStr alt $ figureTemplate opts
+                tit' | "nocaption" `elem` cls = fromMaybe tit $ stripPrefix "fig:" tit
+                     | otherwise = tit
+            in return $ Image (label, cls, attrs) alt' (src, tit')
+       | "fig:" `isPrefixOf` label -> do
+        idxStr <- replaceAttr opts label (lookup "label" attrs) alt imgRefs
+        let alt' = case outFormat opts of
+              f | isFormat "latex" f ->
+                RawInline (Format "tex") ("\\label{"++label++"}") : alt
+              _  -> applyTemplate idxStr alt $ figureTemplate opts
+        return $ Image attr alt' img
+       | otherwise ->
+        return x
 replaceInlines _ x = return x
 
 divBlocks :: Block -> Block
-#if MIN_VERSION_pandoc(1,16,0)
-#else
-divBlocks (Para (Image alt (img, title):c))
-  | Just label <- getRefLabel "fig" c
-  = Div (label,[],[]) [Plain [Image alt (img, "fig:" ++ title)]]
-#endif
 divBlocks (Table title align widths header cells)
   | not $ null title
   , Just label <- getRefLabel "tbl" [last title]
   = Div (label,[],[]) [Table (init title) align widths header cells]
-divBlocks x = bottomUp spanInlines x
+divBlocks x = x
 
 spanInlines :: [Inline] -> [Inline]
 spanInlines (math@(Math DisplayMath _eq):ils)
@@ -182,21 +232,43 @@
 replaceAttr :: Options -> String -> Maybe String -> [Inline] -> Accessor References RefMap -> WS [Inline]
 replaceAttr o label refLabel title prop
   = do
-    chap  <- take (chapDepth o) `fmap` gets curChap
-    i     <- (1+) `fmap` (M.size . M.filter ((==chap) . init . refIndex) <$> get prop)
-    let index = chap ++ [(i, refLabel)]
+    chap  <- take (chaptersDepth o) `fmap` get curChap
+    i     <- (1+) `fmap` (M.size . M.filter (ap ((&&) . (chap ==) . init . refIndex) (isNothing . refSubfigure)) <$> get prop)
+    let index = chap ++ [(i, refLabel <> customLabel o label i)]
     modify prop $ M.insert label RefRec {
       refIndex= index
     , refTitle=normalizeSpaces title
+    , refSubfigure = Nothing
     }
     return $ chapPrefix (chapDelim o) index
 
 replaceAttrSec :: String -> [Inline] -> Accessor References RefMap -> WS ()
 replaceAttrSec label title prop
   = do
-    index  <- gets curChap
+    index  <- get curChap
     modify prop $ M.insert label RefRec {
       refIndex=index
     , refTitle=normalizeSpaces title
+    , refSubfigure = Nothing
     }
     return ()
+
+latexSubFigure :: Inline -> String -> Inline
+latexSubFigure (Image (_, cls, attrs) alt (src, title)) label =
+  let
+    title' = fromMaybe title $ stripPrefix "fig:" title
+    texlabel | null label = []
+             | otherwise = "\\label{" ++ label ++ "}"
+    texalt | "nocaption" `elem` cls  = []
+           | otherwise =
+              [ RawInline (Format "tex") "["] ++ alt ++ [ RawInline (Format "tex") "]"]
+    img = Image (label, cls, attrs) alt (src, title')
+  in Span stopAttr $
+      [ RawInline (Format "tex") "\\subfloat" ] ++ texalt ++
+      [ RawInline (Format "tex") "{" ] ++
+      [img] ++
+      [ RawInline (Format "tex") $ texlabel ++ "}"]
+latexSubFigure x _ = x
+
+stopAttr :: Attr
+stopAttr = ([], ["crossref-stop"], [])
diff --git a/lib/Text/Pandoc/CrossRef/References/List.hs b/lib/Text/Pandoc/CrossRef/References/List.hs
--- a/lib/Text/Pandoc/CrossRef/References/List.hs
+++ b/lib/Text/Pandoc/CrossRef/References/List.hs
@@ -1,7 +1,7 @@
 module Text.Pandoc.CrossRef.References.List (listOf) where
 
 import Text.Pandoc.Definition
-import Control.Monad.State
+import Data.Accessor.Monad.Trans.State
 import Control.Arrow
 import Data.List
 import qualified Data.Map as M
@@ -13,18 +13,18 @@
 listOf :: Options -> [Block] -> WS [Block]
 listOf Options{outFormat=f} x | isFormat "latex" f = return x
 listOf opts (Para [RawInline (Format "tex") "\\listoffigures"]:xs)
-  = gets imgRefs >>= makeList opts lofTitle xs
+  = get imgRefs >>= makeList opts lofTitle xs
 listOf opts (Para [RawInline (Format "tex") "\\listoftables"]:xs)
-  = gets tblRefs >>= makeList opts lotTitle xs
+  = get tblRefs >>= makeList opts lotTitle xs
 listOf opts (Para [RawInline (Format "tex") "\\listoflistings"]:xs)
-  = gets lstRefs >>= makeList opts lolTitle xs
+  = get lstRefs >>= makeList opts lolTitle xs
 listOf _ x = return x
 
 makeList :: Options -> (Options -> [Block]) -> [Block] -> M.Map String RefRec -> WS [Block]
 makeList opts titlef xs refs
   = return $
       titlef opts ++
-      (if chapDepth opts > 0
+      (if chaptersDepth opts > 0
         then Div ("", ["list"], []) (itemChap `map` refsSorted)
         else OrderedList style (item `map` refsSorted))
       : xs
diff --git a/lib/Text/Pandoc/CrossRef/References/Refs.hs b/lib/Text/Pandoc/CrossRef/References/Refs.hs
--- a/lib/Text/Pandoc/CrossRef/References/Refs.hs
+++ b/lib/Text/Pandoc/CrossRef/References/Refs.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE TupleSections #-}
 module Text.Pandoc.CrossRef.References.Refs (replaceRefs) where
 
 import Text.Pandoc.Definition
@@ -12,7 +13,7 @@
 import Data.Accessor
 import Data.Accessor.Monad.Trans.State
 import Text.Pandoc.CrossRef.References.Types
-import Text.Pandoc.CrossRef.References.Accessors
+import Text.Pandoc.CrossRef.Util.Template
 import Text.Pandoc.CrossRef.Util.Util
 import Text.Pandoc.CrossRef.Util.Options
 import Control.Applicative
@@ -44,31 +45,33 @@
 
 -- accessors to state variables
 accMap :: M.Map String (Accessor References RefMap)
-accMap = M.fromList [("fig:",imgRefs')
-                    ,("eq:" ,eqnRefs')
-                    ,("tbl:",tblRefs')
-                    ,("lst:",lstRefs')
-                    ,("sec:",secRefs')
+accMap = M.fromList [("fig:",imgRefs)
+                    ,("eq:" ,eqnRefs)
+                    ,("tbl:",tblRefs)
+                    ,("lst:",lstRefs)
+                    ,("sec:",secRefs)
                     ]
 
 -- accessors to options
-prefMap :: M.Map String (Options -> Bool -> Int -> [Inline])
-prefMap = M.fromList [("fig:",figPrefix)
-                     ,("eq:" ,eqnPrefix)
-                     ,("tbl:",tblPrefix)
-                     ,("lst:",lstPrefix)
-                     ,("sec:",secPrefix)
+prefMap :: M.Map String (Options -> Bool -> Int -> [Inline], Options -> Template)
+prefMap = M.fromList [("fig:",(figPrefix, figPrefixTemplate))
+                     ,("eq:" ,(eqnPrefix, eqnPrefixTemplate))
+                     ,("tbl:",(tblPrefix, tblPrefixTemplate))
+                     ,("lst:",(lstPrefix, lstPrefixTemplate))
+                     ,("sec:",(secPrefix, secPrefixTemplate))
                      ]
 
 prefixes :: [String]
 prefixes = M.keys accMap
 
-getRefPrefix :: Options -> String -> Bool -> Int -> [Inline]
-getRefPrefix opts prefix capitalize num
-  | null refprefix = []
-  | otherwise   = refprefix ++ [Str "\160"]
-  where refprefix = lookupUnsafe prefix prefMap opts capitalize num
+getRefPrefix :: Options -> String -> Bool -> Int -> [Inline] -> [Inline]
+getRefPrefix opts prefix capitalize num cit =
+  applyTemplate' (M.fromDistinctAscList [("i", cit), ("p", refprefix)])
+        $ reftempl opts
+  where (refprefixf, reftempl) = lookupUnsafe prefix prefMap
+        refprefix = refprefixf opts capitalize num
 
+
 lookupUnsafe :: Ord k => k -> M.Map k v -> v
 lookupUnsafe = (fromJust .) . M.lookup
 
@@ -80,19 +83,19 @@
 
 replaceRefsLatex :: String -> Options -> [Citation] -> WS [Inline]
 replaceRefsLatex prefix opts cits =
-  return $ p ++ [texcit]
+  return $ p [texcit]
   where
     texcit =
       RawInline (Format "tex") $
-      if useCleveref opts then
-        cref++"{"++listLabels prefix "" "," "" cits++"}"
+      if cref opts then
+        cref'++"{"++listLabels prefix "" "," "" cits++"}"
         else
           listLabels prefix "\\ref{" ", " "}" cits
-    p | useCleveref opts = []
+    p | cref opts = id
       | otherwise = getRefPrefix opts prefix cap (length cits - 1)
     cap = maybe False isFirstUpper $ getLabelPrefix . citationId . head $ cits
-    cref | cap = "\\Cref"
-         | otherwise = "\\cref"
+    cref' | cap = "\\Cref"
+          | otherwise = "\\cref"
 
 listLabels :: String -> String -> String -> String -> [Citation] -> String
 listLabels prefix p sep s =
@@ -109,15 +112,25 @@
 
 replaceRefsOther :: String -> Options -> [Citation] -> WS [Inline]
 replaceRefsOther prefix opts cits = do
-  indices <- mapM (getRefIndex prefix) cits
+  indices <- mapM (getRefIndex prefix opts) cits
   let
     indices' = groupBy ((==) `on` (fmap init . fst)) (sort indices)
     cap = maybe False isFirstUpper $ getLabelPrefix . citationId . head $ cits
-  return $ normalizeInlines $ getRefPrefix opts prefix cap (length cits - 1) ++ intercalate [Str ",", Space]  (makeIndices opts `map` indices')
+  return $ normalizeInlines $ getRefPrefix opts prefix cap (length cits - 1) $ intercalate [Str ",", Space]  (makeIndices opts `map` indices')
 
-getRefIndex :: String -> Citation -> WS (Maybe Index, [Inline])
-getRefIndex prefix Citation{citationId=cid,citationSuffix=suf}
-  = (\x -> (x,suf)) `fmap` (fmap refIndex . M.lookup lab <$> get prop)
+getRefIndex :: String -> Options -> Citation -> WS (Maybe Index, [Inline])
+getRefIndex prefix opts Citation{citationId=cid,citationSuffix=suf}
+  = do
+    ref <- M.lookup lab <$> get prop
+    let sub = join $ refSubfigure <$> ref
+        idx = refIndex <$> ref
+        suf' | Just sub' <- sub =
+                    suf
+                ++  [Space, Str "("]
+                ++  makeIndices opts [(Just sub',[])]
+                ++  [Str ")"]
+             | otherwise = suf
+    return (idx ,suf')
   where
   prop = lookupUnsafe prefix accMap
   lab = prefix ++ getLabelWithoutPrefix cid
diff --git a/lib/Text/Pandoc/CrossRef/References/Types.hs b/lib/Text/Pandoc/CrossRef/References/Types.hs
--- a/lib/Text/Pandoc/CrossRef/References/Types.hs
+++ b/lib/Text/Pandoc/CrossRef/References/Types.hs
@@ -1,36 +1,36 @@
-module Text.Pandoc.CrossRef.References.Types ( References(..)
-                        , WS
-                        , RefRec(..)
-                        , RefMap
-                        , Index
-                        , def
-                        ) where
+{-# LANGUAGE TemplateHaskell #-}
+module Text.Pandoc.CrossRef.References.Types where
 
 import qualified Data.Map as M
 import Text.Pandoc.Definition
 import Control.Monad.State
 import Data.Default
+import Data.Accessor.Template
 
 type Index = [(Int, Maybe String)]
 
 data RefRec = RefRec { refIndex :: Index
                      , refTitle :: [Inline]
+                     , refSubfigure :: Maybe Index
                      } deriving (Show, Eq)
 
 type RefMap = M.Map String RefRec
 
 -- state data type
-data References = References { imgRefs :: RefMap
-                             , eqnRefs :: RefMap
-                             , tblRefs :: RefMap
-                             , lstRefs :: RefMap
-                             , secRefs :: RefMap
-                             , curChap :: Index
+data References = References { imgRefs_ :: RefMap
+                             , eqnRefs_ :: RefMap
+                             , tblRefs_ :: RefMap
+                             , lstRefs_ :: RefMap
+                             , secRefs_ :: RefMap
+                             , curChap_ :: Index
+                             , subFig_  :: Bool
                              } deriving (Show, Eq)
 
 --state monad
 type WS a = State References a
 
 instance Default References where
-  def = References n n n n n []
+  def = References n n n n n [] False
     where n = M.empty
+
+deriveAccessors ''References
diff --git a/lib/Text/Pandoc/CrossRef/Util/CodeBlockCaptions.hs b/lib/Text/Pandoc/CrossRef/Util/CodeBlockCaptions.hs
--- a/lib/Text/Pandoc/CrossRef/Util/CodeBlockCaptions.hs
+++ b/lib/Text/Pandoc/CrossRef/Util/CodeBlockCaptions.hs
@@ -1,6 +1,6 @@
 module Text.Pandoc.CrossRef.Util.CodeBlockCaptions
     (
-    codeBlockCaptions
+    mkCodeBlockCaptions
     ) where
 
 import Text.Pandoc.Definition
@@ -10,16 +10,16 @@
 import Text.Pandoc.CrossRef.References.Types
 import Text.Pandoc.CrossRef.Util.Options
 
-codeBlockCaptions :: Options -> [Block] -> WS [Block]
-codeBlockCaptions opts x@(cb@(CodeBlock _ _):p@(Para _):xs)
+mkCodeBlockCaptions :: Options -> [Block] -> WS [Block]
+mkCodeBlockCaptions opts x@(cb@(CodeBlock _ _):p@(Para _):xs)
   = return $ fromMaybe x $ orderAgnostic opts $ p:cb:xs
-codeBlockCaptions opts x@(p@(Para _):cb@(CodeBlock _ _):xs)
+mkCodeBlockCaptions opts x@(p@(Para _):cb@(CodeBlock _ _):xs)
   = return $ fromMaybe x $ orderAgnostic opts $ p:cb:xs
-codeBlockCaptions _ x = return x
+mkCodeBlockCaptions _ x = return x
 
 orderAgnostic :: Options -> [Block] -> Maybe [Block]
 orderAgnostic opts (Para ils:CodeBlock (label,classes,attrs) code:xs)
-  | cbCaptions opts
+  | codeBlockCaptions opts
   , Just caption <- getCodeBlockCaption ils
   , not $ null label
   , "lst" `isPrefixOf` label
diff --git a/lib/Text/Pandoc/CrossRef/Util/CustomLabels.hs b/lib/Text/Pandoc/CrossRef/Util/CustomLabels.hs
new file mode 100644
--- /dev/null
+++ b/lib/Text/Pandoc/CrossRef/Util/CustomLabels.hs
@@ -0,0 +1,26 @@
+module Text.Pandoc.CrossRef.Util.CustomLabels (customLabel) where
+
+import Text.Pandoc.Definition
+import Text.Pandoc.CrossRef.Util.Meta
+import Control.Monad
+import Data.List
+import Text.Numeral.Roman
+
+customLabel :: Meta -> String -> Int -> Maybe String
+customLabel meta ref i
+  | refLabel <- takeWhile (/=':') ref
+  , Just cl <- lookupMeta (refLabel++"Labels") meta
+  = mkLabel i cl
+  | otherwise = Nothing
+
+mkLabel :: Int -> MetaValue -> Maybe String
+mkLabel i lt
+  | toString lt == Just "arabic"
+  = Nothing
+  | toString lt == Just "roman"
+  = Just $ toRoman i
+  | Just (startWith:_) <- join $ stripPrefix "alpha " `fmap` toString lt
+  = Just [[startWith..] !! (i-1)]
+  | Just val <- join $ toString `fmap` getList (i-1) lt
+  = Just val
+  | otherwise = error $ "Unknown numeration type: " ++ show lt
diff --git a/lib/Text/Pandoc/CrossRef/Util/Gap.hs b/lib/Text/Pandoc/CrossRef/Util/Gap.hs
--- a/lib/Text/Pandoc/CrossRef/Util/Gap.hs
+++ b/lib/Text/Pandoc/CrossRef/Util/Gap.hs
@@ -5,8 +5,4 @@
 import qualified Text.Pandoc as P
 
 readMarkdown :: P.ReaderOptions -> String -> P.Pandoc
-#if MIN_VERSION_pandoc(1,14,0)
 readMarkdown = (either (error . show) id .) . P.readMarkdown
-#else
-readMarkdown = P.readMarkdown
-#endif
diff --git a/lib/Text/Pandoc/CrossRef/Util/Meta.hs b/lib/Text/Pandoc/CrossRef/Util/Meta.hs
--- a/lib/Text/Pandoc/CrossRef/Util/Meta.hs
+++ b/lib/Text/Pandoc/CrossRef/Util/Meta.hs
@@ -1,11 +1,13 @@
-{-# LANGUAGE CPP #-}
+{-# LANGUAGE CPP, FlexibleContexts #-}
 module Text.Pandoc.CrossRef.Util.Meta where
 
 import Text.Pandoc.CrossRef.Util.Gap
+import Text.Pandoc.CrossRef.Util.Util
 import Text.Pandoc.Shared (stringify)
 import Text.Pandoc.Definition
 import Data.Maybe (fromMaybe)
 import Data.Default
+import Text.Pandoc.Walk
 
 getMetaList :: (Default a) => (MetaValue -> Maybe a) -> String -> Meta -> Int -> a
 getMetaList f name meta i = fromMaybe def $ lookupMeta name meta >>= getList i >>= f
@@ -57,3 +59,16 @@
                    | not $ null list = Just $ last list
                    | otherwise = Nothing
 getList _ x = Just x
+
+tryCapitalizeM :: (Functor m, Monad m, Walkable Inline a, Default a, Eq a) =>
+        (String -> m a) -> String -> Bool -> m a
+tryCapitalizeM f varname capitalize
+  | capitalize = do
+    res <- f (capitalizeFirst varname)
+    case res of
+      xs | xs == def -> f varname >>= walkM capStrFst
+         | otherwise -> return xs
+  | otherwise  = f varname
+  where
+    capStrFst (Str s) = return $ Str $ capitalizeFirst s
+    capStrFst x = return x
diff --git a/lib/Text/Pandoc/CrossRef/Util/ModifyMeta.hs b/lib/Text/Pandoc/CrossRef/Util/ModifyMeta.hs
--- a/lib/Text/Pandoc/CrossRef/Util/ModifyMeta.hs
+++ b/lib/Text/Pandoc/CrossRef/Util/ModifyMeta.hs
@@ -22,14 +22,18 @@
     headerInc (Just (MetaList x)) = MetaList $ x ++ incList
     headerInc (Just x) = MetaList $ x:incList
     incList = map MetaString $
+        subfig ++
         floatnames ++
         listnames  ++
-        [ x | x <- codelisting, not $ useListings opts] ++
+        [ x | x <- codelisting, not $ listings opts] ++
         lolcommand ++
-        [ x | x <- cleveref, useCleveref opts] ++
-        [ x | x <- cleverefCodelisting, useCleveref opts && not (useListings opts)] ++
+        [ x | x <- cleveref, cref opts] ++
+        [ x | x <- cleverefCodelisting, cref opts && not (listings opts)] ++
         []
       where
+        subfig = [
+            "\\usepackage{subfig}"
+          ]
         floatnames = [
             "\\AtBeginDocument{%"
           , "\\renewcommand*\\figurename{"++metaString "figureTitle"++"}"
@@ -51,7 +55,7 @@
           , "\\floatname{codelisting}{"++metaString "listingTitle"++"}"
           ]
         lolcommand
-          | useListings opts = [
+          | listings opts = [
               "\\newcommand*\\listoflistings\\lstlistoflistings"
             , "\\AtBeginDocument{%"
             , "\\renewcommand*{\\lstlistlistingname}{"++metaString' "lolTitle"++"}"
diff --git a/lib/Text/Pandoc/CrossRef/Util/Options.hs b/lib/Text/Pandoc/CrossRef/Util/Options.hs
--- a/lib/Text/Pandoc/CrossRef/Util/Options.hs
+++ b/lib/Text/Pandoc/CrossRef/Util/Options.hs
@@ -1,24 +1,22 @@
-{-# LANGUAGE FlexibleContexts #-}
-
-module Text.Pandoc.CrossRef.Util.Options (Options(..), getOptions) where
+module Text.Pandoc.CrossRef.Util.Options (Options(..)) where
 import Text.Pandoc.Definition
-import Text.Pandoc.CrossRef.Util.Meta
 import Text.Pandoc.CrossRef.Util.Template
-import Text.Pandoc.CrossRef.Util.Util (capitalizeFirst)
-import Text.Pandoc.Walk
-import Data.Default
--- import Control.Monad.Identity
 
-data Options = Options { useCleveref :: Bool
-                       , chapDepth   :: Int
-                       , useListings :: Bool
-                       , cbCaptions  :: Bool
-                       , autoSecLab  :: Bool
+data Options = Options { cref :: Bool
+                       , chaptersDepth   :: Int
+                       , listings :: Bool
+                       , codeBlockCaptions  :: Bool
+                       , autoSectionLabels  :: Bool
                        , figPrefix   :: Bool -> Int -> [Inline]
                        , eqnPrefix   :: Bool -> Int -> [Inline]
                        , tblPrefix   :: Bool -> Int -> [Inline]
                        , lstPrefix   :: Bool -> Int -> [Inline]
                        , secPrefix   :: Bool -> Int -> [Inline]
+                       , figPrefixTemplate :: Template
+                       , eqnPrefixTemplate :: Template
+                       , tblPrefixTemplate :: Template
+                       , lstPrefixTemplate :: Template
+                       , secPrefixTemplate :: Template
                        , chapDelim   :: [Inline]
                        , rangeDelim  :: [Inline]
                        , lofTitle    :: [Block]
@@ -26,49 +24,12 @@
                        , lolTitle    :: [Block]
                        , outFormat   :: Maybe Format
                        , figureTemplate :: Template
+                       , subfigureTemplate :: Template
+                       , subfigureChildTemplate :: Template
+                       , ccsTemplate :: Template
                        , tableTemplate  :: Template
                        , listingTemplate :: Template
+                       , customLabel :: String -> Int -> Maybe String
+                       , ccsDelim :: [Inline]
+                       , ccsLabelSep :: [Inline]
                        }
-
-getOptions :: Meta -> Maybe Format -> Options
-getOptions dtv fmt =
-  Options {
-      useCleveref = getMetaBool "cref" dtv
-    , chapDepth   = if getMetaBool "chapters" dtv
-        then read $ getMetaString "chaptersDepth" dtv
-        else 0
-    , useListings = getMetaBool "listings" dtv
-    , cbCaptions  = getMetaBool "codeBlockCaptions" dtv
-    , autoSecLab  = getMetaBool "autoSectionLabels" dtv
-    , figPrefix   = tryCapitalizeM (flip (getMetaList toInlines) dtv) "figPrefix"
-    , eqnPrefix   = tryCapitalizeM (flip (getMetaList toInlines) dtv) "eqnPrefix"
-    , tblPrefix   = tryCapitalizeM (flip (getMetaList toInlines) dtv) "tblPrefix"
-    , lstPrefix   = tryCapitalizeM (flip (getMetaList toInlines) dtv) "lstPrefix"
-    , secPrefix   = tryCapitalizeM (flip (getMetaList toInlines) dtv) "secPrefix"
-    , chapDelim   = getMetaInlines "chapDelim" dtv
-    , rangeDelim  = getMetaInlines "rangeDelim" dtv
-    , lofTitle    = getMetaBlock "lofTitle" dtv
-    , lotTitle    = getMetaBlock "lotTitle" dtv
-    , lolTitle    = getMetaBlock "lolTitle" dtv
-    , outFormat   = fmt
-    , figureTemplate = makeTemplate dtv $ getMetaInlines "figureTemplate" dtv
-    , tableTemplate  = makeTemplate dtv $ getMetaInlines "tableTemplate" dtv
-    , listingTemplate = makeTemplate dtv $ getMetaInlines "listingTemplate" dtv
-  }
-
-tryCapitalizeM :: (Functor m, Monad m, Walkable Inline a, Default a, Eq a) =>
-        (String -> m a) -> String -> Bool -> m a
-tryCapitalizeM f varname capitalize
-  | capitalize = do
-    res <- f (capitalizeFirst varname)
-    case res of
-      xs | xs == def -> f varname >>= walkM capStrFst
-         | otherwise -> return xs
-  | otherwise  = f varname
-  where
-    capStrFst (Str s) = return $ Str $ capitalizeFirst s
-    capStrFst x = return x
-
--- tryCapitalize :: (Walkable Inline a, Default a, Eq a) =>
---         (String -> a) -> String -> Bool -> a
--- tryCapitalize = ((runIdentity .) .) . tryCapitalizeM . (return .)
diff --git a/lib/Text/Pandoc/CrossRef/Util/Settings.hs b/lib/Text/Pandoc/CrossRef/Util/Settings.hs
--- a/lib/Text/Pandoc/CrossRef/Util/Settings.hs
+++ b/lib/Text/Pandoc/CrossRef/Util/Settings.hs
@@ -19,7 +19,18 @@
 
 defaultMeta :: Meta
 defaultMeta =
-     figureTitle (str "Figure")
+     cref (MetaBool False)
+  <> chapters (MetaBool False)
+  <> chaptersDepth (MetaString "1")
+  <> listings (MetaBool False)
+  <> codeBlockCaptions (MetaBool False)
+  <> autoSectionLabels (MetaBool False)
+  <> figLabels (MetaString "arabic")
+  <> eqnLabels (MetaString "arabic")
+  <> tblLabels (MetaString "arabic")
+  <> lstLabels (MetaString "arabic")
+  <> secLabels (MetaString "arabic")
+  <> figureTitle (str "Figure")
   <> tableTitle (str "Table")
   <> listingTitle (str "Listing")
   <> titleDelim (str ":")
@@ -30,6 +41,11 @@
   <> tblPrefix [str "tbl.", str "tbls."]
   <> lstPrefix [str "lst.", str "lsts."]
   <> secPrefix [str "sec.", str "secs."]
+  <> figPrefixTemplate (var "p" <> str "\160" <> var "i")
+  <> eqnPrefixTemplate (var "p" <> str "\160" <> var "i")
+  <> tblPrefixTemplate (var "p" <> str "\160" <> var "i")
+  <> lstPrefixTemplate (var "p" <> str "\160" <> var "i")
+  <> secPrefixTemplate (var "p" <> str "\160" <> var "i")
   <> lofTitle (header 1 $ text "List of Figures")
   <> lotTitle (header 1 $ text "List of Tables")
   <> lolTitle (header 1 $ text "List of Listings")
@@ -38,4 +54,10 @@
   <> listingTemplate (var "listingTitle" <> space <> var "i" <> var "titleDelim" <> space <> var "t")
   <> crossrefYaml (MetaString "pandoc-crossref.yaml")
   <> chaptersDepth (MetaString "1")
+  <> subfigureChildTemplate (var "i")
+  <> subfigureTemplate (var "figureTitle" <> space <> var "i" <> var "titleDelim" <> space <> var "t" <> str "." <> space <> var "ccs")
+  <> subfigLabels (MetaString "alpha a")
+  <> ccsDelim (str "," <> space)
+  <> ccsLabelSep (space <> str "—" <> space)
+  <> ccsTemplate (var "i" <> var "ccsLabelSep" <> var "t")
   where var = displayMath
diff --git a/lib/Text/Pandoc/CrossRef/Util/Settings/Gen.hs b/lib/Text/Pandoc/CrossRef/Util/Settings/Gen.hs
--- a/lib/Text/Pandoc/CrossRef/Util/Settings/Gen.hs
+++ b/lib/Text/Pandoc/CrossRef/Util/Settings/Gen.hs
@@ -1,61 +1,33 @@
+{-# LANGUAGE TemplateHaskell #-}
+-- {-# OPTIONS_GHC -ddump-splices #-}
 module Text.Pandoc.CrossRef.Util.Settings.Gen where
 
 import Text.Pandoc.CrossRef.Util.Settings.Template
-import Text.Pandoc.Builder
-
-figureTitle :: ToMetaValue a => a -> Meta
-figureTitle = template "figureTitle"
-
-tableTitle :: ToMetaValue a => a -> Meta
-tableTitle = template "tableTitle"
-
-listingTitle :: ToMetaValue a => a -> Meta
-listingTitle = template "listingTitle"
-
-titleDelim :: ToMetaValue a => a -> Meta
-titleDelim = template "titleDelim"
-
-chapDelim :: ToMetaValue a => a -> Meta
-chapDelim = template "chapDelim"
-
-rangeDelim :: ToMetaValue a => a -> Meta
-rangeDelim = template "rangeDelim"
-
-figPrefix :: ToMetaValue a => a -> Meta
-figPrefix = template "figPrefix"
-
-eqnPrefix :: ToMetaValue a => a -> Meta
-eqnPrefix = template "eqnPrefix"
-
-tblPrefix :: ToMetaValue a => a -> Meta
-tblPrefix = template "tblPrefix"
-
-lstPrefix :: ToMetaValue a => a -> Meta
-lstPrefix = template "lstPrefix"
-
-secPrefix :: ToMetaValue a => a -> Meta
-secPrefix = template "secPrefix"
-
-lofTitle :: ToMetaValue a => a -> Meta
-lofTitle = template "lofTitle"
-
-lotTitle :: ToMetaValue a => a -> Meta
-lotTitle = template "lotTitle"
-
-lolTitle :: ToMetaValue a => a -> Meta
-lolTitle = template "lolTitle"
-
-figureTemplate :: ToMetaValue a => a -> Meta
-figureTemplate = template "figureTemplate"
-
-tableTemplate :: ToMetaValue a => a -> Meta
-tableTemplate = template "tableTemplate"
+import Text.Pandoc.CrossRef.Util.Meta
+import Text.Pandoc.CrossRef.Util.Options as O (Options(..))
+import Language.Haskell.TH (mkName)
+import Text.Pandoc.Definition
 
-listingTemplate :: ToMetaValue a => a -> Meta
-listingTemplate = template "listingTemplate"
+nameDeriveSetters ''Options
 
-crossrefYaml :: ToMetaValue a => a -> Meta
-crossrefYaml = template "crossrefYaml"
+fmap concat $ mapM (makeAcc . mkName)
+  [ "figureTitle"
+  , "tableTitle"
+  , "listingTitle"
+  , "titleDelim"
+  , "crossrefYaml"
+  , "subfigLabels"
+  , "chapters"
+  , "figLabels"
+  , "eqnLabels"
+  , "tblLabels"
+  , "lstLabels"
+  , "secLabels"
+  ]
 
-chaptersDepth :: ToMetaValue a => a -> Meta
-chaptersDepth = template "chaptersDepth"
+getOptions :: Meta -> Maybe Format -> Options
+getOptions dtv fmt =
+  let opts = $(makeCon ''Options 'Options)
+  in if getMetaBool "chapters" dtv
+     then opts
+     else opts{O.chaptersDepth = 0}
diff --git a/lib/Text/Pandoc/CrossRef/Util/Settings/Template.hs b/lib/Text/Pandoc/CrossRef/Util/Settings/Template.hs
--- a/lib/Text/Pandoc/CrossRef/Util/Settings/Template.hs
+++ b/lib/Text/Pandoc/CrossRef/Util/Settings/Template.hs
@@ -1,8 +1,75 @@
+{-# LANGUAGE TemplateHaskell, RankNTypes, ViewPatterns, UnicodeSyntax, MultiWayIf #-}
 module Text.Pandoc.CrossRef.Util.Settings.Template where
 
 import Text.Pandoc.Definition
 import Text.Pandoc.Builder
+import Text.Pandoc.CrossRef.Util.Meta
 import qualified Data.Map as M
+import Language.Haskell.TH hiding (Inline)
+import Language.Haskell.TH.Syntax hiding (Inline)
+import Data.List
+import Control.Monad
+import Text.Pandoc.CrossRef.Util.Template
+import Text.Pandoc.CrossRef.Util.CustomLabels (customLabel)
 
-template :: ToMetaValue a => String -> a -> Meta
-template name = Meta . M.singleton name . toMetaValue
+namedFields :: Con -> [VarStrictType]
+namedFields (RecC _ fs) = fs
+namedFields (ForallC _ _ c) = namedFields c
+namedFields _ = []
+
+fromRecDef :: ∀ t a r. Name -> t -> (Name -> Name -> Q [a]) -> (t -> [a] -> r) -> Q r
+fromRecDef t cname f c = do
+  info <- reify t
+  reified <- case info of
+                  TyConI dec -> return dec
+                  _ -> fail "No cons"
+  (_, cons) <- case reified of
+               DataD _ _ params cons' _ -> return (params, cons')
+               NewtypeD _ _ params con' _ -> return (params, [con'])
+               _ -> fail "No cons"
+  decs <- liftM concat . mapM (\ (name,_,_) -> f t name) . nub $ concatMap namedFields cons
+  return $ c cname decs
+
+nameDeriveSetters :: Name -> Q [Dec]
+nameDeriveSetters t = fromRecDef t undefined (const makeAcc) (const id)
+
+dropQualifiers :: Name -> Name
+dropQualifiers (Name occ _) = mkName (occString occ)
+
+makeAcc :: Name -> Q [Dec]
+makeAcc (dropQualifiers -> accName) = do
+    body <- [| Meta . M.singleton $(liftString $ show accName) . toMetaValue |]
+    sig <- [t|forall a. ToMetaValue a => a -> Meta|]
+    return
+      [ SigD accName sig
+      , ValD (VarP accName) (NormalB body) []
+      ]
+
+makeCon :: Name -> Name -> Q Exp
+makeCon t cname = fromRecDef t cname makeCon' RecConE
+
+makeCon' :: Name -> Name -> Q [(Name, Exp)]
+makeCon' t accName = do
+    VarI _ t' _ _ <- reify accName
+    funT <- [t|$(conT t) -> Bool -> Int -> [Inline]|]
+    inlT <- [t|$(conT t) -> [Inline]|]
+    blkT <- [t|$(conT t) -> [Block]|]
+    fmtT <- [t|$(conT t) -> Maybe Format|]
+    boolT <- [t|$(conT t) -> Bool|]
+    intT <- [t|$(conT t) -> Int|]
+    tmplT <- [t|$(conT t) -> Template|]
+    clT <- [t|$(conT t) -> String -> Int -> Maybe String|]
+    let varName | Name (OccName n) _ <- accName = liftString n
+    let dtv = return $ VarE $ mkName "dtv"
+    body <-
+      if
+      | t' == boolT -> [|getMetaBool $(varName) $(dtv)|]
+      | t' == intT -> [|read $ getMetaString $(varName) $(dtv)|]
+      | t' == funT -> [|tryCapitalizeM (flip (getMetaList toInlines) $(dtv)) $(varName)|]
+      | t' == inlT -> [|getMetaInlines $(varName) $(dtv)|]
+      | t' == blkT -> [|getMetaBlock $(varName) $(dtv)|]
+      | t' == tmplT -> [|makeTemplate $(dtv) $ getMetaInlines $(varName) $(dtv)|]
+      | t' == clT -> [|customLabel $(dtv)|]
+      | t' == fmtT -> return $ VarE $ mkName "fmt"
+      | otherwise -> fail $ show t'
+    return [(accName, body)]
diff --git a/lib/Text/Pandoc/CrossRef/Util/Template.hs b/lib/Text/Pandoc/CrossRef/Util/Template.hs
--- a/lib/Text/Pandoc/CrossRef/Util/Template.hs
+++ b/lib/Text/Pandoc/CrossRef/Util/Template.hs
@@ -1,9 +1,15 @@
-module Text.Pandoc.CrossRef.Util.Template (Template,makeTemplate,applyTemplate) where
+module Text.Pandoc.CrossRef.Util.Template
+  ( Template
+  , makeTemplate
+  , applyTemplate
+  , applyTemplate'
+  ) where
 
 import Text.Pandoc.Definition
 import Text.Pandoc.Generic
 import Text.Pandoc.Shared (normalizeInlines)
 import Data.Maybe
+import Data.Map as M
 import Text.Pandoc.CrossRef.Util.Meta
 
 type VarFunc = String -> Maybe MetaValue
@@ -17,10 +23,13 @@
   go _ x = x
   replaceVar val def' = fromMaybe def' $ val >>= toInlines
 
-applyTemplate :: [Inline] -> [Inline] -> Template -> [Inline]
-applyTemplate i t (Template g) =
+applyTemplate' :: Map String [Inline] -> Template -> [Inline]
+applyTemplate' vars (Template g) =
   normalizeInlines $ g internalVars
   where
-  internalVars "i" = Just $ MetaInlines i
-  internalVars "t" = Just $ MetaInlines t
+  internalVars x | Just v <- M.lookup x vars = Just $ MetaInlines v
   internalVars _   = Nothing
+
+applyTemplate :: [Inline] -> [Inline] -> Template -> [Inline]
+applyTemplate i t =
+  applyTemplate' (fromDistinctAscList [("i", i), ("t", t)])
diff --git a/lib/Text/Pandoc/CrossRef/Util/Util.hs b/lib/Text/Pandoc/CrossRef/Util/Util.hs
--- a/lib/Text/Pandoc/CrossRef/Util/Util.hs
+++ b/lib/Text/Pandoc/CrossRef/Util/Util.hs
@@ -1,10 +1,15 @@
-module Text.Pandoc.CrossRef.Util.Util where
+{-# LANGUAGE RankNTypes #-}
+module Text.Pandoc.CrossRef.Util.Util
+  ( module Text.Pandoc.CrossRef.Util.Util
+  , module Data.Generics
+  ) where
 
 import Text.Pandoc.CrossRef.References.Types
 import Text.Pandoc.Definition
 import Data.Char (toUpper, toLower, isUpper)
 import Data.List (intercalate)
 import Data.Maybe (fromMaybe)
+import Data.Generics
 
 isFormat :: String -> Maybe Format -> Bool
 isFormat fmt (Just (Format f)) = takeWhile (`notElem` "+-") f == fmt
@@ -24,3 +29,15 @@
 
 chapPrefix :: [Inline] -> Index -> [Inline]
 chapPrefix delim index = intercalate delim (map (return . Str . uncurry (fromMaybe . show)) index)
+
+-- | Monadic variation on everywhere'
+everywhereMBut' :: Monad m => GenericQ Bool -> GenericM m -> GenericM m
+
+-- Top-down order is also reflected in order of do-actions
+everywhereMBut' q f x
+  | q x = f x
+  | otherwise = do
+    x' <- f x
+    if q x'
+    then return x'
+    else gmapM (everywhereMBut' q f) x'
diff --git a/pandoc-crossref.cabal b/pandoc-crossref.cabal
--- a/pandoc-crossref.cabal
+++ b/pandoc-crossref.cabal
@@ -2,7 +2,7 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                pandoc-crossref
-version:             0.1.6.5
+version:             0.2.0.0
 synopsis:            Pandoc filter for cross-references
 description:         pandoc-crossref is a pandoc filter for numbering figures, equations, tables and cross-references to them.
 license:             GPL-2
@@ -16,6 +16,7 @@
                      BSD3.md
 cabal-version:       >=1.10
 data-files:          demo.md
+extra-source-files:  test/*.inc
 
 source-repository head
   type: git
@@ -24,12 +25,11 @@
 source-repository this
   type: git
   location: https://github.com/lierdakil/pandoc-crossref
-  tag: v0.1.6.5
+  tag: v0.2.0.0
 
 library
   exposed-modules:     Text.Pandoc.CrossRef
   other-modules:       Text.Pandoc.CrossRef.References
-                     , Text.Pandoc.CrossRef.References.Accessors
                      , Text.Pandoc.CrossRef.References.Blocks
                      , Text.Pandoc.CrossRef.References.List
                      , Text.Pandoc.CrossRef.References.Refs
@@ -39,21 +39,26 @@
                      , Text.Pandoc.CrossRef.Util.Options
                      , Text.Pandoc.CrossRef.Util.Template
                      , Text.Pandoc.CrossRef.Util.Util
+                     , Text.Pandoc.CrossRef.Util.CustomLabels
                      , Text.Pandoc.CrossRef.Util.CodeBlockCaptions
                      , Text.Pandoc.CrossRef.Util.ModifyMeta
                      , Text.Pandoc.CrossRef.Util.Settings.Gen
                      , Text.Pandoc.CrossRef.Util.Settings.Template
                      , Text.Pandoc.CrossRef.Util.Gap
   build-depends:       base >=4.2 && <5
-                     , pandoc >= 1.13 && <1.17
+                     , pandoc >= 1.16 && <1.17
                      , mtl >= 1.1 && <2.3
                      , containers >= 0.1 && <0.6
                      , pandoc-types >= 1.12.4.1 && < 1.17
                      , yaml >= 0.8 && <0.9
                      , data-default >= 0.4 && <0.6
                      , bytestring >=0.9 && <0.11
-                     , data-accessor >= 0.2.1.6 && < 0.3.0.0
+                     , data-accessor >= 0.2.2.6 && < 0.3.0.0
+                     , data-accessor-template >= 0.2.1.12 && < 0.3.0.0
                      , data-accessor-transformers >= 0.2.1.6 && < 0.3.0.0
+                     , template-haskell >= 2.7.0.0 && < 3.0.0.0
+                     , roman-numerals == 0.5.*
+                     , syb >= 0.4 && < 0.7
   hs-source-dirs:      lib
   Ghc-Options:         -Wall
   default-language:    Haskell2010
@@ -64,7 +69,7 @@
 executable pandoc-crossref
   main-is:             pandoc-crossref.hs
   build-depends:       base >=4.2 && <5
-                     , pandoc >= 1.13 && <1.17
+                     , pandoc >= 1.16 && <1.17
                      , mtl >= 1.1 && <2.3
                      , containers >= 0.1 && <0.6
                      , pandoc-types >= 1.12.4.1 && < 1.17
@@ -81,7 +86,7 @@
   Main-Is:        test-pandoc-crossref.hs
   hs-source-dirs: test, lib
   Build-Depends:   base >=4.2 && <5
-                 , pandoc >= 1.13 && <1.17
+                 , pandoc >= 1.16 && <1.17
                  , mtl >= 1.1 && <2.3
                  , containers >= 0.1 && <0.6
                  , pandoc-types >= 1.12.4.1 && < 1.17
@@ -90,8 +95,12 @@
                  , bytestring >=0.9 && <0.11
                  , hspec
                  , process >=1 && <1.5
-                 , data-accessor >= 0.2.1.6 && < 0.3.0.0
+                 , data-accessor >= 0.2.2.6 && < 0.3.0.0
+                 , data-accessor-template >= 0.2.1.12 && < 0.3.0.0
                  , data-accessor-transformers >= 0.2.1.6 && < 0.3.0.0
+                 , template-haskell >= 2.7.0.0 && < 3.0.0.0
+                 , roman-numerals == 0.5.*
+                 , syb >= 0.4 && < 0.7
                  , pandoc-crossref
   other-modules: Native
   Ghc-Options:  -rtsopts -Wall -fno-warn-unused-do-bind -threaded
diff --git a/test/Native.hs b/test/Native.hs
--- a/test/Native.hs
+++ b/test/Native.hs
@@ -3,299 +3,9 @@
 
 import Text.Pandoc.Definition
 
-demo :: [Block]
-#if MIN_VERSION_pandoc(1,16,0)
-demo =
-  [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "demo",Space,Str "file",Space,Str "for",Space,Str "pandoc-crossref.",Space,Str "With",Space,Str "this",Space,Str "filter,",Space,Str "you",Space,Str "can",Space,Str "cross-reference",Space,Str "figures",Space,Str "(see",Space,Str "figs.\160\&2-4",Str "),",Space,Str "display",Space,Str "equations",Space,Str "(see",Space,Str "eq.\160\&1",Str "),",Space,Str "tables",Space,Str "(see",Space,Str "tbl.\160\&1",Str ")",Space,Str "and",Space,Str "sections",Space,Str "(",Str "secs.\160\&1,",Space,Str "2,",Space,Str "4.1-4.3",Str ")"]
-  ,Para [Str "For",Space,Str "immediate",Space,Str "example,",Space,Str "see",Space,Str "fig.\160\&1"]
-  ,Para [Image ("fig:figure0",[],[]) [Str "Figure",Space,Str "#",Space,Str "1:",Space,Str "A",Space,Str "figure"] ("img1.jpg","fig:")]
-  ,Para [Str "There",Space,Str "is",Space,Str "also",Space,Str "support",Space,Str "for",Space,Str "code",Space,Str "blocks,",Space,Str "for",Space,Str "example,",Space,Str "lsts.\160\&1-3"]
-  ,Para [Str "It's",Space,Str "possible",Space,Str "to",Space,Str "capitalize",Space,Str "reference",Space,Str "prefixes,",Space,Str "like",Space,Str "this:",Space,Str "Fig.\160\&2",Str "."]
-  ,Para [Str "In",Space,Str "case",Space,Str "of",Space,Str "multiple",Space,Str "references,",Space,Str "capitalization",Space,Str "is",Space,Str "determined",Space,Str "by",Space,Str "first",Space,Str "reference.",Space,Str "Figs.\160\&2,",Space,Str "3",Space,Str "is",Space,Str "capitalized,",Space,Str "while",Space,Str "figs.\160\&2,",Space,Str "3",Space,Str "is",Space,Str "not."]
-  ,Para [Str "It",Space,Str "is",Space,Str "also",Space,Str "possible",Space,Str "to",Space,Str "mix",Space,Str "different",Space,Str "references,",Space,Str "like",Space,Str "fig.\160\&2",Str ",",Space,Str "tbl.\160\&1",Str ",",Space,Str "lsts.\160\&1,",Space,Str "2",Str ",",Space,Str "figs.\160\&3,",Space,Str "4",Str ",",Space,Str "which",Space,Str "will",Space,Str "be",Space,Str "grouped",Space,Str "in",Space,Str "order",Space,Str "they",Space,Str "are",Space,Str "specified.",Space,Str "You",Space,Str "can",Space,Str "even",Space,Str "intermix",Space,Str "this",Space,Str "with",Space,Str "regular",Space,Str "citations,",Space,Str "although",Space,Str "it's",Space,Str "not",Space,Str "recommended:",Space,Str "fig.\160\&2",Str ",",Space,Str "tbl.\160\&1",Str ",",Space,Cite [Citation {citationId = "unprocessedCitation", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@unprocessedCitation]"]]
-  ,Para [Str "You",Space,Str "can",Space,Str "also",Space,Str "have",Space,Str "custom",Space,Str "chapter",Space,Str "reference",Space,Str "labels,",Space,Str "like",Space,Str "sec.\160AppA.CustLab"]
-  ,Header 1 ("sec:sec1",[],[]) [Str "Chapter",Space,Str "1.",Space,Str "Figures"]
-  ,Para [Image ("fig:figure1",[],[]) [Str "Figure",Space,Str "#",Space,Str "2:",Space,Str "First",Space,Str "figure"] ("img1.jpg","fig:")]
-  ,Para [Image ("fig:figure2",[],[]) [Str "Figure",Space,Str "#",Space,Str "3:",Space,Str "Second",Space,Str "figure"] ("img2.jpg","fig:")]
-  ,Para [Image ("fig:figure3",[],[]) [Str "Figure",Space,Str "#",Space,Str "4:",Space,Str "Third",Space,Str "figure"] ("img3.jpg","fig:")]
-  ,Para [Image ("",[],[]) [Str "Unlabelled",Space,Str "image"] ("img1.jpg","fig:")]
-  ,Header 1 ("sec:sec2",[],[]) [Str "Chapter",Space,Str "2.",Space,Str "Equations"]
-  ,Para [Str "Display",Space,Str "equations",Space,Str "are",Space,Str "labelled",Space,Str "and",Space,Str "numbered"]
-  ,Para [Math DisplayMath " P_i(x) = \\sum_i a_i x^i \\qquad(1)"]
-  ,Para [Str "Since",Space,Str "0.1.6.0",Space,Str "those",Space,Str "can",Space,Str "also",Space,Str "appear",Space,Str "in",Space,Str "the",Space,Str "middle",Space,Str "of",Space,Str "paragraph",SoftBreak,Math DisplayMath "a x^2 + b x^2 + c = 0\\qquad(2)",Space,Str "like",Space,Str "this."]
-  ,Header 1 ("sec:chapter-3.-tables",[],[]) [Str "Chapter",Space,Str "3.",Space,Str "Tables"]
-  ,Table [Emph [Str "Table",Space,Str "1"],Str ":",Space,Str "Table",Space,Str "example"] [AlignLeft,AlignLeft] [0.0,0.0]
-   [[Plain [Str "First",Space,Str "Header"]]
-   ,[Plain [Str "Second",Space,Str "Header"]]]
-   [[[Plain [Str "Content",Space,Str "Cell"]]
-    ,[Plain [Str "Content",Space,Str "Cell"]]]
-   ,[[Plain [Str "Content",Space,Str "Cell"]]
-    ,[Plain [Str "Content",Space,Str "Cell"]]]]
-  ,Para [Str "Table",Space,Str "without",Space,Str "caption:"]
-  ,Table [] [AlignLeft,AlignLeft] [0.0,0.0]
-   [[Plain [Str "First",Space,Str "Header"]]
-   ,[Plain [Str "Second",Space,Str "Header"]]]
-   [[[Plain [Str "Content",Space,Str "Cell"]]
-    ,[Plain [Str "Content",Space,Str "Cell"]]]
-   ,[[Plain [Str "Content",Space,Str "Cell"]]
-    ,[Plain [Str "Content",Space,Str "Cell"]]]]
-  ,Header 1 ("sec:chapter-4.-code-blocks",[],[]) [Str "Chapter",Space,Str "4.",Space,Str "Code",Space,Str "blocks"]
-  ,Para [Str "There",Space,Str "are",Space,Str "a",Space,Str "couple",Space,Str "options",Space,Str "for",Space,Str "code",Space,Str "block",Space,Str "labels.",Space,Str "Those",Space,Str "work",Space,Str "only",Space,Str "if",Space,Str "code",Space,Str "block",Space,Str "id",Space,Str "starts",Space,Str "with",Space,Code ("",[],[]) "lst:",Str ",",Space,Str "e.g.",Space,Code ("",[],[]) "{#lst:label}"]
-  ,Header 2 ("sec:caption-attr",[],[]) [Code ("",[],[]) "caption",Space,Str "attribute"]
-  ,Para [Code ("",[],[]) "caption",Space,Str "attribute",Space,Str "will",Space,Str "be",Space,Str "treated",Space,Str "as",Space,Str "code",Space,Str "block",Space,Str "caption.",Space,Str "If",Space,Str "code",Space,Str "block",Space,Str "has",Space,Str "both",Space,Str "id",Space,Str "and",Space,Code ("",[],[]) "caption",Space,Str "attributes,",Space,Str "it",Space,Str "will",Space,Str "be",Space,Str "treated",Space,Str "as",Space,Str "numbered",Space,Str "code",Space,Str "block."]
-  ,Div ("lst:captionAttr",["listing","haskell"],[])
-   [Para [Str "Listing",Space,Str "1:",Space,Str "Listing",Space,Str "caption"]
-   ,CodeBlock ("",["haskell"],[]) "main :: IO ()\nmain = putStrLn \"Hello World!\""]
-  ,Para [RawInline (Format "tex") "\\pagebreak"]
-  ,Header 2 ("sec:table-capts",[],[]) [Str "Table-style",Space,Str "captions"]
-  ,Para [Str "Enabled",Space,Str "with",Space,Code ("",[],[]) "codeBlockCaptions",Space,Str "metadata",Space,Str "option.",Space,Str "If",Space,Str "code",Space,Str "block",Space,Str "is",Space,Str "immediately",SoftBreak,Str "adjacent",Space,Str "to",Space,Str "paragraph,",Space,Str "starting",Space,Str "with",Space,Code ("",[],[]) "Listing:",Space,Str "or",Space,Code ("",[],[]) ":",Str ",",Space,Str "said",Space,Str "paragraph",Space,Str "will",Space,Str "be",SoftBreak,Str "treated",Space,Str "as",Space,Str "code",Space,Str "block",Space,Str "caption."]
-  ,Div ("lst:tableCaption",["listing","haskell"],[])
-   [Para [Str "Listing",Space,Str "2:",Space,Str "Listing",Space,Str "caption"]
-   ,CodeBlock ("",["haskell"],[]) "main :: IO ()\nmain = putStrLn \"Hello World!\""]
-  ,Header 2 ("sec:wrapping-div",[],[]) [Str "Wrapping",Space,Str "div"]
-  ,Para [Str "Wrapping",Space,Str "code",Space,Str "block",Space,Str "without",Space,Str "label",Space,Str "in",Space,Str "a",Space,Str "div",Space,Str "with",Space,Str "id",Space,Code ("",[],[]) "lst:...",Space,Str "and",Space,Str "class,",Space,Str "starting",Space,Str "with",Space,Code ("",[],[]) "listing",Str ",",Space,Str "and",Space,Str "adding",Space,Str "paragraph",Space,Str "before",Space,Str "code",Space,Str "block,",Space,Str "but",Space,Str "inside",Space,Str "div,",Space,Str "will",Space,Str "treat",Space,Str "said",Space,Str "paragraph",Space,Str "as",Space,Str "code",Space,Str "block",Space,Str "caption."]
-  ,Div ("lst:wrappingDiv",["listing","haskell"],[])
-   [Para [Str "Listing",Space,Str "3:",Space,Str "Listing",Space,Str "caption"]
-   ,CodeBlock ("",["haskell"],[]) "main :: IO ()\nmain = putStrLn \"Hello World!\""]
-  ,Header 1 ("sec:unnumbered-chapter.",["unnumbered"],[]) [Str "Unnumbered",Space,Str "chapter."]
-  ,Para [Str "This",Space,Str "chapter",Space,Str "doesn't",Space,Str "change",Space,Str "chapter",Space,Str "prefix",Space,Str "of",Space,Str "referenced",Space,Str "elements,",Space,Str "instead",Space,Str "keeping",Space,Str "number",Space,Str "of",Space,Str "previous",Space,Str "chapter,",Space,Str "e.g.",SoftBreak,Math DisplayMath " S(x) = \\int_{x_1}^{x_2} a x+b \\  \\mathrm{d}x \\qquad(3)"]
-  ,Header 1 ("sec:chapter-5.-reference-lists",[],[]) [Str "Chapter",Space,Str "5.",Space,Str "Reference",Space,Str "lists"]
-  ,Para [Str "It's",Space,Str "also",Space,Str "possible",Space,Str "to",Space,Str "show",Space,Str "lists",Space,Str "of",Space,Str "figures",Space,Str "and",Space,Str "tables,",Space,Str "like",Space,Str "this:"]
-  ,Header 2 ("list-of-figures",[],[]) [Str "List",Space,Str "of",Space,Str "Figures"]
-  ,OrderedList (1,DefaultStyle,DefaultDelim)
-   [[Plain [Str "A",Space,Str "figure"]]
-   ,[Plain [Str "First",Space,Str "figure"]]
-   ,[Plain [Str "Second",Space,Str "figure"]]
-   ,[Plain [Str "Third",Space,Str "figure"]]]
-  ,Header 2 ("list-of-tables",[],[]) [Str "List",Space,Str "of",Space,Str "Tables"]
-  ,OrderedList (1,DefaultStyle,DefaultDelim)
-   [[Plain [Str "Table",Space,Str "example"]]]
-  ,Header 1 ("",[],[]) [Str "List",Space,Str "of",Space,Str "Listings"]
-  ,OrderedList (1,DefaultStyle,DefaultDelim)
-   [[Plain [Str "Listing",Space,Str "caption"]]
-   ,[Plain [Str "Listing",Space,Str "caption"]]
-   ,[Plain [Str "Listing",Space,Str "caption"]]]
-  ,Header 1 ("sec:appendix-a.-custom-labels",[],[("label","AppA")]) [Str "Appendix",Space,Str "A.",Space,Str "Custom",Space,Str "labels"]
-  ,Header 2 ("sec:custlabs",[],[("label","CustLab")]) [Str "This",Space,Str "section",Space,Str "will",Space,Str "have",Space,Str "custom",Space,Str "label"]]
+demo, demochapters :: [Block]
 
-demochapters :: [Block]
-demochapters =
-  [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "demo",Space,Str "file",Space,Str "for",Space,Str "pandoc-crossref.",Space,Str "With",Space,Str "this",Space,Str "filter,",Space,Str "you",Space,Str "can",Space,Str "cross-reference",Space,Str "figures",Space,Str "(see",Space,Str "figs.\160\&1.1-1.3",Str "),",Space,Str "display",Space,Str "equations",Space,Str "(see",Space,Str "eq.\160\&2.1",Str "),",Space,Str "tables",Space,Str "(see",Space,Str "tbl.\160\&3.1",Str ")",Space,Str "and",Space,Str "sections",Space,Str "(",Str "secs.\160\&1,",Space,Str "2,",Space,Str "4.1-4.3",Str ")"]
-  ,Para [Str "For",Space,Str "immediate",Space,Str "example,",Space,Str "see",Space,Str "fig.\160\&1"]
-  ,Para [Image ("fig:figure0",[],[]) [Str "Figure",Space,Str "#",Space,Str "1:",Space,Str "A",Space,Str "figure"] ("img1.jpg","fig:")]
-  ,Para [Str "There",Space,Str "is",Space,Str "also",Space,Str "support",Space,Str "for",Space,Str "code",Space,Str "blocks,",Space,Str "for",Space,Str "example,",Space,Str "lsts.\160\&4.1-4.3"]
-  ,Para [Str "It's",Space,Str "possible",Space,Str "to",Space,Str "capitalize",Space,Str "reference",Space,Str "prefixes,",Space,Str "like",Space,Str "this:",Space,Str "Fig.\160\&1.1",Str "."]
-  ,Para [Str "In",Space,Str "case",Space,Str "of",Space,Str "multiple",Space,Str "references,",Space,Str "capitalization",Space,Str "is",Space,Str "determined",Space,Str "by",Space,Str "first",Space,Str "reference.",Space,Str "Figs.\160\&1.1,",Space,Str "1.2",Space,Str "is",Space,Str "capitalized,",Space,Str "while",Space,Str "figs.\160\&1.1,",Space,Str "1.2",Space,Str "is",Space,Str "not."]
-  ,Para [Str "It",Space,Str "is",Space,Str "also",Space,Str "possible",Space,Str "to",Space,Str "mix",Space,Str "different",Space,Str "references,",Space,Str "like",Space,Str "fig.\160\&1.1",Str ",",Space,Str "tbl.\160\&3.1",Str ",",Space,Str "lsts.\160\&4.1,",Space,Str "4.2",Str ",",Space,Str "figs.\160\&1.2,",Space,Str "1.3",Str ",",Space,Str "which",Space,Str "will",Space,Str "be",Space,Str "grouped",Space,Str "in",Space,Str "order",Space,Str "they",Space,Str "are",Space,Str "specified.",Space,Str "You",Space,Str "can",Space,Str "even",Space,Str "intermix",Space,Str "this",Space,Str "with",Space,Str "regular",Space,Str "citations,",Space,Str "although",Space,Str "it's",Space,Str "not",Space,Str "recommended:",Space,Str "fig.\160\&1.1",Str ",",Space,Str "tbl.\160\&3.1",Str ",",Space,Cite [Citation {citationId = "unprocessedCitation", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@unprocessedCitation]"]]
-  ,Para [Str "You",Space,Str "can",Space,Str "also",Space,Str "have",Space,Str "custom",Space,Str "chapter",Space,Str "reference",Space,Str "labels,",Space,Str "like",Space,Str "sec.\160AppA.CustLab"]
-  ,Header 1 ("sec:sec1",[],[]) [Str "Chapter",Space,Str "1.",Space,Str "Figures"]
-  ,Para [Image ("fig:figure1",[],[]) [Str "Figure",Space,Str "#",Space,Str "1.1:",Space,Str "First",Space,Str "figure"] ("img1.jpg","fig:")]
-  ,Para [Image ("fig:figure2",[],[]) [Str "Figure",Space,Str "#",Space,Str "1.2:",Space,Str "Second",Space,Str "figure"] ("img2.jpg","fig:")]
-  ,Para [Image ("fig:figure3",[],[]) [Str "Figure",Space,Str "#",Space,Str "1.3:",Space,Str "Third",Space,Str "figure"] ("img3.jpg","fig:")]
-  ,Para [Image ("",[],[]) [Str "Unlabelled",Space,Str "image"] ("img1.jpg","fig:")]
-  ,Header 1 ("sec:sec2",[],[]) [Str "Chapter",Space,Str "2.",Space,Str "Equations"]
-  ,Para [Str "Display",Space,Str "equations",Space,Str "are",Space,Str "labelled",Space,Str "and",Space,Str "numbered"]
-  ,Para [Math DisplayMath " P_i(x) = \\sum_i a_i x^i \\qquad(2.1)"]
-  ,Para [Str "Since",Space,Str "0.1.6.0",Space,Str "those",Space,Str "can",Space,Str "also",Space,Str "appear",Space,Str "in",Space,Str "the",Space,Str "middle",Space,Str "of",Space,Str "paragraph",SoftBreak,Math DisplayMath "a x^2 + b x^2 + c = 0\\qquad(2.2)",Space,Str "like",Space,Str "this."]
-  ,Header 1 ("sec:chapter-3.-tables",[],[]) [Str "Chapter",Space,Str "3.",Space,Str "Tables"]
-  ,Table [Emph [Str "Table",Space,Str "3.1"],Str ":",Space,Str "Table",Space,Str "example"] [AlignLeft,AlignLeft] [0.0,0.0]
-   [[Plain [Str "First",Space,Str "Header"]]
-   ,[Plain [Str "Second",Space,Str "Header"]]]
-   [[[Plain [Str "Content",Space,Str "Cell"]]
-    ,[Plain [Str "Content",Space,Str "Cell"]]]
-   ,[[Plain [Str "Content",Space,Str "Cell"]]
-    ,[Plain [Str "Content",Space,Str "Cell"]]]]
-  ,Para [Str "Table",Space,Str "without",Space,Str "caption:"]
-  ,Table [] [AlignLeft,AlignLeft] [0.0,0.0]
-   [[Plain [Str "First",Space,Str "Header"]]
-   ,[Plain [Str "Second",Space,Str "Header"]]]
-   [[[Plain [Str "Content",Space,Str "Cell"]]
-    ,[Plain [Str "Content",Space,Str "Cell"]]]
-   ,[[Plain [Str "Content",Space,Str "Cell"]]
-    ,[Plain [Str "Content",Space,Str "Cell"]]]]
-  ,Header 1 ("sec:chapter-4.-code-blocks",[],[]) [Str "Chapter",Space,Str "4.",Space,Str "Code",Space,Str "blocks"]
-  ,Para [Str "There",Space,Str "are",Space,Str "a",Space,Str "couple",Space,Str "options",Space,Str "for",Space,Str "code",Space,Str "block",Space,Str "labels.",Space,Str "Those",Space,Str "work",Space,Str "only",Space,Str "if",Space,Str "code",Space,Str "block",Space,Str "id",Space,Str "starts",Space,Str "with",Space,Code ("",[],[]) "lst:",Str ",",Space,Str "e.g.",Space,Code ("",[],[]) "{#lst:label}"]
-  ,Header 2 ("sec:caption-attr",[],[]) [Code ("",[],[]) "caption",Space,Str "attribute"]
-  ,Para [Code ("",[],[]) "caption",Space,Str "attribute",Space,Str "will",Space,Str "be",Space,Str "treated",Space,Str "as",Space,Str "code",Space,Str "block",Space,Str "caption.",Space,Str "If",Space,Str "code",Space,Str "block",Space,Str "has",Space,Str "both",Space,Str "id",Space,Str "and",Space,Code ("",[],[]) "caption",Space,Str "attributes,",Space,Str "it",Space,Str "will",Space,Str "be",Space,Str "treated",Space,Str "as",Space,Str "numbered",Space,Str "code",Space,Str "block."]
-  ,Div ("lst:captionAttr",["listing","haskell"],[])
-   [Para [Str "Listing",Space,Str "4.1:",Space,Str "Listing",Space,Str "caption"]
-   ,CodeBlock ("",["haskell"],[]) "main :: IO ()\nmain = putStrLn \"Hello World!\""]
-  ,Para [RawInline (Format "tex") "\\pagebreak"]
-  ,Header 2 ("sec:table-capts",[],[]) [Str "Table-style",Space,Str "captions"]
-  ,Para [Str "Enabled",Space,Str "with",Space,Code ("",[],[]) "codeBlockCaptions",Space,Str "metadata",Space,Str "option.",Space,Str "If",Space,Str "code",Space,Str "block",Space,Str "is",Space,Str "immediately",SoftBreak,Str "adjacent",Space,Str "to",Space,Str "paragraph,",Space,Str "starting",Space,Str "with",Space,Code ("",[],[]) "Listing:",Space,Str "or",Space,Code ("",[],[]) ":",Str ",",Space,Str "said",Space,Str "paragraph",Space,Str "will",Space,Str "be",SoftBreak,Str "treated",Space,Str "as",Space,Str "code",Space,Str "block",Space,Str "caption."]
-  ,Div ("lst:tableCaption",["listing","haskell"],[])
-   [Para [Str "Listing",Space,Str "4.2:",Space,Str "Listing",Space,Str "caption"]
-   ,CodeBlock ("",["haskell"],[]) "main :: IO ()\nmain = putStrLn \"Hello World!\""]
-  ,Header 2 ("sec:wrapping-div",[],[]) [Str "Wrapping",Space,Str "div"]
-  ,Para [Str "Wrapping",Space,Str "code",Space,Str "block",Space,Str "without",Space,Str "label",Space,Str "in",Space,Str "a",Space,Str "div",Space,Str "with",Space,Str "id",Space,Code ("",[],[]) "lst:...",Space,Str "and",Space,Str "class,",Space,Str "starting",Space,Str "with",Space,Code ("",[],[]) "listing",Str ",",Space,Str "and",Space,Str "adding",Space,Str "paragraph",Space,Str "before",Space,Str "code",Space,Str "block,",Space,Str "but",Space,Str "inside",Space,Str "div,",Space,Str "will",Space,Str "treat",Space,Str "said",Space,Str "paragraph",Space,Str "as",Space,Str "code",Space,Str "block",Space,Str "caption."]
-  ,Div ("lst:wrappingDiv",["listing","haskell"],[])
-   [Para [Str "Listing",Space,Str "4.3:",Space,Str "Listing",Space,Str "caption"]
-   ,CodeBlock ("",["haskell"],[]) "main :: IO ()\nmain = putStrLn \"Hello World!\""]
-  ,Header 1 ("sec:unnumbered-chapter.",["unnumbered"],[]) [Str "Unnumbered",Space,Str "chapter."]
-  ,Para [Str "This",Space,Str "chapter",Space,Str "doesn't",Space,Str "change",Space,Str "chapter",Space,Str "prefix",Space,Str "of",Space,Str "referenced",Space,Str "elements,",Space,Str "instead",Space,Str "keeping",Space,Str "number",Space,Str "of",Space,Str "previous",Space,Str "chapter,",Space,Str "e.g.",SoftBreak,Math DisplayMath " S(x) = \\int_{x_1}^{x_2} a x+b \\  \\mathrm{d}x \\qquad(4.1)"]
-  ,Header 1 ("sec:chapter-5.-reference-lists",[],[]) [Str "Chapter",Space,Str "5.",Space,Str "Reference",Space,Str "lists"]
-  ,Para [Str "It's",Space,Str "also",Space,Str "possible",Space,Str "to",Space,Str "show",Space,Str "lists",Space,Str "of",Space,Str "figures",Space,Str "and",Space,Str "tables,",Space,Str "like",Space,Str "this:"]
-  ,Header 2 ("list-of-figures",[],[]) [Str "List",Space,Str "of",Space,Str "Figures"]
-  ,Div ("",["list"],[])
-   [Para [Str "1",Space,Str "A",Space,Str "figure"]
-   ,Para [Str "1",Str ".",Str "1",Space,Str "First",Space,Str "figure"]
-   ,Para [Str "1",Str ".",Str "2",Space,Str "Second",Space,Str "figure"]
-   ,Para [Str "1",Str ".",Str "3",Space,Str "Third",Space,Str "figure"]]
-  ,Header 2 ("list-of-tables",[],[]) [Str "List",Space,Str "of",Space,Str "Tables"]
-  ,Div ("",["list"],[])
-   [Para [Str "3",Str ".",Str "1",Space,Str "Table",Space,Str "example"]]
-  ,Header 1 ("",[],[]) [Str "List",Space,Str "of",Space,Str "Listings"]
-  ,Div ("",["list"],[])
-   [Para [Str "4",Str ".",Str "1",Space,Str "Listing",Space,Str "caption"]
-   ,Para [Str "4",Str ".",Str "2",Space,Str "Listing",Space,Str "caption"]
-   ,Para [Str "4",Str ".",Str "3",Space,Str "Listing",Space,Str "caption"]]
-  ,Header 1 ("sec:appendix-a.-custom-labels",[],[("label","AppA")]) [Str "Appendix",Space,Str "A.",Space,Str "Custom",Space,Str "labels"]
-  ,Header 2 ("sec:custlabs",[],[("label","CustLab")]) [Str "This",Space,Str "section",Space,Str "will",Space,Str "have",Space,Str "custom",Space,Str "label"]]
-#else
 demo =
-  [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "demo",Space,Str "file",Space,Str "for",Space,Str "pandoc-crossref.",Space,Str "With",Space,Str "this",Space,Str "filter,",Space,Str "you",Space,Str "can",Space,Str "cross-reference",Space,Str "figures",Space,Str "(see",Space,Str "figs.\160\&2-4",Str "),",Space,Str "display",Space,Str "equations",Space,Str "(see",Space,Str "eq.\160\&1",Str "),",Space,Str "tables",Space,Str "(see",Space,Str "tbl.\160\&1",Str ")",Space,Str "and",Space,Str "sections",Space,Str "(",Str "secs.\160\&1,",Space,Str "2,",Space,Str "4.1-4.3",Str ")"]
-  ,Para [Str "For",Space,Str "immediate",Space,Str "example,",Space,Str "see",Space,Str "fig.\160\&1"]
-  ,Para [Image [Str "Figure",Space,Str "#",Space,Str "1:",Space,Str "A",Space,Str "figure"] ("img1.jpg","fig:")]
-  ,Para [Str "There",Space,Str "is",Space,Str "also",Space,Str "support",Space,Str "for",Space,Str "code",Space,Str "blocks,",Space,Str "for",Space,Str "example,",Space,Str "lsts.\160\&1-3"]
-  ,Para [Str "It's",Space,Str "possible",Space,Str "to",Space,Str "capitalize",Space,Str "reference",Space,Str "prefixes,",Space,Str "like",Space,Str "this:",Space,Str "Fig.\160\&2",Str "."]
-  ,Para [Str "In",Space,Str "case",Space,Str "of",Space,Str "multiple",Space,Str "references,",Space,Str "capitalization",Space,Str "is",Space,Str "determined",Space,Str "by",Space,Str "first",Space,Str "reference.",Space,Str "Figs.\160\&2,",Space,Str "3",Space,Str "is",Space,Str "capitalized,",Space,Str "while",Space,Str "figs.\160\&2,",Space,Str "3",Space,Str "is",Space,Str "not."]
-  ,Para [Str "It",Space,Str "is",Space,Str "also",Space,Str "possible",Space,Str "to",Space,Str "mix",Space,Str "different",Space,Str "references,",Space,Str "like",Space,Str "fig.\160\&2",Str ",",Space,Str "tbl.\160\&1",Str ",",Space,Str "lsts.\160\&1,",Space,Str "2",Str ",",Space,Str "figs.\160\&3,",Space,Str "4",Str ",",Space,Str "which",Space,Str "will",Space,Str "be",Space,Str "grouped",Space,Str "in",Space,Str "order",Space,Str "they",Space,Str "are",Space,Str "specified.",Space,Str "You",Space,Str "can",Space,Str "even",Space,Str "intermix",Space,Str "this",Space,Str "with",Space,Str "regular",Space,Str "citations,",Space,Str "although",Space,Str "it's",Space,Str "not",Space,Str "recommended:",Space,Str "fig.\160\&2",Str ",",Space,Str "tbl.\160\&1",Str ",",Space,Cite [Citation {citationId = "unprocessedCitation", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@unprocessedCitation]"]]
-  ,Para [Str "You",Space,Str "can",Space,Str "also",Space,Str "have",Space,Str "custom",Space,Str "chapter",Space,Str "reference",Space,Str "labels,",Space,Str "like",Space,Str "sec.\160AppA.CustLab"]
-  ,Header 1 ("sec:sec1",[],[]) [Str "Chapter",Space,Str "1.",Space,Str "Figures"]
-  ,Para [Image [Str "Figure",Space,Str "#",Space,Str "2:",Space,Str "First",Space,Str "figure"] ("img1.jpg","fig:")]
-  ,Para [Image [Str "Figure",Space,Str "#",Space,Str "3:",Space,Str "Second",Space,Str "figure"] ("img2.jpg","fig:")]
-  ,Para [Image [Str "Figure",Space,Str "#",Space,Str "4:",Space,Str "Third",Space,Str "figure"] ("img3.jpg","fig:")]
-  ,Para [Image [Str "Unlabelled",Space,Str "image"] ("img1.jpg","fig:")]
-  ,Header 1 ("sec:sec2",[],[]) [Str "Chapter",Space,Str "2.",Space,Str "Equations"]
-  ,Para [Str "Display",Space,Str "equations",Space,Str "are",Space,Str "labelled",Space,Str "and",Space,Str "numbered"]
-  ,Para [Math DisplayMath " P_i(x) = \\sum_i a_i x^i \\qquad(1)"]
-  ,Para [Str "Since",Space,Str "0.1.6.0",Space,Str "those",Space,Str "can",Space,Str "also",Space,Str "appear",Space,Str "in",Space,Str "the",Space,Str "middle",Space,Str "of",Space,Str "paragraph",Space,Math DisplayMath "a x^2 + b x^2 + c = 0\\qquad(2)",Space,Str "like",Space,Str "this."]
-  ,Header 1 ("sec:chapter-3.-tables",[],[]) [Str "Chapter",Space,Str "3.",Space,Str "Tables"]
-  ,Table [Emph [Str "Table",Space,Str "1"],Str ":",Space,Str "Table",Space,Str "example"] [AlignLeft,AlignLeft] [0.0,0.0]
-   [[Plain [Str "First",Space,Str "Header"]]
-   ,[Plain [Str "Second",Space,Str "Header"]]]
-   [[[Plain [Str "Content",Space,Str "Cell"]]
-    ,[Plain [Str "Content",Space,Str "Cell"]]]
-   ,[[Plain [Str "Content",Space,Str "Cell"]]
-    ,[Plain [Str "Content",Space,Str "Cell"]]]]
-  ,Para [Str "Table",Space,Str "without",Space,Str "caption:"]
-  ,Table [] [AlignLeft,AlignLeft] [0.0,0.0]
-   [[Plain [Str "First",Space,Str "Header"]]
-   ,[Plain [Str "Second",Space,Str "Header"]]]
-   [[[Plain [Str "Content",Space,Str "Cell"]]
-    ,[Plain [Str "Content",Space,Str "Cell"]]]
-   ,[[Plain [Str "Content",Space,Str "Cell"]]
-    ,[Plain [Str "Content",Space,Str "Cell"]]]]
-  ,Header 1 ("sec:chapter-4.-code-blocks",[],[]) [Str "Chapter",Space,Str "4.",Space,Str "Code",Space,Str "blocks"]
-  ,Para [Str "There",Space,Str "are",Space,Str "a",Space,Str "couple",Space,Str "options",Space,Str "for",Space,Str "code",Space,Str "block",Space,Str "labels.",Space,Str "Those",Space,Str "work",Space,Str "only",Space,Str "if",Space,Str "code",Space,Str "block",Space,Str "id",Space,Str "starts",Space,Str "with",Space,Code ("",[],[]) "lst:",Str ",",Space,Str "e.g.",Space,Code ("",[],[]) "{#lst:label}"]
-  ,Header 2 ("sec:caption-attr",[],[]) [Code ("",[],[]) "caption",Space,Str "attribute"]
-  ,Para [Code ("",[],[]) "caption",Space,Str "attribute",Space,Str "will",Space,Str "be",Space,Str "treated",Space,Str "as",Space,Str "code",Space,Str "block",Space,Str "caption.",Space,Str "If",Space,Str "code",Space,Str "block",Space,Str "has",Space,Str "both",Space,Str "id",Space,Str "and",Space,Code ("",[],[]) "caption",Space,Str "attributes,",Space,Str "it",Space,Str "will",Space,Str "be",Space,Str "treated",Space,Str "as",Space,Str "numbered",Space,Str "code",Space,Str "block."]
-  ,Div ("lst:captionAttr",["listing","haskell"],[])
-   [Para [Str "Listing",Space,Str "1:",Space,Str "Listing",Space,Str "caption"]
-   ,CodeBlock ("",["haskell"],[]) "main :: IO ()\nmain = putStrLn \"Hello World!\""]
-  ,Para [RawInline (Format "tex") "\\pagebreak"]
-  ,Header 2 ("sec:table-capts",[],[]) [Str "Table-style",Space,Str "captions"]
-  ,Para [Str "Enabled",Space,Str "with",Space,Code ("",[],[]) "codeBlockCaptions",Space,Str "metadata",Space,Str "option.",Space,Str "If",Space,Str "code",Space,Str "block",Space,Str "is",Space,Str "immediately",Space,Str "adjacent",Space,Str "to",Space,Str "paragraph,",Space,Str "starting",Space,Str "with",Space,Code ("",[],[]) "Listing:",Space,Str "or",Space,Code ("",[],[]) ":",Str ",",Space,Str "said",Space,Str "paragraph",Space,Str "will",Space,Str "be",Space,Str "treated",Space,Str "as",Space,Str "code",Space,Str "block",Space,Str "caption."]
-  ,Div ("lst:tableCaption",["listing","haskell"],[])
-   [Para [Str "Listing",Space,Str "2:",Space,Str "Listing",Space,Str "caption"]
-   ,CodeBlock ("",["haskell"],[]) "main :: IO ()\nmain = putStrLn \"Hello World!\""]
-  ,Header 2 ("sec:wrapping-div",[],[]) [Str "Wrapping",Space,Str "div"]
-  ,Para [Str "Wrapping",Space,Str "code",Space,Str "block",Space,Str "without",Space,Str "label",Space,Str "in",Space,Str "a",Space,Str "div",Space,Str "with",Space,Str "id",Space,Code ("",[],[]) "lst:...",Space,Str "and",Space,Str "class,",Space,Str "starting",Space,Str "with",Space,Code ("",[],[]) "listing",Str ",",Space,Str "and",Space,Str "adding",Space,Str "paragraph",Space,Str "before",Space,Str "code",Space,Str "block,",Space,Str "but",Space,Str "inside",Space,Str "div,",Space,Str "will",Space,Str "treat",Space,Str "said",Space,Str "paragraph",Space,Str "as",Space,Str "code",Space,Str "block",Space,Str "caption."]
-  ,Div ("lst:wrappingDiv",["listing","haskell"],[])
-   [Para [Str "Listing",Space,Str "3:",Space,Str "Listing",Space,Str "caption"]
-   ,CodeBlock ("",["haskell"],[]) "main :: IO ()\nmain = putStrLn \"Hello World!\""]
-  ,Header 1 ("sec:unnumbered-chapter.",["unnumbered"],[]) [Str "Unnumbered",Space,Str "chapter."]
-  ,Para [Str "This",Space,Str "chapter",Space,Str "doesn't",Space,Str "change",Space,Str "chapter",Space,Str "prefix",Space,Str "of",Space,Str "referenced",Space,Str "elements,",Space,Str "instead",Space,Str "keeping",Space,Str "number",Space,Str "of",Space,Str "previous",Space,Str "chapter,",Space,Str "e.g.",Space,Math DisplayMath " S(x) = \\int_{x_1}^{x_2} a x+b \\  \\mathrm{d}x \\qquad(3)"]
-  ,Header 1 ("sec:chapter-5.-reference-lists",[],[]) [Str "Chapter",Space,Str "5.",Space,Str "Reference",Space,Str "lists"]
-  ,Para [Str "It's",Space,Str "also",Space,Str "possible",Space,Str "to",Space,Str "show",Space,Str "lists",Space,Str "of",Space,Str "figures",Space,Str "and",Space,Str "tables,",Space,Str "like",Space,Str "this:"]
-  ,Header 2 ("list-of-figures",[],[]) [Str "List",Space,Str "of",Space,Str "Figures"]
-  ,OrderedList (1,DefaultStyle,DefaultDelim)
-   [[Plain [Str "A",Space,Str "figure"]]
-   ,[Plain [Str "First",Space,Str "figure"]]
-   ,[Plain [Str "Second",Space,Str "figure"]]
-   ,[Plain [Str "Third",Space,Str "figure"]]]
-  ,Header 2 ("list-of-tables",[],[]) [Str "List",Space,Str "of",Space,Str "Tables"]
-  ,OrderedList (1,DefaultStyle,DefaultDelim)
-   [[Plain [Str "Table",Space,Str "example"]]]
-  ,Header 1 ("",[],[]) [Str "List",Space,Str "of",Space,Str "Listings"]
-  ,OrderedList (1,DefaultStyle,DefaultDelim)
-   [[Plain [Str "Listing",Space,Str "caption"]]
-   ,[Plain [Str "Listing",Space,Str "caption"]]
-   ,[Plain [Str "Listing",Space,Str "caption"]]]
-  ,Header 1 ("sec:appendix-a.-custom-labels",[],[("label","AppA")]) [Str "Appendix",Space,Str "A.",Space,Str "Custom",Space,Str "labels"]
-  ,Header 2 ("sec:custlabs",[],[("label","CustLab")]) [Str "This",Space,Str "section",Space,Str "will",Space,Str "have",Space,Str "custom",Space,Str "label"]]
-
-demochapters :: [Block]
+#include "demo.inc"
 demochapters =
-  [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "demo",Space,Str "file",Space,Str "for",Space,Str "pandoc-crossref.",Space,Str "With",Space,Str "this",Space,Str "filter,",Space,Str "you",Space,Str "can",Space,Str "cross-reference",Space,Str "figures",Space,Str "(see",Space,Str "figs.\160\&1.1-1.3",Str "),",Space,Str "display",Space,Str "equations",Space,Str "(see",Space,Str "eq.\160\&2.1",Str "),",Space,Str "tables",Space,Str "(see",Space,Str "tbl.\160\&3.1",Str ")",Space,Str "and",Space,Str "sections",Space,Str "(",Str "secs.\160\&1,",Space,Str "2,",Space,Str "4.1-4.3",Str ")"]
-  ,Para [Str "For",Space,Str "immediate",Space,Str "example,",Space,Str "see",Space,Str "fig.\160\&1"]
-  ,Para [Image [Str "Figure",Space,Str "#",Space,Str "1:",Space,Str "A",Space,Str "figure"] ("img1.jpg","fig:")]
-  ,Para [Str "There",Space,Str "is",Space,Str "also",Space,Str "support",Space,Str "for",Space,Str "code",Space,Str "blocks,",Space,Str "for",Space,Str "example,",Space,Str "lsts.\160\&4.1-4.3"]
-  ,Para [Str "It's",Space,Str "possible",Space,Str "to",Space,Str "capitalize",Space,Str "reference",Space,Str "prefixes,",Space,Str "like",Space,Str "this:",Space,Str "Fig.\160\&1.1",Str "."]
-  ,Para [Str "In",Space,Str "case",Space,Str "of",Space,Str "multiple",Space,Str "references,",Space,Str "capitalization",Space,Str "is",Space,Str "determined",Space,Str "by",Space,Str "first",Space,Str "reference.",Space,Str "Figs.\160\&1.1,",Space,Str "1.2",Space,Str "is",Space,Str "capitalized,",Space,Str "while",Space,Str "figs.\160\&1.1,",Space,Str "1.2",Space,Str "is",Space,Str "not."]
-  ,Para [Str "It",Space,Str "is",Space,Str "also",Space,Str "possible",Space,Str "to",Space,Str "mix",Space,Str "different",Space,Str "references,",Space,Str "like",Space,Str "fig.\160\&1.1",Str ",",Space,Str "tbl.\160\&3.1",Str ",",Space,Str "lsts.\160\&4.1,",Space,Str "4.2",Str ",",Space,Str "figs.\160\&1.2,",Space,Str "1.3",Str ",",Space,Str "which",Space,Str "will",Space,Str "be",Space,Str "grouped",Space,Str "in",Space,Str "order",Space,Str "they",Space,Str "are",Space,Str "specified.",Space,Str "You",Space,Str "can",Space,Str "even",Space,Str "intermix",Space,Str "this",Space,Str "with",Space,Str "regular",Space,Str "citations,",Space,Str "although",Space,Str "it's",Space,Str "not",Space,Str "recommended:",Space,Str "fig.\160\&1.1",Str ",",Space,Str "tbl.\160\&3.1",Str ",",Space,Cite [Citation {citationId = "unprocessedCitation", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@unprocessedCitation]"]]
-  ,Para [Str "You",Space,Str "can",Space,Str "also",Space,Str "have",Space,Str "custom",Space,Str "chapter",Space,Str "reference",Space,Str "labels,",Space,Str "like",Space,Str "sec.\160AppA.CustLab"]
-  ,Header 1 ("sec:sec1",[],[]) [Str "Chapter",Space,Str "1.",Space,Str "Figures"]
-  ,Para [Image [Str "Figure",Space,Str "#",Space,Str "1.1:",Space,Str "First",Space,Str "figure"] ("img1.jpg","fig:")]
-  ,Para [Image [Str "Figure",Space,Str "#",Space,Str "1.2:",Space,Str "Second",Space,Str "figure"] ("img2.jpg","fig:")]
-  ,Para [Image [Str "Figure",Space,Str "#",Space,Str "1.3:",Space,Str "Third",Space,Str "figure"] ("img3.jpg","fig:")]
-  ,Para [Image [Str "Unlabelled",Space,Str "image"] ("img1.jpg","fig:")]
-  ,Header 1 ("sec:sec2",[],[]) [Str "Chapter",Space,Str "2.",Space,Str "Equations"]
-  ,Para [Str "Display",Space,Str "equations",Space,Str "are",Space,Str "labelled",Space,Str "and",Space,Str "numbered"]
-  ,Para [Math DisplayMath " P_i(x) = \\sum_i a_i x^i \\qquad(2.1)"]
-  ,Para [Str "Since",Space,Str "0.1.6.0",Space,Str "those",Space,Str "can",Space,Str "also",Space,Str "appear",Space,Str "in",Space,Str "the",Space,Str "middle",Space,Str "of",Space,Str "paragraph",Space,Math DisplayMath "a x^2 + b x^2 + c = 0\\qquad(2.2)",Space,Str "like",Space,Str "this."]
-  ,Header 1 ("sec:chapter-3.-tables",[],[]) [Str "Chapter",Space,Str "3.",Space,Str "Tables"]
-  ,Table [Emph [Str "Table",Space,Str "3.1"],Str ":",Space,Str "Table",Space,Str "example"] [AlignLeft,AlignLeft] [0.0,0.0]
-   [[Plain [Str "First",Space,Str "Header"]]
-   ,[Plain [Str "Second",Space,Str "Header"]]]
-   [[[Plain [Str "Content",Space,Str "Cell"]]
-    ,[Plain [Str "Content",Space,Str "Cell"]]]
-   ,[[Plain [Str "Content",Space,Str "Cell"]]
-    ,[Plain [Str "Content",Space,Str "Cell"]]]]
-  ,Para [Str "Table",Space,Str "without",Space,Str "caption:"]
-  ,Table [] [AlignLeft,AlignLeft] [0.0,0.0]
-   [[Plain [Str "First",Space,Str "Header"]]
-   ,[Plain [Str "Second",Space,Str "Header"]]]
-   [[[Plain [Str "Content",Space,Str "Cell"]]
-    ,[Plain [Str "Content",Space,Str "Cell"]]]
-   ,[[Plain [Str "Content",Space,Str "Cell"]]
-    ,[Plain [Str "Content",Space,Str "Cell"]]]]
-  ,Header 1 ("sec:chapter-4.-code-blocks",[],[]) [Str "Chapter",Space,Str "4.",Space,Str "Code",Space,Str "blocks"]
-  ,Para [Str "There",Space,Str "are",Space,Str "a",Space,Str "couple",Space,Str "options",Space,Str "for",Space,Str "code",Space,Str "block",Space,Str "labels.",Space,Str "Those",Space,Str "work",Space,Str "only",Space,Str "if",Space,Str "code",Space,Str "block",Space,Str "id",Space,Str "starts",Space,Str "with",Space,Code ("",[],[]) "lst:",Str ",",Space,Str "e.g.",Space,Code ("",[],[]) "{#lst:label}"]
-  ,Header 2 ("sec:caption-attr",[],[]) [Code ("",[],[]) "caption",Space,Str "attribute"]
-  ,Para [Code ("",[],[]) "caption",Space,Str "attribute",Space,Str "will",Space,Str "be",Space,Str "treated",Space,Str "as",Space,Str "code",Space,Str "block",Space,Str "caption.",Space,Str "If",Space,Str "code",Space,Str "block",Space,Str "has",Space,Str "both",Space,Str "id",Space,Str "and",Space,Code ("",[],[]) "caption",Space,Str "attributes,",Space,Str "it",Space,Str "will",Space,Str "be",Space,Str "treated",Space,Str "as",Space,Str "numbered",Space,Str "code",Space,Str "block."]
-  ,Div ("lst:captionAttr",["listing","haskell"],[])
-   [Para [Str "Listing",Space,Str "4.1:",Space,Str "Listing",Space,Str "caption"]
-   ,CodeBlock ("",["haskell"],[]) "main :: IO ()\nmain = putStrLn \"Hello World!\""]
-  ,Para [RawInline (Format "tex") "\\pagebreak"]
-  ,Header 2 ("sec:table-capts",[],[]) [Str "Table-style",Space,Str "captions"]
-  ,Para [Str "Enabled",Space,Str "with",Space,Code ("",[],[]) "codeBlockCaptions",Space,Str "metadata",Space,Str "option.",Space,Str "If",Space,Str "code",Space,Str "block",Space,Str "is",Space,Str "immediately",Space,Str "adjacent",Space,Str "to",Space,Str "paragraph,",Space,Str "starting",Space,Str "with",Space,Code ("",[],[]) "Listing:",Space,Str "or",Space,Code ("",[],[]) ":",Str ",",Space,Str "said",Space,Str "paragraph",Space,Str "will",Space,Str "be",Space,Str "treated",Space,Str "as",Space,Str "code",Space,Str "block",Space,Str "caption."]
-  ,Div ("lst:tableCaption",["listing","haskell"],[])
-   [Para [Str "Listing",Space,Str "4.2:",Space,Str "Listing",Space,Str "caption"]
-   ,CodeBlock ("",["haskell"],[]) "main :: IO ()\nmain = putStrLn \"Hello World!\""]
-  ,Header 2 ("sec:wrapping-div",[],[]) [Str "Wrapping",Space,Str "div"]
-  ,Para [Str "Wrapping",Space,Str "code",Space,Str "block",Space,Str "without",Space,Str "label",Space,Str "in",Space,Str "a",Space,Str "div",Space,Str "with",Space,Str "id",Space,Code ("",[],[]) "lst:...",Space,Str "and",Space,Str "class,",Space,Str "starting",Space,Str "with",Space,Code ("",[],[]) "listing",Str ",",Space,Str "and",Space,Str "adding",Space,Str "paragraph",Space,Str "before",Space,Str "code",Space,Str "block,",Space,Str "but",Space,Str "inside",Space,Str "div,",Space,Str "will",Space,Str "treat",Space,Str "said",Space,Str "paragraph",Space,Str "as",Space,Str "code",Space,Str "block",Space,Str "caption."]
-  ,Div ("lst:wrappingDiv",["listing","haskell"],[])
-   [Para [Str "Listing",Space,Str "4.3:",Space,Str "Listing",Space,Str "caption"]
-   ,CodeBlock ("",["haskell"],[]) "main :: IO ()\nmain = putStrLn \"Hello World!\""]
-  ,Header 1 ("sec:unnumbered-chapter.",["unnumbered"],[]) [Str "Unnumbered",Space,Str "chapter."]
-  ,Para [Str "This",Space,Str "chapter",Space,Str "doesn't",Space,Str "change",Space,Str "chapter",Space,Str "prefix",Space,Str "of",Space,Str "referenced",Space,Str "elements,",Space,Str "instead",Space,Str "keeping",Space,Str "number",Space,Str "of",Space,Str "previous",Space,Str "chapter,",Space,Str "e.g.",Space,Math DisplayMath " S(x) = \\int_{x_1}^{x_2} a x+b \\  \\mathrm{d}x \\qquad(4.1)"]
-  ,Header 1 ("sec:chapter-5.-reference-lists",[],[]) [Str "Chapter",Space,Str "5.",Space,Str "Reference",Space,Str "lists"]
-  ,Para [Str "It's",Space,Str "also",Space,Str "possible",Space,Str "to",Space,Str "show",Space,Str "lists",Space,Str "of",Space,Str "figures",Space,Str "and",Space,Str "tables,",Space,Str "like",Space,Str "this:"]
-  ,Header 2 ("list-of-figures",[],[]) [Str "List",Space,Str "of",Space,Str "Figures"]
-  ,Div ("",["list"],[])
-   [Para [Str "1",Space,Str "A",Space,Str "figure"]
-   ,Para [Str "1",Str ".",Str "1",Space,Str "First",Space,Str "figure"]
-   ,Para [Str "1",Str ".",Str "2",Space,Str "Second",Space,Str "figure"]
-   ,Para [Str "1",Str ".",Str "3",Space,Str "Third",Space,Str "figure"]]
-  ,Header 2 ("list-of-tables",[],[]) [Str "List",Space,Str "of",Space,Str "Tables"]
-  ,Div ("",["list"],[])
-   [Para [Str "3",Str ".",Str "1",Space,Str "Table",Space,Str "example"]]
-  ,Header 1 ("",[],[]) [Str "List",Space,Str "of",Space,Str "Listings"]
-  ,Div ("",["list"],[])
-   [Para [Str "4",Str ".",Str "1",Space,Str "Listing",Space,Str "caption"]
-   ,Para [Str "4",Str ".",Str "2",Space,Str "Listing",Space,Str "caption"]
-   ,Para [Str "4",Str ".",Str "3",Space,Str "Listing",Space,Str "caption"]]
-  ,Header 1 ("sec:appendix-a.-custom-labels",[],[("label","AppA")]) [Str "Appendix",Space,Str "A.",Space,Str "Custom",Space,Str "labels"]
-  ,Header 2 ("sec:custlabs",[],[("label","CustLab")]) [Str "This",Space,Str "section",Space,Str "will",Space,Str "have",Space,Str "custom",Space,Str "label"]]
-#endif
+#include "demo-chapters.inc"
diff --git a/test/demo-chapters.inc b/test/demo-chapters.inc
new file mode 100644
--- /dev/null
+++ b/test/demo-chapters.inc
@@ -0,0 +1,79 @@
+  [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "demo",Space,Str "file",Space,Str "for",Space,Str "pandoc-crossref.",Space,Str "With",Space,Str "this",Space,Str "filter,",Space,Str "you",Space,Str "can",Space,Str "cross-reference",Space,Str "figures",Space,Str "(see",Space,Str "figs.\160\&1.1-1.3",Str "),",Space,Str "display",Space,Str "equations",Space,Str "(see",Space,Str "eq.\160\&2.1",Str "),",Space,Str "tables",Space,Str "(see",Space,Str "tbl.\160\&3.1",Str ")",Space,Str "and",Space,Str "sections",Space,Str "(",Str "secs.\160\&1,",Space,Str "2,",Space,Str "4.1-4.3",Str ")"]
+  ,Para [Str "For",Space,Str "immediate",Space,Str "example,",Space,Str "see",Space,Str "fig.\160\&1"]
+  ,Para [Image ("fig:figure0",[],[]) [Str "Figure",Space,Str "#",Space,Str "1:",Space,Str "A",Space,Str "figure"] ("img1.jpg","fig:")]
+  ,Para [Str "There",Space,Str "is",Space,Str "also",Space,Str "support",Space,Str "for",Space,Str "code",Space,Str "blocks,",Space,Str "for",Space,Str "example,",Space,Str "lsts.\160\&4.1-4.3"]
+  ,Para [Str "It's",Space,Str "possible",Space,Str "to",Space,Str "capitalize",Space,Str "reference",Space,Str "prefixes,",Space,Str "like",Space,Str "this:",Space,Str "Fig.\160\&1.1",Str "."]
+  ,Para [Str "In",Space,Str "case",Space,Str "of",Space,Str "multiple",Space,Str "references,",Space,Str "capitalization",Space,Str "is",Space,Str "determined",Space,Str "by",Space,Str "first",Space,Str "reference.",Space,Str "Figs.\160\&1.1,",Space,Str "1.2",Space,Str "is",Space,Str "capitalized,",Space,Str "while",Space,Str "figs.\160\&1.1,",Space,Str "1.2",Space,Str "is",Space,Str "not."]
+  ,Para [Str "It",Space,Str "is",Space,Str "also",Space,Str "possible",Space,Str "to",Space,Str "mix",Space,Str "different",Space,Str "references,",Space,Str "like",Space,Str "fig.\160\&1.1",Str ",",Space,Str "tbl.\160\&3.1",Str ",",Space,Str "lsts.\160\&4.1,",Space,Str "4.2",Str ",",Space,Str "figs.\160\&1.2,",Space,Str "1.3",Str ",",Space,Str "which",Space,Str "will",Space,Str "be",Space,Str "grouped",Space,Str "in",Space,Str "order",Space,Str "they",Space,Str "are",Space,Str "specified.",Space,Str "You",Space,Str "can",Space,Str "even",Space,Str "intermix",Space,Str "this",Space,Str "with",Space,Str "regular",Space,Str "citations,",Space,Str "although",Space,Str "it's",Space,Str "not",Space,Str "recommended:",Space,Str "fig.\160\&1.1",Str ",",Space,Str "tbl.\160\&3.1",Str ",",Space,Cite [Citation {citationId = "unprocessedCitation", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@unprocessedCitation]"]]
+  ,Para [Str "You",Space,Str "can",Space,Str "also",Space,Str "have",Space,Str "custom",Space,Str "chapter",Space,Str "reference",Space,Str "labels,",Space,Str "like",Space,Str "sec.\160AppA.CustLab"]
+  ,Para [Str "Subfigures",Space,Str "are",Space,Str "supported,",Space,Str "see",Space,Str "figs.\160\&1.4,",Space,Str "1.4",Space,Str "(b)"]
+  ,Header 1 ("sec:sec1",[],[]) [Str "Chapter",Space,Str "1.",Space,Str "Figures"]
+  ,Para [Image ("fig:figure1",[],[]) [Str "Figure",Space,Str "#",Space,Str "1.1:",Space,Str "First",Space,Str "figure"] ("img1.jpg","fig:")]
+  ,Para [Image ("fig:figure2",[],[]) [Str "Figure",Space,Str "#",Space,Str "1.2:",Space,Str "Second",Space,Str "figure"] ("img2.jpg","fig:")]
+  ,Para [Image ("fig:figure3",[],[]) [Str "Figure",Space,Str "#",Space,Str "1.3:",Space,Str "Third",Space,Str "figure"] ("img3.jpg","fig:")]
+  ,Para [Image ("",[],[]) [Str "Unlabelled",Space,Str "image"] ("img1.jpg","fig:")]
+  ,Div ("fig:subfigures",["subfigures"],[])
+   [Para [Image ("",[],[]) [Str "a"] ("img1.jpg","fig:")]
+   ,Para [Image ("fig:subfigureB",[],[]) [Str "b"] ("img1.jpg","fig:")]
+   ,Para [Str "Figure",Space,Str "#",Space,Str "1.4:",Space,Str "Subfigures",Space,Str "caption.",Space,Str "a",Space,Str "\8212",Space,Str "Subfigure",Space,Str "a,",Space,Str "b",Space,Str "\8212",Space,Str "Subfigure",Space,Str "b"]]
+  ,Header 1 ("sec:sec2",[],[]) [Str "Chapter",Space,Str "2.",Space,Str "Equations"]
+  ,Para [Str "Display",Space,Str "equations",Space,Str "are",Space,Str "labelled",Space,Str "and",Space,Str "numbered"]
+  ,Para [Math DisplayMath " P_i(x) = \\sum_i a_i x^i \\qquad(2.1)"]
+  ,Para [Str "Since",Space,Str "0.1.6.0",Space,Str "those",Space,Str "can",Space,Str "also",Space,Str "appear",Space,Str "in",Space,Str "the",Space,Str "middle",Space,Str "of",Space,Str "paragraph",SoftBreak,Math DisplayMath "a x^2 + b x^2 + c = 0\\qquad(2.2)",Space,Str "like",Space,Str "this."]
+  ,Header 1 ("sec:chapter-3.-tables",[],[]) [Str "Chapter",Space,Str "3.",Space,Str "Tables"]
+  ,Table [Emph [Str "Table",Space,Str "3.1"],Str ":",Space,Str "Table",Space,Str "example"] [AlignLeft,AlignLeft] [0.0,0.0]
+   [[Plain [Str "First",Space,Str "Header"]]
+   ,[Plain [Str "Second",Space,Str "Header"]]]
+   [[[Plain [Str "Content",Space,Str "Cell"]]
+    ,[Plain [Str "Content",Space,Str "Cell"]]]
+   ,[[Plain [Str "Content",Space,Str "Cell"]]
+    ,[Plain [Str "Content",Space,Str "Cell"]]]]
+  ,Para [Str "Table",Space,Str "without",Space,Str "caption:"]
+  ,Table [] [AlignLeft,AlignLeft] [0.0,0.0]
+   [[Plain [Str "First",Space,Str "Header"]]
+   ,[Plain [Str "Second",Space,Str "Header"]]]
+   [[[Plain [Str "Content",Space,Str "Cell"]]
+    ,[Plain [Str "Content",Space,Str "Cell"]]]
+   ,[[Plain [Str "Content",Space,Str "Cell"]]
+    ,[Plain [Str "Content",Space,Str "Cell"]]]]
+  ,Header 1 ("sec:chapter-4.-code-blocks",[],[]) [Str "Chapter",Space,Str "4.",Space,Str "Code",Space,Str "blocks"]
+  ,Para [Str "There",Space,Str "are",Space,Str "a",Space,Str "couple",Space,Str "options",Space,Str "for",Space,Str "code",Space,Str "block",Space,Str "labels.",Space,Str "Those",Space,Str "work",Space,Str "only",Space,Str "if",Space,Str "code",Space,Str "block",Space,Str "id",Space,Str "starts",Space,Str "with",Space,Code ("",[],[]) "lst:",Str ",",Space,Str "e.g.",Space,Code ("",[],[]) "{#lst:label}"]
+  ,Header 2 ("sec:caption-attr",[],[]) [Code ("",[],[]) "caption",Space,Str "attribute"]
+  ,Para [Code ("",[],[]) "caption",Space,Str "attribute",Space,Str "will",Space,Str "be",Space,Str "treated",Space,Str "as",Space,Str "code",Space,Str "block",Space,Str "caption.",Space,Str "If",Space,Str "code",Space,Str "block",Space,Str "has",Space,Str "both",Space,Str "id",Space,Str "and",Space,Code ("",[],[]) "caption",Space,Str "attributes,",Space,Str "it",Space,Str "will",Space,Str "be",Space,Str "treated",Space,Str "as",Space,Str "numbered",Space,Str "code",Space,Str "block."]
+  ,Div ("lst:captionAttr",["listing","haskell"],[])
+   [Para [Str "Listing",Space,Str "4.1:",Space,Str "Listing",Space,Str "caption"]
+   ,CodeBlock ("",["haskell"],[]) "main :: IO ()\nmain = putStrLn \"Hello World!\""]
+  ,Para [RawInline (Format "tex") "\\pagebreak"]
+  ,Header 2 ("sec:table-capts",[],[]) [Str "Table-style",Space,Str "captions"]
+  ,Para [Str "Enabled",Space,Str "with",Space,Code ("",[],[]) "codeBlockCaptions",Space,Str "metadata",Space,Str "option.",Space,Str "If",Space,Str "code",Space,Str "block",Space,Str "is",Space,Str "immediately",SoftBreak,Str "adjacent",Space,Str "to",Space,Str "paragraph,",Space,Str "starting",Space,Str "with",Space,Code ("",[],[]) "Listing:",Space,Str "or",Space,Code ("",[],[]) ":",Str ",",Space,Str "said",Space,Str "paragraph",Space,Str "will",Space,Str "be",SoftBreak,Str "treated",Space,Str "as",Space,Str "code",Space,Str "block",Space,Str "caption."]
+  ,Div ("lst:tableCaption",["listing","haskell"],[])
+   [Para [Str "Listing",Space,Str "4.2:",Space,Str "Listing",Space,Str "caption"]
+   ,CodeBlock ("",["haskell"],[]) "main :: IO ()\nmain = putStrLn \"Hello World!\""]
+  ,Header 2 ("sec:wrapping-div",[],[]) [Str "Wrapping",Space,Str "div"]
+  ,Para [Str "Wrapping",Space,Str "code",Space,Str "block",Space,Str "without",Space,Str "label",Space,Str "in",Space,Str "a",Space,Str "div",Space,Str "with",Space,Str "id",Space,Code ("",[],[]) "lst:...",Space,Str "and",Space,Str "class,",Space,Str "starting",Space,Str "with",Space,Code ("",[],[]) "listing",Str ",",Space,Str "and",Space,Str "adding",Space,Str "paragraph",Space,Str "before",Space,Str "code",Space,Str "block,",Space,Str "but",Space,Str "inside",Space,Str "div,",Space,Str "will",Space,Str "treat",Space,Str "said",Space,Str "paragraph",Space,Str "as",Space,Str "code",Space,Str "block",Space,Str "caption."]
+  ,Div ("lst:wrappingDiv",["listing","haskell"],[])
+   [Para [Str "Listing",Space,Str "4.3:",Space,Str "Listing",Space,Str "caption"]
+   ,CodeBlock ("",["haskell"],[]) "main :: IO ()\nmain = putStrLn \"Hello World!\""]
+  ,Header 1 ("sec:unnumbered-chapter.",["unnumbered"],[]) [Str "Unnumbered",Space,Str "chapter."]
+  ,Para [Str "This",Space,Str "chapter",Space,Str "doesn't",Space,Str "change",Space,Str "chapter",Space,Str "prefix",Space,Str "of",Space,Str "referenced",Space,Str "elements,",Space,Str "instead",Space,Str "keeping",Space,Str "number",Space,Str "of",Space,Str "previous",Space,Str "chapter,",Space,Str "e.g.",SoftBreak,Math DisplayMath " S(x) = \\int_{x_1}^{x_2} a x+b \\  \\mathrm{d}x \\qquad(4.1)"]
+  ,Header 1 ("sec:chapter-5.-reference-lists",[],[]) [Str "Chapter",Space,Str "5.",Space,Str "Reference",Space,Str "lists"]
+  ,Para [Str "It's",Space,Str "also",Space,Str "possible",Space,Str "to",Space,Str "show",Space,Str "lists",Space,Str "of",Space,Str "figures",Space,Str "and",Space,Str "tables,",Space,Str "like",Space,Str "this:"]
+  ,Header 2 ("list-of-figures",[],[]) [Str "List",Space,Str "of",Space,Str "Figures"]
+  ,Div ("",["list"],[])
+   [Para [Str "1",Space,Str "A",Space,Str "figure"]
+   ,Para [Str "1",Str ".",Str "1",Space,Str "First",Space,Str "figure"]
+   ,Para [Str "1",Str ".",Str "2",Space,Str "Second",Space,Str "figure"]
+   ,Para [Str "1",Str ".",Str "3",Space,Str "Third",Space,Str "figure"]
+   ,Para [Str "1",Str ".",Str "4",Space,Str "Subfigure",Space,Str "a"]
+   ,Para [Str "1",Str ".",Str "4",Space,Str "Subfigure",Space,Str "b"]
+   ,Para [Str "1",Str ".",Str "4",Space,Str "Subfigures",Space,Str "caption"]]
+  ,Header 2 ("list-of-tables",[],[]) [Str "List",Space,Str "of",Space,Str "Tables"]
+  ,Div ("",["list"],[])
+   [Para [Str "3",Str ".",Str "1",Space,Str "Table",Space,Str "example"]]
+  ,Header 1 ("",[],[]) [Str "List",Space,Str "of",Space,Str "Listings"]
+  ,Div ("",["list"],[])
+   [Para [Str "4",Str ".",Str "1",Space,Str "Listing",Space,Str "caption"]
+   ,Para [Str "4",Str ".",Str "2",Space,Str "Listing",Space,Str "caption"]
+   ,Para [Str "4",Str ".",Str "3",Space,Str "Listing",Space,Str "caption"]]
+  ,Header 1 ("sec:appendix-a.-custom-labels",[],[("label","AppA")]) [Str "Appendix",Space,Str "A.",Space,Str "Custom",Space,Str "labels"]
+  ,Header 2 ("sec:custlabs",[],[("label","CustLab")]) [Str "This",Space,Str "section",Space,Str "will",Space,Str "have",Space,Str "custom",Space,Str "label"]]
diff --git a/test/demo.inc b/test/demo.inc
new file mode 100644
--- /dev/null
+++ b/test/demo.inc
@@ -0,0 +1,79 @@
+  [Para [Str "This",Space,Str "is",Space,Str "a",Space,Str "demo",Space,Str "file",Space,Str "for",Space,Str "pandoc-crossref.",Space,Str "With",Space,Str "this",Space,Str "filter,",Space,Str "you",Space,Str "can",Space,Str "cross-reference",Space,Str "figures",Space,Str "(see",Space,Str "figs.\160\&2-4",Str "),",Space,Str "display",Space,Str "equations",Space,Str "(see",Space,Str "eq.\160\&1",Str "),",Space,Str "tables",Space,Str "(see",Space,Str "tbl.\160\&1",Str ")",Space,Str "and",Space,Str "sections",Space,Str "(",Str "secs.\160\&1,",Space,Str "2,",Space,Str "4.1-4.3",Str ")"]
+  ,Para [Str "For",Space,Str "immediate",Space,Str "example,",Space,Str "see",Space,Str "fig.\160\&1"]
+  ,Para [Image ("fig:figure0",[],[]) [Str "Figure",Space,Str "#",Space,Str "1:",Space,Str "A",Space,Str "figure"] ("img1.jpg","fig:")]
+  ,Para [Str "There",Space,Str "is",Space,Str "also",Space,Str "support",Space,Str "for",Space,Str "code",Space,Str "blocks,",Space,Str "for",Space,Str "example,",Space,Str "lsts.\160\&1-3"]
+  ,Para [Str "It's",Space,Str "possible",Space,Str "to",Space,Str "capitalize",Space,Str "reference",Space,Str "prefixes,",Space,Str "like",Space,Str "this:",Space,Str "Fig.\160\&2",Str "."]
+  ,Para [Str "In",Space,Str "case",Space,Str "of",Space,Str "multiple",Space,Str "references,",Space,Str "capitalization",Space,Str "is",Space,Str "determined",Space,Str "by",Space,Str "first",Space,Str "reference.",Space,Str "Figs.\160\&2,",Space,Str "3",Space,Str "is",Space,Str "capitalized,",Space,Str "while",Space,Str "figs.\160\&2,",Space,Str "3",Space,Str "is",Space,Str "not."]
+  ,Para [Str "It",Space,Str "is",Space,Str "also",Space,Str "possible",Space,Str "to",Space,Str "mix",Space,Str "different",Space,Str "references,",Space,Str "like",Space,Str "fig.\160\&2",Str ",",Space,Str "tbl.\160\&1",Str ",",Space,Str "lsts.\160\&1,",Space,Str "2",Str ",",Space,Str "figs.\160\&3,",Space,Str "4",Str ",",Space,Str "which",Space,Str "will",Space,Str "be",Space,Str "grouped",Space,Str "in",Space,Str "order",Space,Str "they",Space,Str "are",Space,Str "specified.",Space,Str "You",Space,Str "can",Space,Str "even",Space,Str "intermix",Space,Str "this",Space,Str "with",Space,Str "regular",Space,Str "citations,",Space,Str "although",Space,Str "it's",Space,Str "not",Space,Str "recommended:",Space,Str "fig.\160\&2",Str ",",Space,Str "tbl.\160\&1",Str ",",Space,Cite [Citation {citationId = "unprocessedCitation", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@unprocessedCitation]"]]
+  ,Para [Str "You",Space,Str "can",Space,Str "also",Space,Str "have",Space,Str "custom",Space,Str "chapter",Space,Str "reference",Space,Str "labels,",Space,Str "like",Space,Str "sec.\160AppA.CustLab"]
+  ,Para [Str "Subfigures",Space,Str "are",Space,Str "supported,",Space,Str "see",Space,Str "figs.\160\&5,",Space,Str "5",Space,Str "(b)"]
+  ,Header 1 ("sec:sec1",[],[]) [Str "Chapter",Space,Str "1.",Space,Str "Figures"]
+  ,Para [Image ("fig:figure1",[],[]) [Str "Figure",Space,Str "#",Space,Str "2:",Space,Str "First",Space,Str "figure"] ("img1.jpg","fig:")]
+  ,Para [Image ("fig:figure2",[],[]) [Str "Figure",Space,Str "#",Space,Str "3:",Space,Str "Second",Space,Str "figure"] ("img2.jpg","fig:")]
+  ,Para [Image ("fig:figure3",[],[]) [Str "Figure",Space,Str "#",Space,Str "4:",Space,Str "Third",Space,Str "figure"] ("img3.jpg","fig:")]
+  ,Para [Image ("",[],[]) [Str "Unlabelled",Space,Str "image"] ("img1.jpg","fig:")]
+  ,Div ("fig:subfigures",["subfigures"],[])
+   [Para [Image ([],[],[]) [Str "a"] ("img1.jpg","fig:")]
+   ,Para [Image ("fig:subfigureB",[],[]) [Str "b"] ("img1.jpg","fig:")]
+   ,Para [Str "Figure",Space,Str "#",Space,Str "5:",Space,Str "Subfigures",Space,Str "caption.",Space,Str "a",Space,Str "\8212",Space,Str "Subfigure",Space,Str "a,",Space,Str "b",Space,Str "\8212",Space,Str "Subfigure",Space,Str "b"]]
+  ,Header 1 ("sec:sec2",[],[]) [Str "Chapter",Space,Str "2.",Space,Str "Equations"]
+  ,Para [Str "Display",Space,Str "equations",Space,Str "are",Space,Str "labelled",Space,Str "and",Space,Str "numbered"]
+  ,Para [Math DisplayMath " P_i(x) = \\sum_i a_i x^i \\qquad(1)"]
+  ,Para [Str "Since",Space,Str "0.1.6.0",Space,Str "those",Space,Str "can",Space,Str "also",Space,Str "appear",Space,Str "in",Space,Str "the",Space,Str "middle",Space,Str "of",Space,Str "paragraph",SoftBreak,Math DisplayMath "a x^2 + b x^2 + c = 0\\qquad(2)",Space,Str "like",Space,Str "this."]
+  ,Header 1 ("sec:chapter-3.-tables",[],[]) [Str "Chapter",Space,Str "3.",Space,Str "Tables"]
+  ,Table [Emph [Str "Table",Space,Str "1"],Str ":",Space,Str "Table",Space,Str "example"] [AlignLeft,AlignLeft] [0.0,0.0]
+   [[Plain [Str "First",Space,Str "Header"]]
+   ,[Plain [Str "Second",Space,Str "Header"]]]
+   [[[Plain [Str "Content",Space,Str "Cell"]]
+    ,[Plain [Str "Content",Space,Str "Cell"]]]
+   ,[[Plain [Str "Content",Space,Str "Cell"]]
+    ,[Plain [Str "Content",Space,Str "Cell"]]]]
+  ,Para [Str "Table",Space,Str "without",Space,Str "caption:"]
+  ,Table [] [AlignLeft,AlignLeft] [0.0,0.0]
+   [[Plain [Str "First",Space,Str "Header"]]
+   ,[Plain [Str "Second",Space,Str "Header"]]]
+   [[[Plain [Str "Content",Space,Str "Cell"]]
+    ,[Plain [Str "Content",Space,Str "Cell"]]]
+   ,[[Plain [Str "Content",Space,Str "Cell"]]
+    ,[Plain [Str "Content",Space,Str "Cell"]]]]
+  ,Header 1 ("sec:chapter-4.-code-blocks",[],[]) [Str "Chapter",Space,Str "4.",Space,Str "Code",Space,Str "blocks"]
+  ,Para [Str "There",Space,Str "are",Space,Str "a",Space,Str "couple",Space,Str "options",Space,Str "for",Space,Str "code",Space,Str "block",Space,Str "labels.",Space,Str "Those",Space,Str "work",Space,Str "only",Space,Str "if",Space,Str "code",Space,Str "block",Space,Str "id",Space,Str "starts",Space,Str "with",Space,Code ("",[],[]) "lst:",Str ",",Space,Str "e.g.",Space,Code ("",[],[]) "{#lst:label}"]
+  ,Header 2 ("sec:caption-attr",[],[]) [Code ("",[],[]) "caption",Space,Str "attribute"]
+  ,Para [Code ("",[],[]) "caption",Space,Str "attribute",Space,Str "will",Space,Str "be",Space,Str "treated",Space,Str "as",Space,Str "code",Space,Str "block",Space,Str "caption.",Space,Str "If",Space,Str "code",Space,Str "block",Space,Str "has",Space,Str "both",Space,Str "id",Space,Str "and",Space,Code ("",[],[]) "caption",Space,Str "attributes,",Space,Str "it",Space,Str "will",Space,Str "be",Space,Str "treated",Space,Str "as",Space,Str "numbered",Space,Str "code",Space,Str "block."]
+  ,Div ("lst:captionAttr",["listing","haskell"],[])
+   [Para [Str "Listing",Space,Str "1:",Space,Str "Listing",Space,Str "caption"]
+   ,CodeBlock ("",["haskell"],[]) "main :: IO ()\nmain = putStrLn \"Hello World!\""]
+  ,Para [RawInline (Format "tex") "\\pagebreak"]
+  ,Header 2 ("sec:table-capts",[],[]) [Str "Table-style",Space,Str "captions"]
+  ,Para [Str "Enabled",Space,Str "with",Space,Code ("",[],[]) "codeBlockCaptions",Space,Str "metadata",Space,Str "option.",Space,Str "If",Space,Str "code",Space,Str "block",Space,Str "is",Space,Str "immediately",SoftBreak,Str "adjacent",Space,Str "to",Space,Str "paragraph,",Space,Str "starting",Space,Str "with",Space,Code ("",[],[]) "Listing:",Space,Str "or",Space,Code ("",[],[]) ":",Str ",",Space,Str "said",Space,Str "paragraph",Space,Str "will",Space,Str "be",SoftBreak,Str "treated",Space,Str "as",Space,Str "code",Space,Str "block",Space,Str "caption."]
+  ,Div ("lst:tableCaption",["listing","haskell"],[])
+   [Para [Str "Listing",Space,Str "2:",Space,Str "Listing",Space,Str "caption"]
+   ,CodeBlock ("",["haskell"],[]) "main :: IO ()\nmain = putStrLn \"Hello World!\""]
+  ,Header 2 ("sec:wrapping-div",[],[]) [Str "Wrapping",Space,Str "div"]
+  ,Para [Str "Wrapping",Space,Str "code",Space,Str "block",Space,Str "without",Space,Str "label",Space,Str "in",Space,Str "a",Space,Str "div",Space,Str "with",Space,Str "id",Space,Code ("",[],[]) "lst:...",Space,Str "and",Space,Str "class,",Space,Str "starting",Space,Str "with",Space,Code ("",[],[]) "listing",Str ",",Space,Str "and",Space,Str "adding",Space,Str "paragraph",Space,Str "before",Space,Str "code",Space,Str "block,",Space,Str "but",Space,Str "inside",Space,Str "div,",Space,Str "will",Space,Str "treat",Space,Str "said",Space,Str "paragraph",Space,Str "as",Space,Str "code",Space,Str "block",Space,Str "caption."]
+  ,Div ("lst:wrappingDiv",["listing","haskell"],[])
+   [Para [Str "Listing",Space,Str "3:",Space,Str "Listing",Space,Str "caption"]
+   ,CodeBlock ("",["haskell"],[]) "main :: IO ()\nmain = putStrLn \"Hello World!\""]
+  ,Header 1 ("sec:unnumbered-chapter.",["unnumbered"],[]) [Str "Unnumbered",Space,Str "chapter."]
+  ,Para [Str "This",Space,Str "chapter",Space,Str "doesn't",Space,Str "change",Space,Str "chapter",Space,Str "prefix",Space,Str "of",Space,Str "referenced",Space,Str "elements,",Space,Str "instead",Space,Str "keeping",Space,Str "number",Space,Str "of",Space,Str "previous",Space,Str "chapter,",Space,Str "e.g.",SoftBreak,Math DisplayMath " S(x) = \\int_{x_1}^{x_2} a x+b \\  \\mathrm{d}x \\qquad(3)"]
+  ,Header 1 ("sec:chapter-5.-reference-lists",[],[]) [Str "Chapter",Space,Str "5.",Space,Str "Reference",Space,Str "lists"]
+  ,Para [Str "It's",Space,Str "also",Space,Str "possible",Space,Str "to",Space,Str "show",Space,Str "lists",Space,Str "of",Space,Str "figures",Space,Str "and",Space,Str "tables,",Space,Str "like",Space,Str "this:"]
+  ,Header 2 ("list-of-figures",[],[]) [Str "List",Space,Str "of",Space,Str "Figures"]
+  ,OrderedList (1,DefaultStyle,DefaultDelim)
+   [[Plain [Str "A",Space,Str "figure"]]
+   ,[Plain [Str "First",Space,Str "figure"]]
+   ,[Plain [Str "Second",Space,Str "figure"]]
+   ,[Plain [Str "Third",Space,Str "figure"]]
+   ,[Plain [Str "Subfigure",Space,Str "a"]]
+   ,[Plain [Str "Subfigure",Space,Str "b"]]
+   ,[Plain [Str "Subfigures",Space,Str "caption"]]]
+  ,Header 2 ("list-of-tables",[],[]) [Str "List",Space,Str "of",Space,Str "Tables"]
+  ,OrderedList (1,DefaultStyle,DefaultDelim)
+   [[Plain [Str "Table",Space,Str "example"]]]
+  ,Header 1 ("",[],[]) [Str "List",Space,Str "of",Space,Str "Listings"]
+  ,OrderedList (1,DefaultStyle,DefaultDelim)
+   [[Plain [Str "Listing",Space,Str "caption"]]
+   ,[Plain [Str "Listing",Space,Str "caption"]]
+   ,[Plain [Str "Listing",Space,Str "caption"]]]
+  ,Header 1 ("sec:appendix-a.-custom-labels",[],[("label","AppA")]) [Str "Appendix",Space,Str "A.",Space,Str "Custom",Space,Str "labels"]
+  ,Header 2 ("sec:custlabs",[],[("label","CustLab")]) [Str "This",Space,Str "section",Space,Str "will",Space,Str "have",Space,Str "custom",Space,Str "label"]]
diff --git a/test/test-pandoc-crossref.hs b/test/test-pandoc-crossref.hs
--- a/test/test-pandoc-crossref.hs
+++ b/test/test-pandoc-crossref.hs
@@ -1,8 +1,7 @@
-{-# LANGUAGE CPP #-}
+{-# LANGUAGE CPP, FlexibleContexts #-}
 import Test.Hspec
 import Text.Pandoc hiding (readMarkdown)
 import Text.Pandoc.Builder
-import Text.Pandoc.Walk
 import Control.Monad.State
 import Data.List
 import Control.Arrow
@@ -16,8 +15,7 @@
 import Text.Pandoc.CrossRef.Util.Util
 import Text.Pandoc.CrossRef.References.Types
 import Text.Pandoc.CrossRef.Util.Settings
-import Data.Accessor
-import Text.Pandoc.CrossRef.References.Accessors
+import Data.Accessor hiding ((=:))
 import qualified Text.Pandoc.CrossRef.References.Blocks as References.Blocks
 import qualified Text.Pandoc.CrossRef.References.Refs as References.Refs
 import qualified Text.Pandoc.CrossRef.References.List as References.List
@@ -33,11 +31,11 @@
 main = hspec $ do
     describe "References.Blocks.replaceInlines" $ do
       it "Labels equations" $
-        testInlines (equation' "a^2+b^2=c^2" "equation")
+        testAll (equation' "a^2+b^2=c^2" "equation")
         (equation' "a^2+b^2=c^2\\qquad(1)" [],
-          def{eqnRefs=M.fromList $ refRec'' "eq:equation" 1})
+          eqnRefs =: M.fromList $ refRec'' "eq:equation" 1)
       it "Labels equations in the middle of text" $
-        testInlines (
+        testAll (
                 text "This is an equation: "
              <> equation' "a^2+b^2=c^2" "equation"
              <> text " it should be labeled")
@@ -45,46 +43,89 @@
            text "This is an equation: "
         <> equation' "a^2+b^2=c^2\\qquad(1)" []
         <> text " it should be labeled",
-          def{eqnRefs=M.fromList $ refRec'' "eq:equation" 1})
+          eqnRefs =: M.fromList $ refRec'' "eq:equation" 1)
       it "Labels equations in the beginning of text" $
-        testInlines (
+        testAll (
                 equation' "a^2+b^2=c^2" "equation"
              <> text " it should be labeled")
         (
            equation' "a^2+b^2=c^2\\qquad(1)" []
         <> text " it should be labeled",
-          def{eqnRefs=M.fromList $ refRec'' "eq:equation" 1})
+          eqnRefs =: M.fromList $ refRec'' "eq:equation" 1)
       it "Labels equations in the end of text" $
-        testInlines (
+        testAll (
                 text "This is an equation: "
              <> equation' "a^2+b^2=c^2" "equation")
         (
            text "This is an equation: "
         <> equation' "a^2+b^2=c^2\\qquad(1)" [],
-          def{eqnRefs=M.fromList $ refRec'' "eq:equation" 1})
+          eqnRefs =: M.fromList $ refRec'' "eq:equation" 1)
 
     -- TODO:
     -- describe "References.Blocks.spanInlines"
     -- describe "References.Blocks.divBlocks"
 
     describe "References.Blocks.replaceBlocks" $ do
-#if MIN_VERSION_pandoc(1,16,0)
       it "Labels images" $
-        testBlocks (figure "test.jpg" [] "Test figure" "figure")
+        testAll (figure "test.jpg" [] "Test figure" "figure")
         (figure "test.jpg" [] "Figure 1: Test figure" "figure",
-          def{imgRefs=M.fromList $ refRec' "fig:figure" 1 "Test figure"})
-#else
-      it "Labels images" $
-        testBlocks (figure "test.jpg" [] "Test figure" "figure")
-        (figure "test.jpg" "fig:" "Figure 1: Test figure" [],
-          def{imgRefs=M.fromList $ refRec' "fig:figure" 1 "Test figure"})
-#endif
+          imgRefs =: M.fromList $ refRec' "fig:figure" 1 "Test figure")
+      it "Labels subfigures" $
+        testAll (
+          divWith ("fig:subfigure",[],[]) (
+            para (figure' "fig:" "test1.jpg" [] "Test figure 1" "figure1")
+          <>para (figure' "fig:" "test2.jpg" [] "Test figure 2" "figure2")
+          <>para (text "figure caption")
+            ) <>
+          divWith ("fig:subfigure2",[],[]) (
+            para (figure' "fig:" "test21.jpg" [] "Test figure 21" "figure21")
+          <>para (figure' "fig:" "test22.jpg" [] "Test figure 22" "figure22")
+          <>para (text "figure caption 2")
+            )
+          )
+        (
+          divWith ("fig:subfigure",["subfigures"],[]) (
+               para (figure' "fig:" "test1.jpg" [] "a" "figure1")
+            <> para (figure' "fig:" "test2.jpg" [] "b" "figure2")
+            <> para (text "Figure 1: figure caption. a — Test figure 1, b — Test figure 2")
+            ) <>
+          divWith ("fig:subfigure2",["subfigures"],[]) (
+               para (figure' "fig:" "test21.jpg" [] "a" "figure21")
+            <> para (figure' "fig:" "test22.jpg" [] "b" "figure22")
+            <> para (text "Figure 2: figure caption 2. a — Test figure 21, b — Test figure 22")
+            )
+        , imgRefs =: M.fromList [("fig:figure1",RefRec {
+                                            refIndex = [(1,Nothing)],
+                                            refTitle = [Str "Test",Space,Str "figure",Space,Str "1"],
+                                            refSubfigure = Just [(1, Just "a")]}),
+                                    ("fig:figure2",RefRec {
+                                            refIndex = [(1,Nothing)],
+                                            refTitle = [Str "Test",Space,Str "figure",Space,Str "2"],
+                                            refSubfigure = Just [(2, Just "b")]}),
+                                    ("fig:subfigure",RefRec {
+                                            refIndex = [(1,Nothing)],
+                                            refTitle = [Str "figure",Space,Str "caption"],
+                                            refSubfigure = Nothing}),
+                                    ("fig:figure21",RefRec {
+                                            refIndex = [(2,Nothing)],
+                                            refTitle = [Str "Test",Space,Str "figure",Space,Str "21"],
+                                            refSubfigure = Just [(1, Just "a")]}),
+                                    ("fig:figure22",RefRec {
+                                            refIndex = [(2,Nothing)],
+                                            refTitle = [Str "Test",Space,Str "figure",Space,Str "22"],
+                                            refSubfigure = Just [(2, Just "b")]}),
+                                    ("fig:subfigure2",RefRec {
+                                            refIndex = [(2,Nothing)],
+                                            refTitle = [Str "figure",Space,Str "caption",Space,Str "2"],
+                                            refSubfigure = Nothing})
+                                   ]
+            )
       it "Labels equations" $
-        testBlocks (equation "a^2+b^2=c^2" "equation")
+        testAll (equation "a^2+b^2=c^2" "equation")
         (equation "a^2+b^2=c^2\\qquad(1)" [],
-          def{eqnRefs=M.fromList $ refRec'' "eq:equation" 1})
+          eqnRefs =: M.fromList $ refRec'' "eq:equation" 1)
       it "Labels equations in the middle of text" $
-        testBlocks (para $
+        testAll (para $
                 text "This is an equation: "
              <> equation' "a^2+b^2=c^2" "equation"
              <> text " it should be labeled")
@@ -92,95 +133,95 @@
            text "This is an equation: "
         <> equation' "a^2+b^2=c^2\\qquad(1)" []
         <> text " it should be labeled",
-          def{eqnRefs=M.fromList $ refRec'' "eq:equation" 1})
+          eqnRefs =: M.fromList $ refRec'' "eq:equation" 1)
       it "Labels equations in the beginning of text" $
-        testBlocks (para $
+        testAll (para $
                 equation' "a^2+b^2=c^2" "equation"
              <> text " it should be labeled")
         (para $
            equation' "a^2+b^2=c^2\\qquad(1)" []
         <> text " it should be labeled",
-          def{eqnRefs=M.fromList $ refRec'' "eq:equation" 1})
+          eqnRefs =: M.fromList $ refRec'' "eq:equation" 1)
       it "Labels equations in the end of text" $
-        testBlocks (para $
+        testAll (para $
                 text "This is an equation: "
              <> equation' "a^2+b^2=c^2" "equation")
         (para $
            text "This is an equation: "
         <> equation' "a^2+b^2=c^2\\qquad(1)" [],
-          def{eqnRefs=M.fromList $ refRec'' "eq:equation" 1})
+          eqnRefs =: M.fromList $ refRec'' "eq:equation" 1)
       it "Labels tables" $
-        testBlocks (table' "Test table" "table")
+        testAll (table' "Test table" "table")
         (table' "Table 1: Test table" [],
-          def{tblRefs=M.fromList $ refRec' "tbl:table" 1 "Test table"})
+          tblRefs =: M.fromList $ refRec' "tbl:table" 1 "Test table")
       it "Labels code blocks" $
-        testBlocks (codeBlock' "Test code block" "codeblock")
+        testAll (codeBlock' "Test code block" "codeblock")
         (codeBlockDiv "Listing 1: Test code block" "codeblock",
-          def{lstRefs=M.fromList $ refRec' "lst:codeblock" 1 "Test code block"})
+          lstRefs =: M.fromList $ refRec' "lst:codeblock" 1 "Test code block")
       it "Labels code block divs" $
-        testBlocks (codeBlockDiv "Test code block" "codeblock")
+        testAll (codeBlockDiv "Test code block" "codeblock")
         (codeBlockDiv "Listing 1: Test code block" "codeblock",
-          def{lstRefs=M.fromList $ refRec' "lst:codeblock" 1 "Test code block"})
+          lstRefs =: M.fromList $ refRec' "lst:codeblock" 1 "Test code block")
       it "Labels sections divs" $
-        testBlocks (section "Section Header" 1 "section")
+        testAll (section "Section Header" 1 "section")
         (section "Section Header" 1 "section",
-          def{secRefs=M.fromList $ refRec' "sec:section" 1 "Section Header",
-              curChap=[(1,Nothing)]})
+          secRefs ^= M.fromList (refRec' "sec:section" 1 "Section Header")
+          $ curChap =: [(1,Nothing)])
 
     describe "References.Refs.replaceRefs" $ do
       it "References one image" $
-        testRefs' "fig:" [1] [4] imgRefs' "fig.\160\&4"
+        testRefs' "fig:" [1] [4] imgRefs "fig.\160\&4"
       it "References multiple images" $
-        testRefs' "fig:" [1..3] [4..6] imgRefs' "figs.\160\&4-6"
+        testRefs' "fig:" [1..3] [4..6] imgRefs "figs.\160\&4-6"
       it "References one equation" $
-        testRefs' "eq:" [1] [4] eqnRefs' "eq.\160\&4"
+        testRefs' "eq:" [1] [4] eqnRefs "eq.\160\&4"
       it "References multiple equations" $
-        testRefs' "eq:" [1..3] [4..6] eqnRefs' "eqns.\160\&4-6"
+        testRefs' "eq:" [1..3] [4..6] eqnRefs "eqns.\160\&4-6"
       it "References one table" $
-        testRefs' "tbl:" [1] [4] tblRefs' "tbl.\160\&4"
+        testRefs' "tbl:" [1] [4] tblRefs "tbl.\160\&4"
       it "References multiple tables" $
-        testRefs' "tbl:" [1..3] [4..6] tblRefs' "tbls.\160\&4-6"
+        testRefs' "tbl:" [1..3] [4..6] tblRefs "tbls.\160\&4-6"
       it "References one listing" $
-        testRefs' "lst:" [1] [4] lstRefs' "lst.\160\&4"
+        testRefs' "lst:" [1] [4] lstRefs "lst.\160\&4"
       it "References multiple listings" $
-        testRefs' "lst:" [1..3] [4..6] lstRefs' "lsts.\160\&4-6"
+        testRefs' "lst:" [1..3] [4..6] lstRefs "lsts.\160\&4-6"
       it "References one section" $
-        testRefs' "sec:" [1] [4] secRefs' "sec.\160\&4"
+        testRefs' "sec:" [1] [4] secRefs "sec.\160\&4"
       it "References multiple sections" $
-        testRefs' "sec:" [1..3] [4..6] secRefs' "secs.\160\&4-6"
+        testRefs' "sec:" [1..3] [4..6] secRefs "secs.\160\&4-6"
       it "Separates references to different chapter items by a comma" $
-        testRefs'' "lst:" [1..6] (zip [1,1..] [4..6] ++ zip [2,2..] [7..9]) lstRefs' "lsts.\160\&1.4-1.6, 2.7-2.9"
+        testRefs'' "lst:" [1..6] (zip [1,1..] [4..6] ++ zip [2,2..] [7..9]) lstRefs "lsts.\160\&1.4-1.6, 2.7-2.9"
 
     describe "References.Refs.replaceRefs capitalization" $ do
       it "References one image" $
-        testRefs' "Fig:" [1] [4] imgRefs' "Fig.\160\&4"
+        testRefs' "Fig:" [1] [4] imgRefs "Fig.\160\&4"
       it "References multiple images" $
-        testRefs' "Fig:" [1..3] [4..6] imgRefs' "Figs.\160\&4-6"
+        testRefs' "Fig:" [1..3] [4..6] imgRefs "Figs.\160\&4-6"
       it "References one equation" $
-        testRefs' "Eq:" [1] [4] eqnRefs' "Eq.\160\&4"
+        testRefs' "Eq:" [1] [4] eqnRefs "Eq.\160\&4"
       it "References multiple equations" $
-        testRefs' "Eq:" [1..3] [4..6] eqnRefs' "Eqns.\160\&4-6"
+        testRefs' "Eq:" [1..3] [4..6] eqnRefs "Eqns.\160\&4-6"
       it "References one table" $
-        testRefs' "Tbl:" [1] [4] tblRefs' "Tbl.\160\&4"
+        testRefs' "Tbl:" [1] [4] tblRefs "Tbl.\160\&4"
       it "References multiple tables" $
-        testRefs' "Tbl:" [1..3] [4..6] tblRefs' "Tbls.\160\&4-6"
+        testRefs' "Tbl:" [1..3] [4..6] tblRefs "Tbls.\160\&4-6"
       it "References one listing" $
-        testRefs' "Lst:" [1] [4] lstRefs' "Lst.\160\&4"
+        testRefs' "Lst:" [1] [4] lstRefs "Lst.\160\&4"
       it "References multiple listings" $
-        testRefs' "Lst:" [1..3] [4..6] lstRefs' "Lsts.\160\&4-6"
+        testRefs' "Lst:" [1..3] [4..6] lstRefs "Lsts.\160\&4-6"
       it "References one listing" $
-        testRefs' "Sec:" [1] [4] secRefs' "Sec.\160\&4"
+        testRefs' "Sec:" [1] [4] secRefs "Sec.\160\&4"
       it "References multiple listings" $
-        testRefs' "Sec:" [1..3] [4..6] secRefs' "Secs.\160\&4-6"
+        testRefs' "Sec:" [1..3] [4..6] secRefs "Secs.\160\&4-6"
 
     describe "References.List.listOf" $ do
       it "Generates list of tables" $
         testList (para $ rawInline "tex" "\\listoftables")
-                 def{tblRefs=M.fromList $ refRec' "tbl:1" 4 "4" <> refRec' "tbl:2" 5 "5" <> refRec' "tbl:3" 6 "6"}
+                 (tblRefs =: M.fromList $ refRec' "tbl:1" 4 "4" <> refRec' "tbl:2" 5 "5" <> refRec' "tbl:3" 6 "6")
                  (header 1 (text "List of Tables") <> orderedList ((plain . str . show) `map` [4..6 :: Int]))
       it "Generates list of figures" $
         testList (para $ rawInline "tex" "\\listoffigures")
-                 def{imgRefs=M.fromList $ refRec' "fig:1" 4 "4" <> refRec' "fig:2" 5 "5" <> refRec' "fig:3" 6 "6"}
+                 (imgRefs =: M.fromList $ refRec' "fig:1" 4 "4" <> refRec' "fig:2" 5 "5" <> refRec' "fig:3" 6 "6")
                  (header 1 (text "List of Figures") <> orderedList ((plain . str . show) `map` [4..6 :: Int]))
 
     describe "Util.CodeBlockCaptions" $
@@ -238,13 +279,13 @@
 refGen' p l1 l2 = M.fromList $ mconcat $ zipWith refRec''' (((uncapitalizeFirst p++) . show) `map` l1) l2
 
 refRec' :: String -> Int -> String -> [(String, RefRec)]
-refRec' ref i tit = [(ref, RefRec{refIndex=[(i,Nothing)],refTitle=toList $ text tit})]
+refRec' ref i tit = [(ref, RefRec{refIndex=[(i,Nothing)],refTitle=toList $ text tit,refSubfigure=Nothing})]
 
 refRec'' :: String -> Int -> [(String, RefRec)]
 refRec'' ref i = refRec' ref i []
 
 refRec''' :: String -> (Int, Int) -> [(String, RefRec)]
-refRec''' ref (c,i) = [(ref, RefRec{refIndex=[(c,Nothing), (i,Nothing)],refTitle=toList $ text []})]
+refRec''' ref (c,i) = [(ref, RefRec{refIndex=[(c,Nothing), (i,Nothing)],refTitle=toList $ text [],refSubfigure=Nothing})]
 
 testRefs' :: String -> [Int] -> [Int] -> Accessor References (M.Map String RefRec) -> String -> Expectation
 testRefs' p l1 l2 prop res = testRefs (para $ citeGen p l1) (setVal prop (refGen p l1 l2) def) (para $ text res)
@@ -252,12 +293,9 @@
 testRefs'' :: String -> [Int] -> [(Int, Int)] -> Accessor References (M.Map String RefRec) -> String -> Expectation
 testRefs'' p l1 l2 prop res = testRefs (para $ citeGen p l1) (setVal prop (refGen' p l1 l2) def) (para $ text res)
 
-testBlocks :: Blocks -> (Blocks, References) -> Expectation
-testBlocks = testState f def
-  where f = walkM $ References.Blocks.replaceBlocks defaultOptions . References.Blocks.divBlocks
-
-testInlines :: Inlines -> (Inlines, References) -> Expectation
-testInlines = testState (bottomUpM (References.Blocks.replaceInlines defaultOptions) . bottomUp References.Blocks.spanInlines) def
+testAll :: (Eq a, Data a, Show a) => Many a -> (Many a, References) -> Expectation
+testAll = testState f def
+  where f = References.Blocks.replaceAll defaultOptions
 
 testState :: (Eq s, Eq a1, Show s, Show a1, Df.Default s) =>
                ([a] -> State s [a1]) -> s -> Many a -> (Many a1, s) -> Expectation
@@ -267,18 +305,17 @@
 testRefs bs st rbs = testState (bottomUpM (References.Refs.replaceRefs defaultOptions)) st bs (rbs, st)
 
 testCBCaptions :: Blocks -> Blocks -> Expectation
-testCBCaptions bs res = runState (bottomUpM (Util.CodeBlockCaptions.codeBlockCaptions defaultOptions{cbCaptions=True}) (toList bs)) def `shouldBe` (toList res,def)
+testCBCaptions bs res = runState (bottomUpM (Util.CodeBlockCaptions.mkCodeBlockCaptions defaultOptions{Text.Pandoc.CrossRef.Util.Options.codeBlockCaptions=True}) (toList bs)) def `shouldBe` (toList res,def)
 
 testList :: Blocks -> References -> Blocks -> Expectation
 testList bs st res = runState (bottomUpM (References.List.listOf defaultOptions) (toList bs)) st `shouldBe` (toList res,st)
 
 figure :: String -> String -> String -> String -> Blocks
-#if MIN_VERSION_pandoc(1,16,0)
-figure src title alt ref = para (imageWith ("fig:" ++ ref, [], []) src ("fig:" ++ title) (text alt))
-#else
-figure src title alt ref = para (image src title (text alt) <> ref' "fig" ref)
-#endif
+figure = (((para .) .) .) . figure' "fig:"
 
+figure' :: String -> String -> String -> String -> String -> Inlines
+figure' p src title alt ref = imageWith ("fig:" ++ ref, [], []) src (p ++ title) (text alt)
+
 section :: String -> Int -> String -> Blocks
 section text' level label = headerWith ("sec:" ++ label,[],[]) level (text text')
 
@@ -328,3 +365,7 @@
 
 cit :: String -> [Citation]
 cit r = [defCit{citationId=r}]
+
+infixr 0 =:
+(=:) :: Df.Default r => Accessor r a -> a -> r
+a =: b = a ^= b $ def
