diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -73,10 +73,6 @@
 
 To label a table, append `{#tbl:label}` at the end of table caption (with `label` being something unique to reference this table by). Caption and label *must* be separated by at least one space.
 
-### Code Block labels
-
-There are a couple options to add code block labels. Those work only if code block id starts with `lst:`, e.g. `{#lst:label}`
-
 ### Section labels
 
 You can also reference sections of any level. Section labels use native pandoc syntax, but must start with "sec:", e.g.
@@ -87,6 +83,10 @@
 
 You can also use `autoSectionLabels` variable to automatically prepend all section labels (automatically generated with pandoc included) with "sec:". Bear in mind that references can't contain periods, commas etc, so some auto-generated labels will still be unusable.
 
+### Code Block labels
+
+There are a couple options to add code block labels. Those work only if code block id starts with `lst:`, e.g. `{#lst:label}`
+
 #### `caption` attribute
 
 `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.
@@ -204,7 +204,7 @@
 `figPrefix`, `eqnPrefix`, `tblPrefix`, `lstPrefix` can be YAML arrays. That way, value at index corresponds to total number of references in group, f.ex.
 
 ```yaml
-fixPrefix:
+figPrefix:
   - "fig."
   - "figs."
 ```
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.4.0
+version:             0.1.5.1
 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
@@ -23,25 +23,41 @@
 source-repository this
   type: git
   location: https://github.com/lierdakil/pandoc-crossref
-  tag: v0.1.4.0
+  tag: v0.1.5.1
 
+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
+                     , Text.Pandoc.CrossRef.References.Types
+                     , Text.Pandoc.CrossRef.Util.Settings
+                     , Text.Pandoc.CrossRef.Util.Accessor
+                     , Text.Pandoc.CrossRef.Util.Meta
+                     , Text.Pandoc.CrossRef.Util.Options
+                     , Text.Pandoc.CrossRef.Util.Template
+                     , Text.Pandoc.CrossRef.Util.Util
+                     , Text.Pandoc.CrossRef.Util.CodeBlockCaptions
+                     , Text.Pandoc.CrossRef.Util.ModifyMeta
+                     , Text.Pandoc.CrossRef.Util.Settings.Gen
+                     , Text.Pandoc.CrossRef.Util.Settings.Template
+  build-depends:       base >=4.2 && <5
+                     , pandoc >= 1.13 && <1.16
+                     , mtl >= 1.1 && <2.3
+                     , containers >= 0.1 && <0.6
+                     , pandoc-types >= 1.12.4.1 && < 1.13
+                     , yaml >= 0.8 && <0.9
+                     , data-default >= 0.4 && <0.6
+                     , bytestring >=0.9 && <0.11
+                     , template-haskell
+  hs-source-dirs:      src
+  Ghc-Options:         -Wall
+  default-language:    Haskell2010
+
 executable pandoc-crossref
   main-is:             pandoc-crossref.hs
-  other-modules:       References
-                     , References.Accessors
-                     , References.Blocks
-                     , References.List
-                     , References.Refs
-                     , References.Types
-                     , Util.Settings
-                     , Util.Accessor
-                     , Util.Meta
-                     , Util.Options
-                     , Util.Template
-                     , Util.Util
-                     , Util.CodeBlockCaptions
-                     , Util.ModifyMeta
-  other-extensions: CPP
   build-depends:       base >=4.2 && <5
                      , pandoc >= 1.13 && <1.16
                      , mtl >= 1.1 && <2.3
@@ -50,27 +66,14 @@
                      , yaml >= 0.8 && <0.9
                      , data-default >= 0.4 && <0.6
                      , bytestring >=0.9 && <0.11
-  hs-source-dirs:      ., src
+                     , pandoc-crossref
+  hs-source-dirs:      .
+  Ghc-Options:         -Wall
   default-language:    Haskell2010
 
 Test-Suite test-pandoc-crossref
   Type:           exitcode-stdio-1.0
   Main-Is:        test-pandoc-crossref.hs
-  other-modules:       References
-                     , References.Accessors
-                     , References.Blocks
-                     , References.List
-                     , References.Refs
-                     , References.Types
-                     , Util.Settings
-                     , Util.Accessor
-                     , Util.Meta
-                     , Util.Options
-                     , Util.Template
-                     , Util.Util
-                     , Util.CodeBlockCaptions
-                     , Util.ModifyMeta
-  other-extensions: CPP
   hs-source-dirs: ., src
   Build-Depends:   base >=4.2 && <5
                  , pandoc >= 1.13 && <1.16
@@ -82,5 +85,7 @@
                  , bytestring >=0.9 && <0.11
                  , hspec
                  , process >=1 && <1.3
+                 , pandoc-crossref
+                 , template-haskell
   Ghc-Options:  -rtsopts -Wall -fno-warn-unused-do-bind -threaded
   Default-Language: Haskell2010
diff --git a/pandoc-crossref.hs b/pandoc-crossref.hs
--- a/pandoc-crossref.hs
+++ b/pandoc-crossref.hs
@@ -1,26 +1,14 @@
 import Text.Pandoc
 import Text.Pandoc.JSON
-import Text.Pandoc.Walk
-import Control.Monad.State
 
-import References
-import Util.Settings
-import Util.Options
-import Util.CodeBlockCaptions
-import Util.ModifyMeta
+import Text.Pandoc.CrossRef
 
 main :: IO ()
 main = toJSONFilter go
-
-go :: Maybe Format -> Pandoc -> IO Pandoc
-go fmt (Pandoc meta bs) = do
-  dtv <- getSettings meta
-  let
-    doWalk =
-      bottomUpM (codeBlockCaptions opts) (walk divBlocks bs)
-      >>= walkM (replaceBlocks opts)
-      >>= bottomUpM (replaceRefs opts)
-      >>= bottomUpM (listOf opts)
-    opts = getOptions dtv fmt
-    meta' = modifyMeta opts dtv
-  return $ Pandoc meta' $ evalState doWalk def
+  where
+    go fmt p@(Pandoc meta _) = runCrossRefIO meta fmt action p
+      where
+        action (Pandoc _ bs) = do
+          meta' <- crossRefMeta
+          bs' <- crossRefBlocks bs
+          return $ Pandoc meta' bs'
diff --git a/src/References.hs b/src/References.hs
deleted file mode 100644
--- a/src/References.hs
+++ /dev/null
@@ -1,7 +0,0 @@
-module References ( module X ) where
-
-import References.Accessors as X
-import References.Types as X
-import References.Blocks as X
-import References.Refs as X
-import References.List as X
diff --git a/src/References/Accessors.hs b/src/References/Accessors.hs
deleted file mode 100644
--- a/src/References/Accessors.hs
+++ /dev/null
@@ -1,19 +0,0 @@
-module References.Accessors where
-
-import References.Types
-import Util.Accessor
-
-imgRefs' :: Accessor References RefMap
-imgRefs' new r@References{imgRefs=old} = (old, r{imgRefs=new})
-
-eqnRefs' :: Accessor References RefMap
-eqnRefs' new r@References{eqnRefs=old} = (old, r{eqnRefs=new})
-
-tblRefs' :: Accessor References RefMap
-tblRefs' new r@References{tblRefs=old} = (old, r{tblRefs=new})
-
-lstRefs' :: Accessor References RefMap
-lstRefs' new r@References{lstRefs=old} = (old, r{lstRefs=new})
-
-secRefs' :: Accessor References RefMap
-secRefs' new r@References{secRefs=old} = (old, r{secRefs=new})
diff --git a/src/References/Blocks.hs b/src/References/Blocks.hs
deleted file mode 100644
--- a/src/References/Blocks.hs
+++ /dev/null
@@ -1,156 +0,0 @@
-module References.Blocks (divBlocks, replaceBlocks) where
-
-import Text.Pandoc.Definition
-import Text.Pandoc.Builder (text, toList)
-import Text.Pandoc.Shared (stringify, normalizeSpaces)
-import Control.Monad.State
-import Data.List
-import qualified Data.Map as M
-
-import Util.Accessor
-import References.Types
-import References.Accessors
-import Util.Util
-import Util.Options
-import Util.Template
-
-replaceBlocks :: Options -> Block -> WS Block
-replaceBlocks opts (Header n (label, cls, attrs) text')
-  = do
-    let label' = if autoSecLab opts && not ("sec:" `isPrefixOf` label)
-                 then "sec:"++label
-                 else label
-    unless ("unnumbered" `elem` cls) $ do
-      modify $ \r@References{curChap=cc} ->
-        let ln = length cc
-            inc l = init l ++ [last l + 1]
-            cc' | ln > n = inc $ take n cc
-                | ln == n = inc cc
-                | otherwise = cc ++ take (n-ln) [1,1..]
-        in r{curChap=cc'}
-      when ("sec:" `isPrefixOf` label') $ replaceAttrSec label' text' secRefs'
-    return $ Header n (label', cls, attrs) text'
-replaceBlocks opts (Div (label,_,_) [Plain [Image alt img]])
-  | "fig:" `isPrefixOf` label
-  = do
-    idxStr <- replaceAttr opts label alt imgRefs'
-    let alt' = case outFormat opts of
-          f | isFormat "latex" f ->
-            RawInline (Format "tex") ("\\label{"++label++"}") : alt
-          _  -> applyTemplate idxStr alt $ figureTemplate opts
-    return $ Para [Image alt' (fst img,"fig:")]
-replaceBlocks opts (Div (label,_,_) [Plain [Math DisplayMath eq]])
-  | "eq:" `isPrefixOf` label
-  = case outFormat opts of
-      f | isFormat "latex" f ->
-        let eqn = "\\begin{equation}"++eq++"\\label{"++label++"}\\end{equation}"
-        in return $ Para [RawInline (Format "tex") eqn]
-      _ -> do
-        idxStr <- replaceAttr opts label [] eqnRefs'
-        let eq' = eq++"\\qquad("++stringify idxStr++")"
-        return $ Para [Math DisplayMath eq']
-replaceBlocks opts (Div (label,_,_) [Table title align widths header cells])
-  | not $ null title
-  , "tbl:" `isPrefixOf` label
-  = do
-    idxStr <- replaceAttr opts label (init title) tblRefs'
-    let title' =
-          case outFormat opts of
-              f | isFormat "latex" f ->
-                RawInline (Format "tex") ("\\label{"++label++"}") : init title
-              _  -> applyTemplate idxStr (init title) $ tableTemplate opts
-    return $ Table title' align widths header cells
-replaceBlocks opts cb@(CodeBlock (label, classes, attrs) code)
-  | not $ null label
-  , "lst:" `isPrefixOf` label
-  , Just caption <- lookup "caption" attrs
-  = case outFormat opts of
-      f
-        --if used with listings package,nothing shoud be done
-        | isFormat "latex" f, useListings opts -> return cb
-        --if not using listings, however, wrap it in a codelisting environment
-        | isFormat "latex" f ->
-          return $ Div nullAttr [
-              RawBlock (Format "tex")
-                $ "\\begin{codelisting}\n\\caption{"++caption++"}"
-            , cb
-            , RawBlock (Format "tex") "\\end{codelisting}"
-            ]
-      _ -> do
-        let cap = toList $ text caption
-        idxStr <- replaceAttr opts label cap lstRefs'
-        let caption' = applyTemplate idxStr cap $ listingTemplate opts
-        return $ Div (label, "listing":classes, []) [
-            Para caption'
-          , CodeBlock ([], classes, attrs \\ [("caption", caption)]) code
-          ]
-replaceBlocks opts
-  (Div (label,"listing":_, [])
-    [Para caption, CodeBlock ([],classes,attrs) code])
-  | not $ null label
-  , "lst:" `isPrefixOf` label
-  = case outFormat opts of
-      f
-        --if used with listings package, return code block with caption
-        | isFormat "latex" f, useListings 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 [
-              RawBlock (Format "tex") "\\begin{codelisting}"
-            , Para [RawInline (Format "tex") "\\caption",Span nullAttr caption]
-            , CodeBlock (label,classes,attrs) code
-            , RawBlock (Format "tex") "\\end{codelisting}"
-            ]
-      _ -> do
-        idxStr <- replaceAttr opts label caption lstRefs'
-        let caption' = applyTemplate idxStr caption $ listingTemplate opts
-        return $ Div (label, "listing":classes, []) [
-            Para caption'
-          , CodeBlock ([], classes, attrs) code
-          ]
-replaceBlocks _ x = return x
-
-divBlocks :: Block -> Block
-divBlocks (Para (Image alt img:c))
-  | Just label <- getRefLabel "fig" c
-  = Div (label,[],[]) [Plain [Image alt (fst img, "fig:")]]
-divBlocks (Para (math@(Math DisplayMath _eq):c))
-  | Just label <- getRefLabel "eq" c
-  = Div (label,[],[]) [Plain [math]]
-divBlocks (table@(Table title _align _widths _header _cells))
-  | not $ null title
-  , Just label <- getRefLabel "tbl" [last title]
-  = Div (label,[],[]) [table]
-divBlocks x = x
-
-getRefLabel :: String -> [Inline] -> Maybe String
-getRefLabel _ [] = Nothing
-getRefLabel tag ils
-  | Str attr <- last ils
-  , all (==Space) (init ils)
-  , "}" `isSuffixOf` attr
-  , ("{#"++tag++":") `isPrefixOf` attr
-  = init `fmap` stripPrefix "{#" attr
-getRefLabel _ _ = Nothing
-
-replaceAttr :: Options -> String -> [Inline] -> Accessor References RefMap -> WS [Inline]
-replaceAttr o label title prop
-  = do
-    chap  <- take (chapDepth o) `fmap` gets curChap
-    index <- (1+) `fmap` gets (M.size . M.filter ((==chap) . fst . refIndex) . getProp prop)
-    modify $ modifyProp prop $ M.insert label RefRec {
-      refIndex=(chap,index)
-    , refTitle=normalizeSpaces title
-    }
-    return $ chapPrefix (chapDelim o) chap index
-
-replaceAttrSec :: String -> [Inline] -> Accessor References RefMap -> WS ()
-replaceAttrSec label title prop
-  = do
-    chap  <- gets curChap
-    modify $ modifyProp prop $ M.insert label RefRec {
-      refIndex=(init chap,last chap)
-    , refTitle=normalizeSpaces title
-    }
-    return ()
diff --git a/src/References/List.hs b/src/References/List.hs
deleted file mode 100644
--- a/src/References/List.hs
+++ /dev/null
@@ -1,37 +0,0 @@
-module References.List (listOf) where
-
-import Text.Pandoc.Definition
-import Control.Monad.State
-import Control.Arrow
-import Data.List
-import qualified Data.Map as M
-
-import References.Types
-import Util.Util
-import Util.Options
-
-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
-listOf opts (Para [RawInline (Format "tex") "\\listoftables"]:xs)
-  = gets tblRefs >>= makeList opts lotTitle xs
-listOf opts (Para [RawInline (Format "tex") "\\listoflistings"]:xs)
-  = gets 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
-        then Div ("", ["list"], []) (itemChap `map` refsSorted)
-        else OrderedList style (item `map` refsSorted))
-      : xs
-  where
-    refsSorted = sortBy compare' $ M.toList refs
-    compare' (_,RefRec{refIndex=i}) (_,RefRec{refIndex=j}) = compare i j
-    item = (:[]) . Plain . refTitle . snd
-    itemChap = Para . uncurry ((. (Space :)) . (++)) . (numWithChap . refIndex &&& refTitle) . snd
-    numWithChap = uncurry $ chapPrefix (chapDelim opts)
-    style = (1,DefaultStyle,DefaultDelim)
diff --git a/src/References/Refs.hs b/src/References/Refs.hs
deleted file mode 100644
--- a/src/References/Refs.hs
+++ /dev/null
@@ -1,138 +0,0 @@
-module References.Refs (replaceRefs) where
-
-import Text.Pandoc.Definition
-import Text.Pandoc.Shared (normalizeInlines, normalizeSpaces)
-import Control.Monad.State
-import Data.List
-import Data.Maybe
-import Data.Function
-import qualified Data.Map as M
-import Control.Arrow as A
-
-import Util.Accessor
-import References.Types
-import References.Accessors
-import Util.Util
-import Util.Options
-
-replaceRefs :: Options -> [Inline] -> WS [Inline]
-replaceRefs opts (Cite cits _:xs)
-  = (++ xs) `fmap` intercalate [Str ",", Space] `fmap`
-    mapM replaceRefs' (groupBy eqPrefix cits)
-  where
-    eqPrefix a b = uncurry (==) $
-      (fmap uncapitalizeFirst . getLabelPrefix . citationId) <***> (a,b)
-    (<***>) = join (***)
-    replaceRefs' cits'
-      | Just prefix <- allCitsPrefix cits'
-      = replaceRefs'' prefix opts cits'
-      | otherwise = return [Cite cits' il']
-        where
-          il' =  normalizeInlines $
-              [Str "["]
-            ++intercalate [Str ";", Space] (map citationToInlines cits')
-            ++[Str "]"]
-          citationToInlines c = normalizeSpaces $
-            citationPrefix c ++ [Space, Str $ "@"++citationId c] ++ citationSuffix c
-    replaceRefs'' = case outFormat opts of
-                    f | isFormat "latex" f -> replaceRefsLatex
-                    _                      -> replaceRefsOther
-replaceRefs _ x = return x
-
--- accessors to state variables
-accMap :: M.Map String (Accessor References RefMap)
-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)
-                     ]
-
-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
-
-lookupUnsafe :: Ord k => k -> M.Map k v -> v
-lookupUnsafe = (fromJust .) . M.lookup
-
-allCitsPrefix :: [Citation] -> Maybe String
-allCitsPrefix cits = find isCitationPrefix prefixes
-  where
-  isCitationPrefix p =
-    all (p `isPrefixOf`) $ map (uncapitalizeFirst . citationId) cits
-
-replaceRefsLatex :: String -> Options -> [Citation] -> WS [Inline]
-replaceRefsLatex prefix opts cits =
-  return $ p ++ [texcit]
-  where
-    texcit =
-      RawInline (Format "tex") $
-      if useCleveref opts then
-        cref++"{"++listLabels prefix "" "," "" cits++"}"
-        else
-          listLabels prefix "\\ref{" ", " "}" cits
-    p | useCleveref opts = []
-      | otherwise = getRefPrefix opts prefix cap (length cits - 1)
-    cap = maybe False isFirstUpper $ getLabelPrefix . citationId . head $ cits
-    cref | cap = "\\Cref"
-         | otherwise = "\\cref"
-
-listLabels :: String -> String -> String -> String -> [Citation] -> String
-listLabels prefix p sep s =
-  intercalate sep . map ((p ++) . (++ s) . (prefix++) . getLabelWithoutPrefix . citationId)
-
-getLabelWithoutPrefix :: String -> String
-getLabelWithoutPrefix = drop 1 . dropWhile (/=':')
-
-getLabelPrefix :: String -> Maybe String
-getLabelPrefix lab
-  | uncapitalizeFirst p `elem` prefixes = Just p
-  | otherwise = Nothing
-  where p = (++ ":") . takeWhile (/=':') $ lab
-
-replaceRefsOther :: String -> Options -> [Citation] -> WS [Inline]
-replaceRefsOther prefix opts cits = do
-  indices <- mapM (getRefIndex prefix) cits
-  let
-    indices' = groupBy ((==) `on` (fmap fst . 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')
-
-getRefIndex :: String -> Citation -> WS (Maybe ([Int], Int), [Inline])
-getRefIndex prefix Citation{citationId=cid,citationSuffix=suf}
-  = (\x -> (x,suf)) `fmap` gets (fmap refIndex . M.lookup lab . getProp prop)
-  where
-  prop = lookupUnsafe prefix accMap
-  lab = prefix ++ getLabelWithoutPrefix cid
-
-makeIndices :: Options -> [(Maybe ([Int], Int), [Inline])] -> [Inline]
-makeIndices _ s | any (isNothing . fst) s = [Strong [Str "??"]]
-makeIndices o s = intercalate sep $ reverse $ map f $ foldl' f2 [] $ map (A.first fromJust) $ filter (isJust . fst) s
-  where
-  f2 [] (i,suf) = [[(i,suf)]]
-  f2 ([]:xs) (i,suf) = [(i,suf)]:xs
-  f2 l@(x@(((_,hx),sufp):_):xs) (i@(_,ni),suf)
-    | not (null suf) || not (null sufp) = [(i,suf)]:l
-    | ni-hx == 0 = l        -- remove duplicates
-    | ni-hx == 1 = ((i,[]):x):xs -- group sequental
-    | otherwise     = [(i,[])]:l    -- new group
-  f []  = []                          -- drop empty lists
-  f [w] = show' w                    -- single value
-  f [w1,w2] = show' w2 ++ sep ++ show' w1 -- two values
-  f (x:xs) = show' (last xs) ++ rangeDelim o ++ show' x -- shorten more than two values
-  sep = [Str ",", Space]
-  show' ((c,n),suf) = chapPrefix (chapDelim o) c n ++ suf
diff --git a/src/References/Types.hs b/src/References/Types.hs
deleted file mode 100644
--- a/src/References/Types.hs
+++ /dev/null
@@ -1,33 +0,0 @@
-module References.Types ( References(..)
-                        , WS
-                        , RefRec(..)
-                        , RefMap
-                        , def
-                        ) where
-
-import qualified Data.Map as M
-import Text.Pandoc.Definition
-import Control.Monad.State
-import Data.Default
-
-data RefRec = RefRec { refIndex :: ([Int], Int)
-                     , refTitle :: [Inline]
-                     } 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 :: [Int]
-                             } deriving (Show, Eq)
-
---state monad
-type WS a = State References a
-
-instance Default References where
-  def = References n n n n n []
-    where n = M.empty
diff --git a/src/Text/Pandoc/CrossRef.hs b/src/Text/Pandoc/CrossRef.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/CrossRef.hs
@@ -0,0 +1,64 @@
+module Text.Pandoc.CrossRef (
+    getSettings
+  , crossRefBlocks
+  , crossRefMeta
+  , runCrossRef
+  , runCrossRefIO
+  , module SG
+  ) where
+
+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.CodeBlockCaptions
+import Text.Pandoc.CrossRef.Util.ModifyMeta
+import Text.Pandoc.CrossRef.Util.Settings.Gen as SG
+
+data CrossRefEnv = CrossRefEnv {
+                      creSettings :: Meta
+                    , creOptions :: Options
+                   }
+
+type CrossRefM a = R.Reader CrossRefEnv a
+
+crossRefBlocks :: [Block] -> CrossRefM [Block]
+crossRefBlocks blocks = do
+  opts <- R.asks creOptions
+  let
+    doWalk =
+      bottomUpM (codeBlockCaptions opts) (walk divBlocks blocks)
+      >>= walkM (replaceBlocks opts)
+      >>= bottomUpM (replaceRefs opts)
+      >>= bottomUpM (listOf opts)
+  return $ evalState doWalk def
+
+crossRefMeta :: CrossRefM Meta
+crossRefMeta = do
+  opts <- R.asks creOptions
+  dtv <- R.asks creSettings
+  return $ modifyMeta opts dtv
+
+runCrossRef :: (Walkable a b) => Meta -> Maybe Format -> (a -> CrossRefM b) -> a -> b
+runCrossRef meta fmt action arg = R.runReader (action arg) env
+  where
+    settings = meta <> defaultMeta
+    env = CrossRefEnv {
+            creSettings = settings
+          , creOptions = getOptions settings fmt
+         }
+
+runCrossRefIO :: (Walkable a b) => Meta -> Maybe Format -> (a -> CrossRefM b) -> a -> IO b
+runCrossRefIO meta fmt action arg = do
+  settings <- getSettings meta
+  let
+    env = CrossRefEnv {
+            creSettings = settings
+          , creOptions = getOptions settings fmt
+         }
+  return $ R.runReader (action arg) env
diff --git a/src/Text/Pandoc/CrossRef/References.hs b/src/Text/Pandoc/CrossRef/References.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/CrossRef/References.hs
@@ -0,0 +1,7 @@
+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
+import Text.Pandoc.CrossRef.References.Refs as X
+import Text.Pandoc.CrossRef.References.List as X
diff --git a/src/Text/Pandoc/CrossRef/References/Accessors.hs b/src/Text/Pandoc/CrossRef/References/Accessors.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/CrossRef/References/Accessors.hs
@@ -0,0 +1,19 @@
+module Text.Pandoc.CrossRef.References.Accessors where
+
+import Text.Pandoc.CrossRef.References.Types
+import Text.Pandoc.CrossRef.Util.Accessor
+
+imgRefs' :: Accessor References RefMap
+imgRefs' new r@References{imgRefs=old} = (old, r{imgRefs=new})
+
+eqnRefs' :: Accessor References RefMap
+eqnRefs' new r@References{eqnRefs=old} = (old, r{eqnRefs=new})
+
+tblRefs' :: Accessor References RefMap
+tblRefs' new r@References{tblRefs=old} = (old, r{tblRefs=new})
+
+lstRefs' :: Accessor References RefMap
+lstRefs' new r@References{lstRefs=old} = (old, r{lstRefs=new})
+
+secRefs' :: Accessor References RefMap
+secRefs' new r@References{secRefs=old} = (old, r{secRefs=new})
diff --git a/src/Text/Pandoc/CrossRef/References/Blocks.hs b/src/Text/Pandoc/CrossRef/References/Blocks.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/CrossRef/References/Blocks.hs
@@ -0,0 +1,156 @@
+module Text.Pandoc.CrossRef.References.Blocks (divBlocks, replaceBlocks) where
+
+import Text.Pandoc.Definition
+import Text.Pandoc.Builder (text, toList)
+import Text.Pandoc.Shared (stringify, normalizeSpaces)
+import Control.Monad.State
+import Data.List
+import qualified Data.Map as M
+
+import Text.Pandoc.CrossRef.Util.Accessor
+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
+
+replaceBlocks :: Options -> Block -> WS Block
+replaceBlocks opts (Header n (label, cls, attrs) text')
+  = do
+    let label' = if autoSecLab opts && not ("sec:" `isPrefixOf` label)
+                 then "sec:"++label
+                 else label
+    unless ("unnumbered" `elem` cls) $ do
+      modify $ \r@References{curChap=cc} ->
+        let ln = length cc
+            inc l = init l ++ [last l + 1]
+            cc' | ln > n = inc $ take n cc
+                | ln == n = inc cc
+                | otherwise = cc ++ take (n-ln) [1,1..]
+        in r{curChap=cc'}
+      when ("sec:" `isPrefixOf` label') $ replaceAttrSec label' text' secRefs'
+    return $ Header n (label', cls, attrs) text'
+replaceBlocks opts (Div (label,_,_) [Plain [Image alt img]])
+  | "fig:" `isPrefixOf` label
+  = do
+    idxStr <- replaceAttr opts label alt imgRefs'
+    let alt' = case outFormat opts of
+          f | isFormat "latex" f ->
+            RawInline (Format "tex") ("\\label{"++label++"}") : alt
+          _  -> applyTemplate idxStr alt $ figureTemplate opts
+    return $ Para [Image alt' (fst img,"fig:")]
+replaceBlocks opts (Div (label,_,_) [Plain [Math DisplayMath eq]])
+  | "eq:" `isPrefixOf` label
+  = case outFormat opts of
+      f | isFormat "latex" f ->
+        let eqn = "\\begin{equation}"++eq++"\\label{"++label++"}\\end{equation}"
+        in return $ Para [RawInline (Format "tex") eqn]
+      _ -> do
+        idxStr <- replaceAttr opts label [] eqnRefs'
+        let eq' = eq++"\\qquad("++stringify idxStr++")"
+        return $ Para [Math DisplayMath eq']
+replaceBlocks opts (Div (label,_,_) [Table title align widths header cells])
+  | not $ null title
+  , "tbl:" `isPrefixOf` label
+  = do
+    idxStr <- replaceAttr opts label (init title) tblRefs'
+    let title' =
+          case outFormat opts of
+              f | isFormat "latex" f ->
+                RawInline (Format "tex") ("\\label{"++label++"}") : init title
+              _  -> applyTemplate idxStr (init title) $ tableTemplate opts
+    return $ Table title' align widths header cells
+replaceBlocks opts cb@(CodeBlock (label, classes, attrs) code)
+  | not $ null label
+  , "lst:" `isPrefixOf` label
+  , Just caption <- lookup "caption" attrs
+  = case outFormat opts of
+      f
+        --if used with listings package,nothing shoud be done
+        | isFormat "latex" f, useListings opts -> return cb
+        --if not using listings, however, wrap it in a codelisting environment
+        | isFormat "latex" f ->
+          return $ Div nullAttr [
+              RawBlock (Format "tex")
+                $ "\\begin{codelisting}\n\\caption{"++caption++"}"
+            , cb
+            , RawBlock (Format "tex") "\\end{codelisting}"
+            ]
+      _ -> do
+        let cap = toList $ text caption
+        idxStr <- replaceAttr opts label cap lstRefs'
+        let caption' = applyTemplate idxStr cap $ listingTemplate opts
+        return $ Div (label, "listing":classes, []) [
+            Para caption'
+          , CodeBlock ([], classes, attrs \\ [("caption", caption)]) code
+          ]
+replaceBlocks opts
+  (Div (label,"listing":_, [])
+    [Para caption, CodeBlock ([],classes,attrs) code])
+  | not $ null label
+  , "lst:" `isPrefixOf` label
+  = case outFormat opts of
+      f
+        --if used with listings package, return code block with caption
+        | isFormat "latex" f, useListings 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 [
+              RawBlock (Format "tex") "\\begin{codelisting}"
+            , Para [RawInline (Format "tex") "\\caption",Span nullAttr caption]
+            , CodeBlock (label,classes,attrs) code
+            , RawBlock (Format "tex") "\\end{codelisting}"
+            ]
+      _ -> do
+        idxStr <- replaceAttr opts label caption lstRefs'
+        let caption' = applyTemplate idxStr caption $ listingTemplate opts
+        return $ Div (label, "listing":classes, []) [
+            Para caption'
+          , CodeBlock ([], classes, attrs) code
+          ]
+replaceBlocks _ x = return x
+
+divBlocks :: Block -> Block
+divBlocks (Para (Image alt img:c))
+  | Just label <- getRefLabel "fig" c
+  = Div (label,[],[]) [Plain [Image alt (fst img, "fig:")]]
+divBlocks (Para (math@(Math DisplayMath _eq):c))
+  | Just label <- getRefLabel "eq" c
+  = Div (label,[],[]) [Plain [math]]
+divBlocks (table@(Table title _align _widths _header _cells))
+  | not $ null title
+  , Just label <- getRefLabel "tbl" [last title]
+  = Div (label,[],[]) [table]
+divBlocks x = x
+
+getRefLabel :: String -> [Inline] -> Maybe String
+getRefLabel _ [] = Nothing
+getRefLabel tag ils
+  | Str attr <- last ils
+  , all (==Space) (init ils)
+  , "}" `isSuffixOf` attr
+  , ("{#"++tag++":") `isPrefixOf` attr
+  = init `fmap` stripPrefix "{#" attr
+getRefLabel _ _ = Nothing
+
+replaceAttr :: Options -> String -> [Inline] -> Accessor References RefMap -> WS [Inline]
+replaceAttr o label title prop
+  = do
+    chap  <- take (chapDepth o) `fmap` gets curChap
+    index <- (1+) `fmap` gets (M.size . M.filter ((==chap) . fst . refIndex) . getProp prop)
+    modify $ modifyProp prop $ M.insert label RefRec {
+      refIndex=(chap,index)
+    , refTitle=normalizeSpaces title
+    }
+    return $ chapPrefix (chapDelim o) chap index
+
+replaceAttrSec :: String -> [Inline] -> Accessor References RefMap -> WS ()
+replaceAttrSec label title prop
+  = do
+    chap  <- gets curChap
+    modify $ modifyProp prop $ M.insert label RefRec {
+      refIndex=(init chap,last chap)
+    , refTitle=normalizeSpaces title
+    }
+    return ()
diff --git a/src/Text/Pandoc/CrossRef/References/List.hs b/src/Text/Pandoc/CrossRef/References/List.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/CrossRef/References/List.hs
@@ -0,0 +1,37 @@
+module Text.Pandoc.CrossRef.References.List (listOf) where
+
+import Text.Pandoc.Definition
+import Control.Monad.State
+import Control.Arrow
+import Data.List
+import qualified Data.Map as M
+
+import Text.Pandoc.CrossRef.References.Types
+import Text.Pandoc.CrossRef.Util.Util
+import Text.Pandoc.CrossRef.Util.Options
+
+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
+listOf opts (Para [RawInline (Format "tex") "\\listoftables"]:xs)
+  = gets tblRefs >>= makeList opts lotTitle xs
+listOf opts (Para [RawInline (Format "tex") "\\listoflistings"]:xs)
+  = gets 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
+        then Div ("", ["list"], []) (itemChap `map` refsSorted)
+        else OrderedList style (item `map` refsSorted))
+      : xs
+  where
+    refsSorted = sortBy compare' $ M.toList refs
+    compare' (_,RefRec{refIndex=i}) (_,RefRec{refIndex=j}) = compare i j
+    item = (:[]) . Plain . refTitle . snd
+    itemChap = Para . uncurry ((. (Space :)) . (++)) . (numWithChap . refIndex &&& refTitle) . snd
+    numWithChap = uncurry $ chapPrefix (chapDelim opts)
+    style = (1,DefaultStyle,DefaultDelim)
diff --git a/src/Text/Pandoc/CrossRef/References/Refs.hs b/src/Text/Pandoc/CrossRef/References/Refs.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/CrossRef/References/Refs.hs
@@ -0,0 +1,138 @@
+module Text.Pandoc.CrossRef.References.Refs (replaceRefs) where
+
+import Text.Pandoc.Definition
+import Text.Pandoc.Shared (normalizeInlines, normalizeSpaces)
+import Control.Monad.State
+import Data.List
+import Data.Maybe
+import Data.Function
+import qualified Data.Map as M
+import Control.Arrow as A
+
+import Text.Pandoc.CrossRef.Util.Accessor
+import Text.Pandoc.CrossRef.References.Types
+import Text.Pandoc.CrossRef.References.Accessors
+import Text.Pandoc.CrossRef.Util.Util
+import Text.Pandoc.CrossRef.Util.Options
+
+replaceRefs :: Options -> [Inline] -> WS [Inline]
+replaceRefs opts (Cite cits _:xs)
+  = (++ xs) `fmap` intercalate [Str ",", Space] `fmap`
+    mapM replaceRefs' (groupBy eqPrefix cits)
+  where
+    eqPrefix a b = uncurry (==) $
+      (fmap uncapitalizeFirst . getLabelPrefix . citationId) <***> (a,b)
+    (<***>) = join (***)
+    replaceRefs' cits'
+      | Just prefix <- allCitsPrefix cits'
+      = replaceRefs'' prefix opts cits'
+      | otherwise = return [Cite cits' il']
+        where
+          il' =  normalizeInlines $
+              [Str "["]
+            ++intercalate [Str ";", Space] (map citationToInlines cits')
+            ++[Str "]"]
+          citationToInlines c = normalizeSpaces $
+            citationPrefix c ++ [Space, Str $ "@"++citationId c] ++ citationSuffix c
+    replaceRefs'' = case outFormat opts of
+                    f | isFormat "latex" f -> replaceRefsLatex
+                    _                      -> replaceRefsOther
+replaceRefs _ x = return x
+
+-- accessors to state variables
+accMap :: M.Map String (Accessor References RefMap)
+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)
+                     ]
+
+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
+
+lookupUnsafe :: Ord k => k -> M.Map k v -> v
+lookupUnsafe = (fromJust .) . M.lookup
+
+allCitsPrefix :: [Citation] -> Maybe String
+allCitsPrefix cits = find isCitationPrefix prefixes
+  where
+  isCitationPrefix p =
+    all (p `isPrefixOf`) $ map (uncapitalizeFirst . citationId) cits
+
+replaceRefsLatex :: String -> Options -> [Citation] -> WS [Inline]
+replaceRefsLatex prefix opts cits =
+  return $ p ++ [texcit]
+  where
+    texcit =
+      RawInline (Format "tex") $
+      if useCleveref opts then
+        cref++"{"++listLabels prefix "" "," "" cits++"}"
+        else
+          listLabels prefix "\\ref{" ", " "}" cits
+    p | useCleveref opts = []
+      | otherwise = getRefPrefix opts prefix cap (length cits - 1)
+    cap = maybe False isFirstUpper $ getLabelPrefix . citationId . head $ cits
+    cref | cap = "\\Cref"
+         | otherwise = "\\cref"
+
+listLabels :: String -> String -> String -> String -> [Citation] -> String
+listLabels prefix p sep s =
+  intercalate sep . map ((p ++) . (++ s) . (prefix++) . getLabelWithoutPrefix . citationId)
+
+getLabelWithoutPrefix :: String -> String
+getLabelWithoutPrefix = drop 1 . dropWhile (/=':')
+
+getLabelPrefix :: String -> Maybe String
+getLabelPrefix lab
+  | uncapitalizeFirst p `elem` prefixes = Just p
+  | otherwise = Nothing
+  where p = (++ ":") . takeWhile (/=':') $ lab
+
+replaceRefsOther :: String -> Options -> [Citation] -> WS [Inline]
+replaceRefsOther prefix opts cits = do
+  indices <- mapM (getRefIndex prefix) cits
+  let
+    indices' = groupBy ((==) `on` (fmap fst . 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')
+
+getRefIndex :: String -> Citation -> WS (Maybe ([Int], Int), [Inline])
+getRefIndex prefix Citation{citationId=cid,citationSuffix=suf}
+  = (\x -> (x,suf)) `fmap` gets (fmap refIndex . M.lookup lab . getProp prop)
+  where
+  prop = lookupUnsafe prefix accMap
+  lab = prefix ++ getLabelWithoutPrefix cid
+
+makeIndices :: Options -> [(Maybe ([Int], Int), [Inline])] -> [Inline]
+makeIndices _ s | any (isNothing . fst) s = [Strong [Str "??"]]
+makeIndices o s = intercalate sep $ reverse $ map f $ foldl' f2 [] $ map (A.first fromJust) $ filter (isJust . fst) s
+  where
+  f2 [] (i,suf) = [[(i,suf)]]
+  f2 ([]:xs) (i,suf) = [(i,suf)]:xs
+  f2 l@(x@(((_,hx),sufp):_):xs) (i@(_,ni),suf)
+    | not (null suf) || not (null sufp) = [(i,suf)]:l
+    | ni-hx == 0 = l        -- remove duplicates
+    | ni-hx == 1 = ((i,[]):x):xs -- group sequental
+    | otherwise     = [(i,[])]:l    -- new group
+  f []  = []                          -- drop empty lists
+  f [w] = show' w                    -- single value
+  f [w1,w2] = show' w2 ++ sep ++ show' w1 -- two values
+  f (x:xs) = show' (last xs) ++ rangeDelim o ++ show' x -- shorten more than two values
+  sep = [Str ",", Space]
+  show' ((c,n),suf) = chapPrefix (chapDelim o) c n ++ suf
diff --git a/src/Text/Pandoc/CrossRef/References/Types.hs b/src/Text/Pandoc/CrossRef/References/Types.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/CrossRef/References/Types.hs
@@ -0,0 +1,33 @@
+module Text.Pandoc.CrossRef.References.Types ( References(..)
+                        , WS
+                        , RefRec(..)
+                        , RefMap
+                        , def
+                        ) where
+
+import qualified Data.Map as M
+import Text.Pandoc.Definition
+import Control.Monad.State
+import Data.Default
+
+data RefRec = RefRec { refIndex :: ([Int], Int)
+                     , refTitle :: [Inline]
+                     } 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 :: [Int]
+                             } deriving (Show, Eq)
+
+--state monad
+type WS a = State References a
+
+instance Default References where
+  def = References n n n n n []
+    where n = M.empty
diff --git a/src/Text/Pandoc/CrossRef/Util/Accessor.hs b/src/Text/Pandoc/CrossRef/Util/Accessor.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/CrossRef/Util/Accessor.hs
@@ -0,0 +1,17 @@
+module Text.Pandoc.CrossRef.Util.Accessor (Accessor, setProp, getProp, modifyProp) where
+
+-- from data-accessor http://www.haskell.org/haskellwiki/Record_access
+-- Copyright (c) Henning Thielemann <haskell@henning-thielemann.de>, Luke Palmer <lrpalmer@gmail.com>
+-- Licensed under BSD3 -- see BSD3.md
+type Accessor r a  =  a -> r -> (a, r)
+
+setProp :: Accessor r a -> a -> r -> r
+setProp f x = snd . f x
+
+getProp :: Accessor r a -> r -> a
+getProp f = fst . f undefined
+
+modifyProp :: Accessor r a -> (a -> a) -> r -> r
+modifyProp f g rOld =
+   let (a,rNew) = f (g a) rOld
+   in  rNew
diff --git a/src/Text/Pandoc/CrossRef/Util/CodeBlockCaptions.hs b/src/Text/Pandoc/CrossRef/Util/CodeBlockCaptions.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/CrossRef/Util/CodeBlockCaptions.hs
@@ -0,0 +1,37 @@
+module Text.Pandoc.CrossRef.Util.CodeBlockCaptions
+    (
+    codeBlockCaptions
+    ) where
+
+import Text.Pandoc.Definition
+import Text.Pandoc.Shared (normalizeSpaces)
+import Data.List (isPrefixOf, stripPrefix)
+import Data.Maybe (fromMaybe)
+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)
+  = return $ fromMaybe x $ orderAgnostic opts $ p:cb:xs
+codeBlockCaptions opts x@(p@(Para _):cb@(CodeBlock _ _):xs)
+  = return $ fromMaybe x $ orderAgnostic opts $ p:cb:xs
+codeBlockCaptions _ x = return x
+
+orderAgnostic :: Options -> [Block] -> Maybe [Block]
+orderAgnostic opts (Para ils:CodeBlock (label,classes,attrs) code:xs)
+  | cbCaptions opts
+  , Just caption <- getCodeBlockCaption ils
+  , not $ null label
+  , "lst" `isPrefixOf` label
+  = return $ Div (label,"listing":classes, [])
+      [Para caption, CodeBlock ([],classes,attrs) code] : xs
+orderAgnostic _ _ = Nothing
+
+getCodeBlockCaption :: [Inline] -> Maybe [Inline]
+getCodeBlockCaption ils
+  | Just caption <- [Str "Listing:",Space] `stripPrefix` normalizeSpaces ils
+  = Just caption
+  | Just caption <- [Str ":",Space] `stripPrefix` normalizeSpaces ils
+  = Just caption
+  | otherwise
+  = Nothing
diff --git a/src/Text/Pandoc/CrossRef/Util/Meta.hs b/src/Text/Pandoc/CrossRef/Util/Meta.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/CrossRef/Util/Meta.hs
@@ -0,0 +1,69 @@
+{-# LANGUAGE CPP #-}
+module Text.Pandoc.CrossRef.Util.Meta where
+
+import Text.Pandoc (readMarkdown)
+import Text.Pandoc.Shared (stringify)
+import Text.Pandoc.Definition
+import Data.Maybe (fromMaybe)
+import Data.Default
+
+getMetaList :: (Default a) => (MetaValue -> Maybe a) -> String -> Meta -> Int -> a
+getMetaList f name meta i = fromMaybe def $ lookupMeta name meta >>= getList i >>= f
+
+getMetaBool :: String -> Meta -> Bool
+getMetaBool name meta = fromMaybe False $ lookupMeta name meta >>= toBool
+
+getMetaInlines :: String -> Meta -> [Inline]
+getMetaInlines name meta = fromMaybe [] $ lookupMeta name meta >>= toInlines
+
+getMetaBlock :: String -> Meta -> [Block]
+getMetaBlock name meta = fromMaybe [] $ lookupMeta name meta >>= toBlocks
+
+getMetaString :: String -> Meta -> String
+getMetaString name meta = fromMaybe [] $ lookupMeta name meta >>= toString
+
+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
+        getInline _ = []
+toInlines (MetaInlines s) = return s
+toInlines _ = Nothing
+
+toBool :: MetaValue -> Maybe Bool
+toBool (MetaBool b) = return b
+toBool _ = Nothing
+
+toBlocks :: MetaValue -> Maybe [Block]
+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
+
+toString :: MetaValue -> Maybe String
+toString (MetaString s) = Just s
+toString (MetaBlocks b) = Just $ stringify b
+toString (MetaInlines i) = Just $ stringify i
+toString _ = Nothing
+
+getList :: Int -> MetaValue -> Maybe MetaValue
+getList i (MetaList l) = l !!? i
+  where
+    list !!? index | index >= 0 && index < length list = Just $ list !! index
+                   | not $ null list = Just $ last list
+                   | otherwise = Nothing
+getList _ x = Just x
diff --git a/src/Text/Pandoc/CrossRef/Util/ModifyMeta.hs b/src/Text/Pandoc/CrossRef/Util/ModifyMeta.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/CrossRef/Util/ModifyMeta.hs
@@ -0,0 +1,82 @@
+module Text.Pandoc.CrossRef.Util.ModifyMeta
+    (
+    modifyMeta
+    ) where
+
+import Text.Pandoc
+import Text.Pandoc.Builder
+import Text.Pandoc.CrossRef.Util.Options
+import Text.Pandoc.CrossRef.Util.Meta
+import Text.Pandoc.CrossRef.Util.Util
+
+modifyMeta :: Options -> Meta -> Meta
+modifyMeta opts meta
+  | isFormat "latex" (outFormat opts)
+  = setMeta "header-includes"
+      (headerInc $ lookupMeta "header-includes" meta)
+      meta
+  | otherwise = meta
+  where
+    headerInc :: Maybe MetaValue -> MetaValue
+    headerInc Nothing = MetaList incList
+    headerInc (Just (MetaList x)) = MetaList $ x ++ incList
+    headerInc (Just x) = MetaList $ x:incList
+    incList = map MetaString $
+        floatnames ++
+        listnames  ++
+        [ x | x <- codelisting, not $ useListings opts] ++
+        lolcommand ++
+        [ x | x <- cleveref, useCleveref opts] ++
+        [ x | x <- cleverefCodelisting, useCleveref opts && not (useListings opts)] ++
+        []
+      where
+        floatnames = [
+            "\\AtBeginDocument{%"
+          , "\\renewcommand*\\figurename{"++metaString "figureTitle"++"}"
+          , "\\renewcommand*\\tablename{"++metaString "tableTitle"++"}"
+          , "}"
+          ]
+        listnames = [
+            "\\AtBeginDocument{%"
+          , "\\renewcommand*\\listfigurename{"++metaString' "lofTitle"++"}"
+          , "\\renewcommand*\\listtablename{"++metaString' "lotTitle"++"}"
+          , "}"
+          ]
+        codelisting = [
+            "\\usepackage{float}"
+          , "\\floatstyle{ruled}"
+          , "\\makeatletter"
+          , "\\@ifundefined{c@chapter}{\\newfloat{codelisting}{h}{lop}}{\\newfloat{codelisting}{h}{lop}[chapter]}"
+          , "\\makeatother"
+          , "\\floatname{codelisting}{"++metaString "listingTitle"++"}"
+          ]
+        lolcommand
+          | useListings opts = [
+              "\\newcommand*\\listoflistings\\lstlistoflistings"
+            , "\\AtBeginDocument{%"
+            , "\\renewcommand*{\\lstlistlistingname}{"++metaString' "lolTitle"++"}"
+            , "}"
+            ]
+          | otherwise = ["\\newcommand*\\listoflistings{\\listof{codelisting}{"++metaString' "lolTitle"++"}}"]
+        cleveref = [
+            "\\usepackage{cleveref}"
+          , "\\crefname{figure}" ++ prefix figPrefix False
+          , "\\crefname{table}" ++ prefix tblPrefix False
+          , "\\crefname{equation}" ++ prefix eqnPrefix False
+          , "\\crefname{listing}" ++ prefix lstPrefix False
+          , "\\Crefname{figure}" ++ prefix figPrefix True
+          , "\\Crefname{table}" ++ prefix tblPrefix True
+          , "\\Crefname{equation}" ++ prefix eqnPrefix True
+          , "\\Crefname{listing}" ++ prefix lstPrefix True
+          ]
+        cleverefCodelisting = [
+            "\\makeatletter"
+          , "\\crefname{codelisting}{\\cref@listing@name}{\\cref@listing@name@plural}"
+          , "\\Crefname{codelisting}{\\Cref@listing@name}{\\Cref@listing@name@plural}"
+          , "\\makeatother"
+          ]
+        toLatex = writeLaTeX def . Pandoc nullMeta . return . Plain
+        metaString s = toLatex $ getMetaInlines s meta
+        metaString' s = toLatex [Str $ getMetaString s meta]
+        prefix f uc = "{" ++ toLatex (f opts uc 0) ++ "}" ++
+                      "{" ++ toLatex (f opts uc 1) ++ "}"
diff --git a/src/Text/Pandoc/CrossRef/Util/Options.hs b/src/Text/Pandoc/CrossRef/Util/Options.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/CrossRef/Util/Options.hs
@@ -0,0 +1,74 @@
+{-# LANGUAGE FlexibleContexts #-}
+
+module Text.Pandoc.CrossRef.Util.Options (Options(..), getOptions) 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
+                       , figPrefix   :: Bool -> Int -> [Inline]
+                       , eqnPrefix   :: Bool -> Int -> [Inline]
+                       , tblPrefix   :: Bool -> Int -> [Inline]
+                       , lstPrefix   :: Bool -> Int -> [Inline]
+                       , secPrefix   :: Bool -> Int -> [Inline]
+                       , chapDelim   :: [Inline]
+                       , rangeDelim  :: [Inline]
+                       , lofTitle    :: [Block]
+                       , lotTitle    :: [Block]
+                       , lolTitle    :: [Block]
+                       , outFormat   :: Maybe Format
+                       , figureTemplate :: Template
+                       , tableTemplate  :: Template
+                       , listingTemplate :: Template
+                       }
+
+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/src/Text/Pandoc/CrossRef/Util/Settings.hs b/src/Text/Pandoc/CrossRef/Util/Settings.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/CrossRef/Util/Settings.hs
@@ -0,0 +1,44 @@
+{-# LANGUAGE CPP #-}
+module Text.Pandoc.CrossRef.Util.Settings (getSettings, defaultMeta) where
+
+import Text.Pandoc
+import Text.Pandoc.Builder
+import Control.Exception (handle,IOException)
+
+import Text.Pandoc.CrossRef.Util.Settings.Gen
+import Text.Pandoc.CrossRef.Util.Meta
+
+getSettings :: Meta -> IO Meta
+getSettings meta = do
+  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
+defaultMeta =
+     figureTitle (str "Figure")
+  <> tableTitle (str "Table")
+  <> listingTitle (str "Listing")
+  <> titleDelim (str ":")
+  <> chapDelim (str ".")
+  <> rangeDelim (str "-")
+  <> figPrefix ([str "fig.", str "figs."])
+  <> eqnPrefix ([str "eq." , str "eqns."])
+  <> tblPrefix ([str "tbl.", str "tbls."])
+  <> lstPrefix ([str "lst.", str "lsts."])
+  <> secPrefix ([str "sec.", str "secs."])
+  <> lofTitle (header 1 $ text "List of Figures")
+  <> lotTitle (header 1 $ text "List of Tables")
+  <> lolTitle (header 1 $ text "List of Listings")
+  <> figureTemplate (var "figureTitle" <> space <> var "i" <> var "titleDelim" <> space <> var "t")
+  <> tableTemplate (var "tableTitle" <> space <> var "i" <> var "titleDelim" <> space <> var "t")
+  <> listingTemplate (var "listingTitle" <> space <> var "i" <> var "titleDelim" <> space <> var "t")
+  <> crossrefYaml (MetaString "pandoc-crossref.yaml")
+  <> chaptersDepth (MetaString "1")
+  where var = displayMath
diff --git a/src/Text/Pandoc/CrossRef/Util/Settings/Gen.hs b/src/Text/Pandoc/CrossRef/Util/Settings/Gen.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/CrossRef/Util/Settings/Gen.hs
@@ -0,0 +1,31 @@
+{-# LANGUAGE TemplateHaskell #-}
+
+module Text.Pandoc.CrossRef.Util.Settings.Gen where
+
+import Text.Pandoc
+import qualified Data.Map as M
+
+import Text.Pandoc.CrossRef.Util.Settings.Template
+import Text.Pandoc.Builder
+
+$(concat `fmap` mapM genSetting
+  [ "figureTitle"
+  , "tableTitle"
+  , "listingTitle"
+  , "titleDelim"
+  , "chapDelim"
+  , "rangeDelim"
+  , "figPrefix"
+  , "eqnPrefix"
+  , "tblPrefix"
+  , "lstPrefix"
+  , "secPrefix"
+  , "lofTitle"
+  , "lotTitle"
+  , "lolTitle"
+  , "figureTemplate"
+  , "tableTemplate"
+  , "listingTemplate"
+  , "crossrefYaml"
+  , "chaptersDepth"
+  ])
diff --git a/src/Text/Pandoc/CrossRef/Util/Settings/Template.hs b/src/Text/Pandoc/CrossRef/Util/Settings/Template.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/CrossRef/Util/Settings/Template.hs
@@ -0,0 +1,20 @@
+{-# LANGUAGE QuasiQuotes, TemplateHaskell, RankNTypes, FlexibleInstances #-}
+module Text.Pandoc.CrossRef.Util.Settings.Template where
+
+import Language.Haskell.TH
+import Text.Pandoc
+import Text.Pandoc.Builder
+
+genSetting :: String -> Q [Dec]
+genSetting name = do
+  sig <- [t| forall a. ToMetaValue a => a -> Meta |]
+  return
+    [ SigD func sig
+    , FunD func [Clause [VarP value] (NormalB
+        (AppE (ConE $ mkName "Meta")
+          (AppE (AppE (VarE (mkName "M.singleton")) (LitE (StringL name)))
+            (AppE (VarE (mkName "toMetaValue")) (VarE value))))
+      ) []]]
+  where
+    func = mkName name
+    value = mkName "value"
diff --git a/src/Text/Pandoc/CrossRef/Util/Template.hs b/src/Text/Pandoc/CrossRef/Util/Template.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/CrossRef/Util/Template.hs
@@ -0,0 +1,26 @@
+module Text.Pandoc.CrossRef.Util.Template (Template,makeTemplate,applyTemplate) where
+
+import Text.Pandoc.Definition
+import Text.Pandoc.Generic
+import Text.Pandoc.Shared (normalizeInlines)
+import Data.Maybe
+import Text.Pandoc.CrossRef.Util.Meta
+
+type VarFunc = String -> Maybe MetaValue
+newtype Template = Template (VarFunc -> [Inline])
+
+makeTemplate :: Meta -> [Inline] -> Template
+makeTemplate dtv = Template . flip scan . scan (`lookupMeta` dtv)
+  where
+  scan = bottomUp . go
+  go vf (x@(Math DisplayMath var):xs) = replaceVar (vf var) [x] ++ xs
+  go _ x = x
+  replaceVar val def' = fromMaybe def' $ val >>= toInlines
+
+applyTemplate :: [Inline] -> [Inline] -> Template -> [Inline]
+applyTemplate i t (Template g) =
+  normalizeInlines $ g internalVars
+  where
+  internalVars "i" = Just $ MetaInlines i
+  internalVars "t" = Just $ MetaInlines t
+  internalVars _   = Nothing
diff --git a/src/Text/Pandoc/CrossRef/Util/Util.hs b/src/Text/Pandoc/CrossRef/Util/Util.hs
new file mode 100644
--- /dev/null
+++ b/src/Text/Pandoc/CrossRef/Util/Util.hs
@@ -0,0 +1,24 @@
+module Text.Pandoc.CrossRef.Util.Util where
+
+import Text.Pandoc.Definition
+import Data.Char (toUpper, toLower, isUpper)
+import Data.List (intercalate)
+
+isFormat :: String -> Maybe Format -> Bool
+isFormat fmt (Just (Format f)) = takeWhile (`notElem` "+-") f == fmt
+isFormat _ Nothing = False
+
+capitalizeFirst :: String -> String
+capitalizeFirst (x:xs) = toUpper x : xs
+capitalizeFirst [] = []
+
+uncapitalizeFirst :: String -> String
+uncapitalizeFirst (x:xs) = toLower x : xs
+uncapitalizeFirst [] = []
+
+isFirstUpper :: String -> Bool
+isFirstUpper (x:_) = isUpper x
+isFirstUpper [] = False
+
+chapPrefix :: [Inline] -> [Int] -> Int -> [Inline]
+chapPrefix delim chap index = intercalate delim (map (return . Str . show) (chap++[index]))
diff --git a/src/Util/Accessor.hs b/src/Util/Accessor.hs
deleted file mode 100644
--- a/src/Util/Accessor.hs
+++ /dev/null
@@ -1,17 +0,0 @@
-module Util.Accessor (Accessor, setProp, getProp, modifyProp) where
-
--- from data-accessor http://www.haskell.org/haskellwiki/Record_access
--- Copyright (c) Henning Thielemann <haskell@henning-thielemann.de>, Luke Palmer <lrpalmer@gmail.com>
--- Licensed under BSD3 -- see BSD3.md
-type Accessor r a  =  a -> r -> (a, r)
-
-setProp :: Accessor r a -> a -> r -> r
-setProp f x = snd . f x
-
-getProp :: Accessor r a -> r -> a
-getProp f = fst . f undefined
-
-modifyProp :: Accessor r a -> (a -> a) -> r -> r
-modifyProp f g rOld =
-   let (a,rNew) = f (g a) rOld
-   in  rNew
diff --git a/src/Util/CodeBlockCaptions.hs b/src/Util/CodeBlockCaptions.hs
deleted file mode 100644
--- a/src/Util/CodeBlockCaptions.hs
+++ /dev/null
@@ -1,37 +0,0 @@
-module Util.CodeBlockCaptions
-    (
-    codeBlockCaptions
-    ) where
-
-import Text.Pandoc.Definition
-import Text.Pandoc.Shared (normalizeSpaces)
-import Data.List (isPrefixOf, stripPrefix)
-import Data.Maybe (fromMaybe)
-import References.Types
-import Util.Options
-
-codeBlockCaptions :: Options -> [Block] -> WS [Block]
-codeBlockCaptions opts x@(cb@(CodeBlock _ _):p@(Para _):xs)
-  = return $ fromMaybe x $ orderAgnostic opts $ p:cb:xs
-codeBlockCaptions opts x@(p@(Para _):cb@(CodeBlock _ _):xs)
-  = return $ fromMaybe x $ orderAgnostic opts $ p:cb:xs
-codeBlockCaptions _ x = return x
-
-orderAgnostic :: Options -> [Block] -> Maybe [Block]
-orderAgnostic opts (Para ils:CodeBlock (label,classes,attrs) code:xs)
-  | cbCaptions opts
-  , Just caption <- getCodeBlockCaption ils
-  , not $ null label
-  , "lst" `isPrefixOf` label
-  = return $ Div (label,"listing":classes, [])
-      [Para caption, CodeBlock ([],classes,attrs) code] : xs
-orderAgnostic _ _ = Nothing
-
-getCodeBlockCaption :: [Inline] -> Maybe [Inline]
-getCodeBlockCaption ils
-  | Just caption <- [Str "Listing:",Space] `stripPrefix` normalizeSpaces ils
-  = Just caption
-  | Just caption <- [Str ":",Space] `stripPrefix` normalizeSpaces ils
-  = Just caption
-  | otherwise
-  = Nothing
diff --git a/src/Util/Meta.hs b/src/Util/Meta.hs
deleted file mode 100644
--- a/src/Util/Meta.hs
+++ /dev/null
@@ -1,69 +0,0 @@
-{-# LANGUAGE CPP #-}
-module Util.Meta where
-
-import Text.Pandoc (readMarkdown)
-import Text.Pandoc.Shared (stringify)
-import Text.Pandoc.Definition
-import Data.Maybe (fromMaybe)
-import Data.Default
-
-getMetaList :: (Default a) => (MetaValue -> Maybe a) -> String -> Meta -> Int -> a
-getMetaList f name meta i = fromMaybe def $ lookupMeta name meta >>= getList i >>= f
-
-getMetaBool :: String -> Meta -> Bool
-getMetaBool name meta = fromMaybe False $ lookupMeta name meta >>= toBool
-
-getMetaInlines :: String -> Meta -> [Inline]
-getMetaInlines name meta = fromMaybe [] $ lookupMeta name meta >>= toInlines
-
-getMetaBlock :: String -> Meta -> [Block]
-getMetaBlock name meta = fromMaybe [] $ lookupMeta name meta >>= toBlocks
-
-getMetaString :: String -> Meta -> String
-getMetaString name meta = fromMaybe [] $ lookupMeta name meta >>= toString
-
-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
-        getInline _ = []
-toInlines (MetaInlines s) = return s
-toInlines _ = Nothing
-
-toBool :: MetaValue -> Maybe Bool
-toBool (MetaBool b) = return b
-toBool _ = Nothing
-
-toBlocks :: MetaValue -> Maybe [Block]
-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
-
-toString :: MetaValue -> Maybe String
-toString (MetaString s) = Just s
-toString (MetaBlocks b) = Just $ stringify b
-toString (MetaInlines i) = Just $ stringify i
-toString _ = Nothing
-
-getList :: Int -> MetaValue -> Maybe MetaValue
-getList i (MetaList l) = l !!? i
-  where
-    list !!? index | index >= 0 && index < length list = Just $ list !! index
-                   | not $ null list = Just $ last list
-                   | otherwise = Nothing
-getList _ x = Just x
diff --git a/src/Util/ModifyMeta.hs b/src/Util/ModifyMeta.hs
deleted file mode 100644
--- a/src/Util/ModifyMeta.hs
+++ /dev/null
@@ -1,82 +0,0 @@
-module Util.ModifyMeta
-    (
-    modifyMeta
-    ) where
-
-import Text.Pandoc
-import Text.Pandoc.Builder
-import Util.Options
-import Util.Meta
-import Util.Util
-
-modifyMeta :: Options -> Meta -> Meta
-modifyMeta opts meta
-  | isFormat "latex" (outFormat opts)
-  = setMeta "header-includes"
-      (headerInc $ lookupMeta "header-includes" meta)
-      meta
-  | otherwise = meta
-  where
-    headerInc :: Maybe MetaValue -> MetaValue
-    headerInc Nothing = MetaList incList
-    headerInc (Just (MetaList x)) = MetaList $ x ++ incList
-    headerInc (Just x) = MetaList $ x:incList
-    incList = map MetaString $
-        floatnames ++
-        listnames  ++
-        [ x | x <- codelisting, not $ useListings opts] ++
-        lolcommand ++
-        [ x | x <- cleveref, useCleveref opts] ++
-        [ x | x <- cleverefCodelisting, useCleveref opts && not (useListings opts)] ++
-        []
-      where
-        floatnames = [
-            "\\AtBeginDocument{%"
-          , "\\renewcommand*\\figurename{"++metaString "figureTitle"++"}"
-          , "\\renewcommand*\\tablename{"++metaString "tableTitle"++"}"
-          , "}"
-          ]
-        listnames = [
-            "\\AtBeginDocument{%"
-          , "\\renewcommand*\\listfigurename{"++metaString' "lofTitle"++"}"
-          , "\\renewcommand*\\listtablename{"++metaString' "lotTitle"++"}"
-          , "}"
-          ]
-        codelisting = [
-            "\\usepackage{float}"
-          , "\\floatstyle{ruled}"
-          , "\\makeatletter"
-          , "\\@ifundefined{c@chapter}{\\newfloat{codelisting}{h}{lop}}{\\newfloat{codelisting}{h}{lop}[chapter]}"
-          , "\\makeatother"
-          , "\\floatname{codelisting}{"++metaString "listingTitle"++"}"
-          ]
-        lolcommand
-          | useListings opts = [
-              "\\newcommand*\\listoflistings\\lstlistoflistings"
-            , "\\AtBeginDocument{%"
-            , "\\renewcommand*{\\lstlistlistingname}{"++metaString' "lolTitle"++"}"
-            , "}"
-            ]
-          | otherwise = ["\\newcommand*\\listoflistings{\\listof{codelisting}{"++metaString' "lolTitle"++"}}"]
-        cleveref = [
-            "\\usepackage{cleveref}"
-          , "\\crefname{figure}" ++ prefix figPrefix False
-          , "\\crefname{table}" ++ prefix tblPrefix False
-          , "\\crefname{equation}" ++ prefix eqnPrefix False
-          , "\\crefname{listing}" ++ prefix lstPrefix False
-          , "\\Crefname{figure}" ++ prefix figPrefix True
-          , "\\Crefname{table}" ++ prefix tblPrefix True
-          , "\\Crefname{equation}" ++ prefix eqnPrefix True
-          , "\\Crefname{listing}" ++ prefix lstPrefix True
-          ]
-        cleverefCodelisting = [
-            "\\makeatletter"
-          , "\\crefname{codelisting}{\\cref@listing@name}{\\cref@listing@name@plural}"
-          , "\\Crefname{codelisting}{\\Cref@listing@name}{\\Cref@listing@name@plural}"
-          , "\\makeatother"
-          ]
-        toLatex = writeLaTeX def . Pandoc nullMeta . return . Plain
-        metaString s = toLatex $ getMetaInlines s meta
-        metaString' s = toLatex [Str $ getMetaString s meta]
-        prefix f uc = "{" ++ toLatex (f opts uc 0) ++ "}" ++
-                      "{" ++ toLatex (f opts uc 1) ++ "}"
diff --git a/src/Util/Options.hs b/src/Util/Options.hs
deleted file mode 100644
--- a/src/Util/Options.hs
+++ /dev/null
@@ -1,74 +0,0 @@
-{-# LANGUAGE FlexibleContexts #-}
-
-module Util.Options (Options(..), getOptions) where
-import Text.Pandoc.Definition
-import Util.Meta
-import Util.Template
-import 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
-                       , figPrefix   :: Bool -> Int -> [Inline]
-                       , eqnPrefix   :: Bool -> Int -> [Inline]
-                       , tblPrefix   :: Bool -> Int -> [Inline]
-                       , lstPrefix   :: Bool -> Int -> [Inline]
-                       , secPrefix   :: Bool -> Int -> [Inline]
-                       , chapDelim   :: [Inline]
-                       , rangeDelim  :: [Inline]
-                       , lofTitle    :: [Block]
-                       , lotTitle    :: [Block]
-                       , lolTitle    :: [Block]
-                       , outFormat   :: Maybe Format
-                       , figureTemplate :: Template
-                       , tableTemplate  :: Template
-                       , listingTemplate :: Template
-                       }
-
-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/src/Util/Settings.hs b/src/Util/Settings.hs
deleted file mode 100644
--- a/src/Util/Settings.hs
+++ /dev/null
@@ -1,45 +0,0 @@
-{-# LANGUAGE CPP #-}
-module Util.Settings (getSettings, defaultMeta) where
-
-import Text.Pandoc
-import Control.Exception (handle,IOException)
-import qualified Data.Map as M
-import Data.Monoid
-
-import Util.Meta (getMetaString)
-
-getSettings :: Meta -> IO Meta
-getSettings meta = do
-  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
-defaultMeta = Meta $ M.fromList
-  [ ("figureTitle"    , MetaInlines [Str "Figure"])
-  , ("tableTitle"     , MetaInlines [Str "Table"])
-  , ("listingTitle"   , MetaInlines [Str "Listing"])
-  , ("titleDelim"     , MetaInlines [Str ":"])
-  , ("chapDelim"      , MetaInlines [Str "."])
-  , ("rangeDelim"     , MetaInlines [Str "-"])
-  , ("figPrefix"      , MetaList [MetaInlines [Str "fig."], MetaInlines [Str "figs."]])
-  , ("eqnPrefix"      , MetaList [MetaInlines [Str "eq."], MetaInlines [Str "eqns."]])
-  , ("tblPrefix"      , MetaList [MetaInlines [Str "tbl."], MetaInlines [Str "tbls."]])
-  , ("lstPrefix"      , MetaList [MetaInlines [Str "lst."], MetaInlines [Str "lsts."]])
-  , ("secPrefix"      , MetaList [MetaInlines [Str "sec."], MetaInlines [Str "secs."]])
-  , ("lofTitle"       , MetaBlocks [Header 1 nullAttr [Str "List",Space,Str "of",Space,Str "Figures"]])
-  , ("lotTitle"       , MetaBlocks [Header 1 nullAttr [Str "List",Space,Str "of",Space,Str "Tables"]])
-  , ("lolTitle"       , MetaBlocks [Header 1 nullAttr [Str "List",Space,Str "of",Space,Str "Listings"]])
-  , ("figureTemplate" , MetaInlines [var "figureTitle",Space,var "i",var "titleDelim",Space,var "t"])
-  , ("tableTemplate"  , MetaInlines [var "tableTitle",Space,var "i",var "titleDelim",Space,var "t"])
-  , ("listingTemplate", MetaInlines [var "listingTitle",Space,var "i",var "titleDelim",Space,var "t"])
-  , ("crossrefYaml"   , MetaString "pandoc-crossref.yaml")
-  , ("chaptersDepth"  , MetaString "1")
-  ]
-  where var = Math DisplayMath
diff --git a/src/Util/Template.hs b/src/Util/Template.hs
deleted file mode 100644
--- a/src/Util/Template.hs
+++ /dev/null
@@ -1,26 +0,0 @@
-module Util.Template (Template,makeTemplate,applyTemplate) where
-
-import Text.Pandoc.Definition
-import Text.Pandoc.Generic
-import Text.Pandoc.Shared (normalizeInlines)
-import Data.Maybe
-import Util.Meta
-
-type VarFunc = String -> Maybe MetaValue
-newtype Template = Template (VarFunc -> [Inline])
-
-makeTemplate :: Meta -> [Inline] -> Template
-makeTemplate dtv = Template . flip scan . scan (`lookupMeta` dtv)
-  where
-  scan = bottomUp . go
-  go vf (x@(Math DisplayMath var):xs) = replaceVar (vf var) [x] ++ xs
-  go _ x = x
-  replaceVar val def' = fromMaybe def' $ val >>= toInlines
-
-applyTemplate :: [Inline] -> [Inline] -> Template -> [Inline]
-applyTemplate i t (Template g) =
-  normalizeInlines $ g internalVars
-  where
-  internalVars "i" = Just $ MetaInlines i
-  internalVars "t" = Just $ MetaInlines t
-  internalVars _   = Nothing
diff --git a/src/Util/Util.hs b/src/Util/Util.hs
deleted file mode 100644
--- a/src/Util/Util.hs
+++ /dev/null
@@ -1,24 +0,0 @@
-module Util.Util where
-
-import Text.Pandoc.Definition
-import Data.Char (toUpper, toLower, isUpper)
-import Data.List (intercalate)
-
-isFormat :: String -> Maybe Format -> Bool
-isFormat fmt (Just (Format f)) = takeWhile (`notElem` "+-") f == fmt
-isFormat _ Nothing = False
-
-capitalizeFirst :: String -> String
-capitalizeFirst (x:xs) = toUpper x : xs
-capitalizeFirst [] = []
-
-uncapitalizeFirst :: String -> String
-uncapitalizeFirst (x:xs) = toLower x : xs
-uncapitalizeFirst [] = []
-
-isFirstUpper :: String -> Bool
-isFirstUpper (x:_) = isUpper x
-isFirstUpper [] = False
-
-chapPrefix :: [Inline] -> [Int] -> Int -> [Inline]
-chapPrefix delim chap index = intercalate delim (map (return . Str . show) (chap++[index]))
diff --git a/test-pandoc-crossref.hs b/test-pandoc-crossref.hs
--- a/test-pandoc-crossref.hs
+++ b/test-pandoc-crossref.hs
@@ -3,22 +3,23 @@
 import Text.Pandoc.Builder
 import Text.Pandoc.Walk
 import Text.Pandoc.Generic
-import Util.Options
-import Util.Util
 import Control.Monad.State
-import References.Types
-import Util.Settings
-import Util.Accessor
-import References.Accessors
-import qualified References.Blocks
-import qualified References.Refs
-import qualified References.List
-import qualified Util.Template
-import qualified Util.CodeBlockCaptions
-import qualified Data.Map as M
-import Data.Monoid
 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
