diff --git a/changelog b/changelog
--- a/changelog
+++ b/changelog
@@ -1,3 +1,37 @@
+pandoc-citeproc (0.5)
+
+  * Revised locator parsing:
+    + parseLocator now looks for the "short" forms of terms in
+      the style's locale(s).  So, in English you'd use "p." or
+      "ch."; in German, "S." or "Kap."
+    + Note that the locator label must match what is in the locale
+      file, including the period.  Before this change, you could omit
+      the period: "p 12" or "p. 12" would both give you a "page."
+      Also, previously, the locators were case-insensitive; now they must
+      be in the same case as in the locale.  (English "p.", German "S.".)
+    + "no." no longer gets parsed as a "note": closes #74.
+    + Text.CSL.Reference no longer exports parseLocator.
+      parseLocator is now used only locally, in Text.CSL.Pandoc.
+  * Data.getLocale:  Try 2-letter locale lookup if longer locale not found.
+    This should fix an error that occured with less common locales
+    (jgm/pandoc#1548).
+  * Added parseNames field to Agent.  Set parse-names=true
+    when writing CSL JSON and collapsing suffix or particles into
+    first or last names.
+  * Properly handle agents with 'parse-names' set to 'true' (#77).
+    Note that parse-names defaults to true if not set, as in Zotero.
+  * Reference:  added explicit exports.
+  * Styles:  Added explicit export list.
+  * Eval: Fixed isNumericString to recognize en dash (#74).
+  * Allow bibtex double quotes to be escaped inside {} (jgm/pandoc#1568).
+  * Titlecase transform improvements (#76).
+  * Added two csl files missing from tests/.
+  * Performance improvements:  Avoid unnecessary Output groupings.
+    Eliminated some unnecessary generic traversals.  (#71)
+  * Makefile:  Use cpphs. Text.CSL.Data seems to break on OSX 10.9 without it.
+  * Added prof target to Makefile
+  * Test suite: don't exit with success if there were errors!
+
 pandoc-citeproc (0.4.0.1)
 
   * Interpret date literals with underscores (e.g. "2004_2006") as ranges.
diff --git a/pandoc-citeproc.cabal b/pandoc-citeproc.cabal
--- a/pandoc-citeproc.cabal
+++ b/pandoc-citeproc.cabal
@@ -1,5 +1,5 @@
 name:               pandoc-citeproc
-version:            0.4.0.1
+version:            0.5
 cabal-version:      >= 1.12
 synopsis:           Supports using pandoc with citeproc
 
diff --git a/pandoc-citeproc.hs b/pandoc-citeproc.hs
--- a/pandoc-citeproc.hs
+++ b/pandoc-citeproc.hs
@@ -138,6 +138,7 @@
   , literal         = literal ag
   , nameSuffix      = mempty
   , commaSuffix     = False
+  , parseNames      = True
   }
   where
   spcat (Formatted []) y = y
diff --git a/src/Text/CSL.hs b/src/Text/CSL.hs
--- a/src/Text/CSL.hs
+++ b/src/Text/CSL.hs
@@ -32,7 +32,6 @@
     -- ** Reference Representation
     , Reference (..)
     , getReference
-    , parseLocator
     , setNearNote
 
     -- * CSL Parser, Representation, and Processing
diff --git a/src/Text/CSL/Data.hs b/src/Text/CSL/Data.hs
--- a/src/Text/CSL/Data.hs
+++ b/src/Text/CSL/Data.hs
@@ -20,6 +20,7 @@
 import System.FilePath ()
 import qualified Data.ByteString.Lazy as L
 #ifdef EMBED_DATA_FILES
+import Data.Maybe (fromMaybe)
 import Text.CSL.Data.Embedded (localeFiles, defaultCSL)
 import qualified Data.ByteString as S
 #else
@@ -33,14 +34,19 @@
   f <- case length s of
          0 -> maybe (return S.empty) return
               $ lookup "locales-en-US.xml" localeFiles
-         2 -> let fn = ("locales-" ++ maybe "en-US"
-                                      id (lookup s langBase) ++ ".xml")
+         2 -> let fn = ("locales-" ++ fromMaybe s (lookup s langBase) ++ ".xml")
               in case lookup fn localeFiles of
                    Just x' -> return x'
-                   _       -> error "could not load the locale file"
+                   _       -> error $ "could not find locale data for " ++ s
          _ -> case lookup ("locales-" ++ take 5 s ++ ".xml") localeFiles of
                     Just x' -> return x'
-                    _       -> error "could not load the locale file"
+                    _       -> -- try again with 2-letter locale
+                       let s' = take 2 s in
+                       case lookup ("locales-" ++ fromMaybe s'
+                              (lookup s' langBase) ++ ".xml") localeFiles of
+                             Just x'' -> return x''
+                             _        -> error $
+                                         "could not find locale data for " ++ s
   return $ L.fromChunks [f]
 #else
   f <- case length s of
diff --git a/src/Text/CSL/Eval.hs b/src/Text/CSL/Eval.hs
--- a/src/Text/CSL/Eval.hs
+++ b/src/Text/CSL/Eval.hs
@@ -38,7 +38,7 @@
 import Text.CSL.Output.Plain
 import Text.CSL.Reference
 import Text.CSL.Style hiding (Any)
-import Text.CSL.Util ( readNum, last', proc, procM, proc', query, betterThan )
+import Text.CSL.Util ( readNum, last', proc, proc', query, betterThan )
 
 -- | Produce the output with a 'Layout', the 'EvalMode', a 'Bool'
 -- 'True' if the evaluation happens for disambiguation purposes, the
@@ -50,7 +50,7 @@
     = cleanOutput evalOut
     where
       evalOut = case evalState job initSt of
-                  [] -> if (isSorting $ em)
+                  [] -> if isSorting em
                         then []
                         else [noOutputError]
                   x | title r == Formatted [Str (citeId cit), Space, Str "not", Space,
@@ -59,15 +59,13 @@
       locale = case l of
                  [x] -> x
                  _   -> Locale [] [] [] [] []
-      job    = expandMacros es >>= evalElements
+      job    = evalElements es
       cit    = case em of
                  EvalCite    c -> c
                  EvalSorting c -> c
                  EvalBiblio  c -> c
       initSt = EvalState (mkRefMap r) (Env cit (localeTerms locale) m
                          (localeDate locale) o [] a) [] em b False [] [] False [] [] []
-      -- TODO: is this needed? We already remove titlecase in converting
-      -- from bibtex.
       suppTC = let getLang = take 2 . map toLower in
                case (getLang $ localeLang locale, getLang $ unLiteral $ language r) of
                  (_,  "en") -> id
@@ -103,25 +101,14 @@
 evalElements :: [Element] -> State EvalState [Output]
 evalElements = concatMapM evalElement
 
-expandMacros :: [Element] -> State EvalState [Element]
-expandMacros = procM expandMacro
-
-expandMacro :: Element -> State EvalState Element
-expandMacro (Choose i ei xs) =
-  Elements emptyFormatting `fmap` evalIfThen i ei xs
-expandMacro (Macro s fm) = do
-  ms <- gets (macros . env)
-  case lookup s ms of
-       Nothing  -> error $ "Macro " ++ show s ++ " not found!"
-       Just els -> Elements fm `fmap` procM expandMacro els
-expandMacro x = return x
-
 evalElement :: Element -> State EvalState [Output]
 evalElement el
     | Elements fm es <- el        = evalElements es >>= \os ->
                                       if null os
                                          then return []
-                                         else return [Output os fm]
+                                         else if fm == emptyFormatting
+                                                 then return os
+                                                 else return [Output os fm]
     | Const    s   fm       <- el = return $ addSpaces s
                                            $ if fm == emptyFormatting
                                                 then [OPan (readCSLString s)]
@@ -149,8 +136,18 @@
                                    else evalElement (Substitute els)
                            else return res
     -- All macros and conditionals should have been expanded
-    | Choose _ _  _         <- el = error $ "Unexpanded Choose"
-    | Macro    s   _        <- el = error $ "Unexpanded macro " ++ s
+    | Choose i ei xs        <- el = do
+                        res <- evalIfThen i ei xs
+                        evalElement $ Elements emptyFormatting res
+    | Macro    s   fm       <- el = do
+                        ms <- gets (macros . env)
+                        case lookup s ms of
+                             Nothing  -> error $ "Macro " ++ show s ++ " not found!"
+                             Just els -> do
+                               res <- concat <$> mapM evalElement els
+                               if null res
+                                  then return []
+                                  else return [Output res fm]
     | otherwise                   = return []
     where
       addSpaces strng = (if take 1 strng == " " then (OSpace:) else id) .
@@ -362,14 +359,16 @@
 
 isNumericString :: String -> Bool
 isNumericString [] = False
-isNumericString s  = null . filter (not . isNumber &&& not . isSpecialChar >>> uncurry (&&)) $
-                     words s
+isNumericString s  = all (\c -> isNumber c || isSpecialChar c) $ words s
 
 isTransNumber, isSpecialChar,isNumber :: String -> Bool
-isTransNumber = and . map isDigit
-isSpecialChar = and . map (flip elem "&-,")
-isNumber      = filter (not . isLetter) >>> filter (not . flip elem "&-,") >>>
-                map isDigit >>> and &&& not . null >>> uncurry (&&)
+isTransNumber = all isDigit
+isSpecialChar = all (`elem` "&-,\x2013")
+isNumber   cs = case [c | c <- cs
+                        , not (isLetter c)
+                        , not (c `elem` "&-,\x2013")] of
+                     []  -> False
+                     xs  -> all isDigit xs
 
 breakNumericString :: [String] -> [String]
 breakNumericString [] = []
diff --git a/src/Text/CSL/Eval/Names.hs b/src/Text/CSL/Eval/Names.hs
--- a/src/Text/CSL/Eval/Names.hs
+++ b/src/Text/CSL/Eval/Names.hs
@@ -26,7 +26,7 @@
 import Text.CSL.Eval.Common
 import Text.CSL.Eval.Output
 import Text.CSL.Util ( headInline, lastInline, readNum, (<^>), query, toRead,
-                       capitalize, splitStrWhen )
+                       splitStrWhen )
 import Text.CSL.Style
 import Text.Pandoc.Definition
 import Text.Pandoc.Shared ( stringify )
@@ -343,7 +343,6 @@
 formatTerm :: Form -> Formatting -> Bool -> String -> State EvalState [Output]
 formatTerm f fm p s = do
   t <- getTerm p f s
-  pos <- gets (citePosition . cite . env)
   return $ oStr' t fm
 
 formatLabel :: Form -> Formatting -> Bool -> String -> State EvalState [Output]
diff --git a/src/Text/CSL/Input/Bibtex.hs b/src/Text/CSL/Input/Bibtex.hs
--- a/src/Text/CSL/Input/Bibtex.hs
+++ b/src/Text/CSL/Input/Bibtex.hs
@@ -144,9 +144,10 @@
 inQuotes :: BibParser String
 inQuotes = do
   char '"'
-  concat <$> manyTill (try (string "\\\"")
-                     <|> many1 (noneOf "\"\\")
-                     <|> count 1 anyChar) (char '"')
+  concat <$> manyTill (  many1 (noneOf "\"\\{")
+                     <|> (char '\\' >> (\c -> ['\\',c]) <$> anyChar)
+                     <|> braced <$> inBraces
+                      ) (char '"')
 
 fieldName :: BibParser String
 fieldName = (map toLower) <$> many1 (letter <|> digit <|> oneOf "-_")
@@ -322,7 +323,7 @@
 
 resolveKey' :: Lang -> String -> String
 resolveKey' (Lang "en" "US") k =
-  case k of
+  case map toLower k of
        "inpreparation" -> "in preparation"
        "submitted"     -> "submitted"
        "forthcoming"   -> "forthcoming"
@@ -536,6 +537,7 @@
           , nameSuffix      = mempty
           , literal         = Formatted [Str "others"]
           , commaSuffix     = False
+          , parseNames      = True
           }
 toAuthor _ [Span ("",[],[]) ils] =
   return $ -- corporate author
@@ -546,6 +548,7 @@
           , nameSuffix      = mempty
           , literal         = Formatted ils
           , commaSuffix     = False
+          , parseNames      = True
           }
 -- First von Last
 -- von Last, First
@@ -598,6 +601,7 @@
           , nameSuffix      = suffix
           , literal         = mempty
           , commaSuffix     = usecomma
+          , parseNames      = True
           }
 
 isCapitalized :: [Inline] -> Bool
diff --git a/src/Text/CSL/Pandoc.hs b/src/Text/CSL/Pandoc.hs
--- a/src/Text/CSL/Pandoc.hs
+++ b/src/Text/CSL/Pandoc.hs
@@ -8,10 +8,9 @@
 import Text.Pandoc.Shared (stringify)
 import Text.HTML.TagSoup.Entity (lookupEntity)
 import qualified Data.ByteString.Lazy as L
-import Data.List (isPrefixOf)
 import Control.Applicative ((<|>))
 import Data.Aeson
-import Data.Char ( isDigit, isPunctuation, toLower )
+import Data.Char ( isDigit, isPunctuation, isSpace )
 import qualified Data.Map as M
 import Text.CSL.Reference hiding (processCites, Value)
 import Text.CSL.Input.Bibutils (readBiblioFile, convertRefs)
@@ -40,8 +39,9 @@
       Pandoc m3 b2  = evalState (walkM setHashes $ Pandoc m2 b1) 1
       grps          = query getCitation $ Pandoc m3 b2
       m4            = deleteMeta "nocites-wildcards" m3
+      locMap        = locatorMap style
       result        = citeproc procOpts style refs (setNearNote style $
-                        map (map toCslCite) grps)
+                        map (map (toCslCite locMap)) grps)
       cits_map      = M.fromList $ zip grps (citations result)
       biblioList    = map (renderPandoc' style) (bibliography result)
       Pandoc m b3   = bottomUp (mvPunct style) . deNote .
@@ -209,7 +209,7 @@
 deNote :: Pandoc -> Pandoc
 deNote = topDown go
   where go (Cite (c:cs) [Note xs]) =
-            Cite (c:cs) [Note $ sanitize c xs]
+            Cite (c:cs) [Note $ sanitize xs]
         go (Note xs) = Note $ topDown go' xs
         go x = x
         go' (x : Cite cs [Note [Para xs]] : ys) | x /= Space =
@@ -227,10 +227,10 @@
                         then initInline $ removeLeadingPunct xs
                         else removeLeadingPunct xs
            in f xs' ++ ys
-        sanitize :: Citation -> [Block] -> [Block]
-        sanitize Citation{citationPrefix = pref} [Para xs] =
+        sanitize :: [Block] -> [Block]
+        sanitize [Para xs] =
            [Para $ toCapital xs ++ if endWithPunct xs then [Space] else []]
-        sanitize _ bs = bs
+        sanitize bs = bs
 
 isTextualCitation :: [Citation] -> Bool
 isTextualCitation (c:_) = citationMode c == AuthorInText
@@ -253,15 +253,14 @@
   put $ ident + 1
   return c{ citationHash = ident }
 
-toCslCite :: Citation -> CSL.Cite
-toCslCite c
-    = let (l, s)  = locatorWords $ citationSuffix c
-          (la,lo) = parseLocator l
-          s'      = case (l,s) of
+toCslCite :: LocatorMap -> Citation -> CSL.Cite
+toCslCite locMap c
+    = let (la, lo, s)  = locatorWords locMap $ citationSuffix c
+          s'      = case (la,lo,s) of
                          -- treat a bare locator as if it begins with space
                          -- so @item1 [blah] is like [@item1, blah]
-                         ("",(x:_))
-                           | not (isPunct x) -> [Space] ++ s
+                         ("","",(x:_))
+                           | not (isPunct x) -> Space : s
                          _                   -> s
           isPunct (Str (x:_)) = isPunctuation x
           isPunct _           = False
@@ -280,19 +279,18 @@
                      , CSL.citeHash       = citationHash c
                      }
 
-locatorWords :: [Inline] -> (String, [Inline])
-locatorWords inp =
-  case parse pLocatorWords "suffix" $ splitStrWhen (`elem` ";,\160") inp of
+locatorWords :: LocatorMap -> [Inline] -> (String, String, [Inline])
+locatorWords locMap inp =
+  case parse (pLocatorWords locMap) "suffix" $
+         splitStrWhen (\c -> isPunctuation c || isSpace c) inp of
        Right r   -> r
-       Left _    -> ("",inp)
+       Left _    -> ("","",inp)
 
-pLocatorWords :: Parsec [Inline] st (String, [Inline])
-pLocatorWords = do
-  l <- pLocator
+pLocatorWords :: LocatorMap -> Parsec [Inline] st (String, String, [Inline])
+pLocatorWords locMap = do
+  (la,lo) <- pLocator locMap
   s <- getInput -- rest is suffix
-  if length l > 0 && last l == ','
-     then return (init l, Str "," : s)
-     else return (l, s)
+  return (la, lo, s)
 
 pMatch :: (Inline -> Bool) -> Parsec [Inline] st Inline
 pMatch condition = try $ do
@@ -303,24 +301,19 @@
 pSpace :: Parsec [Inline] st Inline
 pSpace = pMatch (\t -> t == Space || t == Str "\160")
 
-pLocator :: Parsec [Inline] st String
-pLocator = try $ do
+pLocator :: LocatorMap -> Parsec [Inline] st (String, String)
+pLocator locMap = try $ do
   optional $ pMatch (== Str ",")
   optional pSpace
-  rawLoc <- many1
+  rawLoc <- many
      (notFollowedBy pSpace >> notFollowedBy (pWordWithDigits True) >> anyToken)
-  let removePeriod xs = case reverse xs of
-                             ('.':xs') -> reverse xs'
-                             _ -> xs
-  let loc = if null rawLoc
-               then "p"
-               else removePeriod $ stringify rawLoc
-  guard $ any (\x -> x `isPrefixOf` map toLower loc)
-          [ "b", "ch", "co", "fi", "fo", "i", "l", "n"
-          , "o", "para", "part", "p", "sec", "sub", "ve", "v" ]
+  la <- case stringify rawLoc of
+                 ""   -> lookAhead (optional pSpace >> pDigit) >> return "page"
+                 s    -> maybe mzero return $ parseLocator locMap s
   g <- pWordWithDigits True
   gs <- many (pWordWithDigits False)
-  return $ concat (loc:" ":g:gs)
+  let lo = concat (g:gs)
+  return (la, lo)
 
 -- we want to capture:  123, 123A, C22, XVII, 33-44, 22-33; 22-11
 pWordWithDigits :: Bool -> Parsec [Inline] st String
@@ -328,16 +321,34 @@
   punct <- if isfirst
               then return ""
               else stringify `fmap` pLocatorPunct
-  sp <- (pSpace >> return " ") <|> return ""
+  sp <- option "" (pSpace >> return " ")
   r <- many1 (notFollowedBy pSpace >> notFollowedBy pLocatorPunct >> anyToken)
   let s = stringify r
   guard $ any isDigit s || all (`elem` "IVXLCM") s
   return $ punct ++ sp ++ s
 
+pDigit :: Parsec [Inline] st ()
+pDigit = do
+  t <- anyToken
+  case t of
+      Str (d:_) | isDigit d -> return ()
+      _ -> mzero
+
 pLocatorPunct :: Parsec [Inline] st Inline
 pLocatorPunct = pMatch isLocatorPunct
 
 isLocatorPunct :: Inline -> Bool
-isLocatorPunct (Str [c]) = c `elem` ",;:"
+isLocatorPunct (Str [c]) = isPunctuation c
 isLocatorPunct _         = False
 
+type LocatorMap = M.Map String String
+
+parseLocator :: LocatorMap -> String -> Maybe String
+parseLocator locMap s = M.lookup s locMap
+
+locatorMap :: Style -> LocatorMap
+locatorMap sty =
+  foldr (\term -> M.insert (termSingular term) (cslTerm term)
+                . M.insert (termPlural term) (cslTerm term))
+    M.empty
+    (concatMap localeTerms $ styleLocale sty)
diff --git a/src/Text/CSL/Proc/Collapse.hs b/src/Text/CSL/Proc/Collapse.hs
--- a/src/Text/CSL/Proc/Collapse.hs
+++ b/src/Text/CSL/Proc/Collapse.hs
@@ -75,7 +75,9 @@
       contribsQ o
           | OContrib _ _ c _ _ <- o = [c]
           | otherwise               = []
-      namesOf y = if null (query contribsQ y) then [] else proc rmNameHash . proc rmGivenNames $ head (query contribsQ y)
+      namesOf y = case query contribsQ y of
+                       []    -> []
+                       (z:_) -> proc rmHashAndGivenNames z
 
 getYearAndSuf :: Output -> Output
 getYearAndSuf x
@@ -129,7 +131,7 @@
                              else (a, Output (b : [ODel d          ]) emptyFormatting) : doCollapse xs
 
       contribsQ o
-          | OContrib _ _ c _ _ <- o = [proc' rmNameHash . proc' rmGivenNames $ c]
+          | OContrib _ _ c _ _ <- o = [proc' rmHashAndGivenNames c]
           | otherwise               = []
       namesOf = query contribsQ
       process = doCollapse . groupBy (\a b -> namesOf (snd a) == namesOf (snd b)) . groupCites
diff --git a/src/Text/CSL/Proc/Disamb.hs b/src/Text/CSL/Proc/Disamb.hs
--- a/src/Text/CSL/Proc/Disamb.hs
+++ b/src/Text/CSL/Proc/Disamb.hs
@@ -60,7 +60,7 @@
                    then if isByCite then ByCite else AllNames
                    else NoGiven
 
-      clean     = if hasGNameOpt then id else proc rmNameHash . proc rmGivenNames
+      clean     = if hasGNameOpt then id else proc rmHashAndGivenNames
       withNames = flip map duplics $ same . clean .
                   map (if hasNamesOpt then disambData else return . disambYS)
 
@@ -111,7 +111,7 @@
 disambAddNames :: GiveNameDisambiguation -> [CiteData] -> [CiteData]
 disambAddNames b needName = addLNames
     where
-      clean     = if b == NoGiven then proc rmNameHash . proc rmGivenNames else id
+      clean     = if b == NoGiven then proc rmHashAndGivenNames else id
       disSolved = zip needName' . disambiguate . map disambData $ needName'
       needName' = nub' needName []
       addLNames = map (\(c,n) -> c { disambed = if null n then collision c else head n }) disSolved
@@ -136,7 +136,7 @@
                                     | otherwise             -> o
     | otherwise = o
     where
-      clean         = if g == NoGiven then proc rmNameHash . proc rmGivenNames else id
+      clean         = if g == NoGiven then proc rmHashAndGivenNames else id
       processGNames = if g /= NoGiven then updateOName n else id
 
 updateOName :: [NameData] -> Output -> Output
@@ -189,7 +189,7 @@
       $ duplicates
     where
       whatToGet  = if b1 then collision else disambYS
-      collide    = proc rmExtras . proc rmNameHash . proc rmGivenNames . whatToGet
+      collide    = proc rmExtras . proc rmHashAndGivenNames . whatToGet
       citeData   = nubBy (\a b -> collide a == collide b && key a == key b) $
                    concatMap (mapGroupOutput $ getCiteData) g
       duplicates = [c | c <- citeData , d <- citeData , collides c d]
@@ -220,8 +220,9 @@
                         [] -> [CD [] [out] [] [] [] [] []]
                               -- allow title to disambiguate
                         xs -> xs
-      yearsQ  = query getYears
-      years o = if yearsQ o /= [] then yearsQ o else [([],[])]
+      years o = case query getYears o of
+                     []    -> [([],[])]
+                     r     -> r
       zipData = uncurry . zipWith $ \c y -> if key c /= []
                                             then c {citYear = snd y}
                                             else c {key     = fst y
@@ -387,16 +388,14 @@
               | OYearSuf _ _ _ _ <- o = ["a"]
               | otherwise             = []
 
--- | Removes all given names form a 'OName' element with 'proc'.
-rmGivenNames :: Output -> Output
-rmGivenNames o
-    | OName i s _ f <- o = OName i s [] f
-    | otherwise          = o
+-- | Removes all given names and name hashes from OName elements.
+rmHashAndGivenNames :: Output -> Output
+rmHashAndGivenNames (OName _ s _ f) = OName emptyAgent s [] f
+rmHashAndGivenNames o = o
 
-rmNameHash :: Output -> Output
-rmNameHash o
-    | OName _ s ss f <- o = OName emptyAgent s ss f
-    | otherwise           = o
+rmGivenNames :: Output -> Output
+rmGivenNames (OName a s _ f) = OName a s [] f
+rmGivenNames o = o
 
 -- | Add, with 'proc', a give name to the family name. Needed for
 -- disambiguation.
diff --git a/src/Text/CSL/Reference.hs b/src/Text/CSL/Reference.hs
--- a/src/Text/CSL/Reference.hs
+++ b/src/Text/CSL/Reference.hs
@@ -16,9 +16,32 @@
 --
 -----------------------------------------------------------------------------
 
-module Text.CSL.Reference where
+module Text.CSL.Reference ( Literal(..)
+                          , Value(..)
+                          , ReferenceMap
+                          , mkRefMap
+                          , formatField
+                          , fromValue
+                          , isValueSet
+                          , Empty(..)
+                          , RefDate(..)
+                          , handleLiteral
+                          , toDatePart
+                          , setCirca
+                          , mkRefDate
+                          , RefType(..)
+                          , CNum(..)
+                          , Reference(..)
+                          , emptyReference
+                          , numericVars
+                          , getReference
+                          , processCites
+                          , setPageFirst
+                          , setNearNote
+                          )
+where
 
-import Data.List  ( elemIndex, isPrefixOf, intercalate )
+import Data.List  ( elemIndex, intercalate )
 import Data.List.Split ( splitWhen )
 import Data.Maybe ( fromMaybe             )
 import Data.Generics hiding (Generic)
@@ -588,28 +611,6 @@
 numericVars = [ "edition", "volume", "number-of-volumes", "number", "issue", "citation-number"
               , "chapter-number", "collection-number", "number-of-pages"]
 
-parseLocator :: String -> (String, String)
-parseLocator s
-    | "b"    `isPrefixOf` formatField s = mk "book"
-    | "ch"   `isPrefixOf` formatField s = mk "chapter"
-    | "co"   `isPrefixOf` formatField s = mk "column"
-    | "fi"   `isPrefixOf` formatField s = mk "figure"
-    | "fo"   `isPrefixOf` formatField s = mk "folio"
-    | "i"    `isPrefixOf` formatField s = mk "issue"
-    | "l"    `isPrefixOf` formatField s = mk "line"
-    | "n"    `isPrefixOf` formatField s = mk "note"
-    | "o"    `isPrefixOf` formatField s = mk "opus"
-    | "para" `isPrefixOf` formatField s = mk "paragraph"
-    | "part" `isPrefixOf` formatField s = mk "part"
-    | "p"    `isPrefixOf` formatField s = mk "page"
-    | "sec"  `isPrefixOf` formatField s = mk "section"
-    | "sub"  `isPrefixOf` formatField s = mk "sub verbo"
-    | "ve"   `isPrefixOf` formatField s = mk "verse"
-    | "v"    `isPrefixOf` formatField s = mk "volume"
-    | otherwise                         =    ([], [])
-    where
-      mk c = if null s then ([], []) else (,) c . unwords . tail . words $ s
-
 getReference :: [Reference] -> Cite -> Maybe Reference
 getReference  r c
     = case citeId c `elemIndex` map (unLiteral . refId) r of
@@ -646,9 +647,9 @@
             isIbid   = case reverse (last a) of
                             []    -> case reverse (init a) of
                                           []     -> False
-                                          (xs:_) -> not (null xs) &&
+                                          (zs:_) -> not (null zs) &&
                                                     all (== citeId c)
-                                                        (map citeId xs)
+                                                        (map citeId zs)
                             (x:_) -> citeId c == citeId x
             isLocSet = citeLocator c /= ""
 
diff --git a/src/Text/CSL/Style.hs b/src/Text/CSL/Style.hs
--- a/src/Text/CSL/Style.hs
+++ b/src/Text/CSL/Style.hs
@@ -15,25 +15,88 @@
 --
 -----------------------------------------------------------------------------
 
-module Text.CSL.Style where
+module Text.CSL.Style ( readCSLString
+                      , writeCSLString
+                      , Formatted(..)
+                      , Style(..)
+                      , Locale(..)
+                      , mergeLocales
+                      , CslTerm(..)
+                      , newTerm
+                      , findTerm
+                      , findTerm'
+                      , Abbreviations(..)
+                      , MacroMap
+                      , Citation(..)
+                      , Bibliography(..)
+                      , Option
+                      , mergeOptions
+                      , Layout(..)
+                      , Element(..)
+                      , IfThen(..)
+                      , Condition(..)
+                      , Delimiter
+                      , Match(..)
+                      , match
+                      , DatePart(..)
+                      , defaultDate
+                      , Sort(..)
+                      , Sorting(..)
+                      , compare'
+                      , Form(..)
+                      , Gender(..)
+                      , NumericForm(..)
+                      , DateForm(..)
+                      , Plural(..)
+                      , Name(..)
+                      , NameAttrs
+                      , NamePart(..)
+                      , isPlural
+                      , isName
+                      , isNames
+                      , hasEtAl
+                      , Formatting(..)
+                      , emptyFormatting
+                      , rmTitleCase
+                      , Quote(..)
+                      , unsetAffixes
+                      , mergeFM
+                      , CSInfo(..)
+                      , CSAuthor(..)
+                      , CSCategory(..)
+                      , CiteprocError(..)
+                      , Output(..)
+                      , Citations
+                      , Cite(..)
+                      , emptyCite
+                      , CitationGroup(..)
+                      , BiblioData(..)
+                      , CiteData(..)
+                      , NameData(..)
+                      , isPunctuationInQuote
+                      , object'
+                      , Agent(..)
+                      , emptyAgent
+                      )
+where
 
 import Data.Aeson hiding (Number)
 import GHC.Generics (Generic)
 import Data.String
-import Data.Monoid (mempty, Monoid, mappend, mconcat)
+import Data.Monoid (mempty, Monoid, mappend, mconcat, (<>))
 import Control.Arrow hiding (left, right)
 import Control.Applicative hiding (Const)
 import qualified Data.Aeson as Aeson
 import Data.Aeson.Types (Pair)
-import Data.List ( nubBy, isPrefixOf, isInfixOf, intercalate )
+import Data.List ( nubBy, isPrefixOf, isInfixOf, intersperse, intercalate )
 import Data.List.Split ( splitWhen, wordsBy )
 import Data.Generics ( Data, Typeable )
 import Data.Maybe ( listToMaybe )
 import qualified Data.Map as M
-import Data.Char (isPunctuation)
-import Text.CSL.Util (mb, parseBool, parseString, (.#?), (.#:), proc', query,
-                      betterThan, trimr, tailInline, headInline, initInline,
-                      lastInline)
+import Data.Char (isPunctuation, isUpper, isLetter)
+import Text.CSL.Util (mb, parseBool, parseString, (.#?), (.#:), query,
+                      betterThan, trimr, tailInline, headInline,
+                      initInline, lastInline, splitStrWhen)
 import Text.Pandoc.Definition hiding (Citation, Cite)
 import Text.Pandoc (readHtml, writeMarkdown, WriterOptions(..),
                     ReaderOptions(..), bottomUp, def)
@@ -50,11 +113,6 @@
 #endif
 import qualified Data.Vector as V
 
--- import Debug.Trace
---
--- tr' :: Show a => [Char] -> a -> a
--- tr' note' x = Debug.Trace.trace (note' ++ ": " ++ show x) x
-
 -- Note:  FromJSON reads HTML, ToJSON writes Markdown.
 -- This means that they aren't proper inverses of each other, which
 -- is odd, but it makes sense given the uses here.  FromJSON is used
@@ -71,8 +129,8 @@
                         Pandoc _ x             -> Walk.query (:[]) x
   -- this is needed for versions of pandoc that don't turn
   -- a span with font-variant:small-caps into a SmallCaps element:
-  where handleSmallCapsSpans (Span ("",[],[("style",s)]) ils)
-            | filter (`notElem` " \t;") s == "font-variant:small-caps" =
+  where handleSmallCapsSpans (Span ("",[],[("style",sty)]) ils)
+            | filter (`notElem` " \t;") sty == "font-variant:small-caps" =
               SmallCaps ils
         handleSmallCapsSpans x = x
 
@@ -229,22 +287,20 @@
 findTerm' s f g
     = listToMaybe . filter (cslTerm &&& termForm &&& termGenderForm >>> (==) (s,(f,g)))
 
-hasOrdinals :: Data a => a -> Bool
-hasOrdinals = or . query hasOrd
+hasOrdinals :: [Locale] -> Bool
+hasOrdinals = any (any hasOrd . localeTerms)
     where
       hasOrd o
           | CT {cslTerm = t} <- o
-          , "ordinal" `isInfixOf` t = [True]
-          | otherwise               = [False]
+          , "ordinal" `isInfixOf` t = True
+          | otherwise               = False
 
-rmOrdinals :: Data a => a -> a
-rmOrdinals = proc' doRemove
-    where
-      doRemove [] = []
-      doRemove (o:os)
-          | CT {cslTerm = t} <- o
-          , "ordinal" `isInfixOf` t =   doRemove os
-          | otherwise               = o:doRemove os
+rmOrdinals :: [CslTerm] -> [CslTerm]
+rmOrdinals [] = []
+rmOrdinals (o:os)
+  | CT {cslTerm = t} <- o
+  , "ordinal" `isInfixOf` t =   rmOrdinals os
+  | otherwise               = o:rmOrdinals os
 
 newtype Abbreviations = Abbreviations {
            unAbbreviations :: M.Map String (M.Map String (M.Map String String))
@@ -438,10 +494,9 @@
 isNames x = case x of Names {} -> True; _ -> False
 
 hasEtAl :: [Name] -> Bool
-hasEtAl = not . null . query getEtAl
-    where getEtAl n
-              | EtAl _ _ <- n = [n]
-              | otherwise     = []
+hasEtAl = any isEtAl
+    where isEtAl (EtAl _ _) = True
+          isEtAl _          = False
 
 data Formatting
     = Formatting
@@ -661,29 +716,99 @@
 
 data Agent
     = Agent { givenName       :: [Formatted]
-            , droppingPart    ::  Formatted
-            , nonDroppingPart ::  Formatted
-            , familyName      ::  Formatted
-            , nameSuffix      ::  Formatted
-            , literal         ::  Formatted
-            , commaSuffix     ::  Bool
+            , droppingPart    :: Formatted
+            , nonDroppingPart :: Formatted
+            , familyName      :: Formatted
+            , nameSuffix      :: Formatted
+            , literal         :: Formatted
+            , commaSuffix     :: Bool
+            , parseNames      :: Bool
             }
       deriving ( Show, Read, Eq, Ord, Typeable, Data, Generic )
 
 emptyAgent :: Agent
-emptyAgent = Agent [] mempty mempty mempty mempty mempty False
+emptyAgent = Agent [] mempty mempty mempty mempty mempty False False
 
 instance FromJSON Agent where
-  parseJSON (Object v) = Agent <$>
+  parseJSON (Object v) = nameTransform <$> (Agent <$>
               (v .: "given" <|> ((map Formatted . wordsBy (== Space) . unFormatted) <$> v .: "given") <|> pure []) <*>
               v .:?  "dropping-particle" .!= mempty <*>
               v .:? "non-dropping-particle" .!= mempty <*>
               v .:? "family" .!= mempty <*>
               v .:? "suffix" .!= mempty <*>
               v .:? "literal" .!= mempty <*>
-              v .:? "comma-suffix" .!= False
+              v .:? "comma-suffix" .!= False <*>
+              v .:? "parse-names" .!= True)
   parseJSON _ = fail "Could not parse Agent"
 
+-- See http://gsl-nagoya-u.net/http/pub/citeproc-doc.html#id28
+nameTransform :: Agent -> Agent
+nameTransform ag
+  | parseNames ag = nonDroppingPartTransform .
+                    droppingPartTransform .
+                    suffixTransform $ ag
+  | otherwise = ag
+
+nonDroppingPartTransform :: Agent -> Agent
+nonDroppingPartTransform ag
+  | nonDroppingPart ag == mempty =
+    case break startWithCapital' (unFormatted $ familyName ag) of
+         ([], _)  -> ag
+         (xs, ys) -> ag { nonDroppingPart = Formatted $ trimSpace xs,
+                          familyName = Formatted ys }
+  | otherwise = ag
+
+trimSpace :: [Inline] -> [Inline]
+trimSpace = reverse . dropWhile isSpace . reverse . dropWhile isSpace
+  where isSpace Space = True
+        isSpace _     = False
+
+droppingPartTransform :: Agent -> Agent
+droppingPartTransform ag
+  | droppingPart ag == mempty =
+    case break startWithCapital $ reverse $ givenName ag of
+          ([],_)  -> ag
+          (ys,zs) -> ag{ droppingPart = mconcat $
+                                         intersperse (Formatted [Space]) $
+                                         reverse ys
+                       , givenName = reverse zs }
+  | otherwise = ag
+
+startWithCapital' :: Inline -> Bool
+startWithCapital' (Str (c:_)) = isUpper c && isLetter c
+startWithCapital' _ = False
+
+startWithCapital :: Formatted -> Bool
+startWithCapital (Formatted (x:_)) = startWithCapital' x
+startWithCapital _ = False
+
+stripFinalComma :: Formatted -> (String, Formatted)
+stripFinalComma (Formatted ils) =
+  case reverse $ splitStrWhen isPunctuation ils of
+       Str ",":xs -> (",", Formatted $ reverse xs)
+       Str "!":Str ",":xs -> (",!", Formatted $ reverse xs)
+       _ -> ("", Formatted ils)
+
+suffixTransform :: Agent -> Agent
+suffixTransform ag
+  | nameSuffix ag == mempty = fst $ foldl go
+                              (ag{ givenName   = mempty
+                                 , nameSuffix  = mempty
+                                 , commaSuffix = False }, False)
+                              (givenName ag)
+  | otherwise = ag
+  where go (ag', False) n =
+               case stripFinalComma n of
+                    ("", _)   -> (ag'{ givenName = givenName ag' ++ [n] }, False)
+                    (",",n')  -> (ag'{ givenName = givenName ag' ++ [n'] }, True)
+                    (",!",n') -> (ag'{ givenName = givenName ag' ++ [n']
+                                     , commaSuffix = True }, True)
+                    _         -> error "stripFinalComma returned unexpected value"
+        go (ag', True) n = (ag'{ nameSuffix = if nameSuffix ag' == mempty
+                                                 then n
+                                                 else nameSuffix ag' <>
+                                                      Formatted [Space] <> n }, True)
+
 instance ToJSON Agent where
   toJSON agent = object' $ [
       "given" .= Formatted (intercalate [Space] $ map unFormatted
@@ -694,6 +819,7 @@
     , "suffix" .= nameSuffix agent
     , "literal" .= literal agent
     ] ++ ["comma-suffix" .= commaSuffix agent | nameSuffix agent /= mempty]
+      ++ ["parse-names" .= False | not (parseNames agent) ]
 
 instance FromJSON [Agent] where
   parseJSON (Array xs) = mapM parseJSON $ V.toList xs
diff --git a/src/Text/CSL/Util.hs b/src/Text/CSL/Util.hs
--- a/src/Text/CSL/Util.hs
+++ b/src/Text/CSL/Util.hs
@@ -52,7 +52,7 @@
 import Text.Pandoc.Shared (safeRead, stringify)
 import Text.Pandoc.Walk (walk)
 import Text.Pandoc
-import Data.List.Split (wordsBy, whenElt, dropBlanks, split )
+import Data.List.Split (wordsBy)
 import Control.Monad.State
 import Data.Monoid (Monoid, mappend, mempty)
 import Data.Generics ( Typeable, Data, everywhere, everywhereM, mkM,
@@ -166,19 +166,21 @@
 splitUpStr = splitStrWhen (\c -> isPunctuation c || c == '\160')
 
 unTitlecase :: [Inline] -> [Inline]
-unTitlecase zs = evalState (caseTransform untc $ splitUpStr zs) SentenceBoundary
+unTitlecase zs = evalState (caseTransform untc zs) SentenceBoundary
   where untc w = do
           st <- get
           case (w, st) of
                (y, NoBoundary) -> return y
                (Str (x:xs), WordBoundary) | isUpper x ->
                  return $ Str (toLower x : xs)
+               (Str (x:xs), SentenceBoundary) | isLower x ->
+                 return $ Str (toUpper x : xs)
                (Span ("",[],[]) xs, _) | hasLowercaseWord xs ->
                  return $ Span ("",["nocase"],[]) xs
                _ -> return w
 
 protectCase :: [Inline] -> [Inline]
-protectCase zs = evalState (caseTransform protect $ splitUpStr zs) SentenceBoundary
+protectCase zs = evalState (caseTransform protect zs) SentenceBoundary
   where protect (Span ("",[],[]) xs)
           | hasLowercaseWord xs = do
             st <- get
@@ -188,16 +190,19 @@
         protect x = return x
 
 titlecase :: [Inline] -> [Inline]
-titlecase zs = evalState (caseTransform tc $ splitUpStr zs) SentenceBoundary
-  where tc (Str (x:xs)) | isLower x && not (isShortWord (x:xs)) = do
+titlecase zs = evalState (caseTransform tc zs) SentenceBoundary
+  where tc (Str (x:xs)) = do
           st <- get
           return $ case st of
-                        WordBoundary -> Str (toUpper x : xs)
+                        WordBoundary -> if isShortWord (x:xs)
+                                           then Str (x:xs)
+                                                -- or? map toLower (x:xs)
+                                           else Str (toUpper x : xs)
                         SentenceBoundary -> Str (toUpper x : xs)
                         _ -> Str (x:xs)
         tc (Span ("",["nocase"],[]) xs) = return $ Span ("",["nocase"],[]) xs
         tc x = return x
-        isShortWord  s = s `elem`
+        isShortWord  s = map toLower s `elem`
                       ["a","an","and","as","at","but","by","c","ca","d","de"
                       ,"down","et","for","from"
                       ,"in","into","nor","of","on","onto","or","over","so"
@@ -207,7 +212,7 @@
 
 caseTransform :: (Inline -> State CaseTransformState Inline) -> [Inline]
               -> State CaseTransformState [Inline]
-caseTransform xform = fmap reverse . foldM go []
+caseTransform xform = fmap reverse . foldM go [] . splitUpStr
   where go acc Space        = do
                modify (\st ->
                  case st of
@@ -248,8 +253,13 @@
 
 splitStrWhen :: (Char -> Bool) -> [Inline] -> [Inline]
 splitStrWhen _ [] = []
-splitStrWhen p (Str xs : ys)
-  | any p xs = map Str ((split . dropBlanks) (whenElt p) xs) ++ splitStrWhen p ys
+splitStrWhen p (Str xs : ys) = go xs ++ splitStrWhen p ys
+  where go [] = []
+        go s = case break p s of
+                     ([],[])     -> []
+                     (zs,[])     -> [Str zs]
+                     ([],(w:ws)) -> Str [w] : go ws
+                     (zs,(w:ws)) -> Str zs : Str [w] : go ws
 splitStrWhen p (x : ys) = x : splitStrWhen p ys
 
 -- | A generic processing function.
diff --git a/tests/apa.csl b/tests/apa.csl
new file mode 100644
--- /dev/null
+++ b/tests/apa.csl
@@ -0,0 +1,474 @@
+<?xml version="1.0" encoding="utf-8"?>
+<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="never">
+  <!-- This style was edited with the Visual CSL Editor (http://steveridout.com/csl/visualEditor/) -->
+  <info>
+    <title>American Psychological Association 6th edition</title>
+    <title-short>APA</title-short>
+    <id>http://www.zotero.org/styles/apa</id>
+    <link href="http://www.zotero.org/styles/apa" rel="self"/>
+    <link href="http://owl.english.purdue.edu/owl/resource/560/01/" rel="documentation"/>
+    <author>
+      <name>Simon Kornblith</name>
+      <email>simon@simonster.com</email>
+    </author>
+    <contributor>
+      <name>Bruce D'Arcus</name>
+    </contributor>
+    <contributor>
+      <name>Curtis M. Humphrey</name>
+    </contributor>
+    <contributor>
+      <name>Richard Karnesky</name>
+      <email>karnesky+zotero@gmail.com</email>
+      <uri>http://arc.nucapt.northwestern.edu/Richard_Karnesky</uri>
+    </contributor>
+    <contributor>
+      <name>Sebastian Karcher</name>
+    </contributor>
+    <category citation-format="author-date"/>
+    <category field="psychology"/>
+    <category field="generic-base"/>
+    <updated>2014-04-12T01:20:52+00:00</updated>
+    <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
+  </info>
+  <locale xml:lang="en">
+    <terms>
+      <term name="editortranslator" form="short">
+        <single>ed. &amp; trans.</single>
+        <multiple>eds. &amp; trans.</multiple>
+      </term>
+      <term name="translator" form="short">
+        <single>trans.</single>
+        <multiple>trans.</multiple>
+      </term>
+    </terms>
+  </locale>
+  <macro name="container-contributors">
+    <choose>
+      <if type="chapter paper-conference" match="any">
+        <names variable="editor translator container-author" delimiter=", " suffix=", ">
+          <name and="symbol" initialize-with=". " delimiter=", "/>
+          <label form="short" prefix=" (" text-case="title" suffix=")"/>
+        </names>
+      </if>
+    </choose>
+  </macro>
+  <macro name="secondary-contributors">
+    <choose>
+      <if type="article-journal chapter paper-conference" match="none">
+        <names variable="translator editor container-author" delimiter=", " prefix=" (" suffix=")">
+          <name and="symbol" initialize-with=". " delimiter=", "/>
+          <label form="short" prefix=", " text-case="title"/>
+        </names>
+      </if>
+    </choose>
+  </macro>
+  <macro name="author">
+    <names variable="author">
+      <name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with=". " delimiter=", " delimiter-precedes-last="always"/>
+      <label form="short" prefix=" (" suffix=")" text-case="capitalize-first"/>
+      <substitute>
+        <names variable="editor"/>
+        <names variable="translator"/>
+        <choose>
+          <if type="report">
+            <text variable="publisher"/>
+            <text macro="title"/>
+          </if>
+          <else>
+            <text macro="title"/>
+          </else>
+        </choose>
+      </substitute>
+    </names>
+  </macro>
+  <macro name="author-short">
+    <names variable="author">
+      <name form="short" and="symbol" delimiter=", " initialize-with=". "/>
+      <substitute>
+        <names variable="editor"/>
+        <names variable="translator"/>
+        <choose>
+          <if type="report">
+            <text variable="publisher"/>
+            <text variable="title" form="short" font-style="italic"/>
+          </if>
+          <else-if type="legal_case">
+            <text variable="title" font-style="italic"/>
+          </else-if>
+          <else-if type="bill book graphic legislation motion_picture song" match="any">
+            <text variable="title" form="short" font-style="italic"/>
+          </else-if>
+          <else>
+            <text variable="title" form="short" quotes="true"/>
+          </else>
+        </choose>
+      </substitute>
+    </names>
+  </macro>
+  <macro name="access">
+    <choose>
+      <if type="thesis">
+        <choose>
+          <if variable="archive" match="any">
+            <group>
+              <text term="retrieved" text-case="capitalize-first" suffix=" "/>
+              <text term="from" suffix=" "/>
+              <text variable="archive" suffix="."/>
+              <text variable="archive_location" prefix=" (" suffix=")"/>
+            </group>
+          </if>
+          <else>
+            <group>
+              <text term="retrieved" text-case="capitalize-first" suffix=" "/>
+              <text term="from" suffix=" "/>
+              <text variable="URL"/>
+            </group>
+          </else>
+        </choose>
+      </if>
+      <else>
+        <choose>
+          <if variable="DOI">
+            <text variable="DOI" prefix="doi:"/>
+          </if>
+          <else>
+            <choose>
+              <if type="webpage">
+                <group delimiter=" ">
+                  <text term="retrieved" text-case="capitalize-first" suffix=" "/>
+                  <group>
+                    <date variable="accessed" form="text" suffix=", "/>
+                  </group>
+                  <text term="from"/>
+                  <text variable="URL"/>
+                </group>
+              </if>
+              <else>
+                <group>
+                  <text term="retrieved" text-case="capitalize-first" suffix=" "/>
+                  <text term="from" suffix=" "/>
+                  <text variable="URL"/>
+                </group>
+              </else>
+            </choose>
+          </else>
+        </choose>
+      </else>
+    </choose>
+  </macro>
+  <macro name="title">
+    <choose>
+      <if type="report thesis" match="any">
+        <text variable="title" font-style="italic"/>
+        <group prefix=" (" suffix=")" delimiter=" ">
+          <text variable="genre"/>
+          <text variable="number" prefix="No. "/>
+        </group>
+      </if>
+      <else-if type="book graphic  motion_picture report song manuscript speech" match="any">
+        <!---This is a hack until we have a computer program type -->
+        <choose>
+          <if variable="version">
+            <group delimiter=" ">
+              <text variable="title"/>
+              <group delimiter=" " prefix="(" suffix=")">
+                <text term="version" text-case="capitalize-first"/>
+                <text variable="version"/>
+              </group>
+            </group>
+          </if>
+          <else>
+            <text variable="title" font-style="italic"/>
+          </else>
+        </choose>
+      </else-if>
+      <else>
+        <text variable="title"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="publisher">
+    <choose>
+      <if type="report" match="any">
+        <group delimiter=": ">
+          <text variable="publisher-place"/>
+          <text variable="publisher"/>
+        </group>
+      </if>
+      <else-if type="thesis" match="any">
+        <group delimiter=", ">
+          <text variable="publisher"/>
+          <text variable="publisher-place"/>
+        </group>
+      </else-if>
+      <else>
+        <group delimiter=", ">
+          <choose>
+            <if variable="event" match="none">
+              <text variable="genre"/>
+            </if>
+          </choose>
+          <choose>
+            <if type="article-journal article-magazine" match="none">
+              <group delimiter=": ">
+                <text variable="publisher-place"/>
+                <text variable="publisher"/>
+              </group>
+            </if>
+          </choose>
+        </group>
+      </else>
+    </choose>
+  </macro>
+  <macro name="event">
+    <choose>
+      <if variable="container-title" match="none">
+        <choose>
+          <if variable="event">
+            <choose>
+              <if variable="genre" match="none">
+                <text term="presented at" text-case="capitalize-first" suffix=" "/>
+                <text variable="event"/>
+              </if>
+              <else>
+                <group delimiter=" ">
+                  <text variable="genre" text-case="capitalize-first"/>
+                  <text term="presented at"/>
+                  <text variable="event"/>
+                </group>
+              </else>
+            </choose>
+          </if>
+        </choose>
+      </if>
+    </choose>
+  </macro>
+  <macro name="issued">
+    <choose>
+      <if type="bill legal_case legislation" match="none">
+        <choose>
+          <if variable="issued">
+            <group prefix=" (" suffix=")">
+              <date variable="issued">
+                <date-part name="year"/>
+              </date>
+              <text variable="year-suffix"/>
+              <choose>
+                <if type="article-journal bill book chapter graphic legal_case legislation motion_picture paper-conference report song" match="none">
+                  <date variable="issued">
+                    <date-part prefix=", " name="month"/>
+                    <date-part prefix=" " name="day"/>
+                  </date>
+                </if>
+              </choose>
+            </group>
+          </if>
+          <else>
+            <group prefix=" (" suffix=")">
+              <text term="no date" form="short"/>
+              <text variable="year-suffix" prefix="-"/>
+            </group>
+          </else>
+        </choose>
+      </if>
+    </choose>
+  </macro>
+  <macro name="issued-sort">
+    <choose>
+      <if type="article-journal bill book chapter graphic legal_case legislation motion_picture paper-conference report song" match="none">
+        <date variable="issued">
+          <date-part name="year"/>
+          <date-part name="month"/>
+          <date-part name="day"/>
+        </date>
+      </if>
+      <else>
+        <date variable="issued">
+          <date-part name="year"/>
+        </date>
+      </else>
+    </choose>
+  </macro>
+  <macro name="issued-year">
+    <choose>
+      <if variable="issued">
+        <date variable="issued">
+          <date-part name="year"/>
+        </date>
+        <text variable="year-suffix"/>
+      </if>
+      <else>
+        <text term="no date" form="short"/>
+        <text variable="year-suffix" prefix="-"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="edition">
+    <choose>
+      <if is-numeric="edition">
+        <group delimiter=" ">
+          <number variable="edition" form="ordinal"/>
+          <text term="edition" form="short"/>
+        </group>
+      </if>
+      <else>
+        <text variable="edition" suffix="."/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="locators">
+    <choose>
+      <if type="article-journal article-magazine" match="any">
+        <group prefix=", " delimiter=", ">
+          <group>
+            <text variable="volume" font-style="italic"/>
+            <text variable="issue" prefix="(" suffix=")"/>
+          </group>
+          <text variable="page"/>
+        </group>
+      </if>
+      <else-if type="article-newspaper">
+        <group delimiter=" " prefix=", ">
+          <label variable="page" form="short"/>
+          <text variable="page"/>
+        </group>
+      </else-if>
+      <else-if type="book graphic motion_picture report song chapter paper-conference" match="any">
+        <group prefix=" (" suffix=")" delimiter=", ">
+          <text macro="edition"/>
+          <group>
+            <text term="volume" form="short" plural="true" text-case="capitalize-first" suffix=" "/>
+            <number variable="number-of-volumes" form="numeric" prefix="1-"/>
+          </group>
+          <group>
+            <text term="volume" form="short" text-case="capitalize-first" suffix=" "/>
+            <number variable="volume" form="numeric"/>
+          </group>
+          <group>
+            <label variable="page" form="short" suffix=" "/>
+            <text variable="page"/>
+          </group>
+        </group>
+      </else-if>
+      <else-if type="legal_case">
+        <group prefix=" (" suffix=")" delimiter=" ">
+          <text variable="authority"/>
+          <date variable="issued" form="text"/>
+        </group>
+      </else-if>
+      <else-if type="bill legislation" match="any">
+        <date variable="issued" prefix=" (" suffix=")">
+          <date-part name="year"/>
+        </date>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="citation-locator">
+    <group>
+      <choose>
+        <if locator="chapter">
+          <label variable="locator" form="long" text-case="capitalize-first"/>
+        </if>
+        <else>
+          <label variable="locator" form="short"/>
+        </else>
+      </choose>
+      <text variable="locator" prefix=" "/>
+    </group>
+  </macro>
+  <macro name="container">
+    <group>
+      <choose>
+        <if type="chapter paper-conference entry-encyclopedia" match="any">
+          <text term="in" text-case="capitalize-first" suffix=" "/>
+        </if>
+      </choose>
+      <text macro="container-contributors"/>
+      <text macro="secondary-contributors"/>
+      <text macro="container-title"/>
+    </group>
+  </macro>
+  <macro name="container-title">
+    <choose>
+      <if type="article article-journal article-magazine article-newspaper" match="any">
+        <text variable="container-title" font-style="italic" text-case="title"/>
+      </if>
+      <else-if type="bill legal_case legislation" match="none">
+        <text variable="container-title" font-style="italic"/>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="legal-cites">
+    <choose>
+      <if type="bill legal_case legislation" match="any">
+        <group delimiter=" " prefix=", ">
+          <choose>
+            <if variable="container-title">
+              <text variable="volume"/>
+              <text variable="container-title"/>
+              <group delimiter=" ">
+                <!--change to label variable="section" as that becomes available -->
+                <text term="section" form="symbol"/>
+                <text variable="section"/>
+              </group>
+              <text variable="page"/>
+            </if>
+            <else>
+              <choose>
+                <if type="legal_case">
+                  <text variable="number" prefix="No. "/>
+                </if>
+                <else>
+                  <text variable="number" prefix="Pub. L. No. "/>
+                  <group delimiter=" ">
+                    <!--change to label variable="section" as that becomes available -->
+                    <text term="section" form="symbol"/>
+                    <text variable="section"/>
+                  </group>
+                </else>
+              </choose>
+            </else>
+          </choose>
+        </group>
+      </if>
+    </choose>
+  </macro>
+  <citation et-al-min="6" et-al-use-first="1" et-al-subsequent-min="3" et-al-subsequent-use-first="1" disambiguate-add-year-suffix="true" disambiguate-add-names="true" disambiguate-add-givenname="true" collapse="year" givenname-disambiguation-rule="primary-name">
+    <sort>
+      <key macro="author"/>
+      <key macro="issued-sort"/>
+    </sort>
+    <layout prefix="(" suffix=")" delimiter="; ">
+      <group delimiter=", ">
+        <text macro="author-short"/>
+        <text macro="issued-year"/>
+        <text macro="citation-locator"/>
+      </group>
+    </layout>
+  </citation>
+  <bibliography hanging-indent="true" et-al-min="8" et-al-use-first="6" et-al-use-last="true" entry-spacing="0" line-spacing="2">
+    <sort>
+      <key macro="author"/>
+      <key macro="issued-sort" sort="ascending"/>
+      <key macro="title"/>
+    </sort>
+    <layout>
+      <group suffix=".">
+        <group delimiter=". ">
+          <text macro="author"/>
+          <text macro="issued"/>
+          <text macro="title" prefix=" "/>
+          <text macro="container"/>
+        </group>
+        <text macro="legal-cites"/>
+        <text macro="locators"/>
+        <group delimiter=", " prefix=". ">
+          <text macro="event"/>
+          <text macro="publisher"/>
+        </group>
+      </group>
+      <text macro="access" prefix=" "/>
+    </layout>
+  </bibliography>
+</style>
diff --git a/tests/issue14.expected.native b/tests/issue14.expected.native
--- a/tests/issue14.expected.native
+++ b/tests/issue14.expected.native
@@ -1,3 +1,3 @@
 Pandoc (Meta {unMeta = fromList [("csl",MetaInlines [Str "chicago-author-date.csl"]),("references",MetaList [MetaMap (fromList [("author",MetaMap (fromList [("family",MetaInlines [Str "Pelikan"]),("given",MetaInlines [Str "Jaroslav"])])),("container-title",MetaInlines [Str "The",Space,Str "Christian",Space,Str "tradition:",Space,Str "A",Space,Str "history",Space,Str "of",Space,Str "the",Space,Str "development",Space,Str "of",Space,Str "doctrine"]),("id",MetaInlines [Str "CTv1c2"]),("issued",MetaList [MetaMap (fromList [("year",MetaString "1971")])]),("language",MetaInlines [Str "en-US"]),("page",MetaInlines [Str "34-56"]),("publisher",MetaInlines [Str "University",Space,Str "of",Space,Str "Chicago",Space,Str "Press"]),("publisher-place",MetaInlines [Str "Chicago"]),("title",MetaInlines [Str "Chapter",Space,Str "two"]),("type",MetaInlines [Str "chapter"]),("volume",MetaString "1"),("volume-title",MetaInlines [Str "The",Space,Str "emergence",Space,Str "of",Space,Str "the",Space,Str "Catholic",Space,Str "tradition",Space,Str "(100\8211\&600)"])]),MetaMap (fromList [("author",MetaMap (fromList [("family",MetaInlines [Str "Pelikan"]),("given",MetaInlines [Str "Jaroslav"])])),("container-title",MetaInlines [Str "The",Space,Str "Christian",Space,Str "tradition:",Space,Str "A",Space,Str "history",Space,Str "of",Space,Str "the",Space,Str "development",Space,Str "of",Space,Str "doctrine"]),("id",MetaInlines [Str "CTv1"]),("issued",MetaList [MetaMap (fromList [("year",MetaString "1971")])]),("language",MetaInlines [Str "en-US"]),("publisher",MetaInlines [Str "University",Space,Str "of",Space,Str "Chicago",Space,Str "Press"]),("publisher-place",MetaInlines [Str "Chicago"]),("title",MetaInlines [Str "The",Space,Str "emergence",Space,Str "of",Space,Str "the",Space,Str "Catholic",Space,Str "tradition",Space,Str "(100\8211\&600)"]),("type",MetaInlines [Str "book"]),("volume",MetaString "1")]),MetaMap (fromList [("author",MetaMap (fromList [("family",MetaInlines [Str "Pelikan"]),("given",MetaInlines [Str "Jaroslav"])])),("id",MetaInlines [Str "CT"]),("issued",MetaList [MetaMap (fromList [("year",MetaString "1971")])]),("language",MetaInlines [Str "en-US"]),("publisher",MetaInlines [Str "University",Space,Str "of",Space,Str "Chicago",Space,Str "Press"]),("publisher-place",MetaInlines [Str "Chicago"]),("title",MetaInlines [Str "The",Space,Str "Christian",Space,Str "tradition:",Space,Str "A",Space,Str "history",Space,Str "of",Space,Str "the",Space,Str "development",Space,Str "of",Space,Str "doctrine"]),("type",MetaInlines [Str "book"])])])]})
-[Para [Str "Foo",Space,Cite [Citation {citationId = "CT", citationPrefix = [], citationSuffix = [Str ",",Space,Str "1:12"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 1}] [Str "(",Str "Pelikan",Space,Str "1971",Str "a",Str ",",Space,Str "1:12",Str ")"],Str ".",Space,Str "Bar",Space,Cite [Citation {citationId = "CTv1", citationPrefix = [], citationSuffix = [Str ",",Space,Str "12"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 2}] [Str "(",Str "Pelikan",Space,Str "1971",Str "b",Str ",",Space,Str "12",Str ")"],Str ".",Space,Str "Baz",Space,Cite [Citation {citationId = "CTv1c2", citationPrefix = [], citationSuffix = [Str ",",Space,Str "12"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 3}] [Str "(",Str "Pelikan",Space,Str "1971",Str "c",Str ",",Space,Str "12",Str ")"],Str "."]
+[Para [Str "Foo",Space,Cite [Citation {citationId = "CT", citationPrefix = [], citationSuffix = [Str ",",Space,Str "1:12"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 1}] [Str "(",Str "Pelikan",Space,Str "1971",Str "a",Str ",",Space,Str "1:12",Str ")"],Str ".",Space,Str "Bar",Space,Cite [Citation {citationId = "CTv1", citationPrefix = [], citationSuffix = [Str ",",Space,Str "12"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 2}] [Str "(",Str "Pelikan",Space,Str "1971",Str "b",Str ",",Space,Str "1:12",Str ")"],Str ".",Space,Str "Baz",Space,Cite [Citation {citationId = "CTv1c2", citationPrefix = [], citationSuffix = [Str ",",Space,Str "12"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 3}] [Str "(",Str "Pelikan",Space,Str "1971",Str "c",Str ",",Space,Str "12",Str ")"],Str "."]
 ,Div ("",["references"],[]) [Header 1 ("references",["unnumbered"],[]) [Str "References"],Para [Str "Pelikan",Str ",",Space,Str "Jaroslav",Str ".",Space,Str "1971",Str "a",Str ".",Space,Emph [Str "The",Space,Str "Christian",Space,Str "Tradition",Str ":",Space,Str "A",Space,Str "History",Space,Str "of",Space,Str "the",Space,Str "Development",Space,Str "of",Space,Str "Doctrine"],Str ".",Space,Str "Chicago",Str ":",Space,Str "University",Space,Str "of",Space,Str "Chicago",Space,Str "Press",Str "."],Para [Str "\8212\8212\8212",Str ".",Space,Str "1971",Str "b",Str ".",Space,Emph [Str "The",Space,Str "Emergence",Space,Str "of",Space,Str "the",Space,Str "Catholic",Space,Str "Tradition",Space,Str "(",Str "100",Str "\8211",Str "600",Str ")"],Str ".",Space,Emph [Str "The",Space,Str "Christian",Space,Str "Tradition",Str ":",Space,Str "A",Space,Str "History",Space,Str "of",Space,Str "the",Space,Str "Development",Space,Str "of",Space,Str "Doctrine"],Str ".",Space,Str "Vol.",Space,Str "1",Str ".",Space,Str "Chicago",Str ":",Space,Str "University",Space,Str "of",Space,Str "Chicago",Space,Str "Press",Str "."],Para [Str "\8212\8212\8212",Str ".",Space,Str "1971",Str "c",Str ".",Space,Str "\8220",Str "Chapter",Space,Str "Two",Str ".",Str "\8221",Space,Str "In",Space,Emph [Str "The",Space,Str "Christian",Space,Str "Tradition",Str ":",Space,Str "A",Space,Str "History",Space,Str "of",Space,Str "the",Space,Str "Development",Space,Str "of",Space,Str "Doctrine"],Str ",",Space,Str "1",Str ":",Str "34\8211\&56",Str ".",Space,Str "Chicago",Str ":",Space,Str "University",Space,Str "of",Space,Str "Chicago",Space,Str "Press",Str "."]]]
diff --git a/tests/issue61.expected.native b/tests/issue61.expected.native
--- a/tests/issue61.expected.native
+++ b/tests/issue61.expected.native
@@ -1,4 +1,4 @@
-Pandoc (Meta {unMeta = fromList [("csl",MetaInlines [Str "modern-humanities-research-association.csl"]),("references",MetaList [MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Doe"]),("given",MetaInlines [Str "John"])])]),("id",MetaInlines [Str "doe"]),("issued",MetaMap (fromList [("date-parts",MetaList [MetaList [MetaString "1985"]])])),("publisher",MetaInlines [Str "Publisher"]),("title",MetaInlines [Str "Title"]),("type",MetaInlines [Str "book"])]),MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Roe"]),("given",MetaInlines [Str "Rob"])])]),("id",MetaInlines [Str "roe"]),("issued",MetaMap (fromList [("date-parts",MetaList [MetaList [MetaString "1985"]])])),("publisher",MetaInlines [Str "Publisher"]),("title",MetaInlines [Str "Title"]),("type",MetaInlines [Str "book"])])])]})
+Pandoc (Meta {unMeta = fromList [("csl",MetaInlines [Str "tests/modern-humanities-research-association.csl"]),("references",MetaList [MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Doe"]),("given",MetaInlines [Str "John"])])]),("id",MetaInlines [Str "doe"]),("issued",MetaMap (fromList [("date-parts",MetaList [MetaList [MetaString "1985"]])])),("publisher",MetaInlines [Str "Publisher"]),("title",MetaInlines [Str "Title"]),("type",MetaInlines [Str "book"])]),MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Roe"]),("given",MetaInlines [Str "Rob"])])]),("id",MetaInlines [Str "roe"]),("issued",MetaMap (fromList [("date-parts",MetaList [MetaList [MetaString "1985"]])])),("publisher",MetaInlines [Str "Publisher"]),("title",MetaInlines [Str "Title"]),("type",MetaInlines [Str "book"])])])]})
 [Header 1 ("text",[],[]) [Str "Text"]
 ,Para [Str "Foo",Str "",Cite [Citation {citationId = "doe", citationPrefix = [], citationSuffix = [Str ",",Space,Str "VIII,",Space,Str "89"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 1}] [Note [Para [Str "John",Space,Str "Doe",Str ",",Space,Emph [Str "Title"],Space,Str "(",Str "Publisher",Str ",",Space,Str "1985",Str ")",Str ",",Space,Str "VIII,",Space,Str "89",Str ".",Space]]]]
 ,Para [Str "Foo",Str "",Cite [Citation {citationId = "roe", citationPrefix = [], citationSuffix = [Str ",",Space,Str "III,",Space,Str "89"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 2}] [Note [Para [Str "Rob",Space,Str "Roe",Str ",",Space,Emph [Str "Title"],Space,Str "(",Str "Publisher",Str ",",Space,Str "1985",Str ")",Str ",",Space,Str "III,",Space,Str "89",Str ".",Space]]]]
diff --git a/tests/issue61.in.native b/tests/issue61.in.native
--- a/tests/issue61.in.native
+++ b/tests/issue61.in.native
@@ -1,4 +1,4 @@
-Pandoc (Meta {unMeta = fromList [("csl",MetaInlines [Str "modern-humanities-research-association.csl"]),("references",MetaList [MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Doe"]),("given",MetaInlines [Str "John"])])]),("id",MetaInlines [Str "doe"]),("issued",MetaMap (fromList [("date-parts",MetaList [MetaList [MetaString "1985"]])])),("publisher",MetaInlines [Str "Publisher"]),("title",MetaInlines [Str "Title"]),("type",MetaInlines [Str "book"])]),MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Roe"]),("given",MetaInlines [Str "Rob"])])]),("id",MetaInlines [Str "roe"]),("issued",MetaMap (fromList [("date-parts",MetaList [MetaList [MetaString "1985"]])])),("publisher",MetaInlines [Str "Publisher"]),("title",MetaInlines [Str "Title"]),("type",MetaInlines [Str "book"])])])]})
+Pandoc (Meta {unMeta = fromList [("csl",MetaInlines [Str "tests/modern-humanities-research-association.csl"]),("references",MetaList [MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Doe"]),("given",MetaInlines [Str "John"])])]),("id",MetaInlines [Str "doe"]),("issued",MetaMap (fromList [("date-parts",MetaList [MetaList [MetaString "1985"]])])),("publisher",MetaInlines [Str "Publisher"]),("title",MetaInlines [Str "Title"]),("type",MetaInlines [Str "book"])]),MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Roe"]),("given",MetaInlines [Str "Rob"])])]),("id",MetaInlines [Str "roe"]),("issued",MetaMap (fromList [("date-parts",MetaList [MetaList [MetaString "1985"]])])),("publisher",MetaInlines [Str "Publisher"]),("title",MetaInlines [Str "Title"]),("type",MetaInlines [Str "book"])])])]})
 [Header 1 ("text",[],[]) [Str "Text"]
 ,Para [Str "Foo",Space,Cite [Citation {citationId = "doe", citationPrefix = [], citationSuffix = [Str ",",Space,Str "VIII,",Space,Str "89"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@doe,",Space,Str "VIII,",Space,Str "89]"]]
 ,Para [Str "Foo",Space,Cite [Citation {citationId = "roe", citationPrefix = [], citationSuffix = [Str ",",Space,Str "III,",Space,Str "89"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@roe,",Space,Str "III,",Space,Str "89]"]]
diff --git a/tests/issue75.expected.native b/tests/issue75.expected.native
new file mode 100644
--- /dev/null
+++ b/tests/issue75.expected.native
@@ -0,0 +1,13 @@
+Pandoc (Meta {unMeta = fromList [("csl",MetaInlines [Str "tests/apa.csl"]),("references",MetaList [MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Doe"]),("given",MetaInlines [Str "John"])])]),("id",MetaInlines [Str "test"]),("issued",MetaMap (fromList [("date-parts",MetaList [MetaList [MetaString "2006"]])])),("title",MetaInlines [Str "Test"]),("type",MetaInlines [Str "article-journal"]),("volume",MetaInlines [Str "81"])])])]})
+[Para [Cite [Citation {citationId = "test", citationPrefix = [], citationSuffix = [Str ",",Space,Str "p.",Space,Str "6"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 1}] [Str "(",Str "Doe",Str ",",Space,Str "2006",Str ",",Space,Str "p.",Space,Str "6",Str ")"]]
+,Para [Cite [Citation {citationId = "test", citationPrefix = [], citationSuffix = [Str ",",Space,Str "chap.",Space,Str "6"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 2}] [Str "(",Str "Doe",Str ",",Space,Str "2006",Str ",",Space,Str "Chapter",Space,Str "6",Str ")"]]
+,Para [Cite [Citation {citationId = "test", citationPrefix = [], citationSuffix = [Str ",",Space,Str "n.",Space,Str "6"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 3}] [Str "(",Str "Doe",Str ",",Space,Str "2006",Str ",",Space,Str "n.",Space,Str "6",Str ")"]]
+,Para [Cite [Citation {citationId = "test", citationPrefix = [], citationSuffix = [Str ",",Space,Str "pp.",Space,Str "34-36,",Space,Str "38-39"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 4}] [Str "(",Str "Doe",Str ",",Space,Str "2006",Str ",",Space,Str "pp.",Space,Str "34\8211\&36,",Space,Str "38\8211\&39",Str ")"]]
+,Para [Cite [Citation {citationId = "test", citationPrefix = [], citationSuffix = [Str ",",Space,Str "sec.",Space,Str "3"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 5}] [Str "(",Str "Doe",Str ",",Space,Str "2006",Str ",",Space,Str "sec.",Space,Str "3",Str ")"]]
+,Para [Cite [Citation {citationId = "test", citationPrefix = [], citationSuffix = [Str ",",Space,Str "p.3"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 6}] [Str "(",Str "Doe",Str ",",Space,Str "2006",Str ",",Space,Str "p.",Space,Str "3",Str ")"]]
+,Para [Cite [Citation {citationId = "test", citationPrefix = [], citationSuffix = [Str ",",Space,Str "33-35,",Space,Str "38-39"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 7}] [Str "(",Str "Doe",Str ",",Space,Str "2006",Str ",",Space,Str "pp.",Space,Str "33\8211\&35,",Space,Str "38\8211\&39",Str ")"]]
+,Para [Cite [Citation {citationId = "test", citationPrefix = [], citationSuffix = [Str ",",Space,Str "14"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 8}] [Str "(",Str "Doe",Str ",",Space,Str "2006",Str ",",Space,Str "p.",Space,Str "14",Str ")"]]
+,Para [Cite [Citation {citationId = "test", citationPrefix = [], citationSuffix = [Space,Str "bk.",Space,Str "VI"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 9}] [Str "(",Str "Doe",Str ",",Space,Str "2006",Str ",",Space,Str "bk.",Space,Str "VI",Str ")"]]
+,Para [Cite [Citation {citationId = "test", citationPrefix = [], citationSuffix = [Str ",",Space,Str "no.",Space,Str "6"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 10}] [Str "(",Str "Doe",Str ",",Space,Str "2006",Str ",",Space,Str "no.",Space,Str "6",Str ")"]]
+,Para [Cite [Citation {citationId = "test", citationPrefix = [], citationSuffix = [Str ",",Space,Str "nos.",Space,Str "6",Space,Str "and",Space,Str "7"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 11}] [Str "(",Str "Doe",Str ",",Space,Str "2006",Str ",",Space,Str "nos.",Space,Str "6",Space,Str "and",Space,Str "7",Str ")"]]
+,Div ("",["references"],[]) [Para [Str "Doe",Str ",",Space,Str "J",Str ".",Space,Str "(",Str "2006",Str ")",Str ".",Space,Str "Test",Str ",",Space,Emph [Str "81"],Str "."]]]
diff --git a/tests/issue75.in.native b/tests/issue75.in.native
new file mode 100644
--- /dev/null
+++ b/tests/issue75.in.native
@@ -0,0 +1,12 @@
+Pandoc (Meta {unMeta = fromList [("csl",MetaInlines [Str "tests/apa.csl"]),("references",MetaList [MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Doe"]),("given",MetaInlines [Str "John"])])]),("id",MetaInlines [Str "test"]),("issued",MetaMap (fromList [("date-parts",MetaList [MetaList [MetaString "2006"]])])),("title",MetaInlines [Str "Test"]),("type",MetaInlines [Str "article-journal"]),("volume",MetaInlines [Str "81"])])])]})
+[Para [Cite [Citation {citationId = "test", citationPrefix = [], citationSuffix = [Str ",",Space,Str "p.",Space,Str "6"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@test,",Space,Str "p.",Space,Str "6]"]]
+,Para [Cite [Citation {citationId = "test", citationPrefix = [], citationSuffix = [Str ",",Space,Str "chap.",Space,Str "6"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@test,",Space,Str "chap.",Space,Str "6]"]]
+,Para [Cite [Citation {citationId = "test", citationPrefix = [], citationSuffix = [Str ",",Space,Str "n.",Space,Str "6"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@test,",Space,Str "n.",Space,Str "6]"]]
+,Para [Cite [Citation {citationId = "test", citationPrefix = [], citationSuffix = [Str ",",Space,Str "pp.",Space,Str "34-36,",Space,Str "38-39"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@test,",Space,Str "pp.",Space,Str "34-36,",Space,Str "38-39]"]]
+,Para [Cite [Citation {citationId = "test", citationPrefix = [], citationSuffix = [Str ",",Space,Str "sec.",Space,Str "3"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@test,",Space,Str "sec.",Space,Str "3]"]]
+,Para [Cite [Citation {citationId = "test", citationPrefix = [], citationSuffix = [Str ",",Space,Str "p.3"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@test,",Space,Str "p.3]"]]
+,Para [Cite [Citation {citationId = "test", citationPrefix = [], citationSuffix = [Str ",",Space,Str "33-35,",Space,Str "38-39"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@test,",Space,Str "33-35,",Space,Str "38-39]"]]
+,Para [Cite [Citation {citationId = "test", citationPrefix = [], citationSuffix = [Str ",",Space,Str "14"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@test,",Space,Str "14]"]]
+,Para [Cite [Citation {citationId = "test", citationPrefix = [], citationSuffix = [Space,Str "bk.",Space,Str "VI"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@test",Space,Str "bk.",Space,Str "VI]"]]
+,Para [Cite [Citation {citationId = "test", citationPrefix = [], citationSuffix = [Str ",",Space,Str "no.",Space,Str "6"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@test,",Space,Str "no.",Space,Str "6]"]]
+,Para [Cite [Citation {citationId = "test", citationPrefix = [], citationSuffix = [Str ",",Space,Str "nos.",Space,Str "6",Space,Str "and",Space,Str "7"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@test,",Space,Str "nos.",Space,Str "6",Space,Str "and",Space,Str "7]"]]]
diff --git a/tests/issue76.expected.native b/tests/issue76.expected.native
new file mode 100644
--- /dev/null
+++ b/tests/issue76.expected.native
@@ -0,0 +1,3 @@
+Pandoc (Meta {unMeta = fromList [("references",MetaList [MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Author"]),("given",MetaInlines [Str "Al"])])]),("id",MetaInlines [Str "item1"]),("issued",MetaMap (fromList [("date-parts",MetaList [MetaList [MetaString "1998"]])])),("title",MetaInlines [Str "foo",Space,Str "bar",Space,Str "baz:",Space,Str "bazbaz",Space,Str "bar",Space,Str "foo"]),("type",MetaInlines [Str "article-journal"])]),MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Author"]),("given",MetaInlines [Str "Al"])])]),("id",MetaInlines [Str "item2"]),("issued",MetaMap (fromList [("date-parts",MetaList [MetaList [MetaString "1998"]])])),("title",MetaInlines [Str "foo",Space,Str "bar",Space,Str "baz:",Space,Str "the",Space,Str "bazbaz",Space,Str "bar",Space,Str "foo"]),("type",MetaInlines [Str "article-journal"])]),MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Author"]),("given",MetaInlines [Str "Al"])])]),("id",MetaInlines [Str "item3"]),("issued",MetaMap (fromList [("date-parts",MetaList [MetaList [MetaString "1998"]])])),("title",MetaInlines [Str "foo",Space,Str "bar",Space,Str "baz:",Space,Str "a",Space,Str "bazbaz",Space,Str "bar",Space,Str "foo"]),("type",MetaInlines [Str "article-journal"])]),MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Author"]),("given",MetaInlines [Str "Al"])])]),("id",MetaInlines [Str "item4"]),("issued",MetaMap (fromList [("date-parts",MetaList [MetaList [MetaString "1998"]])])),("title",MetaInlines [Str "foo",Space,Str "bar",Space,Str "baz:",Space,Str "an",Space,Str "abazbaz",Space,Str "bar",Space,Str "foo"]),("type",MetaInlines [Str "article-journal"])])])]})
+[Para [Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 1}] [Str "Author",Space,Str "(",Str "1998",Str "a",Str ")"],Str ",",Space,Cite [Citation {citationId = "item2", citationPrefix = [], citationSuffix = [], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 2}] [Str "Author",Space,Str "(",Str "1998",Str "b",Str ")"],Str ",",Space,Cite [Citation {citationId = "item3", citationPrefix = [], citationSuffix = [], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 3}] [Str "Author",Space,Str "(",Str "1998",Str "c",Str ")"],Str ",",Space,Cite [Citation {citationId = "item4", citationPrefix = [], citationSuffix = [], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 4}] [Str "Author",Space,Str "(",Str "1998",Str "d",Str ")"]]
+,Div ("",["references"],[]) [Para [Str "Author",Str ",",Space,Str "Al",Str ".",Space,Str "1998",Str "a",Str ".",Space,Str "\8220",Str "Foo",Space,Str "Bar",Space,Str "Baz",Str ":",Space,Str "Bazbaz",Space,Str "Bar",Space,Str "Foo",Str ".",Str "\8221"],Para [Str "\8212\8212\8212",Str ".",Space,Str "1998",Str "b",Str ".",Space,Str "\8220",Str "Foo",Space,Str "Bar",Space,Str "Baz",Str ":",Space,Str "The",Space,Str "Bazbaz",Space,Str "Bar",Space,Str "Foo",Str ".",Str "\8221"],Para [Str "\8212\8212\8212",Str ".",Space,Str "1998",Str "c",Str ".",Space,Str "\8220",Str "Foo",Space,Str "Bar",Space,Str "Baz",Str ":",Space,Str "A",Space,Str "Bazbaz",Space,Str "Bar",Space,Str "Foo",Str ".",Str "\8221"],Para [Str "\8212\8212\8212",Str ".",Space,Str "1998",Str "d",Str ".",Space,Str "\8220",Str "Foo",Space,Str "Bar",Space,Str "Baz",Str ":",Space,Str "An",Space,Str "Abazbaz",Space,Str "Bar",Space,Str "Foo",Str ".",Str "\8221"]]]
diff --git a/tests/issue76.in.native b/tests/issue76.in.native
new file mode 100644
--- /dev/null
+++ b/tests/issue76.in.native
@@ -0,0 +1,2 @@
+Pandoc (Meta {unMeta = fromList [("references",MetaList [MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Author"]),("given",MetaInlines [Str "Al"])])]),("id",MetaInlines [Str "item1"]),("issued",MetaMap (fromList [("date-parts",MetaList [MetaList [MetaString "1998"]])])),("title",MetaInlines [Str "foo",Space,Str "bar",Space,Str "baz:",Space,Str "bazbaz",Space,Str "bar",Space,Str "foo"]),("type",MetaInlines [Str "article-journal"])]),MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Author"]),("given",MetaInlines [Str "Al"])])]),("id",MetaInlines [Str "item2"]),("issued",MetaMap (fromList [("date-parts",MetaList [MetaList [MetaString "1998"]])])),("title",MetaInlines [Str "foo",Space,Str "bar",Space,Str "baz:",Space,Str "the",Space,Str "bazbaz",Space,Str "bar",Space,Str "foo"]),("type",MetaInlines [Str "article-journal"])]),MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Author"]),("given",MetaInlines [Str "Al"])])]),("id",MetaInlines [Str "item3"]),("issued",MetaMap (fromList [("date-parts",MetaList [MetaList [MetaString "1998"]])])),("title",MetaInlines [Str "foo",Space,Str "bar",Space,Str "baz:",Space,Str "a",Space,Str "bazbaz",Space,Str "bar",Space,Str "foo"]),("type",MetaInlines [Str "article-journal"])]),MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Author"]),("given",MetaInlines [Str "Al"])])]),("id",MetaInlines [Str "item4"]),("issued",MetaMap (fromList [("date-parts",MetaList [MetaList [MetaString "1998"]])])),("title",MetaInlines [Str "foo",Space,Str "bar",Space,Str "baz:",Space,Str "an",Space,Str "abazbaz",Space,Str "bar",Space,Str "foo"]),("type",MetaInlines [Str "article-journal"])])])]})
+[Para [Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0}] [Str "@item1"],Str ",",Space,Cite [Citation {citationId = "item2", citationPrefix = [], citationSuffix = [], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0}] [Str "@item2"],Str ",",Space,Cite [Citation {citationId = "item3", citationPrefix = [], citationSuffix = [], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0}] [Str "@item3"],Str ",",Space,Cite [Citation {citationId = "item4", citationPrefix = [], citationSuffix = [], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0}] [Str "@item4"]]]
diff --git a/tests/issue77.expected.native b/tests/issue77.expected.native
new file mode 100644
--- /dev/null
+++ b/tests/issue77.expected.native
@@ -0,0 +1,3 @@
+Pandoc (Meta {unMeta = fromList [("csl",MetaInlines [Str "tests/chicago-fullnote-bibliography.csl"]),("references",MetaList [MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Doe"]),("given",MetaInlines [Str "John,",Space,Str "III"])])]),("id",MetaInlines [Str "item1"]),("type",MetaInlines [Str "book"])]),MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "van",Space,Str "Gogh"]),("given",MetaInlines [Str "Vincent"])])]),("id",MetaInlines [Str "item2"]),("type",MetaInlines [Str "book"])]),MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Humboldt"]),("given",MetaInlines [Str "Alexander",Space,Str "von"])])]),("id",MetaInlines [Str "item3"]),("type",MetaInlines [Str "book"])]),MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Bennett"]),("given",MetaInlines [Str "Frank",Space,Str "G.,!",Space,Str "Jr."]),("parse-names",MetaBool True)])]),("id",MetaInlines [Str "item4"]),("type",MetaInlines [Str "book"])]),MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Dumboldt"]),("given",MetaInlines [Str "Ezekiel,",Space,Str "III"]),("parse-names",MetaBool False)])]),("id",MetaInlines [Str "item5"]),("type",MetaInlines [Str "book"])])])]})
+[Para [Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 1},Citation {citationId = "item2", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 2},Citation {citationId = "item3", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 3},Citation {citationId = "item4", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 4},Citation {citationId = "item5", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 5}] [Note [Para [Str "John",Space,Str "Doe",Space,Str "III",Str ",",Space,Str "n.d.",Str ";",Space,Str "Vincent",Space,Str "van",Space,Str "Gogh",Str ",",Space,Str "n.d.",Str ";",Space,Str "Alexander",Space,Str "von",Space,Str "Humboldt",Str ",",Space,Str "n.d.",Str ";",Space,Str "Frank",Space,Str "G",Str ".",Space,Str "Bennett",Str ",",Space,Str "Jr.",Str ",",Space,Str "n.d.",Str ";",Space,Str "Ezekiel,",Space,Str "III",Space,Str "Dumboldt",Str ",",Space,Str "n.d.",Space]]]]
+,Div ("",["references"],[]) [Para [Str "Bennett",Str ",",Space,Str "Frank",Space,Str "G",Str ".",Str ",",Space,Str "Jr.",Str ",",Space,Str "n.d."],Para [Str "Doe",Str ",",Space,Str "John",Str ",",Space,Str "III",Str ",",Space,Str "n.d."],Para [Str "Dumboldt",Str ",",Space,Str "Ezekiel,",Space,Str "III",Str ",",Space,Str "n.d."],Para [Str "Humboldt",Str ",",Space,Str "Alexander",Space,Str "von",Str ",",Space,Str "n.d."],Para [Str "van",Space,Str "Gogh",Str ",",Space,Str "Vincent",Str ",",Space,Str "n.d."]]]
diff --git a/tests/issue77.in.native b/tests/issue77.in.native
new file mode 100644
--- /dev/null
+++ b/tests/issue77.in.native
@@ -0,0 +1,2 @@
+Pandoc (Meta {unMeta = fromList [("csl",MetaInlines [Str "tests/chicago-fullnote-bibliography.csl"]),("references",MetaList [MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Doe"]),("given",MetaInlines [Str "John,",Space,Str "III"])])]),("id",MetaInlines [Str "item1"]),("type",MetaInlines [Str "book"])]),MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "van",Space,Str "Gogh"]),("given",MetaInlines [Str "Vincent"])])]),("id",MetaInlines [Str "item2"]),("type",MetaInlines [Str "book"])]),MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Humboldt"]),("given",MetaInlines [Str "Alexander",Space,Str "von"])])]),("id",MetaInlines [Str "item3"]),("type",MetaInlines [Str "book"])]),MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Bennett"]),("given",MetaInlines [Str "Frank",Space,Str "G.,!",Space,Str "Jr."]),("parse-names",MetaBool True)])]),("id",MetaInlines [Str "item4"]),("type",MetaInlines [Str "book"])]),MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Dumboldt"]),("given",MetaInlines [Str "Ezekiel,",Space,Str "III"]),("parse-names",MetaBool False)])]),("id",MetaInlines [Str "item5"]),("type",MetaInlines [Str "book"])])])]})
+[Para [Cite [Citation {citationId = "item1", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0},Citation {citationId = "item2", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0},Citation {citationId = "item3", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0},Citation {citationId = "item4", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0},Citation {citationId = "item5", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@item1;",Space,Str "@item2;",Space,Str "@item3;",Space,Str "@item4;",Space,Str "@item5]"]]]
diff --git a/tests/modern-humanities-research-association.csl b/tests/modern-humanities-research-association.csl
new file mode 100644
--- /dev/null
+++ b/tests/modern-humanities-research-association.csl
@@ -0,0 +1,445 @@
+<?xml version="1.0" encoding="utf-8"?>
+<style xmlns="http://purl.org/net/xbiblio/csl" class="note" version="1.0" demote-non-dropping-particle="sort-only" default-locale="en-GB">
+  <info>
+    <title>Modern Humanities Research Association (note with bibliography)</title>
+    <id>http://www.zotero.org/styles/modern-humanities-research-association</id>
+    <link href="http://www.zotero.org/styles/modern-humanities-research-association" rel="self"/>
+    <link href="http://www.mhra.org.uk/Publications/Books/StyleGuide/download.shtml" rel="documentation"/>
+    <author>
+      <name>Rintze Zelle</name>
+      <uri>http://twitter.com/rintzezelle</uri>
+    </author>
+    <contributor>
+      <name>Sebastian Karcher</name>
+    </contributor>
+    <category citation-format="note"/>
+    <category field="generic-base"/>
+    <summary>MHRA format with full notes and bibliography</summary>
+    <updated>2013-04-16T04:40:01+00:00</updated>
+    <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
+  </info>
+  <locale xml:lang="en">
+    <terms>
+      <term name="et-al">and others</term>
+      <term name="editor" form="verb-short">ed. by</term>
+      <term name="edition" form="short">edn</term>
+      <term name="translator" form="verb-short">trans. by</term>
+    </terms>
+  </locale>
+  <macro name="author">
+    <group delimiter=". ">
+      <names variable="author">
+        <name name-as-sort-order="first" and="text" sort-separator=", " delimiter=", " delimiter-precedes-last="always"/>
+        <label form="short" prefix=", " suffix="."/>
+        <substitute>
+          <names variable="editor"/>
+          <names variable="translator"/>
+          <text macro="title-note"/>
+        </substitute>
+      </names>
+      <text macro="recipient"/>
+    </group>
+  </macro>
+  <macro name="recipient">
+    <group delimiter=" ">
+      <choose>
+        <if type="personal_communication">
+          <choose>
+            <if variable="genre">
+              <text variable="genre" text-case="capitalize-first"/>
+            </if>
+            <else>
+              <text term="letter" text-case="capitalize-first"/>
+            </else>
+          </choose>
+        </if>
+      </choose>
+      <text macro="recipient-note"/>
+    </group>
+  </macro>
+  <macro name="contributors-note">
+    <names variable="author">
+      <name and="text" sort-separator=", " delimiter=", " delimiter-precedes-last="never"/>
+      <label form="short" prefix=", "/>
+      <substitute>
+        <names variable="editor"/>
+        <names variable="translator"/>
+        <text macro="title-note"/>
+      </substitute>
+    </names>
+    <text macro="recipient-note"/>
+  </macro>
+  <macro name="title-note">
+    <choose>
+      <if type="bill book graphic legal_case legislation motion_picture report song" match="any">
+        <text variable="title" font-style="italic" text-case="title"/>
+      </if>
+      <else>
+        <text variable="title" quotes="true" text-case="title"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="disambiguate">
+    <choose>
+      <if disambiguate="true">
+        <choose>
+          <if variable="title" match="none">
+            <text macro="issued"/>
+          </if>
+          <else-if type="bill book graphic legal_case legislation motion_picture report song" match="any">
+            <text variable="title" font-style="italic" text-case="title" form="short"/>
+          </else-if>
+          <else>
+            <text variable="title" quotes="true" text-case="title" form="short"/>
+          </else>
+        </choose>
+      </if>
+    </choose>
+  </macro>
+  <macro name="title-sort-substitute">
+    <choose>
+      <if type="bill book graphic legal_case legislation motion_picture report song" match="any">
+        <text variable="title" font-style="italic" text-case="title" form="short"/>
+      </if>
+      <else>
+        <text variable="title" quotes="true" text-case="title" form="short"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="editor-translator">
+    <group delimiter=", ">
+      <choose>
+        <if variable="author">
+          <group delimiter=" ">
+            <choose>
+              <if variable="container-author">
+                <group>
+                  <names variable="container-author">
+                    <label form="verb-short" text-case="lowercase" suffix=" "/>
+                    <name and="text" delimiter=", "/>
+                  </names>
+                </group>
+              </if>
+            </choose>
+          </group>
+          <names variable="editor translator" delimiter=", ">
+            <label form="verb-short" text-case="lowercase" suffix=" "/>
+            <name and="text" delimiter=", "/>
+          </names>
+        </if>
+      </choose>
+    </group>
+  </macro>
+  <macro name="collection-title">
+    <text variable="collection-title" text-case="title"/>
+    <text variable="collection-number" prefix=", "/>
+  </macro>
+  <macro name="locators-note">
+    <choose>
+      <if type="article-journal">
+        <text variable="volume"/>
+      </if>
+      <else-if type="bill book chapter graphic legal_case legislation motion_picture paper-conference report song" match="any">
+        <group delimiter=", ">
+          <text macro="edition-note"/>
+          <group>
+            <number variable="number-of-volumes" form="numeric"/>
+            <text term="volume" form="short" prefix=" " plural="true"/>
+          </group>
+        </group>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="volume">
+    <choose>
+      <if type="article-journal">
+        <text variable="volume"/>
+      </if>
+      <else-if type="bill book chapter graphic legal_case legislation motion_picture paper-conference report song" match="any">
+        <group delimiter=", ">
+          <text macro="edition-note"/>
+          <group>
+            <number variable="number-of-volumes" form="numeric"/>
+            <text term="volume" form="short" prefix=" " plural="true"/>
+          </group>
+        </group>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="issue-note">
+    <choose>
+      <if type="article-journal">
+        <choose>
+          <if variable="volume">
+            <text macro="issued" prefix=" (" suffix=")"/>
+          </if>
+          <else>
+            <text macro="issued" prefix=", "/>
+          </else>
+        </choose>
+      </if>
+      <else-if variable="publisher-place publisher" match="any">
+        <group prefix=" (" suffix=")" delimiter=", ">
+          <group delimiter=" ">
+            <choose>
+              <if variable="title" match="none"/>
+              <else-if type="thesis speech" match="any">
+                <text variable="genre" prefix="unpublished "/>
+              </else-if>
+            </choose>
+            <text macro="event"/>
+          </group>
+          <text macro="publisher"/>
+          <text macro="issued"/>
+        </group>
+      </else-if>
+      <else>
+        <text macro="issued" prefix=", "/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="locators-specific-note">
+    <choose>
+      <if type="bill book chapter graphic legal_case legislation motion_picture paper-conference report song" match="any">
+        <choose>
+          <if is-numeric="volume">
+            <number variable="volume" form="roman" font-variant="small-caps"/>
+          </if>
+        </choose>
+      </if>
+    </choose>
+  </macro>
+  <macro name="container-title-note">
+    <choose>
+      <if type="chapter paper-conference" match="any">
+        <text term="in" text-case="lowercase" suffix=" "/>
+      </if>
+    </choose>
+    <text variable="container-title" font-style="italic"/>
+  </macro>
+  <macro name="edition-note">
+    <choose>
+      <if type="bill book chapter graphic legal_case legislation motion_picture paper-conference report song" match="any">
+        <choose>
+          <if is-numeric="edition">
+            <group delimiter=" ">
+              <number variable="edition" form="ordinal"/>
+              <text term="edition" form="short"/>
+            </group>
+          </if>
+          <else>
+            <text variable="edition"/>
+          </else>
+        </choose>
+      </if>
+    </choose>
+  </macro>
+  <macro name="editor-note">
+    <names variable="editor">
+      <name and="text" sort-separator=", " delimiter=", "/>
+      <label form="short" prefix=", " suffix="."/>
+    </names>
+  </macro>
+  <macro name="translator-note">
+    <names variable="translator">
+      <name and="text" sort-separator=", " delimiter=", "/>
+      <label form="verb-short" prefix=", " suffix="."/>
+    </names>
+  </macro>
+  <macro name="recipient-note">
+    <names variable="recipient" delimiter=", ">
+      <label form="verb" prefix=" " text-case="lowercase" suffix=" "/>
+      <name and="text" delimiter=", "/>
+    </names>
+  </macro>
+  <macro name="recipient-short">
+    <names variable="recipient">
+      <label form="verb" prefix=" " text-case="lowercase" suffix=" "/>
+      <name form="short" and="text" delimiter=", "/>
+    </names>
+  </macro>
+  <macro name="contributors-short">
+    <names variable="author">
+      <name form="short" and="text" sort-separator=", " delimiter=", " delimiter-precedes-last="never"/>
+      <substitute>
+        <names variable="editor"/>
+        <names variable="translator"/>
+        <text macro="title-sort-substitute"/>
+      </substitute>
+    </names>
+    <text macro="recipient-short"/>
+  </macro>
+  <macro name="interviewer-note">
+    <names variable="interviewer" delimiter=", ">
+      <label form="verb" prefix=" " text-case="lowercase" suffix=" "/>
+      <name and="text" delimiter=", "/>
+    </names>
+  </macro>
+  <macro name="locators-newspaper">
+    <choose>
+      <if type="article-newspaper">
+        <group delimiter=", ">
+          <group>
+            <text variable="edition" suffix=" "/>
+            <text term="edition" prefix=" "/>
+          </group>
+          <group>
+            <text term="section" suffix=" "/>
+            <text variable="section"/>
+          </group>
+        </group>
+      </if>
+    </choose>
+  </macro>
+  <macro name="event">
+    <group>
+      <text term="presented at" suffix=" "/>
+      <text variable="event"/>
+    </group>
+  </macro>
+  <macro name="publisher">
+    <group delimiter=": ">
+      <text variable="publisher-place"/>
+      <text variable="publisher"/>
+    </group>
+  </macro>
+  <macro name="issued">
+    <choose>
+      <if type="graphic report article-newspaper article-magazine personal_communication" match="any">
+        <date variable="issued">
+          <date-part name="day" suffix=" "/>
+          <date-part name="month" suffix=" "/>
+          <date-part name="year"/>
+        </date>
+      </if>
+      <else>
+        <date variable="issued">
+          <date-part name="year"/>
+        </date>
+      </else>
+    </choose>
+  </macro>
+  <macro name="pages">
+    <choose>
+      <if type="article-journal">
+        <text variable="page" prefix=", "/>
+      </if>
+      <else>
+        <choose>
+          <if variable="volume">
+            <text variable="page" prefix=", "/>
+          </if>
+          <else>
+            <label variable="page" form="short" prefix=", " suffix=" "/>
+            <text variable="page"/>
+          </else>
+        </choose>
+      </else>
+    </choose>
+  </macro>
+  <macro name="point-locators">
+    <text macro="pages"/>
+    <choose>
+      <if variable="page">
+        <group prefix=" (" suffix=")">
+          <label variable="locator" form="short" suffix=" "/>
+          <text variable="locator"/>
+        </group>
+      </if>
+      <else>
+        <label variable="locator" form="short" prefix=", " suffix=" "/>
+        <text variable="locator"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="point-locators-subsequent">
+    <label variable="locator" form="short" prefix=", " suffix=" "/>
+    <text variable="locator"/>
+  </macro>
+  <macro name="archive-note">
+    <group delimiter=", ">
+      <text variable="archive_location"/>
+      <text variable="archive"/>
+      <text variable="archive-place"/>
+    </group>
+  </macro>
+  <macro name="access-note">
+    <group delimiter=", ">
+      <choose>
+        <if type="article-journal bill chapter legal_case legislation paper-conference" match="none">
+          <text macro="archive-note" prefix=", "/>
+        </if>
+      </choose>
+    </group>
+    <choose>
+      <if variable="DOI">
+        <text variable="DOI" prefix=" &lt;doi:" suffix="&gt;"/>
+      </if>
+      <else>
+        <choose>
+          <if variable="URL">
+            <text variable="URL" prefix=" &lt;" suffix="&gt;"/>
+            <group prefix=" [" suffix="]">
+              <text term="accessed" text-case="lowercase"/>
+              <date variable="accessed">
+                <date-part name="day" prefix=" "/>
+                <date-part name="month" prefix=" "/>
+                <date-part name="year" prefix=" "/>
+              </date>
+            </group>
+          </if>
+        </choose>
+      </else>
+    </choose>
+  </macro>
+  <citation et-al-min="4" et-al-use-first="1" disambiguate-add-names="true" disambiguate-add-givenname="true">
+    <layout prefix="" suffix="." delimiter="; ">
+      <choose>
+        <if position="subsequent">
+          <group delimiter=", ">
+            <text macro="contributors-short"/>
+            <text macro="disambiguate"/>
+            <text macro="locators-specific-note"/>
+          </group>
+          <text macro="point-locators-subsequent"/>
+        </if>
+        <else>
+          <group delimiter=", ">
+            <text macro="contributors-note"/>
+            <text macro="title-note"/>
+            <text macro="container-title-note"/>
+            <text macro="editor-translator"/>
+            <text macro="collection-title"/>
+            <text macro="locators-note"/>
+          </group>
+          <text macro="issue-note"/>
+          <text macro="locators-specific-note" prefix=", "/>
+          <text macro="locators-newspaper" prefix=", "/>
+          <text macro="point-locators"/>
+          <text macro="access-note"/>
+        </else>
+      </choose>
+    </layout>
+  </citation>
+  <bibliography hanging-indent="true" et-al-min="7" et-al-use-first="6" subsequent-author-substitute="---">
+    <sort>
+      <key macro="author"/>
+      <key variable="title"/>
+    </sort>
+    <layout>
+      <group delimiter=", ">
+        <text macro="author"/>
+        <text macro="title-note"/>
+        <text macro="container-title-note"/>
+        <text macro="editor-translator"/>
+        <text macro="collection-title"/>
+        <text macro="volume"/>
+      </group>
+      <text macro="issue-note"/>
+      <text macro="locators-specific-note" prefix=", "/>
+      <text macro="locators-newspaper" prefix=", "/>
+      <text macro="pages"/>
+      <text macro="access-note"/>
+    </layout>
+  </bibliography>
+</style>
diff --git a/tests/test-pandoc-citeproc.hs b/tests/test-pandoc-citeproc.hs
--- a/tests/test-pandoc-citeproc.hs
+++ b/tests/test-pandoc-citeproc.hs
@@ -39,7 +39,7 @@
   putStrLn $ show numpasses ++ " passed; " ++ show numfailures ++
               " failed; " ++ show numskipped ++ " skipped; " ++
               show numerrors ++ " errored."
-  exitWith $ if numfailures == 0
+  exitWith $ if numfailures == 0 && numerrors == 0
                 then ExitSuccess
                 else ExitFailure $ numfailures + numerrors
 
