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 +33/−0
- app/Main.hs +1/−2
- citeproc.cabal +2/−2
- man/citeproc.1 +1/−1
- src/Citeproc/Eval.hs +115/−65
- src/Citeproc/Types.hs +3/−1
- test/Spec.hs +5/−2
- test/extra/case_insensitive.txt +63/−0
- test/extra/disambiguation-author-in-text.txt +781/−0
- test/extra/issue_89.txt +735/−0
- test/extra/issue_90.txt +203/−0
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="———" 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="———" 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 =====<<+