diff --git a/demo.md b/demo.md
new file mode 100644
--- /dev/null
+++ b/demo.md
@@ -0,0 +1,115 @@
+---
+cref: False
+codeBlockCaptions: True
+figureTitle: "Figure \\#"
+lofTitle: "## List of Figures"
+lotTitle: "## List of Tables"
+tableTemplate: "*$$tableTitle$$ $$i$$*$$titleDelim$$ $$t$$"
+autoSectionLabels: True
+---
+
+This is a demo file for pandoc-crossref. With this filter, you can cross-reference figures (see [@fig:figure1;@fig:figure2;@fig:figure3]), display equations (see @eq:eqn1), tables (see [@tbl:table1]) and sections ([@sec:sec1; @sec:sec2; @sec:caption-attr; @sec:table-capts; @sec:wrapping-div])
+
+For immediate example, see @fig:figure0
+
+![A figure](img1.jpg){#fig:figure0}
+
+There is also support for code blocks, for example, [@lst:captionAttr; @lst:tableCaption; @lst:wrappingDiv]
+
+It's possible to capitalize reference prefixes, like this: [@Fig:figure1].
+
+In case of multiple references, capitalization is determined by first reference. [@Fig:figure1; @fig:figure2] is capitalized, while [@fig:figure2; @Fig:figure1] is not.
+
+It is also possible to mix different references, like [@fig:figure1; @tbl:table1; @lst:captionAttr; @lst:tableCaption; @fig:figure2; @fig:figure3], which will be grouped in order they are specified. You can even intermix this with regular citations, although it's not recommended: [@fig:figure1; @tbl:table1; @unprocessedCitation]
+
+You can also have custom chapter reference labels, like @sec:custlabs
+
+# Chapter 1. Figures {#sec:sec1}
+
+![First figure](img1.jpg){#fig:figure1}
+
+![Second figure](img2.jpg){#fig:figure2}
+
+![Third figure](img3.jpg){#fig:figure3}
+
+![Unlabelled image](img1.jpg)
+
+# Chapter 2. Equations {#sec:sec2}
+
+$$ P_i(x) = \sum_i a_i x^i $$ {#eq:eqn1}
+
+# Chapter 3. Tables
+
+| First Header | Second Header |
+|:-------------|:--------------|
+| Content Cell | Content Cell  |
+| Content Cell | Content Cell  |
+
+: Table example {#tbl:table1}
+
+Table without caption:
+
+| First Header | Second Header |
+|:-------------|:--------------|
+| Content Cell | Content Cell  |
+| Content Cell | Content Cell  |
+
+# Chapter 4. Code blocks
+
+There are a couple options for code block labels. Those work only if code block id starts with `lst:`, e.g. `{#lst:label}`
+
+## `caption` attribute {#sec:caption-attr}
+
+`caption` attribute will be treated as code block caption. If code block has both id and `caption` attributes, it will be treated as numbered code block.
+
+```{#lst:captionAttr .haskell caption="Listing caption"}
+main :: IO ()
+main = putStrLn "Hello World!"
+```
+
+\pagebreak
+
+## Table-style captions  {#sec:table-capts}
+
+Enabled with `codeBlockCaptions` metadata option. If code block is immediately
+adjacent to paragraph, starting with `Listing: ` or `: `, said paragraph will be
+treated as code block caption.
+
+Listing: Listing caption
+
+```{#lst:tableCaption .haskell}
+main :: IO ()
+main = putStrLn "Hello World!"
+```
+
+## Wrapping div
+
+Wrapping code block without label in a div with id `lst:...` and class, starting with `listing`, and adding paragraph before code block, but inside div, will treat said paragraph as code block caption.
+
+<div id="lst:wrappingDiv" class="listing">
+Listing caption
+```{.haskell}
+main :: IO ()
+main = putStrLn "Hello World!"
+```
+</div>
+
+# Unnumbered chapter. {-}
+
+This chapter doesn't change chapter prefix of referenced elements, instead keeping number of previous chapter, e.g.
+
+$$ S(x) = \int_{x_1}^{x_2} a x+b \  \mathrm{d}x $$ {#eq:eqn2}
+
+# Chapter 5. Reference lists
+
+It's also possible to show lists of figures and tables, like this:
+
+\listoffigures
+
+\listoftables
+
+\listoflistings
+
+# Appendix A. Custom labels {label=AppA}
+
+## This section will have custom label {#sec:custlabs label=CustLab}
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.5.5
+version:             0.1.5.6
 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
@@ -15,6 +15,7 @@
 extra-doc-files:     README.md
                      BSD3.md
 cabal-version:       >=1.10
+data-files:          demo.md
 
 source-repository head
   type: git
@@ -23,7 +24,7 @@
 source-repository this
   type: git
   location: https://github.com/lierdakil/pandoc-crossref
-  tag: v0.1.5.5
+  tag: v0.1.5.6
 
 library
   exposed-modules:     Text.Pandoc.CrossRef
@@ -43,6 +44,7 @@
                      , 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.16
                      , mtl >= 1.1 && <2.3
@@ -54,6 +56,9 @@
   hs-source-dirs:      src
   Ghc-Options:         -Wall
   default-language:    Haskell2010
+  other-extensions:    RankNTypes
+                     , CPP
+                     , FlexibleContexts
 
 executable pandoc-crossref
   main-is:             pandoc-crossref.hs
@@ -73,7 +78,7 @@
 Test-Suite test-pandoc-crossref
   Type:           exitcode-stdio-1.0
   Main-Is:        test-pandoc-crossref.hs
-  hs-source-dirs: ., src
+  hs-source-dirs: test, src
   Build-Depends:   base >=4.2 && <5
                  , pandoc >= 1.13 && <1.16
                  , mtl >= 1.1 && <2.3
@@ -85,5 +90,6 @@
                  , hspec
                  , process >=1 && <1.3
                  , pandoc-crossref
+  other-modules: Native
   Ghc-Options:  -rtsopts -Wall -fno-warn-unused-do-bind -threaded
   Default-Language: Haskell2010
diff --git a/src/Text/Pandoc/CrossRef.hs b/src/Text/Pandoc/CrossRef.hs
--- a/src/Text/Pandoc/CrossRef.hs
+++ b/src/Text/Pandoc/CrossRef.hs
@@ -46,10 +46,12 @@
 >       <> chaptersDepth (MetaString "2")
 
 -}
+{-# LANGUAGE RankNTypes #-}
 
 module Text.Pandoc.CrossRef (
     crossRefBlocks
   , crossRefMeta
+  , defaultCrossRefAction
   , runCrossRef
   , runCrossRefIO
   , module SG
@@ -105,10 +107,19 @@
   dtv <- R.asks creSettings
   return $ modifyMeta opts dtv
 
+{- | Combines 'crossRefMeta' and 'crossRefBlocks'
+
+Works in 'CrossRefM' monad. -}
+defaultCrossRefAction :: Pandoc -> CrossRefM Pandoc
+defaultCrossRefAction (Pandoc _ bs) = do
+  meta' <- crossRefMeta
+  bs' <- crossRefBlocks bs
+  return $ Pandoc meta' bs'
+
 {- | Run an action in 'CrossRefM' monad with argument, and return pure result.
 
 This is primary function to work with 'CrossRefM' -}
-runCrossRef :: (Walkable a b) => Meta -> Maybe Format -> (a -> CrossRefM b) -> a -> b
+runCrossRef :: forall a b. Meta -> Maybe Format -> (a -> CrossRefM b) -> a -> b
 runCrossRef meta fmt action arg = R.runReader (action arg) env
   where
     settings = meta <> defaultMeta
@@ -121,7 +132,7 @@
 
 This function will attempt to read pandoc-crossref settings from settings
 file specified by crossrefYaml metadata field. -}
-runCrossRefIO :: (Walkable a b) => Meta -> Maybe Format -> (a -> CrossRefM b) -> a -> IO b
+runCrossRefIO :: forall a b. Meta -> Maybe Format -> (a -> CrossRefM b) -> a -> IO b
 runCrossRefIO meta fmt action arg = do
   settings <- getSettings meta
   let
diff --git a/src/Text/Pandoc/CrossRef/Util/Gap.hs b/src/Text/Pandoc/CrossRef/Util/Gap.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/CrossRef/Util/Gap.hs
@@ -0,0 +1,12 @@
+{-# LANGUAGE CPP #-}
+
+module Text.Pandoc.CrossRef.Util.Gap where
+
+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/src/Text/Pandoc/CrossRef/Util/Meta.hs b/src/Text/Pandoc/CrossRef/Util/Meta.hs
--- a/src/Text/Pandoc/CrossRef/Util/Meta.hs
+++ b/src/Text/Pandoc/CrossRef/Util/Meta.hs
@@ -1,7 +1,7 @@
 {-# LANGUAGE CPP #-}
 module Text.Pandoc.CrossRef.Util.Meta where
 
-import Text.Pandoc (readMarkdown)
+import Text.Pandoc.CrossRef.Util.Gap
 import Text.Pandoc.Shared (stringify)
 import Text.Pandoc.Definition
 import Data.Maybe (fromMaybe)
@@ -24,12 +24,7 @@
 
 toInlines :: MetaValue -> Maybe [Inline]
 toInlines (MetaString s) =
-#if MIN_VERSION_pandoc(1,14,0)
-  return $ getInlines $
-    either (error . show) id $ readMarkdown def s
-#else
   return $ getInlines $ readMarkdown def s
-#endif
   where getInlines (Pandoc _ bs) = concatMap getInline bs
         getInline (Plain ils) = ils
         getInline (Para ils) = ils
@@ -45,12 +40,7 @@
 toBlocks (MetaBlocks bs) = return bs
 toBlocks (MetaInlines ils) = return [Plain ils]
 toBlocks (MetaString s) =
-#if MIN_VERSION_pandoc(1,14,0)
-  return $ getBlocks $
-    either (error . show) id $ readMarkdown def s
-#else
   return $ getBlocks $ readMarkdown def s
-#endif
   where getBlocks (Pandoc _ bs) = bs
 toBlocks _ = Nothing
 
diff --git a/src/Text/Pandoc/CrossRef/Util/Settings.hs b/src/Text/Pandoc/CrossRef/Util/Settings.hs
--- a/src/Text/Pandoc/CrossRef/Util/Settings.hs
+++ b/src/Text/Pandoc/CrossRef/Util/Settings.hs
@@ -1,7 +1,8 @@
 {-# LANGUAGE CPP #-}
 module Text.Pandoc.CrossRef.Util.Settings (getSettings, defaultMeta) where
 
-import Text.Pandoc
+import Text.Pandoc hiding (readMarkdown)
+import Text.Pandoc.CrossRef.Util.Gap
 import Text.Pandoc.Builder
 import Control.Exception (handle,IOException)
 
@@ -13,11 +14,7 @@
   let handler :: IOException -> IO String
       handler _ = return []
   yaml <- handle handler $ readFile (getMetaString "crossrefYaml" (meta <> defaultMeta))
-#if MIN_VERSION_pandoc(1,14,0)
-  let Pandoc dtve _ = either (error . show) id $ readMarkdown def ("---\n" ++ yaml ++ "\n---")
-#else
   let Pandoc dtve _ = readMarkdown def ("---\n" ++ yaml ++ "\n---")
-#endif
   return $ meta <> dtve <> defaultMeta
 
 defaultMeta :: Meta
diff --git a/test-pandoc-crossref.hs b/test-pandoc-crossref.hs
deleted file mode 100644
--- a/test-pandoc-crossref.hs
+++ /dev/null
@@ -1,225 +0,0 @@
-import Test.Hspec
-import Text.Pandoc.Definition
-import Text.Pandoc.Builder
-import Text.Pandoc.Walk
-import Text.Pandoc.Generic
-import Control.Monad.State
-import Data.List
-import Control.Arrow
-import Data.Monoid -- needed for ghc<7.10
-import qualified Data.Map as M
-
-import Text.Pandoc.CrossRef.Util.Options
-import Text.Pandoc.CrossRef.Util.Util
-import Text.Pandoc.CrossRef.References.Types
-import Text.Pandoc.CrossRef.Util.Settings
-import Text.Pandoc.CrossRef.Util.Accessor
-import Text.Pandoc.CrossRef.References.Accessors
-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
-import qualified Text.Pandoc.CrossRef.Util.Template as Util.Template
-import qualified Text.Pandoc.CrossRef.Util.CodeBlockCaptions as Util.CodeBlockCaptions
-
-main :: IO ()
-main = hspec $ do
-    describe "References.Blocks.replaceBlocks" $ do
-      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"})
-      it "Labels equations" $
-        testBlocks (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})
-      it "Labels tables" $
-        testBlocks (table' "Test table" "table")
-        (table' "Table 1: Test table" [],
-          def{tblRefs=M.fromList $ refRec' "tbl:table" 1 "Test table"})
-      it "Labels code blocks" $
-        testBlocks (codeBlock' "Test code block" "codeblock")
-        (codeBlockDiv "Listing 1: Test code block" "codeblock",
-          def{lstRefs=M.fromList $ refRec' "lst:codeblock" 1 "Test code block"})
-      it "Labels code block divs" $
-        testBlocks (codeBlockDiv "Test code block" "codeblock")
-        (codeBlockDiv "Listing 1: Test code block" "codeblock",
-          def{lstRefs=M.fromList $ refRec' "lst:codeblock" 1 "Test code block"})
-      it "Labels sections divs" $
-        testBlocks (section "Section Header" 1 "section")
-        (section "Section Header" 1 "section",
-          def{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"
-      it "References multiple images" $
-        testRefs' "fig:" [1..3] [4..6] imgRefs' "figs.\160\&4-6"
-      it "References one equation" $
-        testRefs' "eq:" [1] [4] eqnRefs' "eq.\160\&4"
-      it "References multiple equations" $
-        testRefs' "eq:" [1..3] [4..6] eqnRefs' "eqns.\160\&4-6"
-      it "References one table" $
-        testRefs' "tbl:" [1] [4] tblRefs' "tbl.\160\&4"
-      it "References multiple tables" $
-        testRefs' "tbl:" [1..3] [4..6] tblRefs' "tbls.\160\&4-6"
-      it "References one listing" $
-        testRefs' "lst:" [1] [4] lstRefs' "lst.\160\&4"
-      it "References multiple listings" $
-        testRefs' "lst:" [1..3] [4..6] lstRefs' "lsts.\160\&4-6"
-      it "References one section" $
-        testRefs' "sec:" [1] [4] secRefs' "sec.\160\&4"
-      it "References multiple sections" $
-        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"
-
-    describe "References.Refs.replaceRefs capitalization" $ do
-      it "References one image" $
-        testRefs' "Fig:" [1] [4] imgRefs' "Fig.\160\&4"
-      it "References multiple images" $
-        testRefs' "Fig:" [1..3] [4..6] imgRefs' "Figs.\160\&4-6"
-      it "References one equation" $
-        testRefs' "Eq:" [1] [4] eqnRefs' "Eq.\160\&4"
-      it "References multiple equations" $
-        testRefs' "Eq:" [1..3] [4..6] eqnRefs' "Eqns.\160\&4-6"
-      it "References one table" $
-        testRefs' "Tbl:" [1] [4] tblRefs' "Tbl.\160\&4"
-      it "References multiple tables" $
-        testRefs' "Tbl:" [1..3] [4..6] tblRefs' "Tbls.\160\&4-6"
-      it "References one listing" $
-        testRefs' "Lst:" [1] [4] lstRefs' "Lst.\160\&4"
-      it "References multiple listings" $
-        testRefs' "Lst:" [1..3] [4..6] lstRefs' "Lsts.\160\&4-6"
-      it "References one listing" $
-        testRefs' "Sec:" [1] [4] secRefs' "Sec.\160\&4"
-      it "References multiple listings" $
-        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"}
-                 (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"}
-                 (header 1 (text "List of Figures") <> orderedList ((plain . str . show) `map` [4..6 :: Int]))
-
-    describe "Util.CodeBlockCaptions" $
-      it "Transforms table-style codeBlock captions to codeblock divs" $ do
-        let t x = testCBCaptions x (codeBlockDiv "Code Block" "cb")
-        t (codeBlockForTable "cb" <> paraText ": Code Block")
-        t (codeBlockForTable "cb" <> paraText "Listing: Code Block")
-        t (paraText ": Code Block" <> codeBlockForTable "cb")
-        t (paraText "Listing: Code Block" <> codeBlockForTable "cb")
-
-    describe "Util.Template" $
-      it "Applies templates" $
-        let template=Util.Template.makeTemplate defaultMeta (toList $ displayMath "figureTitle" <> displayMath "i" <> displayMath "t")
-        in Util.Template.applyTemplate [Str "1"] [Str "title"] template `shouldBe`
-           toList (str "Figure" <> str "1" <> str "title")
-
-    describe "Citation groups shouldn't be separated (#22 regression test)" $ do
-      it "Should not separate citation groups" $ do
-        let cits = para $ citeGen "" [1..3]
-        testRefs cits def cits
-
-      it "Should not separate citation groups with unknown prefix" $ do
-        let cits = para $ citeGen "unk:" [1..3]
-        testRefs cits def cits
-
-      it "Should not separate citation groups with different unknown prefixes" $ do
-        let cits = para $ cite (mconcat $ map (cit . uncurry (++) . second show) l) $ text $
-              "[" ++ intercalate "; " (map (("@"++) . uncurry (++) . second show) l) ++ "]"
-            l = zip ["unk1:", "unk2:"] [1,2::Int]
-        testRefs cits def cits
-
-
-citeGen :: String -> [Int] -> Inlines
-citeGen p l = cite (mconcat $ map (cit . (p++) . show) l) $ text $
-  "[" ++ intercalate "; " (map (("@"++) . (p++) . show) l) ++ "]"
-
-refGen :: String -> [Int] -> [Int] -> M.Map String RefRec
-refGen p l1 l2 = M.fromList $ mconcat $ zipWith refRec'' (((uncapitalizeFirst p++) . show) `map` l1) l2
-
-refGen' :: String -> [Int] -> [(Int, Int)] -> M.Map String RefRec
-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'' :: 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 []})]
-
-testRefs' :: String -> [Int] -> [Int] -> Accessor References (M.Map String RefRec) -> String -> Expectation
-testRefs' p l1 l2 prop res = testRefs (para $ citeGen p l1) (setProp prop (refGen p l1 l2) def) (para $ text res)
-
-testRefs'' :: String -> [Int] -> [(Int, Int)] -> Accessor References (M.Map String RefRec) -> String -> Expectation
-testRefs'' p l1 l2 prop res = testRefs (para $ citeGen p l1) (setProp prop (refGen' p l1 l2) def) (para $ text res)
-
-testBlocks :: Blocks -> (Blocks, References) -> Expectation
-testBlocks arg res = runState (walkM (f defaultOptions) arg) def `shouldBe` res
-  where f = (. References.Blocks.divBlocks) . References.Blocks.replaceBlocks
-
-testRefs :: Blocks -> References -> Blocks -> Expectation
-testRefs bs st res = runState (bottomUpM (References.Refs.replaceRefs defaultOptions) (toList bs)) st `shouldBe` (toList res,st)
-
-testCBCaptions :: Blocks -> Blocks -> Expectation
-testCBCaptions bs res = runState (bottomUpM (Util.CodeBlockCaptions.codeBlockCaptions defaultOptions{cbCaptions=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
-figure src title alt ref = para (image src title (text alt) <> ref' "fig" ref)
-
-section :: String -> Int -> String -> Blocks
-section text' level label = headerWith ("sec:" ++ label,[],[]) level (text text')
-
-equation :: String -> String -> Blocks
-equation eq ref = para (displayMath eq <> ref' "eq" ref)
-
-table' :: String -> String -> Blocks
-table' title ref = table (text title <> ref' "tbl" ref) []
-   [para $ str "H1", para $ str "H2"]
-  [[para $ str "C1", para $ str "C2"]]
-
-codeBlock' :: String -> String -> Blocks
-codeBlock' title ref = codeBlockWith
-  ("lst:"++ref,["haskell"],[("caption",title)]) "main :: IO ()"
-
-codeBlockForTable :: String -> Blocks
-codeBlockForTable ref = codeBlockWith
-     ("lst:"++ref,["haskell"],[]) "main :: IO ()"
-
-paraText :: String -> Blocks
-paraText s = para $ text s
-
-codeBlockDiv :: String -> String -> Blocks
-codeBlockDiv title ref = divWith ("lst:"++ref, ["listing","haskell"],[]) $
-  para (text title) <>
-  codeBlockWith
-    ("",["haskell"],[]) "main :: IO ()"
-
-ref' :: String -> String -> Inlines
-ref' p n | null n  = mempty
-         | otherwise = space <> str ("{#"++p++":"++n++"}")
-
-defaultOptions :: Options
-defaultOptions = getOptions defaultMeta Nothing
-
-defCit :: Citation
-defCit = Citation{citationId = ""
-                 ,citationPrefix = []
-                 ,citationSuffix = []
-                 ,citationHash = 0
-                 ,citationNoteNum = 0
-                 ,citationMode = NormalCitation
-                 }
-
-cit :: String -> [Citation]
-cit r = [defCit{citationId=r}]
diff --git a/test/Native.hs b/test/Native.hs
new file mode 100644
--- /dev/null
+++ b/test/Native.hs
@@ -0,0 +1,130 @@
+module Native where
+
+import Text.Pandoc.Definition
+
+demo :: [Block]
+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 [Math DisplayMath " P_i(x) = \\sum_i a_i x^i \\qquad(1)"]
+  ,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."]
+  ,Para [Math DisplayMath " S(x) = \\int_{x_1}^{x_2} a x+b \\  \\mathrm{d}x \\qquad(2)"]
+  ,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]
+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 [Math DisplayMath " P_i(x) = \\sum_i a_i x^i \\qquad(2.1)"]
+  ,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."]
+  ,Para [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"]]
+
diff --git a/test/test-pandoc-crossref.hs b/test/test-pandoc-crossref.hs
new file mode 100644
--- /dev/null
+++ b/test/test-pandoc-crossref.hs
@@ -0,0 +1,243 @@
+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
+import Data.Monoid -- needed for ghc<7.10
+import qualified Data.Map as M
+
+import Text.Pandoc.CrossRef
+import Text.Pandoc.CrossRef.Util.Options
+import Text.Pandoc.CrossRef.Util.Gap
+import Text.Pandoc.CrossRef.Util.Util
+import Text.Pandoc.CrossRef.References.Types
+import Text.Pandoc.CrossRef.Util.Settings
+import Text.Pandoc.CrossRef.Util.Accessor
+import Text.Pandoc.CrossRef.References.Accessors
+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
+import qualified Text.Pandoc.CrossRef.Util.Template as Util.Template
+import qualified Text.Pandoc.CrossRef.Util.CodeBlockCaptions as Util.CodeBlockCaptions
+
+import qualified Native
+import Paths_pandoc_crossref
+
+main :: IO ()
+main = hspec $ do
+    describe "References.Blocks.replaceBlocks" $ do
+      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"})
+      it "Labels equations" $
+        testBlocks (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})
+      it "Labels tables" $
+        testBlocks (table' "Test table" "table")
+        (table' "Table 1: Test table" [],
+          def{tblRefs=M.fromList $ refRec' "tbl:table" 1 "Test table"})
+      it "Labels code blocks" $
+        testBlocks (codeBlock' "Test code block" "codeblock")
+        (codeBlockDiv "Listing 1: Test code block" "codeblock",
+          def{lstRefs=M.fromList $ refRec' "lst:codeblock" 1 "Test code block"})
+      it "Labels code block divs" $
+        testBlocks (codeBlockDiv "Test code block" "codeblock")
+        (codeBlockDiv "Listing 1: Test code block" "codeblock",
+          def{lstRefs=M.fromList $ refRec' "lst:codeblock" 1 "Test code block"})
+      it "Labels sections divs" $
+        testBlocks (section "Section Header" 1 "section")
+        (section "Section Header" 1 "section",
+          def{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"
+      it "References multiple images" $
+        testRefs' "fig:" [1..3] [4..6] imgRefs' "figs.\160\&4-6"
+      it "References one equation" $
+        testRefs' "eq:" [1] [4] eqnRefs' "eq.\160\&4"
+      it "References multiple equations" $
+        testRefs' "eq:" [1..3] [4..6] eqnRefs' "eqns.\160\&4-6"
+      it "References one table" $
+        testRefs' "tbl:" [1] [4] tblRefs' "tbl.\160\&4"
+      it "References multiple tables" $
+        testRefs' "tbl:" [1..3] [4..6] tblRefs' "tbls.\160\&4-6"
+      it "References one listing" $
+        testRefs' "lst:" [1] [4] lstRefs' "lst.\160\&4"
+      it "References multiple listings" $
+        testRefs' "lst:" [1..3] [4..6] lstRefs' "lsts.\160\&4-6"
+      it "References one section" $
+        testRefs' "sec:" [1] [4] secRefs' "sec.\160\&4"
+      it "References multiple sections" $
+        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"
+
+    describe "References.Refs.replaceRefs capitalization" $ do
+      it "References one image" $
+        testRefs' "Fig:" [1] [4] imgRefs' "Fig.\160\&4"
+      it "References multiple images" $
+        testRefs' "Fig:" [1..3] [4..6] imgRefs' "Figs.\160\&4-6"
+      it "References one equation" $
+        testRefs' "Eq:" [1] [4] eqnRefs' "Eq.\160\&4"
+      it "References multiple equations" $
+        testRefs' "Eq:" [1..3] [4..6] eqnRefs' "Eqns.\160\&4-6"
+      it "References one table" $
+        testRefs' "Tbl:" [1] [4] tblRefs' "Tbl.\160\&4"
+      it "References multiple tables" $
+        testRefs' "Tbl:" [1..3] [4..6] tblRefs' "Tbls.\160\&4-6"
+      it "References one listing" $
+        testRefs' "Lst:" [1] [4] lstRefs' "Lst.\160\&4"
+      it "References multiple listings" $
+        testRefs' "Lst:" [1..3] [4..6] lstRefs' "Lsts.\160\&4-6"
+      it "References one listing" $
+        testRefs' "Sec:" [1] [4] secRefs' "Sec.\160\&4"
+      it "References multiple listings" $
+        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"}
+                 (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"}
+                 (header 1 (text "List of Figures") <> orderedList ((plain . str . show) `map` [4..6 :: Int]))
+
+    describe "Util.CodeBlockCaptions" $
+      it "Transforms table-style codeBlock captions to codeblock divs" $ do
+        let t x = testCBCaptions x (codeBlockDiv "Code Block" "cb")
+        t (codeBlockForTable "cb" <> paraText ": Code Block")
+        t (codeBlockForTable "cb" <> paraText "Listing: Code Block")
+        t (paraText ": Code Block" <> codeBlockForTable "cb")
+        t (paraText "Listing: Code Block" <> codeBlockForTable "cb")
+
+    describe "Util.Template" $
+      it "Applies templates" $
+        let template=Util.Template.makeTemplate defaultMeta (toList $ displayMath "figureTitle" <> displayMath "i" <> displayMath "t")
+        in Util.Template.applyTemplate [Str "1"] [Str "title"] template `shouldBe`
+           toList (str "Figure" <> str "1" <> str "title")
+
+    describe "Citation groups shouldn't be separated (#22 regression test)" $ do
+      it "Should not separate citation groups" $ do
+        let cits = para $ citeGen "" [1..3]
+        testRefs cits def cits
+
+      it "Should not separate citation groups with unknown prefix" $ do
+        let cits = para $ citeGen "unk:" [1..3]
+        testRefs cits def cits
+
+      it "Should not separate citation groups with different unknown prefixes" $ do
+        let cits = para $ cite (mconcat $ map (cit . uncurry (++) . second show) l) $ text $
+              "[" ++ intercalate "; " (map (("@"++) . uncurry (++) . second show) l) ++ "]"
+            l = zip ["unk1:", "unk2:"] [1,2::Int]
+        testRefs cits def cits
+
+    describe "Test files" $ do
+
+      it "demo.md matches demo.native" $ do
+        demomd <- readFile =<< getDataFileName "demo.md"
+        let Pandoc m b = readMarkdown def demomd
+        runCrossRef m Nothing crossRefBlocks b `shouldBe` Native.demo
+
+      it "demo.md with chapters matches demo-chapters.native" $ do
+        demomd <- readFile =<< getDataFileName "demo.md"
+        let Pandoc m b = readMarkdown def demomd
+            m' = setMeta "chapters" True m
+        runCrossRef m' Nothing crossRefBlocks b `shouldBe` Native.demochapters
+
+
+
+citeGen :: String -> [Int] -> Inlines
+citeGen p l = cite (mconcat $ map (cit . (p++) . show) l) $ text $
+  "[" ++ intercalate "; " (map (("@"++) . (p++) . show) l) ++ "]"
+
+refGen :: String -> [Int] -> [Int] -> M.Map String RefRec
+refGen p l1 l2 = M.fromList $ mconcat $ zipWith refRec'' (((uncapitalizeFirst p++) . show) `map` l1) l2
+
+refGen' :: String -> [Int] -> [(Int, Int)] -> M.Map String RefRec
+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'' :: 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 []})]
+
+testRefs' :: String -> [Int] -> [Int] -> Accessor References (M.Map String RefRec) -> String -> Expectation
+testRefs' p l1 l2 prop res = testRefs (para $ citeGen p l1) (setProp prop (refGen p l1 l2) def) (para $ text res)
+
+testRefs'' :: String -> [Int] -> [(Int, Int)] -> Accessor References (M.Map String RefRec) -> String -> Expectation
+testRefs'' p l1 l2 prop res = testRefs (para $ citeGen p l1) (setProp prop (refGen' p l1 l2) def) (para $ text res)
+
+testBlocks :: Blocks -> (Blocks, References) -> Expectation
+testBlocks arg res = runState (walkM (f defaultOptions) arg) def `shouldBe` res
+  where f = (. References.Blocks.divBlocks) . References.Blocks.replaceBlocks
+
+testRefs :: Blocks -> References -> Blocks -> Expectation
+testRefs bs st res = runState (bottomUpM (References.Refs.replaceRefs defaultOptions) (toList bs)) st `shouldBe` (toList res,st)
+
+testCBCaptions :: Blocks -> Blocks -> Expectation
+testCBCaptions bs res = runState (bottomUpM (Util.CodeBlockCaptions.codeBlockCaptions defaultOptions{cbCaptions=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
+figure src title alt ref = para (image src title (text alt) <> ref' "fig" ref)
+
+section :: String -> Int -> String -> Blocks
+section text' level label = headerWith ("sec:" ++ label,[],[]) level (text text')
+
+equation :: String -> String -> Blocks
+equation eq ref = para (displayMath eq <> ref' "eq" ref)
+
+table' :: String -> String -> Blocks
+table' title ref = table (text title <> ref' "tbl" ref) []
+   [para $ str "H1", para $ str "H2"]
+  [[para $ str "C1", para $ str "C2"]]
+
+codeBlock' :: String -> String -> Blocks
+codeBlock' title ref = codeBlockWith
+  ("lst:"++ref,["haskell"],[("caption",title)]) "main :: IO ()"
+
+codeBlockForTable :: String -> Blocks
+codeBlockForTable ref = codeBlockWith
+     ("lst:"++ref,["haskell"],[]) "main :: IO ()"
+
+paraText :: String -> Blocks
+paraText s = para $ text s
+
+codeBlockDiv :: String -> String -> Blocks
+codeBlockDiv title ref = divWith ("lst:"++ref, ["listing","haskell"],[]) $
+  para (text title) <>
+  codeBlockWith
+    ("",["haskell"],[]) "main :: IO ()"
+
+ref' :: String -> String -> Inlines
+ref' p n | null n  = mempty
+         | otherwise = space <> str ("{#"++p++":"++n++"}")
+
+defaultOptions :: Options
+defaultOptions = getOptions defaultMeta Nothing
+
+defCit :: Citation
+defCit = Citation{citationId = ""
+                 ,citationPrefix = []
+                 ,citationSuffix = []
+                 ,citationHash = 0
+                 ,citationNoteNum = 0
+                 ,citationMode = NormalCitation
+                 }
+
+cit :: String -> [Citation]
+cit r = [defCit{citationId=r}]
