packages feed

citeproc 0.5 → 0.6

raw patch · 11 files changed

+1942/−73 lines, 11 filesdep ~data-defaultdep ~transformersPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: data-default, transformers

API changes (from Hackage documentation)

+ Citeproc.Types: TagPrefix :: Tag
+ Citeproc.Types: TagSuffix :: Tag
- Citeproc.Types: TagTerm :: Tag
+ Citeproc.Types: TagTerm :: Term -> Tag

Files

CHANGELOG.md view
@@ -1,5 +1,38 @@ # citeproc changelog +## 0.6++  * Add Term parameter to TagTerm [API change].++  * Add TagPrefix, TagSuffix constructors to Tag [API change].++  * Make sure that extracted AuthorOnly names have the correct+    formatting (#55).++  * Do case-insensitive sorting, like Zotero (#91).++  * Ignore "ibid" entries in computing ambiguities.++  * Improved disambiguation for author-in-text citations.++  * In disambiguating, convert author-in-text to normal citations.+    Otherwise we disambiguate incorrectly.++  * Fix title disambiguation with note style (#90).+    Previously we'd been calculating ambiguities by generating+    renderings for citation items independently of context.+    This meant that we didn't detect ambiguities in "subsequent"+    citations (which might e.g. just have an author).++  * Ensure we don't do collapsing of items across a prefix or suffix (#89).+    If we have `[@doe99; for contrasting views see @smith33; @doe00]`,+    we don't want to get collapsing to+    `(Doe 1999, 2000; for contrasting views, see Smith 1933)`.+    This isn't strictly by the spec, but it gives better results.++  * Allow collapsing after an initial prefix.++ ## 0.5    * Add `linkBibliography` field to `CiteprocOptions` [API change].
app/Main.hs view
@@ -32,7 +32,7 @@     putStr $ usageInfo "citeproc [OPTIONS] [FILE]" options     exitSuccess   when (optVersion opt) $ do-    putStrLn $ "citeproc version " <> VERSION_citeproc+    putStrLn $ "citeproc version " ++ VERSION_citeproc     exitSuccess   format <- case optFormat opt of               Just "html" -> return Html@@ -77,7 +77,6 @@         Left e -> err (T.unpack $ prettyCiteprocError e)         Right parsedStyle -> do           let style = parsedStyle{ styleAbbreviations = abbreviations }-          let locale = mergeLocales lang style           let result= citeproc defaultCiteprocOptions                          style                          lang
citeproc.cabal view
@@ -1,6 +1,6 @@ cabal-version:       2.2 name:                citeproc-version:             0.5+version:             0.6 synopsis:            Generates citations and bibliography from CSL styles. description:         citeproc parses CSL style files and uses them to                      generate a list of formatted citations and bibliography@@ -66,7 +66,7 @@                      , bytestring                      , text                      , containers >= 0.6.0.1 && < 0.7-                     , transformers >= 0.5.6 && < 0.6+                     , transformers >= 0.5.6 && < 0.7                      , case-insensitive >= 1.2 && < 1.3                      , vector                      , scientific
man/citeproc.1 view
@@ -1,6 +1,6 @@ .\" Automatically generated by Pandoc 2.13 .\"-.TH "citeproc" "1" "" "citeproc 0.4" ""+.TH "citeproc" "1" "" "citeproc 0.6" "" .hy .SH NAME .PP
src/Citeproc/Eval.hs view
@@ -29,11 +29,11 @@ import Data.Generics.Uniplate.Operations (universe, transform)  -- import Debug.Trace (trace)-+-- -- traceShowIdLabeled :: Show a => String -> a -> a -- traceShowIdLabeled label x = --   trace (label ++ ": " ++ show x) x-+-- -- import Text.Show.Pretty (ppShow) -- ppTrace :: Show a => a -> a -- ppTrace x = trace (ppShow x) x@@ -85,9 +85,11 @@ updateVarCount :: Int -> Int -> Eval a () updateVarCount total' nonempty' =   modify $ \st ->-    let VarCount total nonempty = stateVarCount st+    let VarCount{ variablesAccessed = total+                , variablesNonempty = nonempty } = stateVarCount st      in st{ stateVarCount =-              VarCount (total + total') (nonempty + nonempty') }+              VarCount { variablesAccessed = total + total',+                         variablesNonempty = nonempty + nonempty' } }  evalStyle  :: CiteprocOutput a            => Style a          -- ^ Parsed CSL style.@@ -155,6 +157,17 @@       let sortedCiteIds = sortOn               (fromMaybe maxBound . (`M.lookup` citationOrder))               (map referenceId refs)+      let layoutOpts = layoutOptions $ styleCitation style+      let mbcgDelim =+            case styleCiteGroupDelimiter (styleOptions style) of+              Just x -> Just x+              Nothing+                -- grouping is activated whenever there is+                -- collapsing; this is the default+                -- cite-group-delimiter+                | isJust (layoutCollapse layoutOpts) -> Just ", "+                | otherwise -> Nothing+       assignCitationNumbers sortedCiteIds       -- sorting of bibliography, insertion of citation-number       collate <- asks contextCollate@@ -222,17 +235,7 @@                         $ groupBy canGroup                         $ citationItems citation' }       let citCitations = map sortCitationItems citations-      let layoutOpts = layoutOptions $ styleCitation style       cs <- disambiguateCitations style bibSortKeyMap citCitations-      let mbcgDelim =-            case styleCiteGroupDelimiter (styleOptions style) of-              Just x -> Just x-              Nothing-                -- grouping is activated whenever there is-                -- collapsing; this is the default-                -- cite-group-delimiter-                | isJust (layoutCollapse layoutOpts) -> Just ", "-                | otherwise -> Nothing       let cs' = case mbcgDelim of                    Nothing -> cs                    Just citeGroupDelim -> map@@ -278,16 +281,14 @@                   (x@(Tagged (TagItem AuthorOnly _) _):xs) : ys)                   | isNoteCitation                     -> formatted mempty-                        (Formatted f'{ formatPrefix = Nothing-                                     , formatSuffix = Nothing } [x] :+                        (x :                          if null xs && null ys                             then []                             else [InNote (formatted f                                            (formatted f' xs : ys))])                   | otherwise                     -> Formatted mempty-                        (Formatted f'{ formatPrefix = Nothing-                                     , formatSuffix = Nothing } [x] :+                        (x :                          if null xs && null ys                             then []                             else [Literal (fromText " "),@@ -426,10 +427,26 @@   let ghostItems = [ ident                    | ident <- refIds                    , not (ident `Set.member` citeIdsSet)]++  -- for purposes of disambiguation, we remove prefixes and+  -- suffixes and locators, and we convert author-in-text to normal citation.+  let removeAffix item = item{ citationItemLabel = Nothing+                             , citationItemLocator = Nothing+                             , citationItemPrefix = Nothing+                             , citationItemSuffix = Nothing }+  let cleanCitation (Citation a b (i1:i2:is))+       | citationItemType i1 == AuthorOnly+       , citationItemType i2 == SuppressAuthor+        = Citation a b+            (map removeAffix (i2{ citationItemType = NormalCite }:is))+      cleanCitation (Citation a b is)+        = Citation a b (map removeAffix is)+   -- note that citations must go first, and order must be preserved:   -- we use a "basic item" that strips off prefixes, suffixes, locators-  let allItems = map basicItem $ citeIds ++ ghostItems-  allCites <- renderItems allItems+  let citations' = map cleanCitation citations +++                   [Citation Nothing Nothing (map basicItem ghostItems)]+  allCites <- renderCitations citations'    mblang <- asks (localeLanguage . contextLocale)   styleOpts <- asks contextStyleOptions@@ -485,55 +502,51 @@                      (unReferenceMap $ stateRefMap st)                      refIds }            -- redo citations-           renderItems allItems+           renderCitations citations'    case getAmbiguities allCites' of     []          -> return ()-    ambiguities -> analyzeAmbiguities mblang strategy ambiguities-  withRWST (\ctx st -> (ctx,-                        st { stateLastCitedMap = mempty-                           , stateNoteMap = mempty })) $-     mapM (evalLayout (styleCitation style)) (zip [1..] citations)+    ambiguities -> analyzeAmbiguities mblang strategy citations' ambiguities+  renderCitations citations   where -  renderItems :: [CitationItem a] -> Eval a [Output a]-  renderItems = withRWST (\ctx st -> (ctx,-                                      st { stateLastCitedMap = mempty-                                         , stateNoteMap = mempty })) .-                  mapM (\item ->-                          Tagged (TagItem NormalCite (citationItemId item)) . grouped <$>-                                   evalItem (styleCitation style) ([], item))+  renderCitations :: [Citation a] -> Eval a [Output a]+  renderCitations cs =+    withRWST (\ctx st -> (ctx,+                          st { stateLastCitedMap = mempty+                             , stateNoteMap = mempty })) $+     mapM (evalLayout (styleCitation style)) (zip [1..] cs) -  refreshAmbiguities :: [[DisambData]] -> Eval a [[DisambData]]-  refreshAmbiguities = fmap (concatMap getAmbiguities) .-                            mapM (renderItems . map (basicItem . ddItem))+  refreshAmbiguities :: [Citation a] -> Eval a [[DisambData]]+  refreshAmbiguities = fmap getAmbiguities . renderCitations    analyzeAmbiguities :: Maybe Lang                      -> DisambiguationStrategy+                     -> [Citation a]                      -> [[DisambData]]                      -> Eval a ()-  analyzeAmbiguities mblang strategy ambiguities = do+  analyzeAmbiguities mblang strategy cs ambiguities = do     -- add names to et al.     return ambiguities       >>= (\as ->            (if not (null as) && disambiguateAddNames strategy                then do                  mapM_ (tryAddNames mblang (disambiguateAddGivenNames strategy)) as-                 refreshAmbiguities as+                 refreshAmbiguities cs                else                  return as))       >>= (\as ->            (case disambiguateAddGivenNames strategy of                   Just ByCite | not (null as) -> do                      mapM_ (tryAddGivenNames mblang) as-                     refreshAmbiguities as+                     refreshAmbiguities cs                   _           -> return as))       >>= (\as ->            (if not (null as) && disambiguateAddYearSuffix strategy                then do                  addYearSuffixes bibSortKeyMap as-                 refreshAmbiguities as+                 refreshAmbiguities cs                else return as))       >>= mapM_ tryDisambiguateCondition @@ -729,14 +742,27 @@       . groupBy (\x y -> ddRendered x == ddRendered y)       . sortOn ddRendered       . map toDisambData+      . extractTagItems -toDisambData :: CiteprocOutput a => Output a -> DisambData-toDisambData (Tagged (TagItem NormalCite iid) x) =+extractTagItems :: [Output a] -> [(ItemId, Output a)]+extractTagItems xs =+  [(iid, x) | Tagged (TagItem NormalCite iid) x <- concatMap universe xs+            , not (hasIbid x)]+ where -- we don't want two "ibid" entries to be treated as ambiguous.+  hasIbid x = not $ null [ trm | Tagged (TagTerm trm) _ <- universe x+                               , termName trm == "ibid" ]+++toDisambData :: CiteprocOutput a => (ItemId, Output a) -> DisambData+toDisambData (iid, x) =   let xs = universe x       ns' = getNames xs       ds' = getDates xs       t   = outputToText x-   in DisambData iid ns' ds' t+   in DisambData { ddItem = iid+                 , ddNames = ns'+                 , ddDates = ds'+                 , ddRendered = t }  where   getNames :: [Output a] -> [Name]   getNames (Tagged (TagNames _ _ ns) _ : xs)@@ -749,7 +775,6 @@                   = d : getDates xs   getDates (_ : xs)   = getDates xs   getDates []         = []-toDisambData _ = error "toDisambData called without tagged item"   --@@ -779,13 +804,30 @@                  (groupWith sameNames xs)  where   --   Note that we cannot assume we've sorted by name,-  --   so we can't just use Data.ListgroupBy-  groupWith :: (b -> b -> Bool) -> [b] -> [[b]]+  --   so we can't just use Data.ListgroupBy.  We also+  --   take care not to move anything past a prefix or suffix.+  groupWith :: (Output a -> Output a -> Bool)+            -> [Output a]+            -> [[Output a]]   groupWith _ [] = []-  groupWith isMatched (z:zs) =-    (z : filter (isMatched z) zs) :-         groupWith isMatched (filter (not . isMatched z) zs)+  groupWith isMatched (z:zs)+   | hasSuffix z = [z] : groupWith isMatched zs+   | otherwise =  -- we allow a prefix on first item in collapsed group+    case span hasNoPrefixOrSuffix zs of+      ([],ys) -> [z] : groupWith isMatched ys+      (ws,ys) ->+        (z : filter (isMatched z) ws) :+          groupWith isMatched (filter (not . isMatched z) ws ++ ys) +  hasNoPrefixOrSuffix :: Output a -> Bool+  hasNoPrefixOrSuffix x = not (hasPrefix x) && not (hasSuffix x)++  hasPrefix :: Output a -> Bool+  hasPrefix x = not $ null [y | y@(Tagged TagPrefix _) <- universe x]++  hasSuffix :: Output a -> Bool+  hasSuffix x = not $ null [y | y@(Tagged TagSuffix _) <- universe x]+   collapseRange :: [Output a] -> [Output a] -> [Output a]   collapseRange ys zs     | length ys >= 3@@ -982,8 +1024,9 @@              <$> mapM getNamePartSortOrder ns       Just (DateVal d)  -> return $ Just [T.toLower $ dateToText d] +-- Note: we do a case-insensitive sort (using toCaseFold): normalizeSortKey :: Text -> [Text]-normalizeSortKey = filter (not . T.null) . T.split isWordSep+normalizeSortKey = filter (not . T.null) . T.split isWordSep . T.toCaseFold  where   isWordSep c = isSpace c || c == '\'' || c == '’' || c == ',' ||                 c == 'ʾ' || c == 'ʿ' -- ayn/hamza in transliterated arabic@@ -1104,9 +1147,9 @@       updateLastCitedMap citationGroupNumber positionInCitation citation item      return $-          maybe id (\pref x -> grouped [Literal pref, x])+          maybe id (\pref x -> Tagged TagPrefix (grouped [Literal pref, x]))                 (citationItemPrefix item)-        . maybe id (\suff x -> grouped [x, Literal suff])+        . maybe id (\suff x -> Tagged TagSuffix (grouped [x, Literal suff]))                    (citationItemSuffix item)         . (\x -> case x of                    NullOutput -> x@@ -1154,8 +1197,8 @@           }))         $ do xs <- mconcat <$> mapM eElement (layoutElements layout) -             -- find identifiers that can be used to hyperlink the title -             let mbident = +             -- find identifiers that can be used to hyperlink the title+             let mbident =                     foldl (<|>) Nothing                       [ IdentDOI   <$> (valToText =<< lookupVariable "DOI" ref)                       , IdentPMCID <$> (valToText =<< lookupVariable "PMCID" ref)@@ -1163,14 +1206,14 @@                       , IdentURL   <$> (valToText =<< lookupVariable "URL" ref)                       ]              let mburl = identifierToURL <$> mbident-            +              -- hyperlink any titles in the output              let linkTitle url (Tagged TagTitle x) = Linked url [Tagged TagTitle x]                  linkTitle _ x = x-             +              usedLink  <- gets stateUsedIdentifier              usedTitle <- gets stateUsedTitle-             inBiblio  <- asks contextInBibliography +             inBiblio  <- asks contextInBibliography               -- when no links were rendered for a bibliography item, hyperlink              -- the title, if it exists, otherwise hyperlink the whole item@@ -1183,7 +1226,7 @@                                         -- hyperlink the title                                         then fmap (transform (linkTitle url)) xs                                         -- hyperlink the entire bib item-                                        else [Linked url xs] +                                        else [Linked url xs]               let mblang = lookupVariable "language" ref                           >>= valToText@@ -1263,8 +1306,8 @@ capitalizeInitialTerm [] = [] capitalizeInitialTerm (z:zs) = go z : zs  where-  go (Tagged TagTerm x) =-    Tagged TagTerm+  go (Tagged (TagTerm t) x) =+    Tagged (TagTerm t)       (formatted mempty{ formatTextCase = Just CapitalizeFirst } [x])   go (Formatted f xs) = Formatted f (capitalizeInitialTerm xs)   go (Tagged tg x) = Tagged tg (go x)@@ -1586,7 +1629,7 @@             let url = identifierToURL (identConstr t)             return $ Linked url [Literal $ fromText t]       handleSubst :: Eval a ()-      handleSubst = do inSubst <- asks contextInSubstitute +      handleSubst = do inSubst <- asks contextInSubstitute                        when inSubst $                          modify $ \st -> -- delete variable so it isn't used again...                            st{ stateReference =@@ -1608,7 +1651,7 @@                     -> return $ grouped [t', Literal (fromText " "), suff]                   | otherwise -> return $ grouped [t', suff]             else return t'-  return $ Tagged TagTerm t''+  return $ Tagged (TagTerm term) t''   -- Numbers with prefixes or suffixes are never ordinalized@@ -1955,8 +1998,12 @@                    else return vars               else return vars   inSubstitute <- asks contextInSubstitute-  let (nameFormat, nameFormatting) =-        fromMaybe (defaultNameFormat, mempty) $ namesName namesFormat+  let (nameFormat, nameFormatting') =+        fromMaybe (defaultNameFormat, mempty) (namesName namesFormat)+  let nameFormatting = nameFormatting' <>+                       formatting{ formatPrefix = Nothing+                                 , formatSuffix = Nothing+                                 , formatDelimiter = Nothing }   rawContribs <- mapM (\var -> (var,) <$>                        askVariable                        (if var == "editortranslator"@@ -1995,7 +2042,10 @@              CountName -> Literal $ fromText $ T.pack $ show $ length                [name                  | Tagged (TagName name) _ <- concatMap universe xs]-             _ -> formatted formatting xs+             _ -> formatted mempty{ formatPrefix = formatPrefix formatting+                                  , formatSuffix = formatSuffix formatting+                                  , formatDelimiter =+                                    formatDelimiter formatting } xs  eSubstitute :: CiteprocOutput a             => [Element a]
src/Citeproc/Types.hs view
@@ -1492,7 +1492,7 @@                    else x  data Tag =-      TagTerm+      TagTerm Term     | TagCitationNumber Int     | TagCitationLabel     | TagTitle@@ -1503,6 +1503,8 @@     | TagDate Date     | TagYearSuffix Int     | TagLocator+    | TagPrefix+    | TagSuffix   deriving (Show, Eq)  outputToText :: CiteprocOutput a => Output a -> Text
test/Spec.hs view
@@ -1,10 +1,10 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE StrictData #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE OverloadedStrings #-} module Main (main) where import Citeproc import Citeproc.CslJson-import Data.Semigroup import Data.Algorithm.DiffContext import System.TimeIt (timeIt) import Control.Monad (unless)@@ -30,6 +30,9 @@ import System.FilePath import Data.Maybe (fromMaybe) import Text.Printf (printf)+#if !MIN_VERSION_base(4,11,0)+import Data.Semigroup+#endif  data CiteprocTest a =   CiteprocTest@@ -336,7 +339,7 @@                (length (skipped counts))   case length (failed counts) + length (errored counts) of     0 -> exitSuccess-    n | n <= 66 -> do+    n | n <= 65 -> do          putStrLn "We have passed all the CSL tests we expect to..."          exitSuccess       | otherwise -> exitWith $ ExitFailure n
+ test/extra/case_insensitive.txt view
@@ -0,0 +1,63 @@+Zotero does a case-insensitive sort, so we will too.++>>===== MODE =====>>+bibliography+<<===== MODE =====<<++++>>===== RESULT =====>>+<div class="csl-bib-body">+  <div class="csl-entry">The Civil Law</div>+  <div class="csl-entry">The civil life</div>+</div>+<<===== RESULT =====<<+++>>===== CSL =====>>+<style +      xmlns="http://purl.org/net/xbiblio/csl"+      class="note"+      version="1.0">+  <info>+    <id />+    <title />+    <updated>2009-08-10T04:49:00+09:00</updated>+  </info>+  <citation>+    <layout>+      <text value="dummy"/>+    </layout>+  </citation>+  <bibliography>+    <sort>+      <text variable="title"/>+    </sort>+    <layout>+      <text variable="title"/>+    </layout>+  </bibliography>+</style>+<<===== CSL =====<<+++>>===== INPUT =====>>+[+    {+        "title": "The Civil Law",+        "id": "ITEM-1",+        "type": "book"+    },+    {+        "title": "The civil life",+        "id": "ITEM-2",+        "type": "book"+    }+]+<<===== INPUT =====<<+++>>===== VERSION =====>>+1.0+<<===== VERSION =====<<+
+ test/extra/disambiguation-author-in-text.txt view
@@ -0,0 +1,781 @@+>>===== MODE =====>>+citation+<<===== MODE =====<<+++++>>===== RESULT =====>>+<i>Magazine</i> (2012a, 3)+<i>Magazine</i> (2012b)+<i>Magazine</i> (2012c)+<i>Magazine</i> (2012d)+<i>Newspaper</i> (2012a)+<i>Newspaper</i> (2012b)+<<===== RESULT =====<<+++>>===== CSL =====>>+<?xml version="1.0" encoding="utf-8"?>+<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="display-and-sort" page-range-format="chicago">+  <info>+    <title>Chicago Manual of Style 17th edition (author-date)</title>+    <id>http://www.zotero.org/styles/chicago-author-date</id>+    <link href="http://www.zotero.org/styles/chicago-author-date" rel="self"/>+    <link href="http://www.chicagomanualofstyle.org/tools_citationguide.html" rel="documentation"/>+    <author>+      <name>Julian Onions</name>+      <email>julian.onions@gmail.com</email>+    </author>+    <contributor>+      <name>Sebastian Karcher</name>+    </contributor>+    <contributor>+      <name>Richard Karnesky</name>+      <email>karnesky+zotero@gmail.com</email>+      <uri>http://arc.nucapt.northwestern.edu/Richard_Karnesky</uri>+    </contributor>+    <contributor>+      <name>Andrew Dunning</name>+      <email>andrew.dunning@utoronto.ca</email>+      <uri>https://orcid.org/0000-0003-0464-5036</uri>+    </contributor>+    <contributor>+      <name>Matthew Roth</name>+      <email>matthew.g.roth@yale.edu</email>+      <uri> https://orcid.org/0000-0001-7902-6331</uri>+    </contributor>+    <contributor>+      <name>Brenton M. Wiernik</name>+    </contributor>+    <category citation-format="author-date"/>+    <category field="generic-base"/>+    <summary>The author-date variant of the Chicago style</summary>+    <updated>2018-01-24T12:00:00+00:00</updated>+    <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>+  </info>+  <locale xml:lang="en">+    <terms>+      <term name="editor" form="verb-short">ed.</term>+      <term name="container-author" form="verb">by</term>+      <term name="translator" form="verb-short">trans.</term>+      <term name="editortranslator" form="verb">edited and translated by</term>+      <term name="translator" form="short">trans.</term>+    </terms>+  </locale>+  <macro name="secondary-contributors">+    <choose>+      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="none">+        <group delimiter=". ">+          <names variable="editor translator" delimiter=". ">+            <label form="verb" text-case="capitalize-first" suffix=" "/>+            <name and="text" delimiter=", "/>+          </names>+          <names variable="director" delimiter=". ">+            <label form="verb" text-case="capitalize-first" suffix=" "/>+            <name and="text" delimiter=", "/>+          </names>+        </group>+      </if>+    </choose>+  </macro>+  <macro name="container-contributors">+    <choose>+      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">+        <group prefix=", " delimiter=", ">+          <names variable="container-author" delimiter=", ">+            <label form="verb" suffix=" "/>+            <name and="text" delimiter=", "/>+          </names>+          <names variable="editor translator" delimiter=", ">+            <label form="verb" suffix=" "/>+            <name and="text" delimiter=", "/>+          </names>+        </group>+      </if>+    </choose>+  </macro>+  <macro name="editor">+    <names variable="editor">+      <name name-as-sort-order="first" and="text" sort-separator=", " delimiter=", " delimiter-precedes-last="always"/>+      <label form="short" prefix=", "/>+    </names>+  </macro>+  <macro name="translator">+    <names variable="translator">+      <name name-as-sort-order="first" and="text" sort-separator=", " delimiter=", " delimiter-precedes-last="always"/>+      <label form="short" prefix=", "/>+    </names>+  </macro>+  <macro name="recipient">+    <choose>+      <if type="personal_communication">+        <choose>+          <if variable="genre">+            <text variable="genre" text-case="capitalize-first"/>+          </if>+          <else>+            <text term="letter" text-case="capitalize-first"/>+          </else>+        </choose>+      </if>+    </choose>+    <names variable="recipient" delimiter=", ">+      <label form="verb" prefix=" " text-case="lowercase" suffix=" "/>+      <name and="text" delimiter=", "/>+    </names>+  </macro>+  <macro name="substitute-title">+    <choose>+      <if type="article-magazine article-newspaper review review-book" match="any">+        <text macro="container-title"/>+      </if>+    </choose>+  </macro>+  <macro name="contributors">+    <group delimiter=". ">+      <names variable="author">+        <name and="text" name-as-sort-order="first" sort-separator=", " delimiter=", " delimiter-precedes-last="always"/>+        <label form="short" prefix=", "/>+        <substitute>+          <names variable="editor"/>+          <names variable="translator"/>+          <names variable="director"/>+          <text macro="substitute-title"/>+          <text macro="title"/>+        </substitute>+      </names>+      <text macro="recipient"/>+    </group>+  </macro>+  <macro name="contributors-short">+    <names variable="author">+      <name form="short" and="text" delimiter=", " initialize-with=". "/>+      <substitute>+        <names variable="editor"/>+        <names variable="translator"/>+        <names variable="director"/>+        <text macro="substitute-title"/>+        <text macro="title"/>+      </substitute>+    </names>+  </macro>+  <macro name="interviewer">+    <names variable="interviewer" delimiter=", ">+      <label form="verb" prefix=" " text-case="capitalize-first" suffix=" "/>+      <name and="text" delimiter=", "/>+    </names>+  </macro>+  <macro name="archive">+    <group delimiter=". ">+      <text variable="archive_location" text-case="capitalize-first"/>+      <text variable="archive"/>+      <text variable="archive-place"/>+    </group>+  </macro>+  <macro name="access">+    <group delimiter=". ">+      <choose>+        <if type="graphic report" match="any">+          <text macro="archive"/>+        </if>+        <else-if type="article-journal bill book chapter legal_case legislation motion_picture paper-conference" match="none">+          <text macro="archive"/>+        </else-if>+      </choose>+      <choose>+        <if type="webpage post-weblog" match="any">+          <date variable="issued" form="text"/>+        </if>+      </choose>+      <choose>+        <if variable="issued" match="none">+          <group delimiter=" ">+            <text term="accessed" text-case="capitalize-first"/>+            <date variable="accessed" form="text"/>+          </group>+        </if>+      </choose>+      <choose>+        <if type="legal_case" match="none">+          <choose>+            <if variable="DOI">+              <text variable="DOI" prefix="https://doi.org/"/>+            </if>+            <else>+              <text variable="URL"/>+            </else>+          </choose>+        </if>+      </choose>+    </group>+  </macro>+  <macro name="title">+    <choose>+      <if variable="title" match="none">+        <choose>+          <if type="personal_communication" match="none">+            <text variable="genre" text-case="capitalize-first"/>+          </if>+        </choose>+      </if>+      <else-if type="bill book graphic legislation motion_picture song" match="any">+        <text variable="title" text-case="title" font-style="italic"/>+        <group prefix=" (" suffix=")" delimiter=" ">+          <text term="version"/>+          <text variable="version"/>+        </group>+      </else-if>+      <else-if variable="reviewed-author">+        <choose>+          <if variable="reviewed-title">+            <group delimiter=". ">+              <text variable="title" text-case="title" quotes="true"/>+              <group delimiter=", ">+                <text variable="reviewed-title" text-case="title" font-style="italic" prefix="Review of "/>+                <names variable="reviewed-author">+                  <label form="verb-short" text-case="lowercase" suffix=" "/>+                  <name and="text" delimiter=", "/>+                </names>+              </group>+            </group>+          </if>+          <else>+            <group delimiter=", ">+              <text variable="title" text-case="title" font-style="italic" prefix="Review of "/>+              <names variable="reviewed-author">+                <label form="verb-short" text-case="lowercase" suffix=" "/>+                <name and="text" delimiter=", "/>+              </names>+            </group>+          </else>+        </choose>+      </else-if>+      <else-if type="legal_case interview patent" match="any">+        <text variable="title"/>+      </else-if>+      <else>+        <text variable="title" text-case="title" quotes="true"/>+      </else>+    </choose>+  </macro>+  <macro name="edition">+    <choose>+      <if type="bill book graphic legal_case legislation motion_picture report song" match="any">+        <choose>+          <if is-numeric="edition">+            <group delimiter=" " prefix=". ">+              <number variable="edition" form="ordinal"/>+              <text term="edition" form="short" strip-periods="true"/>+            </group>+          </if>+          <else>+            <text variable="edition" text-case="capitalize-first" prefix=". "/>+          </else>+        </choose>+      </if>+      <else-if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">+        <choose>+          <if is-numeric="edition">+            <group delimiter=" " prefix=", ">+              <number variable="edition" form="ordinal"/>+              <text term="edition" form="short"/>+            </group>+          </if>+          <else>+            <text variable="edition" prefix=", "/>+          </else>+        </choose>+      </else-if>+    </choose>+  </macro>+  <macro name="locators">+    <choose>+      <if type="article-journal">+        <choose>+          <if variable="volume">+            <text variable="volume" prefix=" "/>+            <group prefix=" (" suffix=")">+              <choose>+                <if variable="issue">+                  <text variable="issue"/>+                </if>+                <else>+                  <date variable="issued">+                    <date-part name="month"/>+                  </date>+                </else>+              </choose>+            </group>+          </if>+          <else-if variable="issue">+            <group delimiter=" " prefix=", ">+              <text term="issue" form="short"/>+              <text variable="issue"/>+              <date variable="issued" prefix="(" suffix=")">+                <date-part name="month"/>+              </date>+            </group>+          </else-if>+          <else>+            <date variable="issued" prefix=", ">+              <date-part name="month"/>+            </date>+          </else>+        </choose>+      </if>+      <else-if type="legal_case">+        <text variable="volume" prefix=", "/>+        <text variable="container-title" prefix=" "/>+        <text variable="page" prefix=" "/>+      </else-if>+      <else-if type="bill book graphic legal_case legislation motion_picture report song" match="any">+        <group prefix=". " delimiter=". ">+          <group>+            <text term="volume" form="short" text-case="capitalize-first" suffix=" "/>+            <number variable="volume" form="numeric"/>+          </group>+          <group>+            <number variable="number-of-volumes" form="numeric"/>+            <text term="volume" form="short" prefix=" " plural="true"/>+          </group>+        </group>+      </else-if>+      <else-if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">+        <choose>+          <if variable="page" match="none">+            <group prefix=". ">+              <text term="volume" form="short" text-case="capitalize-first" suffix=" "/>+              <number variable="volume" form="numeric"/>+            </group>+          </if>+        </choose>+      </else-if>+    </choose>+  </macro>+  <macro name="locators-chapter">+    <choose>+      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">+        <choose>+          <if variable="page">+            <group prefix=", ">+              <text variable="volume" suffix=":"/>+              <text variable="page"/>+            </group>+          </if>+        </choose>+      </if>+    </choose>+  </macro>+  <macro name="locators-article">+    <choose>+      <if type="article-newspaper">+        <group prefix=", " delimiter=", ">+          <group delimiter=" ">+            <text variable="edition"/>+            <text term="edition"/>+          </group>+          <group>+            <text term="section" form="short" suffix=" "/>+            <text variable="section"/>+          </group>+        </group>+      </if>+      <else-if type="article-journal">+        <choose>+          <if variable="volume issue" match="any">+            <text variable="page" prefix=": "/>+          </if>+          <else>+            <text variable="page" prefix=", "/>+          </else>+        </choose>+      </else-if>+    </choose>+  </macro>+  <macro name="point-locators">+    <choose>+      <if variable="locator">+        <choose>+          <if locator="page" match="none">+            <choose>+              <if type="bill book graphic legal_case legislation motion_picture report song" match="any">+                <choose>+                  <if variable="volume">+                    <group>+                      <text term="volume" form="short" suffix=" "/>+                      <number variable="volume" form="numeric"/>+                      <label variable="locator" form="short" prefix=", " suffix=" "/>+                    </group>+                  </if>+                  <else>+                    <label variable="locator" form="short" suffix=" "/>+                  </else>+                </choose>+              </if>+              <else>+                <label variable="locator" form="short" suffix=" "/>+              </else>+            </choose>+          </if>+          <else-if type="bill book graphic legal_case legislation motion_picture report song" match="any">+            <number variable="volume" form="numeric" suffix=":"/>+          </else-if>+        </choose>+        <text variable="locator"/>+      </if>+    </choose>+  </macro>+  <macro name="container-prefix">+    <text term="in" text-case="capitalize-first"/>+  </macro>+  <macro name="container-title">+    <choose>+      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">+        <text macro="container-prefix" suffix=" "/>+      </if>+    </choose>+    <choose>+      <if type="webpage">+        <text variable="container-title" text-case="title"/>+      </if>+      <else-if type="legal_case" match="none">+        <group delimiter=" ">+          <text variable="container-title" text-case="title" font-style="italic"/>+          <choose>+            <if type="post-weblog">+              <text value="(blog)"/>+            </if>+          </choose>+        </group>+      </else-if>+    </choose>+  </macro>+  <macro name="publisher">+    <group delimiter=": ">+      <text variable="publisher-place"/>+      <text variable="publisher"/>+    </group>+  </macro>+  <macro name="date">+    <choose>+      <if variable="issued">+        <group delimiter=" ">+          <date variable="original-date" form="text" date-parts="year" prefix="(" suffix=")"/>+          <date variable="issued">+            <date-part name="year"/>+          </date>+        </group>+      </if>+      <else-if variable="status">+        <text variable="status" text-case="capitalize-first"/>+      </else-if>+      <else>+        <text term="no date" form="short"/>+      </else>+    </choose>+  </macro>+  <macro name="date-in-text">+    <choose>+      <if variable="issued">+        <group delimiter=" ">+          <date variable="original-date" form="text" date-parts="year" prefix="[" suffix="]"/>+          <date variable="issued">+            <date-part name="year"/>+          </date>+        </group>+      </if>+      <else-if variable="status">+        <text variable="status"/>+      </else-if>+      <else>+        <text term="no date" form="short"/>+      </else>+    </choose>+  </macro>+  <macro name="day-month">+    <date variable="issued">+      <date-part name="month"/>+      <date-part name="day" prefix=" "/>+    </date>+  </macro>+  <macro name="collection-title">+    <choose>+      <if match="none" type="article-journal">+        <choose>+          <if match="none" is-numeric="collection-number">+            <group delimiter=", ">+              <text variable="collection-title" text-case="title"/>+              <text variable="collection-number"/>+            </group>+          </if>+          <else>+            <group delimiter=" ">+              <text variable="collection-title" text-case="title"/>+              <text variable="collection-number"/>+            </group>+          </else>+        </choose>+      </if>+    </choose>+  </macro>+  <macro name="collection-title-journal">+    <choose>+      <if type="article-journal">+        <group delimiter=" ">+          <text variable="collection-title"/>+          <text variable="collection-number"/>+        </group>+      </if>+    </choose>+  </macro>+  <macro name="event">+    <group delimiter=" ">+      <choose>+        <if variable="genre">+          <text term="presented at"/>+        </if>+        <else>+          <text term="presented at" text-case="capitalize-first"/>+        </else>+      </choose>+      <text variable="event"/>+    </group>+  </macro>+  <macro name="description">+    <choose>+      <if type="interview">+        <group delimiter=". ">+          <text macro="interviewer"/>+          <text variable="medium" text-case="capitalize-first"/>+        </group>+      </if>+      <else-if type="patent">+        <group delimiter=" " prefix=". ">+          <text variable="authority"/>+          <text variable="number"/>+        </group>+      </else-if>+      <else>+        <text variable="medium" text-case="capitalize-first" prefix=". "/>+      </else>+    </choose>+    <choose>+      <if variable="title" match="none"/>+      <else-if type="thesis personal_communication speech" match="any"/>+      <else>+        <group delimiter=" " prefix=". ">+          <text variable="genre" text-case="capitalize-first"/>+          <choose>+            <if type="report">+              <text variable="number"/>+            </if>+          </choose>+        </group>+      </else>+    </choose>+  </macro>+  <macro name="issue">+    <choose>+      <if type="legal_case">+        <text variable="authority" prefix=". "/>+      </if>+      <else-if type="speech">+        <group prefix=". " delimiter=", ">+          <group delimiter=" ">+            <text variable="genre" text-case="capitalize-first"/>+            <text macro="event"/>+          </group>+          <text variable="event-place"/>+          <text macro="day-month"/>+        </group>+      </else-if>+      <else-if type="article-newspaper article-magazine personal_communication" match="any">+        <date variable="issued" form="text" prefix=", "/>+      </else-if>+      <else-if type="patent">+        <group delimiter=", " prefix=", ">+          <group delimiter=" ">+            <!--Needs Localization-->+            <text value="filed"/>+            <date variable="submitted" form="text"/>+          </group>+          <group delimiter=" ">+            <choose>+              <if variable="issued submitted" match="all">+                <text term="and"/>+              </if>+            </choose>+            <!--Needs Localization-->+            <text value="issued"/>+            <date variable="issued" form="text"/>+          </group>+        </group>+      </else-if>+      <else-if type="article-journal" match="any"/>+      <else>+        <group prefix=". " delimiter=", ">+          <choose>+            <if type="thesis">+              <text variable="genre" text-case="capitalize-first"/>+            </if>+          </choose>+          <text macro="publisher"/>+        </group>+      </else>+    </choose>+  </macro>+  <citation et-al-min="4" et-al-use-first="1" disambiguate-add-year-suffix="true" disambiguate-add-names="true" disambiguate-add-givenname="true" givenname-disambiguation-rule="primary-name" collapse="year" after-collapse-delimiter="; ">+    <layout prefix="(" suffix=")" delimiter="; ">+      <group delimiter=", ">+        <choose>+          <if variable="issued accessed" match="any">+            <group delimiter=" ">+              <text macro="contributors-short"/>+              <text macro="date-in-text"/>+            </group>+          </if>+          <!---comma before forthcoming and n.d.-->+          <else>+            <group delimiter=", ">+              <text macro="contributors-short"/>+              <text macro="date-in-text"/>+            </group>+          </else>+        </choose>+        <text macro="point-locators"/>+      </group>+    </layout>+  </citation>+  <bibliography hanging-indent="true" et-al-min="11" et-al-use-first="7" subsequent-author-substitute="&#8212;&#8212;&#8212;" entry-spacing="0">+    <sort>+      <key macro="contributors"/>+      <key variable="issued"/>+      <key variable="title"/>+    </sort>+    <layout suffix=".">+      <group delimiter=". ">+        <text macro="contributors"/>+        <text macro="date"/>+        <text macro="title"/>+      </group>+      <text macro="description"/>+      <text macro="secondary-contributors" prefix=". "/>+      <text macro="container-title" prefix=". "/>+      <text macro="container-contributors"/>+      <text macro="edition"/>+      <text macro="locators-chapter"/>+      <text macro="collection-title-journal" prefix=", " suffix=", "/>+      <text macro="locators"/>+      <text macro="collection-title" prefix=". "/>+      <text macro="issue"/>+      <text macro="locators-article"/>+      <text macro="access" prefix=". "/>+    </layout>+  </bibliography>+</style>+<<===== CSL =====<<++>>===== CITATION-ITEMS =====>>+[ [ {"id":"item1","type":"author-only"}+  , {"id":"item1","type":"suppress-author","locator":"3","label":"page"}]+, [ {"id":"item2","type":"author-only"}+  , {"id":"item2","type":"suppress-author"} ]+, [ {"id":"item3","type":"author-only"}+  , {"id":"item3","type":"suppress-author"} ]+, [ {"id":"item4","type":"author-only"}+  , {"id":"item4","type":"suppress-author"} ]+, [ {"id":"item5","type":"author-only"}+  , {"id":"item5","type":"suppress-author"} ]+, [ {"id":"item6","type":"author-only"}+  , {"id":"item6","type":"suppress-author"} ] ]+<<===== CITATION-ITEMS =====<<++>>===== INPUT =====>>+[+  {+    "container-title": "Magazine",+    "id": "item1",+    "issued": {+      "date-parts": [+        [+          2012+        ]+      ]+    },+    "title": "Title A",+    "type": "article-magazine"+  },+  {+    "container-title": "Magazine",+    "id": "item2",+    "issued": {+      "date-parts": [+        [+          2012+        ]+      ]+    },+    "title": "Title B",+    "type": "article-magazine"+  },+  {+    "container-title": "Magazine",+    "id": "item3",+    "issued": {+      "date-parts": [+        [+          2012+        ]+      ]+    },+    "title": "Title C",+    "type": "article-magazine"+  },+  {+    "container-title": "Magazine",+    "id": "item4",+    "issued": {+      "date-parts": [+        [+          2012+        ]+      ]+    },+    "title": "Title D",+    "type": "article-magazine"+  },+  {+    "container-title": "Newspaper",+    "id": "item5",+    "issued": {+      "date-parts": [+        [+          2012+        ]+      ]+    },+    "title": "Title E",+    "type": "article-magazine"+  },+  {+    "container-title": "Newspaper",+    "id": "item6",+    "issued": {+      "date-parts": [+        [+          2012+        ]+      ]+    },+    "title": "Title F",+    "type": "article-magazine"+  }+]+<<===== INPUT =====<<+++>>===== VERSION =====>>+1.0+<<===== VERSION =====<<+
+ test/extra/issue_89.txt view
@@ -0,0 +1,735 @@+>>===== MODE =====>>+citation+<<===== MODE =====<<+++++>>===== RESULT =====>>+(Doe 2020; see also Cork 2018; Doe 2019)+<<===== RESULT =====<<+++>>===== CSL =====>>+<?xml version="1.0" encoding="utf-8"?>+<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="display-and-sort" page-range-format="chicago">+  <info>+    <title>Chicago Manual of Style 17th edition (author-date)</title>+    <id>http://www.zotero.org/styles/chicago-author-date</id>+    <link href="http://www.zotero.org/styles/chicago-author-date" rel="self"/>+    <link href="http://www.chicagomanualofstyle.org/tools_citationguide.html" rel="documentation"/>+    <author>+      <name>Julian Onions</name>+      <email>julian.onions@gmail.com</email>+    </author>+    <contributor>+      <name>Sebastian Karcher</name>+    </contributor>+    <contributor>+      <name>Richard Karnesky</name>+      <email>karnesky+zotero@gmail.com</email>+      <uri>http://arc.nucapt.northwestern.edu/Richard_Karnesky</uri>+    </contributor>+    <contributor>+      <name>Andrew Dunning</name>+      <email>andrew.dunning@utoronto.ca</email>+      <uri>https://orcid.org/0000-0003-0464-5036</uri>+    </contributor>+    <contributor>+      <name>Matthew Roth</name>+      <email>matthew.g.roth@yale.edu</email>+      <uri> https://orcid.org/0000-0001-7902-6331</uri>+    </contributor>+    <category citation-format="author-date"/>+    <category field="generic-base"/>+    <summary>The author-date variant of the Chicago style</summary>+    <updated>2018-01-24T12:00:00+00:00</updated>+    <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>+  </info>+  <locale xml:lang="en">+    <terms>+      <term name="editor" form="verb-short">ed.</term>+      <term name="container-author" form="verb">by</term>+      <term name="translator" form="verb-short">trans.</term>+      <term name="editortranslator" form="verb">edited and translated by</term>+      <term name="translator" form="short">trans.</term>+    </terms>+  </locale>+  <macro name="secondary-contributors">+    <choose>+      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="none">+        <group delimiter=". ">+          <names variable="editor translator" delimiter=". ">+            <label form="verb" text-case="capitalize-first" suffix=" "/>+            <name and="text" delimiter=", "/>+          </names>+          <names variable="director" delimiter=". ">+            <label form="verb" text-case="capitalize-first" suffix=" "/>+            <name and="text" delimiter=", "/>+          </names>+        </group>+      </if>+    </choose>+  </macro>+  <macro name="container-contributors">+    <choose>+      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">+        <group prefix=", " delimiter=", ">+          <names variable="container-author" delimiter=", ">+            <label form="verb" suffix=" "/>+            <name and="text" delimiter=", "/>+          </names>+          <names variable="editor translator" delimiter=", ">+            <label form="verb" suffix=" "/>+            <name and="text" delimiter=", "/>+          </names>+        </group>+      </if>+    </choose>+  </macro>+  <macro name="editor">+    <names variable="editor">+      <name name-as-sort-order="first" and="text" sort-separator=", " delimiter=", " delimiter-precedes-last="always"/>+      <label form="short" prefix=", "/>+    </names>+  </macro>+  <macro name="translator">+    <names variable="translator">+      <name name-as-sort-order="first" and="text" sort-separator=", " delimiter=", " delimiter-precedes-last="always"/>+      <label form="short" prefix=", "/>+    </names>+  </macro>+  <macro name="recipient">+    <choose>+      <if type="personal_communication">+        <choose>+          <if variable="genre">+            <text variable="genre" text-case="capitalize-first"/>+          </if>+          <else>+            <text term="letter" text-case="capitalize-first"/>+          </else>+        </choose>+      </if>+    </choose>+    <names variable="recipient" delimiter=", ">+      <label form="verb" prefix=" " text-case="lowercase" suffix=" "/>+      <name and="text" delimiter=", "/>+    </names>+  </macro>+  <macro name="substitute-title">+    <choose>+      <if type="article-magazine article-newspaper review review-book" match="any">+        <text macro="container-title"/>+      </if>+    </choose>+  </macro>+  <macro name="contributors">+    <group delimiter=". ">+      <names variable="author">+        <name and="text" name-as-sort-order="first" sort-separator=", " delimiter=", " delimiter-precedes-last="always"/>+        <label form="short" prefix=", "/>+        <substitute>+          <names variable="editor"/>+          <names variable="translator"/>+          <names variable="director"/>+          <text macro="substitute-title"/>+          <text macro="title"/>+        </substitute>+      </names>+      <text macro="recipient"/>+    </group>+  </macro>+  <macro name="contributors-short">+    <names variable="author">+      <name form="short" and="text" delimiter=", " initialize-with=". "/>+      <substitute>+        <names variable="editor"/>+        <names variable="translator"/>+        <names variable="director"/>+        <text macro="substitute-title"/>+        <text macro="title"/>+      </substitute>+    </names>+  </macro>+  <macro name="interviewer">+    <names variable="interviewer" delimiter=", ">+      <label form="verb" prefix=" " text-case="capitalize-first" suffix=" "/>+      <name and="text" delimiter=", "/>+    </names>+  </macro>+  <macro name="archive">+    <group delimiter=". ">+      <text variable="archive_location" text-case="capitalize-first"/>+      <text variable="archive"/>+      <text variable="archive-place"/>+    </group>+  </macro>+  <macro name="access">+    <group delimiter=". ">+      <choose>+        <if type="graphic report" match="any">+          <text macro="archive"/>+        </if>+        <else-if type="article-journal bill book chapter legal_case legislation motion_picture paper-conference" match="none">+          <text macro="archive"/>+        </else-if>+      </choose>+      <choose>+        <if type="webpage post-weblog" match="any">+          <date variable="issued" form="text"/>+        </if>+      </choose>+      <choose>+        <if variable="issued" match="none">+          <group delimiter=" ">+            <text term="accessed" text-case="capitalize-first"/>+            <date variable="accessed" form="text"/>+          </group>+        </if>+      </choose>+      <choose>+        <if type="legal_case" match="none">+          <choose>+            <if variable="DOI">+              <text variable="DOI" prefix="https://doi.org/"/>+            </if>+            <else>+              <text variable="URL"/>+            </else>+          </choose>+        </if>+      </choose>+    </group>+  </macro>+  <macro name="title">+    <choose>+      <if variable="title" match="none">+        <choose>+          <if type="personal_communication" match="none">+            <text variable="genre" text-case="capitalize-first"/>+          </if>+        </choose>+      </if>+      <else-if type="bill book graphic legislation motion_picture song" match="any">+        <text variable="title" text-case="title" font-style="italic"/>+        <group prefix=" (" suffix=")" delimiter=" ">+          <text term="version"/>+          <text variable="version"/>+        </group>+      </else-if>+      <else-if variable="reviewed-author">+        <choose>+          <if variable="reviewed-title">+            <group delimiter=". ">+              <text variable="title" text-case="title" quotes="true"/>+              <group delimiter=", ">+                <text variable="reviewed-title" text-case="title" font-style="italic" prefix="Review of "/>+                <names variable="reviewed-author">+                  <label form="verb-short" text-case="lowercase" suffix=" "/>+                  <name and="text" delimiter=", "/>+                </names>+              </group>+            </group>+          </if>+          <else>+            <group delimiter=", ">+              <text variable="title" text-case="title" font-style="italic" prefix="Review of "/>+              <names variable="reviewed-author">+                <label form="verb-short" text-case="lowercase" suffix=" "/>+                <name and="text" delimiter=", "/>+              </names>+            </group>+          </else>+        </choose>+      </else-if>+      <else-if type="legal_case interview patent" match="any">+        <text variable="title"/>+      </else-if>+      <else>+        <text variable="title" text-case="title" quotes="true"/>+      </else>+    </choose>+  </macro>+  <macro name="edition">+    <choose>+      <if type="bill book graphic legal_case legislation motion_picture report song" match="any">+        <choose>+          <if is-numeric="edition">+            <group delimiter=" " prefix=". ">+              <number variable="edition" form="ordinal"/>+              <text term="edition" form="short" strip-periods="true"/>+            </group>+          </if>+          <else>+            <text variable="edition" text-case="capitalize-first" prefix=". "/>+          </else>+        </choose>+      </if>+      <else-if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">+        <choose>+          <if is-numeric="edition">+            <group delimiter=" " prefix=", ">+              <number variable="edition" form="ordinal"/>+              <text term="edition" form="short"/>+            </group>+          </if>+          <else>+            <text variable="edition" prefix=", "/>+          </else>+        </choose>+      </else-if>+    </choose>+  </macro>+  <macro name="locators">+    <choose>+      <if type="article-journal">+        <choose>+          <if variable="volume">+            <text variable="volume" prefix=" "/>+            <group prefix=" (" suffix=")">+              <choose>+                <if variable="issue">+                  <text variable="issue"/>+                </if>+                <else>+                  <date variable="issued">+                    <date-part name="month"/>+                  </date>+                </else>+              </choose>+            </group>+          </if>+          <else-if variable="issue">+            <group delimiter=" " prefix=", ">+              <text term="issue" form="short"/>+              <text variable="issue"/>+              <date variable="issued" prefix="(" suffix=")">+                <date-part name="month"/>+              </date>+            </group>+          </else-if>+          <else>+            <date variable="issued" prefix=", ">+              <date-part name="month"/>+            </date>+          </else>+        </choose>+      </if>+      <else-if type="legal_case">+        <text variable="volume" prefix=", "/>+        <text variable="container-title" prefix=" "/>+        <text variable="page" prefix=" "/>+      </else-if>+      <else-if type="bill book graphic legal_case legislation motion_picture report song" match="any">+        <group prefix=". " delimiter=". ">+          <group>+            <text term="volume" form="short" text-case="capitalize-first" suffix=" "/>+            <number variable="volume" form="numeric"/>+          </group>+          <group>+            <number variable="number-of-volumes" form="numeric"/>+            <text term="volume" form="short" prefix=" " plural="true"/>+          </group>+        </group>+      </else-if>+      <else-if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">+        <choose>+          <if variable="page" match="none">+            <group prefix=". ">+              <text term="volume" form="short" text-case="capitalize-first" suffix=" "/>+              <number variable="volume" form="numeric"/>+            </group>+          </if>+        </choose>+      </else-if>+    </choose>+  </macro>+  <macro name="locators-chapter">+    <choose>+      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">+        <choose>+          <if variable="page">+            <group prefix=", ">+              <text variable="volume" suffix=":"/>+              <text variable="page"/>+            </group>+          </if>+        </choose>+      </if>+    </choose>+  </macro>+  <macro name="locators-article">+    <choose>+      <if type="article-newspaper">+        <group prefix=", " delimiter=", ">+          <group delimiter=" ">+            <text variable="edition"/>+            <text term="edition"/>+          </group>+          <group>+            <text term="section" form="short" suffix=" "/>+            <text variable="section"/>+          </group>+        </group>+      </if>+      <else-if type="article-journal">+        <choose>+          <if variable="volume issue" match="any">+            <text variable="page" prefix=": "/>+          </if>+          <else>+            <text variable="page" prefix=", "/>+          </else>+        </choose>+      </else-if>+    </choose>+  </macro>+  <macro name="point-locators">+    <choose>+      <if variable="locator">+        <choose>+          <if locator="page" match="none">+            <choose>+              <if type="bill book graphic legal_case legislation motion_picture report song" match="any">+                <choose>+                  <if variable="volume">+                    <group>+                      <text term="volume" form="short" suffix=" "/>+                      <number variable="volume" form="numeric"/>+                      <label variable="locator" form="short" prefix=", " suffix=" "/>+                    </group>+                  </if>+                  <else>+                    <label variable="locator" form="short" suffix=" "/>+                  </else>+                </choose>+              </if>+              <else>+                <label variable="locator" form="short" suffix=" "/>+              </else>+            </choose>+          </if>+          <else-if type="bill book graphic legal_case legislation motion_picture report song" match="any">+            <number variable="volume" form="numeric" suffix=":"/>+          </else-if>+        </choose>+        <text variable="locator"/>+      </if>+    </choose>+  </macro>+  <macro name="container-prefix">+    <text term="in" text-case="capitalize-first"/>+  </macro>+  <macro name="container-title">+    <choose>+      <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="any">+        <text macro="container-prefix" suffix=" "/>+      </if>+    </choose>+    <choose>+      <if type="webpage">+        <text variable="container-title" text-case="title"/>+      </if>+      <else-if type="legal_case" match="none">+        <group delimiter=" ">+          <text variable="container-title" text-case="title" font-style="italic"/>+          <choose>+            <if type="post-weblog">+              <text value="(blog)"/>+            </if>+          </choose>+        </group>+      </else-if>+    </choose>+  </macro>+  <macro name="publisher">+    <group delimiter=": ">+      <text variable="publisher-place"/>+      <text variable="publisher"/>+    </group>+  </macro>+  <macro name="date">+    <choose>+      <if variable="issued">+        <group delimiter=" ">+          <date variable="original-date" form="text" date-parts="year" prefix="(" suffix=")"/>+          <date variable="issued">+            <date-part name="year"/>+          </date>+        </group>+      </if>+      <else-if variable="status">+        <text variable="status" text-case="capitalize-first"/>+      </else-if>+      <else>+        <text term="no date" form="short"/>+      </else>+    </choose>+  </macro>+  <macro name="date-in-text">+    <choose>+      <if variable="issued">+        <group delimiter=" ">+          <date variable="original-date" form="text" date-parts="year" prefix="[" suffix="]"/>+          <date variable="issued">+            <date-part name="year"/>+          </date>+        </group>+      </if>+      <else-if variable="status">+        <text variable="status"/>+      </else-if>+      <else>+        <text term="no date" form="short"/>+      </else>+    </choose>+  </macro>+  <macro name="day-month">+    <date variable="issued">+      <date-part name="month"/>+      <date-part name="day" prefix=" "/>+    </date>+  </macro>+  <macro name="collection-title">+    <choose>+      <if match="none" type="article-journal">+        <choose>+          <if match="none" is-numeric="collection-number">+            <group delimiter=", ">+              <text variable="collection-title" text-case="title"/>+              <text variable="collection-number"/>+            </group>+          </if>+          <else>+            <group delimiter=" ">+              <text variable="collection-title" text-case="title"/>+              <text variable="collection-number"/>+            </group>+          </else>+        </choose>+      </if>+    </choose>+  </macro>+  <macro name="collection-title-journal">+    <choose>+      <if type="article-journal">+        <group delimiter=" ">+          <text variable="collection-title"/>+          <text variable="collection-number"/>+        </group>+      </if>+    </choose>+  </macro>+  <macro name="event">+    <group>+      <text term="presented at" suffix=" "/>+      <text variable="event"/>+    </group>+  </macro>+  <macro name="description">+    <choose>+      <if type="interview">+        <group delimiter=". ">+          <text macro="interviewer"/>+          <text variable="medium" text-case="capitalize-first"/>+        </group>+      </if>+      <else-if type="patent">+        <group delimiter=" " prefix=". ">+          <text variable="authority"/>+          <text variable="number"/>+        </group>+      </else-if>+      <else>+        <text variable="medium" text-case="capitalize-first" prefix=". "/>+      </else>+    </choose>+    <choose>+      <if variable="title" match="none"/>+      <else-if type="thesis personal_communication speech" match="any"/>+      <else>+        <group delimiter=" " prefix=". ">+          <text variable="genre" text-case="capitalize-first"/>+          <choose>+            <if type="report">+              <text variable="number"/>+            </if>+          </choose>+        </group>+      </else>+    </choose>+  </macro>+  <macro name="issue">+    <choose>+      <if type="legal_case">+        <text variable="authority" prefix=". "/>+      </if>+      <else-if type="speech">+        <group prefix=". " delimiter=", ">+          <group delimiter=" ">+            <text variable="genre" text-case="capitalize-first"/>+            <text macro="event"/>+          </group>+          <text variable="event-place"/>+          <text macro="day-month"/>+        </group>+      </else-if>+      <else-if type="article-newspaper article-magazine personal_communication" match="any">+        <date variable="issued" form="text" prefix=", "/>+      </else-if>+      <else-if type="patent">+        <group delimiter=", " prefix=", ">+          <group delimiter=" ">+            <!--Needs Localization-->+            <text value="filed"/>+            <date variable="submitted" form="text"/>+          </group>+          <group delimiter=" ">+            <choose>+              <if variable="issued submitted" match="all">+                <text term="and"/>+              </if>+            </choose>+            <!--Needs Localization-->+            <text value="issued"/>+            <date variable="issued" form="text"/>+          </group>+        </group>+      </else-if>+      <else-if type="article-journal" match="any"/>+      <else>+        <group prefix=". " delimiter=", ">+          <choose>+            <if type="thesis">+              <text variable="genre" text-case="capitalize-first"/>+            </if>+          </choose>+          <text macro="publisher"/>+        </group>+      </else>+    </choose>+  </macro>+  <citation et-al-min="4" et-al-use-first="1" disambiguate-add-year-suffix="true" disambiguate-add-names="true" disambiguate-add-givenname="true" givenname-disambiguation-rule="primary-name" collapse="year" after-collapse-delimiter="; ">+    <layout prefix="(" suffix=")" delimiter="; ">+      <group delimiter=", ">+        <choose>+          <if variable="issued accessed" match="any">+            <group delimiter=" ">+              <text macro="contributors-short"/>+              <text macro="date-in-text"/>+            </group>+          </if>+          <!---comma before forthcoming and n.d.-->+          <else>+            <group delimiter=", ">+              <text macro="contributors-short"/>+              <text macro="date-in-text"/>+            </group>+          </else>+        </choose>+        <text macro="point-locators"/>+      </group>+    </layout>+  </citation>+  <bibliography hanging-indent="true" et-al-min="11" et-al-use-first="7" subsequent-author-substitute="&#8212;&#8212;&#8212;" entry-spacing="0">+    <sort>+      <key macro="contributors"/>+      <key variable="issued"/>+      <key variable="title"/>+    </sort>+    <layout suffix=".">+      <group delimiter=". ">+        <text macro="contributors"/>+        <text macro="date"/>+        <text macro="title"/>+      </group>+      <text macro="description"/>+      <text macro="secondary-contributors" prefix=". "/>+      <text macro="container-title" prefix=". "/>+      <text macro="container-contributors"/>+      <text macro="edition"/>+      <text macro="locators-chapter"/>+      <text macro="collection-title-journal" prefix=", " suffix=", "/>+      <text macro="locators"/>+      <text macro="collection-title" prefix=". "/>+      <text macro="issue"/>+      <text macro="locators-article"/>+      <text macro="access" prefix=". "/>+    </layout>+  </bibliography>+</style>+<<===== CSL =====<<++>>===== CITATION-ITEMS =====>>+[ [ {"id":"doeA"},+    {"id":"cork", "prefix":"see also "},+    {"id":"doeB"}] ]+<<===== CITATION-ITEMS =====<<++++>>===== INPUT =====>>+[+  {+    "author": [+      {+        "family": "Doe",+        "given": "John"+      }+    ],+    "id": "doeA",+    "title": "Fruits",+    "type": "book",+    "issued": {+      "date-parts": [+        [+          2020+        ]+      ]+    }+  },+  {+    "author": [+      {+        "family": "Doe",+        "given": "John"+      }+    ],+    "id": "doeB",+    "title": "Veggies",+    "type": "book",+    "issued": {+      "date-parts": [+        [+          2019+        ]+      ]+    }+  },+  {+    "author": [+      {+        "family": "Cork",+        "given": "John"+      }+    ],+    "id": "cork",+    "title": "Meat",+    "type": "book",+    "issued": {+      "date-parts": [+        [+          2018+        ]+      ]+    }+  }+]+<<===== INPUT =====<<+++>>===== VERSION =====>>+1.0+<<===== VERSION =====<<+
+ test/extra/issue_90.txt view
@@ -0,0 +1,203 @@+>>===== MODE =====>>+citation+<<===== MODE =====<<+++++>>===== RESULT =====>>+<b>Alfred Koller</b>, Schweizerisches Obligationenrecht Besonderer Teil Band I, Bern, Stämpfli Verlag, 2012; <b>Alfred Koller</b>, Schweizerisches Werkvertragsrecht, Zürich/St. Gallen, Dike Verlag AG, 2015.+<b>Koller</b>, Werkvertragsrecht.+<b>Koller</b>, OR BT I.+<<===== RESULT =====<<+++>>===== CSL =====>>+<?xml version="1.0" encoding="utf-8"?>+<style xmlns="http://purl.org/net/xbiblio/csl" class="note" version="1.0" delimiter-precedes-et-al="never" delimiter-precedes-last="always" et-al-min="5" et-al-use-first="1" page-range-format="expanded" default-locale="tr-TR">+  <info>+    <title xml:lang="tr-TR">temel</title>+    <id>hakan</id>+    <category citation-format="note"/>+    <category field="law"/>+    <summary xml:lang="tr-TR"></summary>+    <updated>2021-09-06T20:43:44+03:00</updated>+  </info>+  <locale xml:lang="tr-TR">+    <terms>+      <term name="page" form="short">+        <single>s.</single>+        <multiple>s.</multiple></term>+      <term name="paragraph" form="short">+        <single>p.</single>+        <multiple>p.</multiple></term>+    </terms>+  </locale>+  <macro name="author-cit">+    <names variable="author">+      <name font-weight="bold" sort-separator=" " delimiter="/"/>+    </names>+  </macro>+  <macro name="author-subsequent">+    <names variable="author">+      <name font-weight="bold" form="short" sort-separator=" " initialize-with="." delimiter="/"/>+    </names>+  </macro>+  <macro name="author-bib">+    <names variable="author">+      <name font-weight="bold" name-as-sort-order="all" sort-separator=" " delimiter="/"/>+    </names>+  </macro>+  <macro name="editor-cit">+    <names variable="editor">+      <name font-weight="bold" sort-separator=" " delimiter="/"/>+    </names>+  </macro>+  <macro name="editor-bib">+    <names variable="editor">+      <name font-weight="bold" name-as-sort-order="all" sort-separator=" " delimiter="/"/>+    </names>+  </macro>+  <macro name="title-bib/cit">+   <choose>+     <if type="article-journal chapter entry-encyclopedia" match="any">+       <text variable="title" quotes="true"/>+     </if>+     <else-if type="book">+       <text variable="title"/>+     </else-if>+   </choose> +  </macro>+  <macro name="disambiguate">+   <choose>+    <if disambiguate="true">+     <text variable="title-short"/>+    </if>+   </choose>+  </macro>+  <citation disambiguate-add-givenname="true" givenname-disambiguation-rule="primary-name-with-initials">+    <sort>+      <key variable="author"/>+      <key variable="title"/>+      <key variable="issued"/>+    </sort>+    <layout suffix="." delimiter="; ">+      <choose>+        <if position="subsequent">+          <text macro="author-subsequent"/>+          <text macro="disambiguate" prefix=", "/>+  	  <label variable="locator" form="short" prefix=", " suffix=" "/>+	  <text variable="locator"/>+        </if>+        <else>+	  <text macro="author-cit" suffix=", "/>+	  <text macro="title-bib/cit" suffix=", "/>+          <text variable="container-title" suffix=", "/>+          <text macro="editor-cit" prefix="ed. " suffix=", "/>+          <number variable="edition" suffix=". bs., "/>+	  <text variable="publisher-place" suffix=", "/>+	  <text variable="publisher" suffix=", "/>+	  <date variable="issued" form="numeric"/>+          <number variable="volume" prefix=", c. "/>+	  <number variable="issue" prefix=", sy. "/>+	  <text variable="page" prefix=", ss. "/>+    	  <label variable="locator" form="short" prefix=", " suffix=" "/>+	  <text variable="locator"/>+ 	</else>+      </choose>+    </layout>+  </citation>+  <bibliography entry-spacing="0" hanging-indent="true">+    <sort>+      <key variable="language"/>+      <key variable="type"/>+      <key variable="author"/>+      <key variable="title"/>+      <key variable="issued"/>+    </sort>+    <layout suffix="">+      <group suffix=".">+	<text macro="author-bib" suffix=", "/>+	<text macro="title-bib/cit" suffix=", "/>+	<text variable="container-title" suffix=", "/>+	<text macro="editor-bib" prefix="ed. " suffix=", "/>+	<number variable="edition" suffix=". bs., "/>+	<text variable="publisher-place" suffix=", "/>+	<text variable="publisher" suffix=", "/>+	<date variable="issued" form="numeric"/>+	<number variable="volume" prefix=", c. "/>+	<number variable="issue" prefix=", sy. "/>+	<text variable="page" prefix=", ss. "/>+      </group>+      <text macro="disambiguate" prefix=" (Atıf: " suffix=")"/>+    </layout>+  </bibliography>+</style>+<<===== CSL =====<<+++>>===== CITATION-ITEMS =====>>+[ [ {"id":"kollerSchweizerischesWerkvertragsrecht2015"},+    {"id":"kollerSchweizerischesObligationenrechtBesonderer2012"}+  ],+  [ {"id":"kollerSchweizerischesWerkvertragsrecht2015"} ],+  [ {"id":"kollerSchweizerischesObligationenrechtBesonderer2012"} ]+]+<<===== CITATION-ITEMS =====<<++++>>===== INPUT =====>>+[+  {+    "author": [+      {+        "family": "Koller",+        "given": "Alfred"+      }+    ],+    "id": "kollerSchweizerischesWerkvertragsrecht2015",+    "issued": {+      "date-parts": [+        [+          2015+        ]+      ]+    },+    "language": "de-DE",+    "publisher": "Dike Verlag AG",+    "publisher-place": "Zürich/St. Gallen",+    "title": "Schweizerisches Werkvertragsrecht",+    "title-short": "Werkvertragsrecht",+    "type": "book"+  },+  {+    "author": [+      {+        "family": "Koller",+        "given": "Alfred"+      }+    ],+    "id": "kollerSchweizerischesObligationenrechtBesonderer2012",+    "issued": {+      "date-parts": [+        [+          2012+        ]+      ]+    },+    "language": "de-DE",+    "publisher": "Stämpfli Verlag",+    "publisher-place": "Bern",+    "title": "Schweizerisches Obligationenrecht Besonderer Teil Band I",+    "title-short": "OR BT I",+    "type": "book"+  }+]+<<===== INPUT =====<<+++>>===== VERSION =====>>+1.0+<<===== VERSION =====<<+