diff --git a/changelog b/changelog
--- a/changelog
+++ b/changelog
@@ -1,3 +1,39 @@
+pandoc-citeproc (0.15)
+
+  * Support BibLaTeX extended name format (#266).
+  * Add refOtherIds field to Reference, and populate it with
+    the 'ids' field in biblatex (#356).  Search on refOtherIds
+    as well as refId when looking for references.
+  * Allow the extent of the locator to be explicitly indicated
+    using curly braces, as in:  [@key{67}], [@key, {p. 95 A 3}, suffix]
+    (Cormac Relf).
+  * Parse balanced brackets in locators like '1(2)(a)(i)' (Cormac Relf).
+    This is useful for citing legislation. It is necessary to be more liberal
+    in locator parsing because some styles put other elements after a locator,
+    like short titles in the case of AGLC, and if you can't parse a locator,
+    it gets rendered after, or worse, split in half.
+  * Drop ibid-with-locator when prev cite has same locator and label (#241,
+    Cormac Relf).
+    ```
+    [@key]      => "first"
+    [@key]      => "ibid"
+    [@key, 53]  => "ibid-with-locator"
+    [@key, 123] => "ibid-with-locator"
+    [@key, 123] => "ibid"
+    [@key]      => "subsequent"
+    ```
+    See http://docs.citationstyles.org/en/stable/specification.html#locators
+  * Fix bug wherein nonbreaking spaces classed a name as East Asian,
+    so that spaces aren't used between given and family (#365).
+    Also regularized logic for detecting "byzantine" names
+    (those that get the space).  Now a name is treated as
+    byzantine if there are any byzantine characters in it.
+    Previously some checks required all byzantine characters.
+  * Add mktest.sh for wrangling test cases (#364, Cormac Relf).
+  * Update pandoc-citeproc man page.
+  * Update locales el-GR, fi-FI.
+  * Add CONTRIBUTING.md.
+
 pandoc-citeproc (0.14.8.1)
 
   * Avoid putting a space after nonbreaking space at end of prefix.
diff --git a/locales/locales-el-GR.xml b/locales/locales-el-GR.xml
--- a/locales/locales-el-GR.xml
+++ b/locales/locales-el-GR.xml
@@ -172,12 +172,12 @@
     <term name="note" form="short">σημ.</term>
     <term name="opus" form="short">έργ.</term>
     <term name="page" form="short">
-      <single>σ</single>
-      <multiple>σσ</multiple>
+      <single>σ.</single>
+      <multiple>σσ.</multiple>
     </term>
     <term name="number-of-pages" form="short">
-      <single>σ</single>
-      <multiple>σσ</multiple>
+      <single>σ.</single>
+      <multiple>σσ.</multiple>
     </term>
     <term name="paragraph" form="short">παρ.</term>
     <term name="part" form="short">μέρ.</term>
diff --git a/locales/locales-fi-FI.xml b/locales/locales-fi-FI.xml
--- a/locales/locales-fi-FI.xml
+++ b/locales/locales-fi-FI.xml
@@ -70,8 +70,8 @@
     <term name="version">versio</term>
 
     <!-- ANNO DOMINI; BEFORE CHRIST -->
-    <term name="ad">eaa.</term>
-    <term name="bc">jaa.</term>
+    <term name="ad">jaa.</term>
+    <term name="bc">eaa.</term>
 
     <!-- PUNCTUATION -->
     <term name="open-quote">”</term>
diff --git a/man/man1/pandoc-citeproc.1 b/man/man1/pandoc-citeproc.1
--- a/man/man1/pandoc-citeproc.1
+++ b/man/man1/pandoc-citeproc.1
@@ -1,7 +1,7 @@
 .\"t
 .\" Automatically generated by Pandoc 2.4
 .\"
-.TH "pandoc\-citeproc" "1" "2018-10-19" "pandoc-citeproc 0.14.7" ""
+.TH "pandoc\-citeproc" "1" "2018-11-13" "pandoc-citeproc 0.15" ""
 .hy
 .SH NAME
 .PP
@@ -34,7 +34,7 @@
 .IP
 .nf
 \f[C]
-pandoc\ \-\-filter\ pandoc\-citeproc\ input.md\ \-s\ \-o\ output.html
+pandoc \-\-filter pandoc\-citeproc input.md \-s \-o output.html
 \f[R]
 .fi
 .PP
@@ -117,8 +117,8 @@
 T}
 .TE
 .PP
-Note that \f[C]\&.bib\f[R] can generally be used with both BibTeX and
-BibLaTeX files, but you can use \f[C]\&.bibtex\f[R] to force BibTeX.
+Note that \f[C].bib\f[R] can generally be used with both BibTeX and
+BibLaTeX files, but you can use \f[C].bibtex\f[R] to force BibTeX.
 .RE
 .TP
 .B \f[C]references\f[R]
@@ -130,17 +130,17 @@
 .IP
 .nf
 \f[C]
-\-\ id:\ doe2006
-\ \ author:
-\ \ \ \ family:\ Doe
-\ \ \ \ given:\ [John,\ F.]
-\ \ title:\ Article
-\ \ page:\ 33\-34
-\ \ issued:
-\ \ \ \ year:\ 2006
-\ \ type:\ article\-journal
-\ \ volume:\ 6
-\ \ container\-title:\ Journal\ of\ Generic\ Studies
+\- id: doe2006
+  author:
+    family: Doe
+    given: [John, F.]
+  title: Article
+  page: 33\-34
+  issued:
+    year: 2006
+  type: article\-journal
+  volume: 6
+  container\-title: Journal of Generic Studies
 \f[R]
 .fi
 .PP
@@ -160,15 +160,11 @@
 \f[C]$HOME/.pandoc/default.csl\f[R], and if this is not present, it will
 use \f[C]chicago\-author\-date.csl\f[R], looking first in
 \f[C]$HOME/.csl\f[R] and then in its own data files.
-.RS
-.RE
 .TP
 .B \f[C]link\-citations\f[R]
 If this has a true value, citations in author\-date and numerical styles
 will be hyperlinked to their corresponding bibliography entries.
 The default is not to add hyperlinks.
-.RS
-.RE
 .TP
 .B \f[C]citation\-abbreviations\f[R]
 Path to a CSL abbreviations JSON file.
@@ -178,7 +174,7 @@
 Windows 7).
 The format is described
 here (http://citationstylist.org/2011/10/19/abbreviations-for-zotero-test-release).
-Abbreviations are only output if, in the \f[C]\&.csl\f[R] file,
+Abbreviations are only output if, in the \f[C].csl\f[R] file,
 \f[C]form=\[dq]short\[dq]\f[R] is set on the element that renders the
 variable.
 .RS
@@ -187,13 +183,13 @@
 .IP
 .nf
 \f[C]
-{\ \[dq]default\[dq]:\ {
-\ \ \ \ \[dq]container\-title\[dq]:\ {
-\ \ \ \ \ \ \ \ \ \ \ \ \[dq]Lloyd\[aq]s\ Law\ Reports\[dq]:\ \[dq]Lloyd\[aq]s\ Rep\[dq],
-\ \ \ \ \ \ \ \ \ \ \ \ \[dq]Estates\ Gazette\[dq]:\ \[dq]EG\[dq],
-\ \ \ \ \ \ \ \ \ \ \ \ \[dq]Scots\ Law\ Times\[dq]:\ \[dq]SLT\[dq]
-\ \ \ \ }
-\ \ }
+{ \[dq]default\[dq]: {
+    \[dq]container\-title\[dq]: {
+            \[dq]Lloyd\[aq]s Law Reports\[dq]: \[dq]Lloyd\[aq]s Rep\[dq],
+            \[dq]Estates Gazette\[dq]: \[dq]EG\[dq],
+            \[dq]Scots Law Times\[dq]: \[dq]SLT\[dq]
+    }
+  }
 }
 \f[R]
 .fi
@@ -208,16 +204,12 @@
 (For backwards compatibility, the field \f[C]locale\f[R] can be used
 instead of \f[C]lang\f[R], but this \f[C]lang\f[R] should be used going
 forward.)
-.RS
-.RE
 .TP
 .B \f[C]suppress\-bibliography\f[R]
 If this has a true value, the bibliography will be left off.
 Otherwise a bibliography will be inserted into each Div element with id
 \f[C]refs\f[R].
 If there is no such Div, one will be created at the end of the document.
-.RS
-.RE
 .TP
 .B \f[C]reference\-section\-title\f[R]
 If this has a value, a section header with this title will be added
@@ -225,20 +217,15 @@
 If \f[C]reference\-section\-title\f[R] is not specified and the document
 ends with a section header, this final header will be treated as the
 bibliography header.
-.RS
-.RE
 .TP
 .B \f[C]notes\-after\-punctuation\f[R]
 If true (the default), pandoc will put footnote citations after
 following punctuation.
-For example, if the source contains
-\f[C]blah\ blah\ [\[at]jones99].\f[R], the result will look like
-\f[C]blah\ blah.[\[ha]1]\f[R], with the note moved after the period and
-the space collapsed.
+For example, if the source contains \f[C]blah blah [\[at]jones99].\f[R],
+the result will look like \f[C]blah blah.[\[ha]1]\f[R], with the note
+moved after the period and the space collapsed.
 If false, the space will still be collapsed, but the footnote will not
 be moved after the punctuation.
-.RS
-.RE
 .PP
 The metadata must contain either \f[C]references\f[R] or
 \f[C]bibliography\f[R] or both as a source of references.
@@ -280,15 +267,11 @@
 CSL implementations.
 .SH OPTIONS
 .TP
-.B \f[C]\-y,\ \-\-bib2yaml\f[R]
+.B \f[C]\-y, \-\-bib2yaml\f[R]
 Convert bibliography to YAML suitable for inclusion in pandoc metadata.
-.RS
-.RE
 .TP
-.B \f[C]\-j,\ \-\-bib2json\f[R]
+.B \f[C]\-j, \-\-bib2json\f[R]
 Convert bibliography to CSL JSON suitable for import into Zotero.
-.RS
-.RE
 .TP
 .B \f[C]\-f\f[R] \f[I]FORMAT\f[R], \f[C]\-\-format=\f[R]\f[I]FORMAT\f[R]
 Specify format of bibliography to be converted.
@@ -296,36 +279,24 @@
 \f[C]endnote\f[R], \f[C]endnotexml\f[R], \f[C]isi\f[R],
 \f[C]medline\f[R], \f[C]copac\f[R], \f[C]mods\f[R], \f[C]nbib\f[R], and
 \f[C]json\f[R].
-.RS
-.RE
 .TP
-.B \f[C]\-h,\ \-\-help\f[R]
+.B \f[C]\-h, \-\-help\f[R]
 Print usage information.
-.RS
-.RE
 .TP
 .B \f[C]\-\-man\f[R]
 Print the man page in groff man format.
 To get a plain text version,
-\f[C]pandoc\-citeproc\ \-\-man\ |\ groff\ \-mman\ \-Tutf8\f[R].
-To \f[C]pandoc\-citeproc\ \-\-man\ |\ groff\ \-mman\ \-Thtml\f[R].
-.RS
-.RE
+\f[C]pandoc\-citeproc \-\-man | groff \-mman \-Tutf8\f[R].
+To \f[C]pandoc\-citeproc \-\-man | groff \-mman \-Thtml\f[R].
 .TP
 .B \f[C]\-\-license\f[R]
 Print the license.
-.RS
-.RE
 .TP
-.B \f[C]\-q,\ \-\-quiet\f[R]
+.B \f[C]\-q, \-\-quiet\f[R]
 Silence all warnings.
-.RS
-.RE
 .TP
-.B \f[C]\-V,\ \-\-version\f[R]
+.B \f[C]\-V, \-\-version\f[R]
 Print version.
-.RS
-.RE
 .SH NOTES
 .SS General
 .PP
@@ -343,7 +314,7 @@
 fields) and
 <http://citationstyles.org/downloads/specification.html#appendix-iv-variables>
 (which does contain comments).
-.SS Titles: Title vs.\~Sentence Case
+.SS Titles: Title vs.\ Sentence Case
 .PP
 If you are using a bibtex or biblatex bibliography, then observe the
 following rules:
@@ -364,7 +335,7 @@
 .IP
 .nf
 \f[C]
-title\ =\ {My\ Dinner\ with\ {Andre}}
+title = {My Dinner with {Andre}}
 \f[R]
 .fi
 .RE
@@ -375,7 +346,7 @@
 .IP
 .nf
 \f[C]
-title\ =\ {Spin\ Wave\ Dispersion\ on\ the\ {nm}\ Scale}
+title = {Spin Wave Dispersion on the {nm} Scale}
 \f[R]
 .fi
 .PP
@@ -402,11 +373,11 @@
 .IP
 .nf
 \f[C]
-Spin\ wave\ dispersion\ on\ the\ <span\ class=\[dq]nocase\[dq]>nm</span>\ scale
+Spin wave dispersion on the <span class=\[dq]nocase\[dq]>nm</span> scale
 \f[R]
 .fi
 .RE
-.SS Conference Papers, Published vs.\~Unpublished
+.SS Conference Papers, Published vs.\ Unpublished
 .PP
 For a formally published conference paper, use the biblatex entry type
 \f[C]inproceedings\f[R] (which will be mapped to CSL
@@ -421,7 +392,7 @@
 \f[C]eventtitle\f[R] field (this entry type will be mapped to CSL
 \f[C]speech\f[R]).
 Use the biblatex \f[C]type\f[R] field to indicate the type,
-e.g.\~\[lq]Paper\[rq], or \[lq]Poster\[rq].
+e.g.\ \[lq]Paper\[rq], or \[lq]Poster\[rq].
 \f[C]venue\f[R] and \f[C]eventdate\f[R] may be useful too, though
 \f[C]eventdate\f[R] will not be rendered by most CSL styles.
 Note that \f[C]venue\f[R] is for the event\[cq]s venue, unlike
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.14.8.1
+version:            0.15
 cabal-version:      1.12
 synopsis:           Supports using pandoc with citeproc
 
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
@@ -375,7 +375,7 @@
                     _           -> maybe "" show . (safeRead :: String -> Maybe Int)
 
       roman :: Int -> String
-      roman     = foldr (++) [] . reverse . map (uncurry (!!)) . zip romanList .
+      roman     = concat . reverse . zipWith (!!) romanList .
                   map (readNum . return) . take 4 .
                   reverse . show
       romanList = [[ "", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix" ]
diff --git a/src/Text/CSL/Eval/Date.hs b/src/Text/CSL/Eval/Date.hs
--- a/src/Text/CSL/Eval/Date.hs
+++ b/src/Text/CSL/Eval/Date.hs
@@ -175,19 +175,23 @@
 ordinal :: [CslTerm] -> String -> Int -> String
 ordinal ts v s
     | s < 10        = let a = termPlural (getWith1 (show s)) in
-                      if  a == [] then setOrd (term []) else show s ++ a
+                      if  null a then setOrd (term []) else show s ++ a
     | s < 100       = let a = termPlural (getWith2 (show s))
                           b = getWith1 [last (show s)] in
-                      if  a /= []
+                      if  not (null a)
                       then show s ++ a
-                      else if termPlural b == [] || (termMatch b /= [] && termMatch b /= "last-digit")
-                           then setOrd (term []) else setOrd b
+                      else if null (termPlural b) ||
+                              (not (null (termMatch b)) &&
+                               termMatch b /= "last-digit")
+                           then setOrd (term [])
+                           else setOrd b
     | otherwise     = let a = getWith2  last2
                           b = getWith1 [last (show s)] in
-                      if termPlural a /= [] && termMatch a /= "whole-number"
+                      if not (null (termPlural a)) &&
+                         termMatch a /= "whole-number"
                       then setOrd a
                       else if null (termPlural b) ||
-                              (termMatch b /= [] &&
+                              (not (null (termMatch b)) &&
                                termMatch b /= "last-digit")
                            then setOrd (term [])
                            else setOrd b
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
@@ -278,7 +278,7 @@
                      $ splitStrWhen (=='-') x
 
       sortSep g s = when_ g $ separator ++ addAffixes (g <+> s) "given" mempty
-      separator   = if any isByzantine (stringify family)
+      separator   = if isByzantineFamily
                        then
                          if null (getOptionVal "sort-separator" ops)
                             then [OPan [Str ",", Space]]
@@ -323,6 +323,7 @@
                       (c >= '\x021a' && c <= '\x021b') ||
                       (c >= '\x202a' && c <= '\x202e')
 
+      isByzantineFamily = any isByzantine (stringify family)
       shortName = oPan' (unFormatted $ nondropping <+> family) (form "family")
 
       longName g
@@ -338,7 +339,7 @@
                                                           in oPan' (unFormatted fam) (form "family") <> sortSep g par <> suffCom
         | otherwise = let fam = addAffixes (dropping <+> nondropping <+> family) "family" suff
                           gvn = oPan' (unFormatted g) (form "given")
-                      in  if all isByzantine $ stringify $ unFormatted family
+                      in  if isByzantineFamily
                           then gvn <++> fam
                           else fam <> gvn
 
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
@@ -38,7 +38,7 @@
 import           Text.CSL.Exception     (CiteprocException (ErrorReadingBib, ErrorReadingBibFile))
 import           Text.CSL.Parser        (parseLocale)
 import           Text.CSL.Reference
-import           Text.CSL.Style         (Agent (..), CslTerm (..),
+import           Text.CSL.Style         (Agent (..), emptyAgent, CslTerm (..),
                                          Formatted (..), Locale (..))
 import           Text.CSL.Util          (onBlocks, protectCase, safeRead,
                                          splitStrWhen, trim, unTitlecase)
@@ -1009,7 +1009,7 @@
 
 toAuthorList :: Options -> [Block] -> Bib [Agent]
 toAuthorList opts [Para xs] =
-  mapM (toAuthor opts) $ splitByAnd xs
+  filter (/= emptyAgent) <$> mapM (toAuthor opts) (splitByAnd xs)
 toAuthorList opts [Plain xs] = toAuthorList opts [Para xs]
 toAuthorList _ _ = mzero
 
@@ -1036,6 +1036,25 @@
           , commaSuffix     = False
           , parseNames      = False
           }
+ -- extended BibLaTeX name format - see #266
+toAuthor _ ils@(Str ys:_) | '=' `elem` ys = do
+  let commaParts = splitWhen (== Str ",")
+                   $ splitStrWhen (\c -> c == ',' || c == '=' || c == '\160')
+                   $ ils
+  let addPart ag (Str "given" : Str "=" : xs) =
+        ag{ givenName = givenName ag ++ [Formatted xs] }
+      addPart ag (Str "family" : Str "=" : xs) =
+        ag{ familyName = Formatted xs }
+      addPart ag (Str "prefix" : Str "=" : xs) =
+        ag{ droppingPart = Formatted xs }
+      addPart ag (Str "useprefix" : Str "=" : Str "true" : _) =
+        ag{ nonDroppingPart = droppingPart ag, droppingPart = mempty }
+      addPart ag (Str "suffix" : Str "=" : xs) =
+        ag{ nameSuffix = Formatted xs }
+      addPart ag (Space : xs) = addPart ag xs
+      addPart ag _ = ag
+  return $ foldl' addPart emptyAgent commaParts
+
 -- First von Last
 -- von Last, First
 -- von Last, Jr ,First
@@ -1227,6 +1246,8 @@
                                          Lang "en" _ -> caseTransform
                                          _           -> False }
   id' <- asks identifier
+  otherIds <- (map trim . splitWhen (==',') <$> getRawField "ids")
+                <|> return []
   et <- asks entryType
   guard $ et /= "xdata"
   opts <- (parseOptions <$> getRawField "options") <|> return []
@@ -1521,6 +1542,7 @@
 
   return $ emptyReference
          { refId               = Literal id'
+         , refOtherIds         = map Literal otherIds
          , refType             = reftype
          , author              = author'
          , editor              = editor'
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
@@ -90,8 +90,7 @@
    splitUp :: [(Int, [String])] -> [(Int, String)]
    splitUp = concatMap (\(n,ss) -> map (n,) ss)
    go :: (Int, String) -> M.Map String Int -> M.Map String Int
-   go (notenumber, citeid) notemap =
-     M.insert citeid notenumber notemap
+   go (notenumber, citeid) = M.insert citeid notenumber
 
 -- if document contains a Div with id="refs", insert
 -- references as its contents.  Otherwise, insert references
@@ -157,8 +156,7 @@
 -- if the 'nocite' Meta field contains a citation with id = '*',
 -- create a cite with to all the references.
 mkNociteWildcards :: [Reference] -> [[Citation]] -> [[Citation]]
-mkNociteWildcards refs nocites =
-  map expandStar nocites
+mkNociteWildcards refs = map expandStar
   where expandStar cs =
          case [c | c <- cs
                  , citationId c == "*"] of
@@ -271,7 +269,7 @@
 #if MIN_VERSION_tagsoup(0,13,0)
                                        Just s  -> s ++ decodeEntities ws
 #else
-                                       Just c  -> [c] ++ decodeEntities ws
+                                       Just c  -> c   : decodeEntities ws
 #endif
                                        Nothing -> '&' : decodeEntities xs
            _      -> '&' : decodeEntities xs
@@ -389,7 +387,7 @@
       removeLeadingPunct zs = zs
   in  f xs' ++ ys
 
--- | Retrieve all citations from a 'Pandoc' docuument. To be used with
+-- | Retrieve all citations from a 'Pandoc' document. To be used with
 -- 'query'.
 getCitation :: Inline -> [[Citation]]
 getCitation i | Cite t _ <- i = [t]
@@ -432,42 +430,195 @@
                      , CSL.citeHash       = citationHash c
                      }
 
+splitInp :: [Inline] -> [Inline]
+splitInp = splitStrWhen (\c -> splitOn c || isSpace c)
+  where
+      splitOn ':' = False
+      splitOn c   = isPunctuation c
+
 locatorWords :: LocatorMap -> [Inline] -> (String, String, [Inline])
 locatorWords locMap inp =
-  case parse (pLocatorWords locMap) "suffix" $
-         splitStrWhen (\c -> isLocatorPunct c || isSpace c) inp of
+  case parse (pLocatorWords locMap) "suffix" $ splitInp inp of
        Right r -> r
        Left _  -> ("","",inp)
 
+-- Some terminology
+-- ----------------
+-- Word       => 89
+--               12-15
+--               13(a)(i)-(iv)
+--               [1.2.5]
+--
+-- Integrated => [@citekey, 89]
+--               [@citekey, p. 40, 41, 89-199, suffix]
+-- Delimited  => [@citekey{89}]
+--               [@citekey, {p. literally anything except unbalanced curly quotes}, suffix]
+--
+-- When parsing integrated locators you have to be careful not to include
+-- 'suffix' in the locator, so that means pretty strict control over when
+-- you're allowed to use NO digits in a word. [@citekey, p. 40(a) (bcd)] will
+-- stop parsing the locator after (a). You also have to be careful not to parse
+-- random terms like 'and' in en-US as citeLabels, which means careful control
+-- over what must come directly after any label string (via notFollowedBy).
+--
+-- With delimited locators, it's a different story. Parse as long a locator
+-- label as you can find in the terms map, then include EVERYTHING in the outer
+-- {} braces.
+--
+-- Ultimately the complexity is driven by wanting as many locator words as
+-- possible being parsed in the integrated style, because it fits with the
+-- aims of Markdown (being readable). Ideally, anything except a word with
+-- neither roman numerals nor arabic digits can be integrated. Some
+-- counter-examples:
+-- a
+-- (a)(b)(c)
+-- (hello)
+
 pLocatorWords :: LocatorMap -> Parsec [Inline] st (String, String, [Inline])
 pLocatorWords locMap = do
-  (la,lo) <- pLocator locMap
+  optional $ pMatchChar "," (== ',')
+  optional pSpace
+  (la, lo) <- pLocatorDelimited locMap <|> pLocatorIntegrated locMap
   s <- getInput -- rest is suffix
-  return (la, lo, s)
+  -- need to trim, otherwise "p. 9" and "9" will have 'different' locators later on
+  -- i.e. the first one will be " 9"
+  return (la, trim lo, s)
 
-pMatch :: (Inline -> Bool) -> Parsec [Inline] st Inline
-pMatch condition = try $ do
-  t <- anyToken
-  guard $ condition t
-  return t
+pLocatorDelimited :: LocatorMap -> Parsec [Inline] st (String, String)
+pLocatorDelimited locMap = try $ do
+  _ <- pMatchChar "{" (== '{')
+  skipMany pSpace -- gobble pre-spaces so label doesn't try to include them
+  (la, _) <- pLocatorLabelDelimited locMap
+  -- we only care about balancing {} and [] (because of the outer [] scope);
+  -- the rest can be anything
+  let inner = do { t <- anyToken; return (True, stringify t) }
+  gs <- many (pBalancedBraces [('{','}'), ('[',']')] inner)
+  _ <- pMatchChar "}" (== '}')
+  let lo = concatMap snd gs
+  return (la, lo)
 
-pSpace :: Parsec [Inline] st Inline
-pSpace = pMatch (\t -> isSpacy t || t == Str "\160")
+pLocatorLabelDelimited :: LocatorMap -> Parsec [Inline] st (String, Bool)
+pLocatorLabelDelimited locMap
+  = pLocatorLabel' locMap lim <|> return ("page", True)
+    where
+        lim = stringify <$> anyToken
 
-pLocator :: LocatorMap -> Parsec [Inline] st (String, String)
-pLocator locMap = try $ do
-  optional $ pMatch (== Str ",")
-  optional pSpace
-  la <- try (do ts <- many1 (notFollowedBy (pWordWithDigits True) >> anyToken)
-                case M.lookup (trim (stringify ts)) locMap of
-                       Just l  -> return l
-                       Nothing -> mzero)
-      <|> (lookAhead pDigit >> return "page")
-  g <- pWordWithDigits True
-  gs <- many (pWordWithDigits False)
+pLocatorIntegrated :: LocatorMap -> Parsec [Inline] st (String, String)
+pLocatorIntegrated locMap = try $ do
+  (la, wasImplicit) <- pLocatorLabelIntegrated locMap
+  -- if we got the label implicitly, we have presupposed the first one is going
+  -- to have a digit, so guarantee that. You _can_ have p. (a) because you
+  -- specified it.
+  let modifier = if wasImplicit
+                    then requireDigits
+                    else requireRomansOrDigits
+  g <- try $ pLocatorWordIntegrated (not wasImplicit) >>= modifier
+  gs <- many (try $ pLocatorWordIntegrated False >>= modifier)
   let lo = concat (g:gs)
   return (la, lo)
 
+pLocatorLabelIntegrated :: LocatorMap -> Parsec [Inline] st (String, Bool)
+pLocatorLabelIntegrated locMap
+  = pLocatorLabel' locMap lim <|> (lookAhead digital >> return ("page", True))
+    where
+      lim = try $ pLocatorWordIntegrated True >>= requireRomansOrDigits
+      digital = try $ pLocatorWordIntegrated True >>= requireDigits
+
+pLocatorLabel' :: LocatorMap -> Parsec [Inline] st String -> Parsec [Inline] st (String, Bool)
+pLocatorLabel' locMap lim = go ""
+    where
+      -- grow the match string until we hit the end
+      -- trying to find the largest match for a label
+      go acc = try $ do
+          -- advance at least one token each time
+          -- the pathological case is "p.3"
+          t <- anyToken
+          ts <- manyTill anyToken (try $ lookAhead lim)
+          let s = acc ++ stringify (t:ts)
+          case M.lookup (trim s) locMap of
+            -- try to find a longer one, or return this one
+            Just l -> go s <|> return (l, False)
+            Nothing -> go s
+
+-- hard requirement for a locator to have some real digits in it
+requireDigits :: (Bool, String) -> Parsec [Inline] st String
+requireDigits (_, s) = if not (any isDigit s)
+                          then fail "requireDigits"
+                          else return s
+
+-- soft requirement for a sequence with some roman or arabic parts
+-- (a)(iv) -- because iv is roman
+-- 1(a)  -- because 1 is an actual digit
+-- NOT: a, (a)-(b), hello, (some text in brackets)
+requireRomansOrDigits :: (Bool, String) -> Parsec [Inline] st String
+requireRomansOrDigits (d, s) = if not d
+                                  then fail "requireRomansOrDigits"
+                                  else return s
+
+pLocatorWordIntegrated :: Bool -> Parsec [Inline] st (Bool, String)
+pLocatorWordIntegrated isFirst = try $ do
+  punct <- if isFirst
+              then return ""
+              else stringify <$> option (Str "") pLocatorSep
+  sp <- option "" (pSpace >> return " ")
+  (dig, s) <- pBalancedBraces [('(',')'), ('[',']'), ('{','}')] pPageSeq
+  return (dig, punct ++ sp ++ s)
+
+-- we want to capture:  123, 123A, C22, XVII, 33-44, 22-33; 22-11
+--                      34(1), 34A(A), 34(1)(i)(i), (1)(a)
+--                      [17], [17]-[18], '591 [84]'
+--                      (because CSL cannot pull out individual pages/sections
+--                      to wrap in braces on a per-style basis)
+pBalancedBraces :: [(Char, Char)] -> Parsec [Inline] st (Bool, String) -> Parsec [Inline] st (Bool, String)
+pBalancedBraces braces p = try $ do
+  ss <- many1 surround
+  return $ anyWereDigitLike ss
+  where
+      except = notFollowedBy pBraces >> p
+      -- outer and inner
+      surround = foldl (\a (open, close) -> sur open close except <|> a) except braces
+
+      isc c = stringify <$> pMatchChar [c] (== c)
+
+      sur c c' m = try $ do
+          (d, mid) <- between (isc c) (isc c') (option (False, "") m)
+          return (d, [c] ++  mid ++ [c'])
+
+      flattened = concatMap (\(o, c) -> [o, c]) braces
+      pBraces = pMatchChar "braces" (`elem` flattened)
+
+-- YES 1, 1.2, 1.2.3
+-- NO  1., 1.2. a.6
+-- can't use sepBy because we want to leave trailing .s
+pPageSeq :: Parsec [Inline] st (Bool, String)
+pPageSeq = oneDotTwo <|> withPeriod
+  where
+      oneDotTwo = do
+          u <- pPageUnit
+          us <- many withPeriod
+          return $ anyWereDigitLike (u:us)
+      withPeriod = try $ do
+          -- .2
+          p <- pMatchChar "." (== '.')
+          u <- try pPageUnit
+          return (fst u, stringify p ++ snd u)
+
+anyWereDigitLike :: [(Bool, String)] -> (Bool, String)
+anyWereDigitLike as = (any fst as, concatMap snd as)
+
+pPageUnit :: Parsec [Inline] st (Bool, String)
+pPageUnit = roman <|> plainUnit
+  where
+      -- roman is a 'digit'
+      roman = (True,) <$> pRoman
+      plainUnit = do
+          ts <- many1 (notFollowedBy pSpace >>
+                       notFollowedBy pLocatorPunct >>
+                       anyToken)
+          let s = stringify ts
+          -- otherwise look for actual digits or -s
+          return (any isDigit s, s)
+
 pRoman :: Parsec [Inline] st String
 pRoman = try $ do
   t <- anyToken
@@ -477,37 +628,37 @@
                       Just _  -> return xs
        _      -> mzero
 
--- we want to capture:  123, 123A, C22, XVII, 33-44, 22-33; 22-11
-pWordWithDigits :: Bool -> Parsec [Inline] st String
-pWordWithDigits isfirst = try $ do
-  punct <- if isfirst
-              then return ""
-              else stringify `fmap` pLocatorPunct
-  sp <- option "" (pSpace >> return " ")
-  s <-  pRoman <|>
-        try (do ts <- many1 (notFollowedBy pSpace >>
-                             notFollowedBy pLocatorPunct >>
-                             anyToken)
-                let ts' = stringify ts
-                guard (any isDigit ts')
-                return ts')
-  return $ punct ++ sp ++ s
-
-pDigit :: Parsec [Inline] st ()
-pDigit = do
-  t <- anyToken
-  case t of
-      Str (d:_) | isDigit d -> return ()
-      _         -> mzero
+isLocatorPunct :: Char -> Bool
+isLocatorPunct '-' = False -- page range
+isLocatorPunct ':' = False -- vol:page-range hack
+isLocatorPunct c   = isPunctuation c -- includes [{()}]
 
 pLocatorPunct :: Parsec [Inline] st Inline
-pLocatorPunct = pMatch isLocatorPunct'
-  where isLocatorPunct' (Str [c]) = isLocatorPunct c
-        isLocatorPunct' _         = False
+pLocatorPunct = pMatchChar "punctuation" isLocatorPunct
 
-isLocatorPunct :: Char -> Bool
-isLocatorPunct ':' = False
-isLocatorPunct c   = isPunctuation c
+pLocatorSep :: Parsec [Inline] st Inline
+pLocatorSep = pMatchChar "locator separator" isLocatorSep
+
+isLocatorSep :: Char -> Bool
+isLocatorSep ',' = True
+isLocatorSep ';' = True
+isLocatorSep _   = False
+
+pMatchChar :: String -> (Char -> Bool) -> Parsec [Inline] st Inline
+pMatchChar msg f = pMatch msg mc
+    where
+        mc (Str [c]) = f c
+        mc _         = False
+
+pSpace :: Parsec [Inline] st Inline
+pSpace = pMatch "' '" (\t -> isSpacy t || t == Str "\160")
+
+pMatch :: String -> (Inline -> Bool) -> Parsec [Inline] st Inline
+pMatch msg condition = try $ do
+  t <- anyToken
+  if not (condition t)
+     then fail msg
+     else return t
 
 type LocatorMap = M.Map String String
 
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
@@ -25,13 +25,13 @@
 import Prelude
 import           Control.Arrow      (second, (&&&), (>>>))
 import           Data.List          (elemIndex, find, findIndex, groupBy,
-                                     isPrefixOf, mapAccumL, nub, nubBy, sortBy)
+                                     isPrefixOf, mapAccumL, nub, nubBy, sortOn)
 import           Data.Maybe
-import           Data.Ord           (comparing)
 import           Text.CSL.Eval
 import           Text.CSL.Reference
 import           Text.CSL.Style
 import           Text.CSL.Util      (proc, query)
+import           Text.Pandoc.Shared (ordNub)
 
 -- | Given the 'Style', the list of references and the citation
 -- groups, disambiguate citations according to the style options.
@@ -42,7 +42,7 @@
     where
       -- utils
       when_ b f = if b then f else []
-      filter_ f = concatMap (map fst) . map (filter f) . map (uncurry zip)
+      filter_ f = concatMap (map fst . filter f . uncurry zip)
 
       -- the list of the position and the reference of each citation
       -- for each citation group.
@@ -89,14 +89,16 @@
 
       withYearS = addNames $
                   if hasYSuffOpt
-                  then map (mapCitationGroup $ setYearSuffCollision hasNamesOpt needYSuff) $ reEvaluated
-                  else rmYearSuff $ reEvaluated
+                     then map (mapCitationGroup
+                               (setYearSuffCollision hasNamesOpt needYSuff))
+                              reEvaluated
+                     else rmYearSuff reEvaluated
 
       yearSuffs = when_ hasYSuffOpt . generateYearSuffix bibs . concatMap getYearSuffixes $ withYearS
 
       addNames  = proc (updateContrib giveNameDisamb newNames newGName)
       processed = if hasYSuffOpt
-                  then proc (updateYearSuffixes yearSuffs) $ withYearS
+                  then proc (updateYearSuffixes yearSuffs) withYearS
                   else withYearS
 
       citOutput = if disOpts /= [] then processed else reEvaluated
@@ -122,10 +124,12 @@
       needName' = nub' needName []
       addLNames = map (\(c,n) -> c { disambed = if null n then collision c else head n }) disSolved
       nub' []     r = r
-      nub' (x:xs) r = case elemIndex (disambData $ clean x) (map (disambData . clean) r) of
+      nub' (x:xs) r = case elemIndex (disambData $ clean x)
+                           (map (disambData . clean) r) of
                          Nothing -> nub' xs (x:r)
                          Just i  -> let y = r !! i
-                                    in nub' xs (y {sameAs = key x : sameAs y} : filter (/= y) r)
+                                    in nub' xs (y {sameAs = key x : sameAs y}
+                                                 : filter (/= y) r)
 
 disambAddGivenNames :: [NameData] -> [NameData]
 disambAddGivenNames needName = addGName
@@ -158,9 +162,13 @@
 -- | Evaluate again a citation group with the 'EvalState' 'disamb'
 -- field set to 'True' (for matching the @\"disambiguate\"@
 -- condition).
-reEvaluate :: Style -> [CiteData] -> [(Cite, Maybe Reference)] -> CitationGroup -> CitationGroup
-reEvaluate (Style {citation = ct, csMacros = ms , styleLocale = lo,
-                   styleAbbrevs = as}) l cr (CG a f d os)
+reEvaluate :: Style
+           -> [CiteData]
+           -> [(Cite, Maybe Reference)]
+           -> CitationGroup
+           -> CitationGroup
+reEvaluate Style{citation = ct, csMacros = ms , styleLocale = lo,
+                   styleAbbrevs = as} l cr (CG a f d os)
     = CG a f d . flip concatMap (zip cr os) $
       \((c,mbr),out) ->
          case mbr of
@@ -175,8 +183,8 @@
 -- disambiguation strategies have failed. To be used with the generic
 -- 'query' function.
 hasIfDis :: IfThen -> [Bool]
-hasIfDis (IfThen (Condition {disambiguation = (_:_)}) _ _) = [True]
-hasIfDis _                                                 = [False]
+hasIfDis (IfThen Condition{disambiguation = (_:_)} _ _) = [True]
+hasIfDis _                                              = [False]
 
 -- | Get the list of disambiguation options set in the 'Style' for
 -- citations.
@@ -194,13 +202,15 @@
 -- year-suffix option is set).
 getDuplCiteData :: GiveNameDisambiguation -> Bool -> Bool -> [CitationGroup] -> [[CiteData]]
 getDuplCiteData giveNameDisamb b1 b2 g
-    = groupBy (\x y -> collide x == collide y) . sortBy (comparing collide)
+    = groupBy (\x y -> collide x == collide y) . sortOn collide
       $ duplicates
     where
       whatToGet  = if b1 then collision else disambYS
-      collide    = proc (rmExtras giveNameDisamb) . proc rmHashAndGivenNames . whatToGet
+      collide    = proc (rmExtras giveNameDisamb) .
+                   proc rmHashAndGivenNames .
+                   whatToGet
       citeData   = nubBy (\a b -> collide a == collide b && key a == key b) $
-                   concatMap (mapGroupOutput $ getCiteData) g
+                   concatMap (mapGroupOutput getCiteData) g
       duplicates = [c | c <- citeData , d <- citeData , collides c d]
       collides x y = x /= y && (collide x == collide y)
                             && (not b2 || citYear x == citYear y)
@@ -252,15 +262,14 @@
 
 getDuplNameData :: [CitationGroup] -> [[NameData]]
 getDuplNameData g
-    = groupBy (\a b -> collide a == collide b) . sortBy (comparing collide) $ duplicates
+    = groupBy (\a b -> collide a == collide b) . sortOn collide $ duplicates
     where
       collide    = nameCollision
       nameData   = nub $ concatMap (mapGroupOutput getName) g
       duplicates = filter (flip elem (getDuplNames g) . collide) nameData
 
 getDuplNames :: [CitationGroup] -> [[Output]]
-getDuplNames xs
-    = nub . catMaybes . snd . mapAccumL dupl [] . getData $ xs
+getDuplNames = ordNub . catMaybes . snd . mapAccumL dupl [] . getData
     where
       getData = concatMap (mapGroupOutput getName)
       dupl a c = if nameCollision c `elem` map nameCollision a
@@ -278,14 +287,14 @@
 generateYearSuffix refs
     = concatMap (`zip` suffs) .
       -- sort clashing cites using their position in the sorted bibliography
-      getFst . map (sort' . (filter ((/=) 0 . snd)) . (map getP)) .
+      getFst . map (sort' . filter ((/=) 0 . snd) . map getP) .
       -- group clashing cites
       getFst . filter (\grp -> length grp >= 2) . map nub .
       groupBy (\a b -> snd a == snd b) .
       sort' . filter (not . null . snd)
     where
       sort'  :: (Ord a, Ord b) => [(a,b)] -> [(a,b)]
-      sort'  = sortBy (comparing snd)
+      sort'  = sortOn snd
       getFst = map $ map fst
       getP k = case findIndex ((==) k . unLiteral . refId) refs of
                    Just x -> (k, x + 1)
@@ -294,16 +303,17 @@
       letters = map (:[]) ['a'..'z']
 
 setYearSuffCollision :: Bool -> [CiteData] -> [Output] -> [Output]
-setYearSuffCollision b cs = proc (setYS cs) . (map $ \x -> if hasYearSuf x then x else addYearSuffix x)
+setYearSuffCollision b cs = proc (setYS cs) .
+    map (\x -> if hasYearSuf x then x else addYearSuffix x)
     where
       setYS c o
           | OYearSuf _ k _ f <- o = OYearSuf [] k (getCollision k c) f
           | otherwise             = o
       collide = if b then disambed else disambYS
       getCollision k c = case find ((==) k . key) c of
-                           Just x -> if collide x == []
-                                     then [OStr (citYear x) emptyFormatting]
-                                     else collide x
+                           Just x -> case collide x of
+                                        [] -> [OStr (citYear x) emptyFormatting]
+                                        ys -> ys
                            _      -> []
 
 updateYearSuffixes :: [(String, String)] -> Output -> Output
@@ -334,8 +344,8 @@
 rmYearSuff = proc rmYS
     where
       rmYS o
-          | OYearSuf _ _ _ _  <- o = ONull
-          | otherwise              = o
+          | OYearSuf{}   <- o = ONull
+          | otherwise         = o
 
 -- List Utilities
 
@@ -353,8 +363,7 @@
       heads = map (take 1) l
       rest  = map (\(b,x) -> if b then tail_ x else take 1 x) . zip (same heads)
 
-      hasMult []     = False
-      hasMult (x:xs) = length x > 1 || hasMult xs
+      hasMult = foldr (\x -> (||) (length x > 1)) False
 
       tail_ [x] = [x]
       tail_  x  = if null x then x else tail x
@@ -396,16 +405,16 @@
 hasYear :: Output -> Bool
 hasYear = not . null . query getYear
     where getYear o
-              | OYear _ _ _ <- o = [o]
-              | otherwise        = []
+              | OYear{}   <- o = [o]
+              | otherwise      = []
 
 
 hasYearSuf :: Output -> Bool
 hasYearSuf = not . null . query getYearSuf
     where getYearSuf :: Output -> [String]
           getYearSuf o
-              | OYearSuf _ _ _ _ <- o = ["a"]
-              | otherwise             = []
+              | OYearSuf{}   <- o = ["a"]
+              | otherwise         = []
 
 -- | Removes all given names and name hashes from OName elements.
 rmHashAndGivenNames :: Output -> Output
@@ -430,4 +439,4 @@
 
 -- | Map the evaluated output of a citation group.
 mapGroupOutput :: (Output -> [a]) -> CitationGroup -> [a]
-mapGroupOutput f (CG _ _ _ os) = concatMap f $ map snd os
+mapGroupOutput f (CG _ _ _ os) = concatMap (f . snd) os
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
@@ -66,7 +66,7 @@
 import           Data.Either         (lefts, rights)
 import           Data.Generics       hiding (Generic)
 import qualified Data.HashMap.Strict as H
-import           Data.List           (elemIndex)
+import           Data.List           (findIndex, elemIndex)
 import           Data.List.Split     (splitWhen)
 import           Data.Maybe          (fromMaybe, isNothing)
 import           Data.String
@@ -408,6 +408,7 @@
 data Reference =
     Reference
     { refId                    :: Literal
+    , refOtherIds              :: [Literal]
     , refType                  :: RefType
 
     , author                   :: [Agent]
@@ -493,6 +494,7 @@
      v <- parseSuppFields v' <|> return v'
      addPageFirst <$> (Reference <$>
        v .:? "id" .!= "" <*>
+       v .:? "other-ids" .!= [] <*>
        v .:? "type" .!= NoType <*>
        v .:? "author" .!= [] <*>
        v .:? "editor" .!= [] <*>
@@ -620,6 +622,7 @@
 instance ToJSON Reference where
   toJSON ref = object' [
       "id" .= refId ref
+    , "other-ids" .= refOtherIds ref
     , "type" .= refType ref
     , "author" .= author ref
     , "editor" .= editor ref
@@ -699,6 +702,7 @@
 instance ToYaml Reference where
   toYaml ref = mapping' [
       "id" &= refId ref
+    , "other-ids" &= refOtherIds ref
     , (("type" Y..= refType ref) :)
     , "author" &= author ref
     , "editor" &= editor ref
@@ -786,6 +790,7 @@
 emptyReference =
     Reference
     { refId               = mempty
+    , refOtherIds         = mempty
     , refType             = NoType
 
     , author              = []
@@ -871,44 +876,82 @@
               , "chapter-number", "collection-number", "number-of-pages"]
 
 getReference :: [Reference] -> Cite -> Maybe Reference
-getReference  r c
-    = case citeId c `elemIndex` map (unLiteral . refId) r of
-        Just i  -> Just $ setPageFirst $ r !! i
+getReference  rs c
+    = case (hasId (citeId c)) `findIndex` rs of
+        Just i  -> Just $ setPageFirst $ rs !! i
         Nothing -> Nothing
+  where hasId :: String -> Reference -> Bool
+        hasId ident r = ident `elem` (map unLiteral (refId r : refOtherIds r))
 
 processCites :: [Reference] -> [[Cite]] -> [[(Cite, Maybe Reference)]]
 processCites rs cs
-    = procGr [[]] cs
+    = procGr [] cs
     where
       procRef r = case filter ((==) (unLiteral $ refId r) . citeId) $ concat cs of
                     x:_ -> r { firstReferenceNoteNumber = readNum $ citeNoteNumber x}
                     []  -> r
 
       procGr _ [] = []
-      procGr a (x:xs) = let (a',res) = procCs a x
-                        in res : procGr (a' ++ [[]]) xs
+      procGr acc (x:xs) = let (a',res) = procCs acc x
+                          in res : procGr ([] : a') xs
 
-      procCs a [] = (a,[])
-      procCs a (c:xs)
-          | isIbid,  isLocSet = go "ibid-with-locator"
-          | isIbid            = go "ibid"
-          | isElem            = go "subsequent"
-          | otherwise         = go "first"
+      -- process, given the accumulated history, the current group's cites
+      procCs acc [] = (acc,[])
+      procCs acc (c:xs) = let (a, rest) = procCs addCite xs
+                              ref       = procRef <$> getReference rs c
+                              c'        = c { citePosition = getCitePosition }
+                          in  (a, (c', ref) : rest)
           where
-            go s = let addCite    = init a ++ [last a ++ [c]]
-                       (a', rest) = procCs addCite xs
-                   in  (a', (c { citePosition = s},
-                             procRef <$> getReference rs c) : rest)
-            isElem   = citeId c `elem` map citeId (concat a)
-            isIbid   = case reverse (last a) of
-                            []    -> case reverse (init a) of
-                                          []     -> False
-                                          (zs:_) -> not (null zs) &&
-                                                    all (== citeId c)
-                                                        (map citeId zs)
-                            (x:_) -> citeId c == citeId x
-            isLocSet = citeLocator c /= ""
+            addCite = case acc of
+                        []     -> [[c]]
+                        (a:as) -> (c : a) : as
 
+            -- http://docs.citationstyles.org/en/stable/specification.html#locators
+            getCitePosition = fromMaybe notIbid (ibidPosition <$> prevSameCite)
+                where
+                    notIbid = if citeId c `elem` map citeId (concat acc)
+                                 then "subsequent"
+                                 else "first"
+
+            ibidPosition x = let hasL k   = citeLocator k /= ""
+                                 withIf b = if b then "ibid-with-locator" else "ibid"
+                                 diffLoc  = citeLocator x /= citeLocator c
+                                           || citeLabel x /= citeLabel c
+                             in  case (hasL x, hasL c) of
+                                   (False, cur)  -> withIf cur
+                                   (True, True)  -> withIf diffLoc
+                                   (True, False) -> "subsequent"
+
+            -- x is previous cite in current group
+            -- zs is the previous group
+            prevSameCite = case acc of
+                             []     -> Nothing
+                             (a:as) -> psc a as
+              where
+                -- you can't have an ibid at the start of your document
+                psc [] []     = Nothing
+
+                -- a. the current cite immediately follows on another cite,
+                --    within the same citation, that references the same item
+                psc (x:_) _   = if citeId c == citeId x
+                                   then Just x
+                                   else Nothing
+
+                -- b.  [] => the current cite is the first cite in the citation
+                --     zs => and the previous citation consists of a single cite
+                --           that refs the same item
+                -- The spec appears to be concerned that you cannot know the
+                -- correct one to match the locator against.
+                -- It is a super clunky if you have [@a, 1; @a, 2] then [@a, 3],
+                -- where the second citation gets "subsequent" even though there were
+                -- only @a keys.
+                -- This is silly. We will use the last one to match against.
+                psc [] (zs:_) = case zs of
+                                  [] -> Nothing
+                                  (z:_) -> if all (== citeId c) (map citeId zs)
+                                              then Just z
+                                              else Nothing
+
 setPageFirst :: Reference -> Reference
 setPageFirst ref =
   let Formatted ils = page ref
@@ -1039,24 +1082,24 @@
   let sep = P.oneOf [' ','/',','] >> P.spaces
   let rangesep = P.try $ P.spaces >> P.char '-' >> P.spaces
   let refDate = RefDate Nothing Nothing Nothing Nothing mempty False
-  let date = P.choice $ map P.try [
-                 (do s <- pseason
+  let date = P.choice $ map P.try
+                [ do s <- pseason
                      sep
                      y <- pyear
-                     return refDate{ year = y, season = s })
-               , (do m <- pmonth
+                     return refDate{ year = y, season = s }
+                , do m <- pmonth
                      sep
                      d <- pday
                      sep
                      y <- pyear
-                     return refDate{ year = y, month = m, day = d })
-               , (do m <- pmonth
+                     return refDate{ year = y, month = m, day = d }
+                , do m <- pmonth
                      sep
                      y <- pyear
-                     return refDate{ year = y, month = m })
-               , (do y <- pyear
-                     return refDate{ year = y })
-               ]
+                     return refDate{ year = y, month = m }
+                , do y <- pyear
+                     return refDate{ year = y }
+                ]
   d1 <- date
   P.option [d1] ((\x -> [d1,x]) <$> (rangesep >> date))
 
diff --git a/stack.yaml b/stack.yaml
--- a/stack.yaml
+++ b/stack.yaml
@@ -9,16 +9,19 @@
 packages:
 - '.'
 extra-deps:
-- haddock-library-1.6.0
-- HsYAML-0.1.1.1
-- network-2.7.0.2
 - rfc5051-0.1.0.3
-- hs-bibutils-6.5.0.0
-- yaml-0.9.0
-- hslua-1.0.0
+- hs-bibutils-6.6.0.0
+- pandoc-2.4
+- haddock-library-1.7.0
+- HsYAML-0.1.1.2
+- texmath-0.11.1.2
+- yaml-0.11.0.0
+- libyaml-0.1.0.0
+- cmark-gfm-0.1.6
+- hslua-1.0.1
 - hslua-module-text-0.2.0
-- github: jgm/pandoc
-  commit: c292a0bae3167570511543d3d96a0385b9b5f2d8
+- skylighting-0.7.4
+- skylighting-core-0.7.4
 ghc-options:
    "$locals": -fhide-source-paths
-resolver: lts-12.0
+resolver: lts-12.18
diff --git a/tests/biblio2yaml/266.biblatex b/tests/biblio2yaml/266.biblatex
new file mode 100644
--- /dev/null
+++ b/tests/biblio2yaml/266.biblatex
@@ -0,0 +1,28 @@
+@book{goethe2005,
+  langid = {german},
+  location = {{Frankfurt am Main}},
+  title = {Not A Real Book},
+  date = {2005},
+  author = {family=Goethe, given=Johann Wolfgang, prefix=von, useprefix=false and given=Antonie, prefix=van, family=Leeuwenhoek, useprefix=true}, editor = {Schöne, Albrecht}
+}
+
+---
+references:
+- id: goethe2005
+  type: book
+  author:
+  - family: Goethe
+    given: Johann Wolfgang
+    dropping-particle: von
+  - family: Leeuwenhoek
+    given: Antonie
+    non-dropping-particle: van
+  editor:
+  - family: Schöne
+    given: Albrecht
+  issued:
+  - year: 2005
+  title: Not A Real Book
+  publisher-place: Frankfurt am Main
+  language: de-DE
+...
diff --git a/tests/issue356.expected.native b/tests/issue356.expected.native
new file mode 100644
--- /dev/null
+++ b/tests/issue356.expected.native
@@ -0,0 +1,5 @@
+Pandoc (Meta {unMeta = fromList [("references",MetaList [MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Alice"])])]),("id",MetaInlines [Str "foo"]),("issued",MetaList [MetaMap (fromList [("year",MetaInlines [Str "2042"])])]),("other-ids",MetaList [MetaInlines [Str "bar"],MetaInlines [Str "doz"]]),("type",MetaInlines [Str "book"])])])]})
+[Para [Cite [Citation {citationId = "bar", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 1}] [Str "(Alice",Space,Str "2042)"]]
+,Div ("refs",["references"],[])
+ [Div ("ref-foo",[],[])
+  [Para [Str "Alice.",Space,Str "2042."]]]]
diff --git a/tests/issue356.in.native b/tests/issue356.in.native
new file mode 100644
--- /dev/null
+++ b/tests/issue356.in.native
@@ -0,0 +1,2 @@
+Pandoc (Meta {unMeta = fromList [("references",MetaList [MetaMap (fromList [("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Alice"])])]),("id",MetaInlines [Str "foo"]),("issued",MetaList [MetaMap (fromList [("year",MetaInlines [Str "2042"])])]),("other-ids",MetaList [MetaInlines [Str "bar"],MetaInlines [Str "doz"]]),("type",MetaInlines [Str "book"])])])]})
+[Para [Cite [Citation {citationId = "bar", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@bar]"]]]
diff --git a/tests/issue361.expected.native b/tests/issue361.expected.native
new file mode 100644
--- /dev/null
+++ b/tests/issue361.expected.native
@@ -0,0 +1,12 @@
+Pandoc (Meta {unMeta = fromList [("csl",MetaInlines [Str "tests/locators.csl"]),("references",MetaList [MetaMap (fromList [("id",MetaInlines [Str "citekey"]),("title",MetaInlines [Str "Title"]),("type",MetaInlines [Str "article-journal"])]),MetaMap (fromList [("id",MetaInlines [Str "other"]),("title",MetaInlines [Str "Other"]),("type",MetaInlines [Str "article-journal"])])]),("suppress-bibliography",MetaBool True)]})
+[Para [Str "Content",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 1}] [Note [Para [Str "Title."]]]]
+,Para [Str "Content",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "1"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 2}] [Note [Para [Str "Ibid-with-locator",Space,Str "{1}."]]]]
+,Para [Str "Content",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "2"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 3}] [Note [Para [Str "Ibid-with-locator",Space,Str "{2}."]]]]
+,Para [Str "Content",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "2"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 4}] [Note [Para [Str "Ibid."]]]]
+,Para [Str "Content",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Space,Str "2"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 5}] [Note [Para [Str "Ibid."]]]]
+,Para [Str "Content",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "p.\160\&2"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 6}] [Note [Para [Str "Ibid."]]]]
+,Para [Str "Content",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Space,Str "p.\160\&2"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 7}] [Note [Para [Str "Ibid."]]]]
+,Para [Str "Content",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 8}] [Note [Para [Str "Subsequent."]]]]
+,Para [Str "Content",Cite [Citation {citationId = "other", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 9}] [Note [Para [Str "Other."]]]]
+,Para [Str "Content",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "3"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 10}] [Note [Para [Str "Subsequent",Space,Str "{3}."]]]]
+,Para [Str "Content",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "3"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 11}] [Note [Para [Str "Ibid."]]]]]
diff --git a/tests/issue361.in.native b/tests/issue361.in.native
new file mode 100644
--- /dev/null
+++ b/tests/issue361.in.native
@@ -0,0 +1,12 @@
+Pandoc (Meta {unMeta = fromList [("csl",MetaInlines [Str "tests/locators.csl"]),("references",MetaList [MetaMap (fromList [("id",MetaInlines [Str "citekey"]),("title",MetaInlines [Str "Title"]),("type",MetaInlines [Str "article-journal"])]),MetaMap (fromList [("id",MetaInlines [Str "other"]),("title",MetaInlines [Str "Other"]),("type",MetaInlines [Str "article-journal"])])]),("suppress-bibliography",MetaBool True)]})
+[Para [Str "Content",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey]"]]
+,Para [Str "Content",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "1"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "1]"]]
+,Para [Str "Content",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "2"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "2]"]]
+,Para [Str "Content",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "2"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "2]"]]
+,Para [Str "Content",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Space,Str "2"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey",Space,Str "2]"]]
+,Para [Str "Content",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "p.\160\&2"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "p.",Space,Str "2]"]]
+,Para [Str "Content",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Space,Str "p.\160\&2"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey",Space,Str "p.",Space,Str "2]"]]
+,Para [Str "Content",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey]"]]
+,Para [Str "Content",Cite [Citation {citationId = "other", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@other]"]]
+,Para [Str "Content",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "3"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "3]"]]
+,Para [Str "Content",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "3"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "3]"]]]
diff --git a/tests/issue365.expected.native b/tests/issue365.expected.native
new file mode 100644
--- /dev/null
+++ b/tests/issue365.expected.native
@@ -0,0 +1,5 @@
+Pandoc (Meta {unMeta = fromList [("csl",MetaInlines [Str "tests/le-tapuscrit-note.csl"]),("references",MetaList [MetaMap (fromList [("ISBN",MetaInlines [Str "978-2-912573-52-0"]),("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Le\160Gras"]),("given",MetaInlines [Str "Gw\233na\235lle"])])]),("call-number",MetaInlines [Str "Tolbiac",Space,Str "-",Space,Str "Rez",Space,Str "de",Space,Str "Jardin",Space,Str "-",Space,Str "Litt\233rature",Space,Str "et",Space,Str "art",Space,Str "-",Space,Str "Magasin",Space,Str "-",Space,Str "2010-82178"]),("collection-title",MetaInlines [Str "Jeux",Space,Str "d\8217acteurs"]),("id",MetaInlines [Str "legras_michel_2010"]),("issued",MetaList [MetaMap (fromList [("year",MetaInlines [Str "2010"])])]),("language",MetaInlines [Str "fre"]),("number-of-pages",MetaInlines [Str "128"]),("publisher",MetaInlines [Str "Scope"]),("publisher-place",MetaInlines [Str "Paris"]),("source",MetaInlines [Str "BnF",Space,Str "Catalogue",Space,Str "g\233n\233ral",Space,Str "(http://catalogue.bnf.fr)"]),("title",MetaInlines [Str "Michel",Space,Str "Simon\160:",Space,Str "l\8217art",Space,Str "de",Space,Str "la",Space,Str "disgr\226ce"]),("title-short",MetaInlines [Str "Michel",Space,Str "Simon"]),("type",MetaInlines [Str "book"])])])]})
+[Para [Str "Foo",Str ".",Cite [Citation {citationId = "legras_michel_2010", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 1}] [Note [Para [Str "Gw\233na\235lle",Space,Str "Le\160Gras,",Space,Emph [Str "Michel",Space,Str "Simon\160:",Space,Str "l\8217art",Space,Str "de",Space,Str "la",Space,Str "disgr\226ce"],Str ",",Space,Str "Paris,",Space,Str "Scope,",Space,Str "2010,",Space,Str "128\160p."]]]]
+,Div ("refs",["references"],[])
+ [Div ("ref-legras_michel_2010",[],[])
+  [Para [SmallCaps [Str "Le\160Gras"],Space,Str "Gw\233na\235lle,",Space,Emph [Str "Michel",Space,Str "Simon\160:",Space,Str "l\8217art",Space,Str "de",Space,Str "la",Space,Str "disgr\226ce"],Str ",",Space,Str "Paris,",Space,Str "Scope",Space,Str "(coll.\160\171\160Jeux",Space,Str "d\8217acteurs\160\187),",Space,Str "2010,",Space,Str "128\160p."]]]]
diff --git a/tests/issue365.in.native b/tests/issue365.in.native
new file mode 100644
--- /dev/null
+++ b/tests/issue365.in.native
@@ -0,0 +1,2 @@
+Pandoc (Meta {unMeta = fromList [("csl",MetaInlines [Str "tests/le-tapuscrit-note.csl"]),("references",MetaList [MetaMap (fromList [("ISBN",MetaInlines [Str "978-2-912573-52-0"]),("author",MetaList [MetaMap (fromList [("family",MetaInlines [Str "Le\160Gras"]),("given",MetaInlines [Str "Gw\233na\235lle"])])]),("call-number",MetaInlines [Str "Tolbiac",Space,Str "-",Space,Str "Rez",Space,Str "de",Space,Str "Jardin",Space,Str "-",Space,Str "Litt\233rature",Space,Str "et",Space,Str "art",Space,Str "-",Space,Str "Magasin",Space,Str "-",Space,Str "2010-82178"]),("collection-title",MetaInlines [Str "Jeux",Space,Str "d\8217acteurs"]),("id",MetaInlines [Str "legras_michel_2010"]),("issued",MetaList [MetaMap (fromList [("year",MetaInlines [Str "2010"])])]),("language",MetaInlines [Str "fre"]),("number-of-pages",MetaInlines [Str "128"]),("publisher",MetaInlines [Str "Scope"]),("publisher-place",MetaInlines [Str "Paris"]),("source",MetaInlines [Str "BnF",Space,Str "Catalogue",Space,Str "g\233n\233ral",Space,Str "(http://catalogue.bnf.fr)"]),("title",MetaInlines [Str "Michel",Space,Str "Simon\160:",Space,Str "l\8217art",Space,Str "de",Space,Str "la",Space,Str "disgr\226ce"]),("title-short",MetaInlines [Str "Michel",Space,Str "Simon"]),("type",MetaInlines [Str "book"])])])]})
+[Para [Str "Foo",Space,Cite [Citation {citationId = "legras_michel_2010", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@legras_michel_2010]"],Str "."]]
diff --git a/tests/le-tapuscrit-note.csl b/tests/le-tapuscrit-note.csl
new file mode 100644
--- /dev/null
+++ b/tests/le-tapuscrit-note.csl
@@ -0,0 +1,496 @@
+<?xml version="1.0" encoding="utf-8"?>
+<style xmlns="http://purl.org/net/xbiblio/csl" class="note" default-locale="fr-FR" version="1.0" page-range-format="expanded">
+  <info>
+    <title>Le tapuscrit (École des hautes études en sciences sociales) (note, French)</title>
+    <title-short>Tapuscrit-EHESS</title-short>
+    <id>http://www.zotero.org/styles/le-tapuscrit-note</id>
+    <link href="http://www.zotero.org/styles/le-tapuscrit-note" rel="self"/>
+    <link href="http://www.editions.ehess.fr/ouvrages/ouvrage/le-tapuscrit/" rel="documentation"/>
+    <author>
+      <name>Franziska Heimburger</name>
+      <email>zotero@franziska.fr</email>
+    </author>
+    <category citation-format="note"/>
+    <category field="social_science"/>
+    <category field="generic-base"/>
+    <updated>2018-07-12T11:20:37+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="fr">
+    <terms>
+      <term name="ordinal-01">ère</term>
+      <term name="ordinal-02">e</term>
+      <term name="ordinal-03">e</term>
+      <term name="ordinal-04">e</term>
+      <term name="cited">op.&#160;cit.</term>
+      <term name="page" form="short">p.</term>
+      <term name="editor" form="short">
+        <single>ed.</single>
+        <multiple>eds.</multiple>
+      </term>
+      <term name="in">dans</term>
+    </terms>
+  </locale>
+  <macro name="author">
+    <choose>
+      <if variable="author">
+        <names variable="author">
+          <name form="long" and="text" delimiter-precedes-last="never" sort-separator=" "/>
+        </names>
+      </if>
+      <else-if variable="editor">
+        <names variable="editor">
+          <name form="long" and="text" delimiter-precedes-last="never" sort-separator=" "/>
+          <label form="short" prefix="&#160;(" suffix=".)"/>
+        </names>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="author-bib">
+    <choose>
+      <if variable="author">
+        <names variable="author">
+          <name name-as-sort-order="all" form="long" and="text" delimiter-precedes-last="never" sort-separator=" ">
+            <name-part name="family" font-variant="small-caps"/>
+          </name>
+        </names>
+      </if>
+      <else-if variable="editor">
+        <names variable="editor">
+          <name name-as-sort-order="all" form="long" and="text" delimiter-precedes-last="never" sort-separator=" ">
+            <name-part name="family" font-variant="small-caps"/>
+          </name>
+          <label form="short" prefix="&#160;(" suffix=".)"/>
+        </names>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="author-ibid">
+    <choose>
+      <if variable="author">
+        <names variable="author">
+          <name and="text" initialize="true" initialize-with="." delimiter-precedes-last="never" sort-separator=" " font-style="normal"/>
+        </names>
+      </if>
+      <else-if variable="editor">
+        <names variable="editor">
+          <name form="long" and="text" delimiter-precedes-last="never" sort-separator=" "/>
+          <label form="short" prefix="&#160;(" suffix=".)"/>
+        </names>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="editor">
+    <names variable="editor">
+      <name form="long" and="text" delimiter-precedes-last="never" sort-separator=" "/>
+      <label form="short" prefix="&#160;(" suffix=".)"/>
+    </names>
+  </macro>
+  <macro name="translator">
+    <names variable="translator">
+      <name form="long" and="text" delimiter-precedes-last="never" sort-separator=" " prefix=" traduit par "/>
+    </names>
+  </macro>
+  <macro name="title">
+    <choose>
+      <if type="bill book graphic legal_case motion_picture report song" match="any">
+        <text variable="title" text-case="capitalize-first" font-style="italic"/>
+      </if>
+      <else-if type="article-journal article-newspaper article-magazine" match="any">
+        <group delimiter=", ">
+          <text variable="title" text-case="capitalize-first" quotes="true"/>
+          <text variable="container-title" font-style="italic"/>
+        </group>
+      </else-if>
+      <else-if type="thesis" match="any">
+        <group delimiter="">
+          <text variable="title" text-case="capitalize-first" font-style="italic" suffix=","/>
+          <text variable="genre" suffix=", " prefix=" "/>
+          <text variable="publisher"/>
+        </group>
+      </else-if>
+      <else-if type="manuscript" match="any">
+        <group delimiter=",">
+          <text variable="title" text-case="capitalize-first" font-style="italic"/>
+          <text variable="genre" prefix=" [" suffix="]"/>
+        </group>
+      </else-if>
+      <else-if type="chapter entry-dictionary entry-encyclopedia" match="any">
+        <group delimiter="">
+          <text variable="title" text-case="capitalize-first" quotes="true"/>
+          <text value="dans" suffix=" " prefix=" "/>
+          <text macro="editor" suffix=", "/>
+          <text variable="container-title" text-case="capitalize-first" font-style="italic"/>
+        </group>
+      </else-if>
+      <else-if type="webpage post-weblog" match="any">
+        <group delimiter="">
+          <text variable="title" text-case="capitalize-first" font-style="italic" suffix=", "/>
+          <text variable="URL"/>
+          <group prefix=" , ">
+            <date variable="issued">
+              <date-part name="day" suffix=" "/>
+              <date-part name="month" suffix=" "/>
+              <date-part name="year"/>
+            </date>
+          </group>
+        </group>
+      </else-if>
+      <else>
+        <text variable="title" quotes="true"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="pub-place">
+    <choose>
+      <if type="bill book chapter entry-dictionary entry-encyclopedia thesis graphic legal_case manuscript motion_picture paper-conference report song" match="any">
+        <choose>
+          <if variable="publisher-place" match="any">
+            <text variable="publisher-place"/>
+          </if>
+          <else>
+            <text value="s.l."/>
+          </else>
+        </choose>
+      </if>
+    </choose>
+  </macro>
+  <macro name="publisher">
+    <choose>
+      <if type="bill book chapter entry-dictionary entry-encyclopedia graphic legal_case motion_picture paper-conference report song" match="any">
+        <text variable="publisher"/>
+      </if>
+    </choose>
+  </macro>
+  <macro name="yearpage">
+    <choose>
+      <if type="bill book graphic legal_case motion_picture paper-conference manuscript report song thesis" match="any">
+        <group delimiter=", ">
+          <date variable="issued">
+            <date-part name="year"/>
+          </date>
+          <group>
+            <text term="volume" form="short" suffix="."/>
+            <text variable="number-of-volumes" prefix=". " suffix="/"/>
+            <text variable="volume"/>
+          </group>
+          <choose>
+            <if variable="locator" match="any">
+              <group delimiter="&#8239;">
+                <label variable="locator" form="short"/>
+                <text variable="locator"/>
+              </group>
+            </if>
+            <else-if variable="locator" match="none">
+              <text variable="number-of-pages" suffix="&#160;p"/>
+            </else-if>
+          </choose>
+        </group>
+      </if>
+      <else-if type="chapter entry-dictionary entry-encyclopedia" match="any">
+        <group delimiter=" ">
+          <date variable="issued">
+            <date-part name="year" suffix=", "/>
+          </date>
+          <group>
+            <text term="volume" form="short" suffix="."/>
+            <text variable="number-of-volumes" prefix=". " suffix="/"/>
+            <text variable="volume" suffix=","/>
+          </group>
+          <choose>
+            <if variable="locator" match="any">
+              <group delimiter="&#8239;">
+                <label variable="locator" form="short"/>
+                <text variable="locator"/>
+              </group>
+            </if>
+            <else-if variable="locator" match="none">
+              <label variable="page" form="short"/>
+              <text variable="page"/>
+            </else-if>
+          </choose>
+        </group>
+      </else-if>
+      <else-if type="article-journal" match="any">
+        <group delimiter=" " font-style="normal">
+          <choose>
+            <if variable="locator" match="any">
+              <group delimiter="&#8239;">
+                <label variable="locator" form="short"/>
+                <text variable="locator"/>
+              </group>
+            </if>
+            <else-if variable="locator" match="none">
+              <label variable="page" form="short"/>
+              <text variable="page"/>
+            </else-if>
+          </choose>
+        </group>
+      </else-if>
+      <else-if type="article-newspaper article-magazine" match="any">
+        <date variable="issued">
+          <date-part name="day" suffix=" "/>
+          <date-part name="month" form="short" suffix=" "/>
+          <date-part name="year"/>
+        </date>
+        <group delimiter=" " font-style="normal">
+          <label variable="page" form="short"/>
+          <text variable="page"/>
+        </group>
+        <group delimiter=" " font-style="normal">
+          <choose>
+            <if variable="locator" match="any">
+              <group delimiter="&#8239;">
+                <label variable="locator" form="short"/>
+                <text variable="locator"/>
+              </group>
+            </if>
+            <else-if variable="locator" match="none">
+              <label variable="page" form="short"/>
+            </else-if>
+          </choose>
+        </group>
+      </else-if>
+      <else-if type="webpage post-weblog" match="any">
+        <group delimiter=" " prefix="(" suffix=")">
+          <text value="consulté le" suffix=" " prefix=" "/>
+          <date variable="accessed" form="text">
+            <date-part name="day"/>
+            <date-part name="month"/>
+            <date-part name="year"/>
+          </date>
+        </group>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="yearpage-bib">
+    <choose>
+      <if type="bill book graphic legal_case motion_picture paper-conference report song thesis" match="any">
+        <group delimiter=", ">
+          <group delimiter=", ">
+            <date variable="issued">
+              <date-part name="year"/>
+            </date>
+            <group>
+              <text term="volume" form="short" suffix="."/>
+              <text variable="number-of-volumes" prefix=". " suffix="/"/>
+              <text variable="volume"/>
+            </group>
+            <text variable="number-of-pages" suffix="&#160;p"/>
+          </group>
+          <group>
+            <label variable="locator" form="short"/>
+            <text variable="locator"/>
+          </group>
+        </group>
+      </if>
+      <else-if type="chapter entry-dictionary entry-encyclopedia" match="any">
+        <group delimiter=", ">
+          <date variable="issued">
+            <date-part name="year"/>
+          </date>
+          <group>
+            <text term="volume" form="short" suffix="."/>
+            <text variable="number-of-volumes" prefix=". " suffix="/"/>
+            <text variable="volume"/>
+          </group>
+          <group>
+            <label variable="page" form="short"/>
+            <text variable="page" prefix="&#160;"/>
+          </group>
+        </group>
+      </else-if>
+      <else-if type="article-journal chapter" match="any">
+        <group delimiter=" ">
+          <label variable="page" form="short"/>
+          <text variable="page"/>
+        </group>
+      </else-if>
+      <else-if type="article-newspaper article-magazine" match="any">
+        <group delimiter=" ">
+          <date variable="issued">
+            <date-part name="day" suffix=" "/>
+            <date-part name="month" form="short" suffix=" "/>
+            <date-part name="year"/>
+          </date>
+          <label variable="page" form="short"/>
+          <text variable="page"/>
+        </group>
+      </else-if>
+      <else-if type="manuscript">
+        <group delimiter="" font-style="normal">
+          <choose>
+            <if variable="issued">
+              <date variable="issued">
+                <date-part name="day" suffix=" "/>
+                <date-part name="month" suffix=" "/>
+                <date-part name="year"/>
+              </date>
+            </if>
+            <else>
+              <text value="s. d."/>
+            </else>
+          </choose>
+        </group>
+      </else-if>
+      <else-if type="webpage post-weblog" match="any">
+        <group delimiter=" ">
+          <text value="consulté le" suffix=" " prefix=" "/>
+          <date variable="accessed" form="text">
+            <date-part name="day"/>
+            <date-part name="month"/>
+            <date-part name="year"/>
+          </date>
+        </group>
+      </else-if>
+    </choose>
+  </macro>
+  <macro name="edition">
+    <choose>
+      <if type="bill book graphic legal_case motion_picture report song chapter paper-conference" 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" text-case="capitalize-first" suffix="."/>
+          </else>
+        </choose>
+      </if>
+      <else-if type="article-journal article-magazine" match="any">
+        <group delimiter="">
+          <choose>
+            <if variable="issued">
+              <date variable="issued">
+                <date-part name="day" suffix=" "/>
+                <date-part name="month" suffix=" "/>
+                <date-part name="year"/>
+              </date>
+              <text macro="volume" prefix=", "/>
+            </if>
+            <else>
+              <text macro="volume" text-case="capitalize-first"/>
+            </else>
+          </choose>
+        </group>
+      </else-if>
+    </choose>
+    <text macro="issue" prefix=", "/>
+  </macro>
+  <macro name="volume">
+    <choose>
+      <if is-numeric="volume">
+        <text term="volume" form="short" suffix=".&#160;"/>
+        <text variable="volume"/>
+      </if>
+      <else>
+        <text variable="volume"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="issue">
+    <choose>
+      <if is-numeric="issue">
+        <text term="issue" form="short" suffix="&#160;"/>
+        <text variable="issue"/>
+      </if>
+      <else>
+        <text variable="issue"/>
+      </else>
+    </choose>
+  </macro>
+  <macro name="collection">
+    <text variable="collection-title" quotes="true" prefix=" (coll.&#160;" suffix=")"/>
+  </macro>
+  <citation et-al-min="4" et-al-use-first="1">
+    <layout suffix="." delimiter="&#160;; ">
+      <choose>
+        <if position="ibid-with-locator">
+          <group delimiter=", ">
+            <text term="ibid" text-case="capitalize-first" font-style="italic" suffix="."/>
+            <text variable="locator" prefix="p.&#160;"/>
+          </group>
+        </if>
+        <else-if position="ibid">
+          <text term="ibid" text-case="capitalize-first" font-style="italic"/>
+        </else-if>
+        <else-if position="subsequent">
+          <group delimiter=", ">
+            <text macro="author-ibid"/>
+            <choose>
+              <if type="bill book graphic legal_case motion_picture report song thesis manuscript" match="any">
+                <text variable="title" form="short" font-style="italic"/>
+                <text term="cited" font-style="italic" suffix="."/>
+              </if>
+              <else>
+                <text variable="title" text-case="capitalize-first" form="short" quotes="true"/>
+                <text value="art cit"/>
+              </else>
+            </choose>
+            <text variable="locator" prefix="p.&#160;"/>
+          </group>
+        </else-if>
+        <else>
+          <choose>
+            <if type="manuscript">
+              <group delimiter=", ">
+                <text variable="archive"/>
+                <text variable="archive_location"/>
+                <text variable="call-number"/>
+                <text macro="title"/>
+                <text macro="yearpage-bib"/>
+              </group>
+            </if>
+            <else-if type="bill chapter article-journal article-newspaper interview book graphic legal_case motion_picture paper-conference report song thesis webpage post-weblog article-magazine" match="any">
+              <group delimiter=", ">
+                <text macro="author"/>
+                <text macro="title"/>
+                <text macro="translator"/>
+                <text macro="edition"/>
+                <text macro="pub-place"/>
+                <text macro="publisher"/>
+                <text macro="yearpage"/>
+              </group>
+            </else-if>
+          </choose>
+        </else>
+      </choose>
+    </layout>
+  </citation>
+  <bibliography>
+    <sort>
+      <key macro="author" names-min="3" names-use-first="3"/>
+      <key variable="issued" sort="descending"/>
+    </sort>
+    <layout suffix=".">
+      <choose>
+        <if type="manuscript">
+          <group delimiter=", ">
+            <text variable="archive"/>
+            <text variable="archive_location"/>
+            <text variable="call-number"/>
+            <text macro="title"/>
+            <text macro="yearpage-bib"/>
+          </group>
+        </if>
+        <else-if type="bill chapter article-journal article-newspaper interview book graphic legal_case motion_picture paper-conference report song thesis webpage post-weblog article-magazine" match="any">
+          <group delimiter=", ">
+            <text macro="author-bib"/>
+            <text macro="title"/>
+            <text macro="translator"/>
+            <text macro="edition"/>
+            <text macro="pub-place"/>
+            <group delimiter=" ">
+              <text macro="publisher"/>
+              <text macro="collection"/>
+            </group>
+            <text macro="yearpage-bib"/>
+          </group>
+        </else-if>
+      </choose>
+    </layout>
+  </bibliography>
+</style>
diff --git a/tests/locators-delimited.expected.native b/tests/locators-delimited.expected.native
new file mode 100644
--- /dev/null
+++ b/tests/locators-delimited.expected.native
@@ -0,0 +1,20 @@
+Pandoc (Meta {unMeta = fromList [("csl",MetaInlines [Str "tests/locators.csl"]),("references",MetaList [MetaMap (fromList [("id",MetaInlines [Str "citekey"]),("title",MetaInlines [Str "Title"]),("type",MetaInlines [Str "article-journal"])])]),("suppress-bibliography",MetaBool True)]})
+[Para [Str "See",Space,Link ("",["uri"],[]) [Str "https://github.com/jgm/pandoc-citeproc/pull/362"] ("https://github.com/jgm/pandoc-citeproc/pull/362",""),Str "."]
+,Para [Str "Standard",Space,Str "page",Space,Str "range",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str "{35-89,",Space,Str "102}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 1}] [Note [Para [Str "Title",Space,Str "{35\8211\&89,",Space,Str "102}."]]]]
+,Para [Str "Alphanumeric",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str "{abcdefg1234}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 2}] [Note [Para [Str "Ibid-with-locator",Space,Str "{abcdefg1234}."]]]]
+,Para [Str "Kitchen",Space,Str "sink",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "{123(4)a-8([a]12.398{8})}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 3}] [Note [Para [Str "Ibid-with-locator",Space,Str "{123(4)a\8211\&8([a]12.398{8})}."]]]]
+,Para [Str "Empty",Space,Str "braces",Space,Str "inside",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "{{}}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 4}] [Note [Para [Str "Ibid-with-locator",Space,Str "{{}}."]]]]
+,Para [Str "Label",Space,Str "specified",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str "{p.\160a}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 5}] [Note [Para [Str "Ibid-with-locator",Space,Str "{a}."]]]]
+,Para [Str "Should",Space,Str "it",Space,Str "work",Space,Str "outside?",Space,Str "No.",Str "",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "p.",Space,Str "{(a)}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 6}] [Note [Para [Str "Subsequent,",Space,Str "p.",Space,Str "{(a)}."]]]]
+,Para [Str "Empty",Space,Str "locator",Str "",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "{}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 7}] [Note [Para [Str "Ibid."]]]]
+,Para [Str "Empty",Space,Str "locator",Space,Str "to",Space,Str "force",Space,Str "suffix",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str "{}",Space,Str "123-35",Space,Str "numbers",Space,Str "are",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 8}] [Note [Para [Str "Ibid",Space,Str "123-35",Space,Str "numbers",Space,Str "are",Space,Str "suffix."]]]]
+,Para [Str "Suffix",Space,Str "generally",Str "",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str "{123-35}",Space,Str "numbers",Space,Str "not,",Space,Str "but",Space,Str "text",Space,Str "is",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 9}] [Note [Para [Str "Ibid-with-locator",Space,Str "{123\8211\&35}",Space,Str "numbers",Space,Str "not,",Space,Str "but",Space,Str "text",Space,Str "is",Space,Str "suffix."]]]]
+,Para [Str "With",Space,Str "preceding",Space,Str "comma",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "{p.\160VI}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 10}] [Note [Para [Str "Ibid-with-locator",Space,Str "{VI}."]]]]
+,Para [Str "No",Space,Str "commas",Space,Str "before",Space,Str "label",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "{,",Space,Str "p.",Space,Str "(p.\160is",Space,Str "not",Space,Str "recognised)}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 11}] [Note [Para [Str "Ibid-with-locator",Space,Str "{,",Space,Str "p.",Space,Str "(p.",Space,Str "is",Space,Str "not",Space,Str "recognised)}."]]]]
+,Para [Str "Trim",Space,Str "white",Space,Str "space",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "{",Space,Str "p.\160\&9",Space,Str "}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 12}] [Note [Para [Str "Ibid-with-locator",Space,Str "{9}."]]]]
+,Para [Str "Without",Space,Str "delimiters",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 13}] [Note [Para [Str "Subsequent,",Space,Str "suffix."]]]]
+,Para [Str "With",Space,Str "rendering",Space,Str "label",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str "{ss",Space,Str "IV",Space,Str "div",Space,Str "4",Space,Str "s",Space,Str "128L(7)(a)(i)-(iv),",Space,Str "129(5),",SoftBreak,Str "130(b)}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 14}] [Note [Para [Str "Ibid-with-locator",Space,Str "ss",Space,Str "{IV",Space,Str "div",Space,Str "4",Space,Str "s",Space,Str "128L(7)(a)(i)\8211(iv),",Space,Str "129(5),",Space,Str "130(b)}."]]]]
+,Para [Str "The",Space,Str "text",Space,Str "is",Space,Str "apparently",Space,Str "NOT",Space,Str "verbatim;",Space,Str "it",Space,Str "is",Space,Str "lightly",Space,Str "processed",Space,Str "as",Space,Str "page",Space,Str "numbers.",Str "",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str "{no",Space,Str "comma,",Space,Str "no",Space,Str "label,",Space,Str "no",Space,Str "nothing}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 15}] [Note [Para [Str "Ibid-with-locator",Space,Str "{no",Space,Str "comma,",Space,Str "nolabel,",Space,Str "nonothing}."]]]]
+,Para [Str "AGLC-style",Space,Str "page",Space,Str "[para]",Str "",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str "{584",Space,Str "[78]}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 16}] [Note [Para [Str "Ibid-with-locator",Space,Str "{584",Space,Str "[78]}."]]]]
+,Para [Str "Unbalanced",Space,Str "curly",Space,Str "{",Space,Str "breaks",Space,Str "the",Space,Str "parse",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str "{p.\160suffix{suffix}suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 17}] [Note [Para [Str "Subsequent",Space,Str "{p.\160suffix{suffix}suffix."]]]]
+,Para [Str "Unbalanced",Space,Str "curly",Space,Str "}",Space,Str "ends",Space,Str "early",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str "{green}suffix}suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 18}] [Note [Para [Str "Ibid-with-locator",Space,Str "{green}",Space,Str "suffix}suffix."]]]]]
diff --git a/tests/locators-delimited.in.native b/tests/locators-delimited.in.native
new file mode 100644
--- /dev/null
+++ b/tests/locators-delimited.in.native
@@ -0,0 +1,20 @@
+Pandoc (Meta {unMeta = fromList [("csl",MetaInlines [Str "tests/locators.csl"]),("references",MetaList [MetaMap (fromList [("id",MetaInlines [Str "citekey"]),("title",MetaInlines [Str "Title"]),("type",MetaInlines [Str "article-journal"])])]),("suppress-bibliography",MetaBool True)]})
+[Para [Str "See",Space,Link ("",["uri"],[]) [Str "https://github.com/jgm/pandoc-citeproc/pull/362"] ("https://github.com/jgm/pandoc-citeproc/pull/362",""),Str "."]
+,Para [Str "Standard",Space,Str "page",Space,Str "range",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str "{35-89,",Space,Str "102}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey{35-89,",Space,Str "102}]"]]
+,Para [Str "Alphanumeric",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str "{abcdefg1234}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey{abcdefg1234}]"]]
+,Para [Str "Kitchen",Space,Str "sink",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "{123(4)a-8([a]12.398{8})}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "{123(4)a-8(\\[a\\]12.398{8})}]"]]
+,Para [Str "Empty",Space,Str "braces",Space,Str "inside",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "{{}}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "{{}}]"]]
+,Para [Str "Label",Space,Str "specified",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str "{p.\160a}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey{p.",Space,Str "a}]"]]
+,Para [Str "Should",Space,Str "it",Space,Str "work",Space,Str "outside?",Space,Str "No.",Space,Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "p.",Space,Str "{(a)}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "p.",Space,Str "{(a)}]"]]
+,Para [Str "Empty",Space,Str "locator",Space,Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "{}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "{}]"]]
+,Para [Str "Empty",Space,Str "locator",Space,Str "to",Space,Str "force",Space,Str "suffix",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str "{}",Space,Str "123-35",Space,Str "numbers",Space,Str "are",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey{}",Space,Str "123-35",Space,Str "numbers",Space,Str "are",Space,Str "suffix]"]]
+,Para [Str "Suffix",Space,Str "generally",Space,Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str "{123-35}",Space,Str "numbers",Space,Str "not,",Space,Str "but",Space,Str "text",Space,Str "is",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey{123-35}",Space,Str "numbers",Space,Str "not,",Space,Str "but",Space,Str "text",Space,Str "is",Space,Str "suffix]"]]
+,Para [Str "With",Space,Str "preceding",Space,Str "comma",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "{p.\160VI}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "{p.",Space,Str "VI}]"]]
+,Para [Str "No",Space,Str "commas",Space,Str "before",Space,Str "label",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "{,",Space,Str "p.",Space,Str "(p.\160is",Space,Str "not",Space,Str "recognised)}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "{,",Space,Str "p.",Space,Str "(p.",Space,Str "is",Space,Str "not",Space,Str "recognised)}]"]]
+,Para [Str "Trim",Space,Str "white",Space,Str "space",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "{",Space,Str "p.\160\&9",Space,Str "}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "{",Space,Str "p.",Space,Str "9",Space,Str "}]"]]
+,Para [Str "Without",Space,Str "delimiters",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "suffix]"]]
+,Para [Str "With",Space,Str "rendering",Space,Str "label",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str "{ss",Space,Str "IV",Space,Str "div",Space,Str "4",Space,Str "s",Space,Str "128L(7)(a)(i)-(iv),",Space,Str "129(5),",SoftBreak,Str "130(b)}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey{ss",Space,Str "IV",Space,Str "div",Space,Str "4",Space,Str "s",Space,Str "128L(7)(a)(i)-(iv),",Space,Str "129(5),",SoftBreak,Str "130(b)}]"]]
+,Para [Str "The",Space,Str "text",Space,Str "is",Space,Str "apparently",Space,Str "NOT",Space,Str "verbatim;",Space,Str "it",Space,Str "is",Space,Str "lightly",Space,Str "processed",Space,Str "as",Space,Str "page",Space,Str "numbers.",SoftBreak,Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str "{no",Space,Str "comma,",Space,Str "no",Space,Str "label,",Space,Str "no",Space,Str "nothing}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey{no",Space,Str "comma,",Space,Str "no",Space,Str "label,",Space,Str "no",Space,Str "nothing}]"]]
+,Para [Str "AGLC-style",Space,Str "page",Space,Str "[para]",SoftBreak,Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str "{584",Space,Str "[78]}"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey{584",Space,Str "[78]}]"]]
+,Para [Str "Unbalanced",Space,Str "curly",Space,Str "{",Space,Str "breaks",Space,Str "the",Space,Str "parse",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str "{p.\160suffix{suffix}suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey{p.",Space,Str "suffix{suffix}suffix]"]]
+,Para [Str "Unbalanced",Space,Str "curly",Space,Str "}",Space,Str "ends",Space,Str "early",Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str "{green}suffix}suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey{green}suffix}suffix]"]]]
diff --git a/tests/locators-integrated.expected.native b/tests/locators-integrated.expected.native
new file mode 100644
--- /dev/null
+++ b/tests/locators-integrated.expected.native
@@ -0,0 +1,26 @@
+Pandoc (Meta {unMeta = fromList [("csl",MetaInlines [Str "tests/locators.csl"]),("references",MetaList [MetaMap (fromList [("id",MetaInlines [Str "citekey"]),("title",MetaInlines [Str "Title"]),("type",MetaInlines [Str "article-journal"])])]),("suppress-bibliography",MetaBool True)]})
+[Para [Str "See",Space,Link ("",["uri"],[]) [Str "https://github.com/jgm/pandoc-citeproc/pull/362"] ("https://github.com/jgm/pandoc-citeproc/pull/362",""),Str "."]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "89,",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 1}] [Note [Para [Str "Title",Space,Str "{89},",Space,Str "and",Space,Str "suffix."]]]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "89,",Space,Str "perfect",Space,Str "Ibid",Space,Str "with",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 2}] [Note [Para [Str "Ibid,",Space,Str "perfect",Space,Str "Ibid",Space,Str "with",Space,Str "suffix."]]]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "123-79,",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 3}] [Note [Para [Str "Ibid-with-locator",Space,Str "{123\8211\&79},",Space,Str "and",Space,Str "suffix."]]]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "xi,",Space,Str "will",Space,Str "be",Space,Str "entirely",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 4}] [Note [Para [Str "Subsequent,",Space,Str "xi,",Space,Str "will",Space,Str "be",Space,Str "entirely",Space,Str "suffix."]]]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "p.\160xi,",Space,Str "gives",Space,Str "you",Space,Str "a",Space,Str "(page)",Space,Str "locator",Space,Str "xi"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 5}] [Note [Para [Str "Ibid-with-locator",Space,Str "{xi},",Space,Str "gives",Space,Str "you",Space,Str "a",Space,Str "(page)",Space,Str "locator",Space,Str "xi."]]]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "pp.\160VII,",Space,Str "89,",Space,Str "gives",Space,Str "you",Space,Str "a",Space,Str "(pages)",Space,Str "locator",Space,Str "VII,",Space,Str "89"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 6}] [Note [Para [Str "Ibid-with-locator",Space,Str "{VII,",Space,Str "89},",Space,Str "gives",Space,Str "you",Space,Str "a",Space,Str "(pages)",Space,Str "locator",Space,Str "VII,",Space,Str "89."]]]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "p.\160VI,",Space,Str "VII,",Space,Str "VIII-IX,",Space,Str "explicit",Space,Str "romans"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 7}] [Note [Para [Str "Ibid-with-locator",Space,Str "{VI,",Space,Str "VII,",Space,Str "VIII\8211IX},",Space,Str "explicit",Space,Str "romans."]]]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Space,Str "[89]"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 8}] [Note [Para [Str "Ibid-with-locator",Space,Str "{[89]}."]]]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "p.",Space,Str "[89]"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 9}] [Note [Para [Str "Ibid."]]]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Space,Str "and",Space,Str "nothing",Space,Str "else"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 10}] [Note [Para [Str "Subsequent",Space,Str "and",Space,Str "nothing",Space,Str "else."]]],Str "."]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "123(4)[5]6,",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 11}] [Note [Para [Str "Ibid-with-locator",Space,Str "{123(4)[5]6},",Space,Str "and",Space,Str "suffix."]]]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "3(a),",Space,Str "4.4.8,",Space,Str "[7.6],",Space,Str "7A(2)(a)(i)-(iv)"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 12}] [Note [Para [Str "Ibid-with-locator",Space,Str "{3(a),",Space,Str "4.4.8,",Space,Str "[7.6],",Space,Str "7A(2)(a)(i)\8211(iv)}."]]]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "4B.2a.i(3.4),",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 13}] [Note [Para [Str "Ibid-with-locator",Space,Str "{4B.2a.i(3.4)},",Space,Str "and",Space,Str "suffix."]]]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "IV.2A,",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 14}] [Note [Para [Str "Ibid-with-locator",Space,Str "{IV.2A},",Space,Str "and",Space,Str "suffix."]]]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "[28],",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 15}] [Note [Para [Str "Ibid-with-locator",Space,Str "{[28]},",Space,Str "and",Space,Str "suffix."]]]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "[39-52],",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 16}] [Note [Para [Str "Ibid-with-locator",Space,Str "{[39\8211\&52]},",Space,Str "and",Space,Str "suffix."]]]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "[39]-[52],",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 17}] [Note [Para [Str "Ibid-with-locator",Space,Str "{[39]\8211[52]},",Space,Str "and",Space,Str "suffix."]]]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "s",Space,Str "123(4)(a)(iv),",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 18}] [Note [Para [Str "Ibid-with-locator",Space,Str "s",Space,Str "{123(4)(a)(iv)},",Space,Str "and",Space,Str "suffix."]]]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "ss",Space,Str "123(4)-(6),",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 19}] [Note [Para [Str "Ibid-with-locator",Space,Str "ss",Space,Str "{123(4)\8211(6)},",Space,Str "and",Space,Str "suffix."]]]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "[13],",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 20}] [Note [Para [Str "Ibid-with-locator",Space,Str "{[13]},",Space,Str "and",Space,Str "suffix."]]]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "p.3,",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 21}] [Note [Para [Str "Ibid-with-locator",Space,Str "{3},",Space,Str "and",Space,Str "suffix."]]]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "(13",Space,Str "entirely",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 22}] [Note [Para [Str "Subsequent,",Space,Str "(13",Space,Str "entirely",Space,Str "suffix."]]]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "p.a",Space,Str "entirely",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 23}] [Note [Para [Str "Ibid,",Space,Str "p.a",Space,Str "entirely",Space,Str "suffix."]]]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "s",Space,Str "(a)",Space,Str "entirely",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 24}] [Note [Para [Str "Ibid,",Space,Str "s",Space,Str "(a)",Space,Str "entirely",Space,Str "suffix."]]]]]
diff --git a/tests/locators-integrated.in.native b/tests/locators-integrated.in.native
new file mode 100644
--- /dev/null
+++ b/tests/locators-integrated.in.native
@@ -0,0 +1,26 @@
+Pandoc (Meta {unMeta = fromList [("csl",MetaInlines [Str "tests/locators.csl"]),("references",MetaList [MetaMap (fromList [("id",MetaInlines [Str "citekey"]),("title",MetaInlines [Str "Title"]),("type",MetaInlines [Str "article-journal"])])]),("suppress-bibliography",MetaBool True)]})
+[Para [Str "See",Space,Link ("",["uri"],[]) [Str "https://github.com/jgm/pandoc-citeproc/pull/362"] ("https://github.com/jgm/pandoc-citeproc/pull/362",""),Str "."]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "89,",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "89,",Space,Str "and",Space,Str "suffix]"]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "89,",Space,Str "perfect",Space,Str "Ibid",Space,Str "with",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "89,",Space,Str "perfect",Space,Str "Ibid",Space,Str "with",Space,Str "suffix]"]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "123-79,",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "123-79,",Space,Str "and",Space,Str "suffix]"]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "xi,",Space,Str "will",Space,Str "be",Space,Str "entirely",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "xi,",Space,Str "will",Space,Str "be",Space,Str "entirely",Space,Str "suffix]"]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "p.\160xi,",Space,Str "gives",Space,Str "you",Space,Str "a",Space,Str "(page)",Space,Str "locator",Space,Str "xi"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "p.\160xi,",Space,Str "gives",Space,Str "you",Space,Str "a",Space,Str "(page)",Space,Str "locator",Space,Str "xi]"]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "pp.\160VII,",Space,Str "89,",Space,Str "gives",Space,Str "you",Space,Str "a",Space,Str "(pages)",Space,Str "locator",Space,Str "VII,",Space,Str "89"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "pp.\160VII,",Space,Str "89,",Space,Str "gives",Space,Str "you",Space,Str "a",Space,Str "(pages)",Space,Str "locator",Space,Str "VII,",Space,Str "89]"]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "p.\160VI,",Space,Str "VII,",Space,Str "VIII-IX,",Space,Str "explicit",Space,Str "romans"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "p.\160VI,",Space,Str "VII,",Space,Str "VIII-IX,",Space,Str "explicit",Space,Str "romans]"]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Space,Str "[89]"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey",Space,Str "\\[89\\]]"]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "p.",Space,Str "[89]"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "p.",Space,Str "\\[89\\]]"]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Space,Str "and",Space,Str "nothing",Space,Str "else"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey",Space,Str "and",Space,Str "nothing",Space,Str "else]"],Str "."]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "123(4)[5]6,",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "123(4)\\[5\\]6,",Space,Str "and",Space,Str "suffix]"]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "3(a),",Space,Str "4.4.8,",Space,Str "[7.6],",Space,Str "7A(2)(a)(i)-(iv)"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "3(a),",Space,Str "4.4.8,",Space,Str "\\[7.6\\],",Space,Str "7A(2)(a)(i)-(iv)]"]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "4B.2a.i(3.4),",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "4B.2a.i(3.4),",Space,Str "and",Space,Str "suffix]"]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "IV.2A,",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "IV.2A,",Space,Str "and",Space,Str "suffix]"]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "[28],",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "\\[28\\],",Space,Str "and",Space,Str "suffix]"]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "[39-52],",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "\\[39-52\\],",Space,Str "and",Space,Str "suffix]"]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "[39]-[52],",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "\\[39\\]-\\[52\\],",Space,Str "and",Space,Str "suffix]"]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "s",Space,Str "123(4)(a)(iv),",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "s",Space,Str "123(4)(a)(iv),",Space,Str "and",Space,Str "suffix]"]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "ss",Space,Str "123(4)-(6),",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "ss",Space,Str "123(4)-(6),",Space,Str "and",Space,Str "suffix]"]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "[13],",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "\\[13\\],",Space,Str "and",Space,Str "suffix]"]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "p.3,",Space,Str "and",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "p.3,",Space,Str "and",Space,Str "suffix]"]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "(13",Space,Str "entirely",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "(13",Space,Str "entirely",Space,Str "suffix]"]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "p.a",Space,Str "entirely",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "p.a",Space,Str "entirely",Space,Str "suffix]"]]
+,Para [Cite [Citation {citationId = "citekey", citationPrefix = [], citationSuffix = [Str ",",Space,Str "s",Space,Str "(a)",Space,Str "entirely",Space,Str "suffix"], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@citekey,",Space,Str "s",Space,Str "(a)",Space,Str "entirely",Space,Str "suffix]"]]]
diff --git a/tests/locators.csl b/tests/locators.csl
new file mode 100644
--- /dev/null
+++ b/tests/locators.csl
@@ -0,0 +1,68 @@
+<?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>A CSL to test locator parsing in pandoc-citeproc</title>
+    <title-short>test-locators</title-short>
+    <id>https://example.com/test-locators</id>
+    <link href="https://forums.zotero.org/discussion/4841/new-australian-legal-citation-style/?Focus=20831#Comment_20831" rel="documentation"/>
+    <category citation-format="note"/>
+  </info>
+
+  <locale>
+    <terms>
+      <term name="section" form="short">
+        <single>s</single>
+        <multiple>ss</multiple>
+      </term>
+    </terms>
+  </locale>
+
+  <macro name="locator">
+    <choose>
+      <if locator="section">
+        <!-- s or ss -->
+        <group delimiter=" ">
+          <label variable="locator" form="short" />
+          <text variable="locator" prefix="{" suffix="}" />
+        </group>
+      </if>
+      <else>
+        <text variable="locator" prefix="{" suffix="}" />
+      </else>
+    </choose>
+  </macro>
+
+  <macro name="title">
+      <text variable="title" suffix=" "/>
+  </macro>
+
+  <citation>
+    <layout prefix="" suffix="." delimiter="; ">
+      <choose>
+        <if position="ibid-with-locator">
+          <text value="ibid-with-locator "/>
+          <text macro="locator"/>
+        </if>
+        <else-if position="ibid">
+          <text value="ibid"/>
+        </else-if>
+        <else-if position="subsequent">
+          <text value="subsequent "/>
+          <text macro="locator"/>
+        </else-if>
+        <else>
+          <text macro="title" />
+          <text macro="locator" />
+        </else>
+      </choose>
+    </layout>
+  </citation>
+  <bibliography>
+    <sort>
+      <key variable="issued"/>
+    </sort>
+    <layout>
+      <text variable="title" />
+    </layout>
+  </bibliography>
+</style>
