citeproc 0.1.1.1 → 0.2
raw patch · 12 files changed
+872/−115 lines, 12 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Citeproc.CaseTransform: AfterOtherPunctuation :: CaseTransformState
- Citeproc.Types: instance Data.Aeson.Types.FromJSON.FromJSON Citeproc.Types.Lang
- Citeproc.Types: instance Data.Aeson.Types.ToJSON.ToJSON Citeproc.Types.Lang
- Citeproc.Types: instance GHC.Classes.Eq Citeproc.Types.Lang
- Citeproc.Types: instance GHC.Classes.Ord Citeproc.Types.Lang
- Citeproc.Types: instance GHC.Show.Show Citeproc.Types.Lang
- Citeproc.Types: newtype SortKeyValue
+ Citeproc.Types: data SortKeyValue
- Citeproc.Types: SortKeyValue :: (SortDirection, Maybe [Text]) -> SortKeyValue
+ Citeproc.Types: SortKeyValue :: SortDirection -> Maybe Lang -> Maybe [Text] -> SortKeyValue
Files
- CHANGELOG.md +15/−0
- app/Main.hs +1/−1
- citeproc.cabal +2/−1
- man/citeproc.1 +2/−2
- src/Citeproc/CaseTransform.hs +13/−27
- src/Citeproc/CslJson.hs +1/−1
- src/Citeproc/Data.hs +0/−1
- src/Citeproc/Eval.hs +41/−28
- src/Citeproc/Pandoc.hs +1/−1
- src/Citeproc/Types.hs +21/−53
- src/Citeproc/Unicode.hs +85/−0
- test/extra/issue27.txt +690/−0
CHANGELOG.md view
@@ -1,5 +1,20 @@ # citeproc changelog +## 0.2++ * Remove `AfterOtherPunctuation` constructor from+ `CaseTransformState` [API change].+ This gave bad results with things like parentheses (#27).+ * Change `SortKeyValue` to include `Maybe Lang` [API change].+ This allows us to do locale-sensitive sorting (though this+ won't matter much unless the `icu` flag is used).+ * Add `Maybe Lang` parameter on `initialize` (since+ capitalization can be locale-dependent).+ * Add cabal.project.icu for building with icu lib.+ * Add (unexported) Citeproc.Unicode compatibility module.+ This allows us to use the same functions whether or not+ the `icu` flag is used.+ ## 0.1.1.1 * Pay attention to citationNoteNumber in computing position.
app/Main.hs view
@@ -136,7 +136,7 @@ , Option ['r'] ["references"] (ReqArg (\fp opt -> opt{ optReferences = Just fp }) "FILE") "CSL JSON bibliography"- , Option ['a'] ["abbrevations"]+ , Option ['a'] ["abbreviations"] (ReqArg (\fp opt -> opt{ optAbbreviations = Just fp }) "FILE") "CSL abbreviations table" , Option ['l'] ["lang"]
citeproc.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.2 name: citeproc-version: 0.1.1.1+version: 0.2 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@@ -58,6 +58,7 @@ Citeproc.CaseTransform other-modules: Citeproc.Element Citeproc.Data+ Citeproc.Unicode build-depends: base >= 4.8 && < 5 , safe
man/citeproc.1 view
@@ -1,6 +1,6 @@-.\" Automatically generated by Pandoc 2.11.0.2+.\" Automatically generated by Pandoc 2.11.2 .\"-.TH "citeproc" "1" "" "citeproc 0.1.0.3" ""+.TH "citeproc" "1" "" "citeproc 0.2" "" .hy .SH NAME .PP
src/Citeproc/CaseTransform.hs view
@@ -23,6 +23,7 @@ import Data.Text (Text) import qualified Data.Text as T import Citeproc.Types (Lang(..))+import qualified Citeproc.Unicode as Unicode -- | Wraps a function used to define textcase transformations. newtype CaseTransformer =@@ -36,35 +37,18 @@ | AfterWordEnd | AfterWordChar | AfterSentenceEndingPunctuation- | AfterOtherPunctuation | BeforeLastWord deriving (Show, Eq) -toUpper' :: Maybe Lang -> Text -> Text-toUpper' mblang = T.toUpper .- case mblang of- Just (Lang "tr" _) -> T.map (\c -> case c of- 'i' -> 'İ'- 'ı' -> 'I'- _ -> c)- _ -> id--toLower' :: Maybe Lang -> Text -> Text-toLower' mblang = T.toLower .- case mblang of- Just (Lang "tr" _) -> T.map (\c -> case c of- 'İ' -> 'i'- 'I' -> 'ı'- _ -> c)- _ -> id- -- | Uppercase everything. withUppercaseAll :: CaseTransformer-withUppercaseAll = CaseTransformer (\mblang _ -> toUpper' mblang)+withUppercaseAll =+ CaseTransformer (\mblang _ -> Unicode.toUpper mblang) -- | Lowercase everything. withLowercaseAll :: CaseTransformer-withLowercaseAll = CaseTransformer (\mblang _ -> toLower' mblang)+withLowercaseAll =+ CaseTransformer (\mblang _ -> Unicode.toLower mblang) -- | Capitalize all words. withCapitalizeWords :: CaseTransformer@@ -98,10 +82,10 @@ go mblang st chunk | isCapitalized chunk , not (st == Start || st == StartSentence)- = T.toLower chunk+ = Unicode.toLower mblang chunk | isCapitalized chunk || T.all isLower chunk , st == Start || st == StartSentence- = capitalizeText mblang $ T.toLower chunk+ = capitalizeText mblang $ Unicode.toLower mblang chunk | otherwise = chunk -- | Use title case.@@ -114,12 +98,14 @@ -- textcase_TitleCapitalization.txt | T.any (not . isAscii) chunk = chunk | st == StartSentence || st == Start =- capitalizeText mblang $ T.toLower chunk+ capitalizeText mblang $ Unicode.toLower mblang chunk | st == AfterWordEnd , not (isStopWord chunk)- , T.compareLength chunk 1 == GT = capitalizeText mblang $ T.toLower chunk+ , T.compareLength chunk 1 == GT =+ capitalizeText mblang $ Unicode.toLower mblang chunk | st == BeforeLastWord- , T.compareLength chunk 1 == GT = capitalizeText mblang $ T.toLower chunk+ , T.compareLength chunk 1 == GT =+ capitalizeText mblang $ Unicode.toLower mblang chunk | otherwise = chunk isCapitalized :: Text -> Bool@@ -134,7 +120,7 @@ capitalizeText :: Maybe Lang -> Text -> Text capitalizeText mblang x = case T.uncons x of- Just (c,x') -> toUpper' mblang (T.singleton c) <> x'+ Just (c,x') -> Unicode.toUpper mblang (T.singleton c) <> x' Nothing -> x isStopWord :: Text -> Bool
src/Citeproc/CslJson.hs view
@@ -534,7 +534,7 @@ | isSpace c , st == AfterSentenceEndingPunctuation -> StartSentence | isWordBreak c -> AfterWordEnd- | otherwise -> AfterOtherPunctuation+ | otherwise -> st return $ if T.all isAlphaNum t then f st t
src/Citeproc/Data.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE TemplateHaskell #-} module Citeproc.Data (localeFiles)
src/Citeproc/Eval.hs view
@@ -9,6 +9,7 @@ where import Citeproc.Types import Citeproc.Style (mergeLocales)+import qualified Citeproc.Unicode as Unicode import Data.Semigroup import Control.Monad.Trans.RWS.CPS import Data.Containers.ListUtils (nubOrdOn, nubOrd)@@ -400,7 +401,7 @@ , stateNoteMap = mempty })) $ mapM (evalLayout False (styleCitation style)) (zip [1..] (citations ++ ghostCitations))-+ mblang <- asks (localeLanguage . contextLocale) styleOpts <- asks contextStyleOptions let strategy = styleDisambiguation styleOpts let allNameGroups = [ns | Tagged (TagNames _ _ ns) _ <-@@ -423,7 +424,7 @@ , nameFamily v == Just name]) familyNames let toHint names name =- if any (initialsMatch name) (filter (/= name) names)+ if any (initialsMatch mblang name) (filter (/= name) names) then case rule of AllNamesWithInitials -> Nothing@@ -463,25 +464,27 @@ case getAmbiguities allCites' of [] -> return $ take (length citations) allCites' ambiguities -> do- analyzeAmbiguities bibSortKeyMap strategy (map snd ambiguities)+ analyzeAmbiguities mblang bibSortKeyMap strategy (map snd ambiguities) withRWST (\ctx st -> (ctx, st { stateLastCitedMap = mempty , stateNoteMap = mempty })) $ mapM (evalLayout False (styleCitation style)) (zip [1..] citations) where- analyzeAmbiguities :: M.Map ItemId [SortKeyValue]+ analyzeAmbiguities :: Maybe Lang+ -> M.Map ItemId [SortKeyValue] -> DisambiguationStrategy -> [[DisambData]] -> Eval a ()- analyzeAmbiguities bibSortKeyMap' strategy ambiguities = do+ analyzeAmbiguities mblang bibSortKeyMap' strategy ambiguities = do -- add names to et al. as1 <- if disambiguateAddNames strategy- then mapM (tryAddNames (disambiguateAddGivenNames strategy))+ then mapM (tryAddNames mblang+ (disambiguateAddGivenNames strategy)) ambiguities else return ambiguities as2 <- case disambiguateAddGivenNames strategy of- Just ByCite -> mapM tryAddGivenNames as1+ Just ByCite -> mapM (tryAddGivenNames mblang) as1 _ -> return as1 as3 <- if disambiguateAddYearSuffix strategy then do@@ -490,12 +493,13 @@ else return as2 mapM_ tryDisambiguateCondition as3 - isDisambiguated :: Maybe GivenNameDisambiguationRule+ isDisambiguated :: Maybe Lang+ -> Maybe GivenNameDisambiguationRule -> Int -- et al min -> [DisambData] -> DisambData -> Bool- isDisambiguated mbrule etAlMin xs x =+ isDisambiguated mblang mbrule etAlMin xs x = all (\y -> x == y || disambiguatedName y /= disambiguatedName x) xs where disambiguatedName = nameParts . take etAlMin . ddNames@@ -503,7 +507,7 @@ case mbrule of Just AllNames -> id Just AllNamesWithInitials ->- map (\name -> name{ nameGiven = initialize True False ""+ map (\name -> name{ nameGiven = initialize mblang True False "" <$> nameGiven name }) Just PrimaryName -> \case@@ -512,13 +516,15 @@ Just PrimaryNameWithInitials -> \case [] -> []- (z:zs) -> z{ nameGiven = initialize True False "" <$> nameGiven z } :+ (z:zs) -> z{ nameGiven =+ initialize mblang True False "" <$> nameGiven z } : map (\name -> name{ nameGiven = Nothing }) zs Just ByCite -> id -- hints will be added later _ -> map (\name -> name{ nameGiven = Nothing }) - tryAddNames mbrule bs = (case mbrule of- Just ByCite -> bs <$ tryAddGivenNames bs+ tryAddNames mblang mbrule bs =+ (case mbrule of+ Just ByCite -> bs <$ tryAddGivenNames mblang bs _ -> return bs) >>= go 1 -- if ByCite, we want to make sure that -- tryAddGivenNames is still applied, as@@ -528,7 +534,7 @@ go n as | n > maxnames as = return as | otherwise = do- let ds = filter (isDisambiguated mbrule n as) as+ let ds = filter (isDisambiguated mblang mbrule n as) as if null ds then go (n + 1) as else do@@ -538,15 +544,16 @@ (unReferenceMap $ stateRefMap st) as } go (n + 1) (as \\ ds) - tryAddGivenNames :: [DisambData]+ tryAddGivenNames :: Maybe Lang+ -> [DisambData] -> Eval a [DisambData]- tryAddGivenNames as = do+ tryAddGivenNames mblang as = do let correspondingNames = map (zip (map ddItem as)) $ transpose $ map ddNames as go [] _ = return [] go (as' :: [DisambData]) (ns :: [(ItemId, Name)]) = do hintedIds <- Set.fromList . catMaybes <$>- mapM (addNameHint (map snd ns)) ns+ mapM (addNameHint mblang (map snd ns)) ns return $ filter (\x -> ddItem x `Set.notMember` hintedIds) as' foldM go as correspondingNames @@ -586,20 +593,21 @@ } Just x -> Just x } - initialsMatch x y =+ initialsMatch mblang x y = case (nameGiven x, nameGiven y) of (Just x', Just y') ->- initialize True False "" x' == initialize True False "" y'+ initialize mblang True False "" x' ==+ initialize mblang True False "" y' _ -> False - addNameHint names (item, name) = do+ addNameHint mblang names (item, name) = do let familyMatches = [n | n <- names , n /= name , nameFamily n == nameFamily name] case familyMatches of [] -> return Nothing _ -> do- let hint = if any (initialsMatch name) familyMatches+ let hint = if any (initialsMatch mblang name) familyMatches then AddGivenName else AddInitials modify $ \st ->@@ -842,20 +850,22 @@ -> SortKey a -> Eval a SortKeyValue evalSortKey citeId (SortKeyMacro sortdir elts) = do+ mblang <- asks (localeLanguage . contextLocale) refmap <- gets stateRefMap case lookupReference citeId refmap of- Nothing -> return $ SortKeyValue (sortdir, Nothing)+ Nothing -> return $ SortKeyValue sortdir mblang Nothing Just ref -> do k <- normalizeSortKey . toText . renderOutput defaultCiteprocOptions . grouped <$> withRWS newContext (mconcat <$> mapM eElement elts)- return $ SortKeyValue (sortdir, Just k)+ return $ SortKeyValue sortdir mblang (Just k) where newContext oldContext s = (oldContext, s{ stateReference = ref }) evalSortKey citeId (SortKeyVariable sortdir var) = do+ mblang <- asks (localeLanguage . contextLocale) refmap <- gets stateRefMap- SortKeyValue . (sortdir,) <$>+ SortKeyValue sortdir mblang <$> case lookupReference citeId refmap >>= lookupVariable var of Nothing -> return Nothing Just (TextVal t) -> return $ Just $ normalizeSortKey t@@ -1981,12 +1991,13 @@ in T.pack [chr (ord 'a' - 1 + (x' `div` 26)), chr (ord 'a' + (x' `mod` 26))] -initialize :: Bool -- ^ initialize+initialize :: Maybe Lang+ -> Bool -- ^ initialize -> Bool -- ^ with hyphen -> Text -- ^ initialize with (suffix) -> Text -> Text-initialize makeInitials useHyphen initializeWith =+initialize mblang makeInitials useHyphen initializeWith = T.strip . T.replace " -" "-" . mconcat . map initializeWord . splitWords where -- Left values are already initials@@ -2019,8 +2030,8 @@ case T.uncons t' of Just (c, _) | isUpper c- , useHyphen -> "-" <> T.toUpper (T.singleton c)- | isUpper c -> T.toUpper (T.singleton c)+ , useHyphen -> "-" <> Unicode.toUpper mblang (T.singleton c)+ | isUpper c -> Unicode.toUpper mblang (T.singleton c) _ -> mempty -- e.g. Ji-ping -> J. not J.-p. Just (c, t') | isUpper c ->@@ -2049,6 +2060,7 @@ asks (styleDemoteNonDroppingParticle . contextStyleOptions) initializeWithHyphen <- asks (styleInitializeWithHyphen . contextStyleOptions)+ mblang <- asks (localeLanguage . contextLocale) let initialize' = case nameFamily name of Nothing -> id@@ -2056,6 +2068,7 @@ case nameInitializeWith nameFormat of Just initializeWith -> initialize+ mblang (nameInitialize nameFormat) initializeWithHyphen initializeWith
src/Citeproc/Pandoc.hs view
@@ -267,7 +267,7 @@ | isSpace c , st == AfterSentenceEndingPunctuation -> StartSentence | isWordBreak c -> AfterWordEnd- | otherwise -> AfterOtherPunctuation+ | otherwise -> st return $ if T.all isAlphaNum t then f st t
src/Citeproc/Types.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} {-# LANGUAGE StrictData #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE DeriveFoldable #-}@@ -128,12 +127,8 @@ import qualified Data.Attoparsec.Text as P import Safe (readMay) import Data.String (IsString)--#ifdef MIN_VERSION_text_icu-import qualified Data.Text.ICU as ICU-#else-import qualified Data.RFC5051 as RFC5051-#endif+import Citeproc.Unicode (Lang(..), parseLang, renderLang)+import qualified Citeproc.Unicode as Unicode -- import Debug.Trace -- import Text.Show.Pretty (ppShow)@@ -581,43 +576,39 @@ | SortKeyMacro SortDirection [Element a] deriving (Show, Eq) -newtype SortKeyValue =- SortKeyValue (SortDirection, Maybe [Text])+data SortKeyValue =+ SortKeyValue SortDirection (Maybe Lang) (Maybe [Text]) deriving (Show, Eq) -- absence should sort AFTER all values -- see sort_StatusFieldAscending.txt, sort_StatusFieldDescending.txt instance Ord SortKeyValue where- SortKeyValue (Ascending, _) <= SortKeyValue (Ascending, Nothing)+ SortKeyValue Ascending _ _ <= SortKeyValue Ascending _ Nothing = True- SortKeyValue (Ascending, Nothing) <= SortKeyValue (Ascending, Just _)+ SortKeyValue Ascending _ Nothing <= SortKeyValue Ascending _ (Just _) = False- SortKeyValue (Ascending, Just t1) <= SortKeyValue (Ascending, Just t2) =- t1 `keyLEQ` t2- SortKeyValue (Descending, _) <= SortKeyValue (Descending, Nothing)+ SortKeyValue Ascending mblang (Just t1) <=+ SortKeyValue Ascending _ (Just t2) =+ keyLEQ mblang t1 t2+ SortKeyValue Descending _ _ <= SortKeyValue Descending _ Nothing = True- SortKeyValue (Descending, Nothing) <= SortKeyValue (Descending, Just _)+ SortKeyValue Descending _ Nothing <= SortKeyValue Descending _ (Just _) = False- SortKeyValue (Descending, Just t1) <= SortKeyValue (Descending, Just t2) =- t2 `keyLEQ` t1- SortKeyValue _ <= SortKeyValue _ = False+ SortKeyValue Descending mblang (Just t1) <=+ SortKeyValue Descending _ (Just t2) =+ keyLEQ mblang t2 t1+ SortKeyValue{} <= SortKeyValue{} = False -- We need special comparison operators to ensure that -- á sorts before b, for example.-keyLEQ :: [Text] -> [Text] -> Bool-keyLEQ _ [] = False-keyLEQ [] _ = True-keyLEQ (x:xs) (y:ys) =- case comp x y of- EQ -> xs `keyLEQ` ys+keyLEQ :: Maybe Lang -> [Text] -> [Text] -> Bool+keyLEQ _ _ [] = False+keyLEQ _ [] _ = True+keyLEQ mblang (x:xs) (y:ys) =+ case Unicode.comp mblang x y of+ EQ -> keyLEQ mblang xs ys GT -> False LT -> True- where-#ifdef MIN_VERSION_text_icu- comp = ICU.collate (ICU.collator ICU.Current)-#else- comp = RFC5051.compareUnicode-#endif data Layout a = Layout@@ -762,29 +753,6 @@ (isNothing gen1 || isNothing gen2 || gen1 == gen2) && (isNothing gf1 || isNothing gf2 || gf1 == gf2 ) && (isNothing match1 || isNothing match2 || match1 == match2)---- | A parsed IETF language tag, with language and optional variant.--- For example, @Lang "en" (Just "US")@ corresponds to @en-US@.-data Lang = Lang{ langLanguage :: Text- , langVariant :: Maybe Text }- deriving (Show, Eq, Ord)--instance ToJSON Lang where- toJSON = toJSON . renderLang--instance FromJSON Lang where- parseJSON = fmap parseLang . parseJSON---- | Render a 'Lang' an an IETF language tag.-renderLang :: Lang -> Text-renderLang (Lang l Nothing) = l-renderLang (Lang l (Just v)) = l <> "-" <> v---- | Parse an IETF language tag.-parseLang :: Text -> Lang-parseLang t = Lang l (snd <$> T.uncons v)- where- (l,v) = T.break (\c -> c == '-' || c == '_') t -- | Defines locale-specific terms, punctuation styles, and date -- formats.
+ src/Citeproc/Unicode.hs view
@@ -0,0 +1,85 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}+module Citeproc.Unicode+ ( Lang(..),+ parseLang,+ renderLang,+ toUpper,+ toLower,+ comp+ )+where+#ifdef MIN_VERSION_text_icu+import qualified Data.Text.ICU as ICU+#else+import qualified Data.RFC5051 as RFC5051+#endif+import Data.Text (Text)+import qualified Data.Text as T+import Data.Aeson (FromJSON (..), ToJSON (..))+import Data.Semigroup++-- | A parsed IETF language tag, with language and optional variant.+-- For example, @Lang "en" (Just "US")@ corresponds to @en-US@.+data Lang = Lang{ langLanguage :: Text+ , langVariant :: Maybe Text }+ deriving (Show, Eq, Ord)++instance ToJSON Lang where+ toJSON = toJSON . renderLang++instance FromJSON Lang where+ parseJSON = fmap parseLang . parseJSON++-- | Render a 'Lang' an an IETF language tag.+renderLang :: Lang -> Text+renderLang (Lang l Nothing) = l+renderLang (Lang l (Just v)) = l <> "-" <> v++-- | Parse an IETF language tag.+parseLang :: Text -> Lang+parseLang t = Lang l (snd <$> T.uncons v)+ where+ (l,v) = T.break (\c -> c == '-' || c == '_') t++#ifdef MIN_VERSION_text_icu+toICULocale :: Maybe Lang -> ICU.LocaleName+toICULocale Nothing = ICU.Current+toICULocale (Just l) = ICU.Locale (T.unpack (renderLang l))+#endif++toUpper :: Maybe Lang -> Text -> Text+#ifdef MIN_VERSION_text_icu+toUpper mblang =+ ICU.toUpper (toICULocale mblang)+#else+toUpper mblang = T.toUpper .+ case mblang of+ Just (Lang "tr" _) -> T.map (\c -> case c of+ 'i' -> 'İ'+ 'ı' -> 'I'+ _ -> c)+ _ -> id+#endif++toLower :: Maybe Lang -> Text -> Text+#ifdef MIN_VERSION_text_icu+toLower mblang =+ ICU.toLower (toICULocale mblang)+#else+toLower mblang = T.toLower .+ case mblang of+ Just (Lang "tr" _) -> T.map (\c -> case c of+ 'İ' -> 'i'+ 'I' -> 'ı'+ _ -> c)+ _ -> id+#endif++comp :: Maybe Lang -> Text -> Text -> Ordering+#ifdef MIN_VERSION_text_icu+comp mblang = ICU.collate (ICU.collator (toICULocale mblang))+#else+comp _mblang = RFC5051.compareUnicode+#endif+
+ test/extra/issue27.txt view
@@ -0,0 +1,690 @@+>>===== MODE =====>>+bibliography+<<===== MODE =====<<+++++>>===== RESULT =====>>+<div class="csl-bib-body">+ <div class="csl-entry">Doe, John. n.d. <i>Fruits (Apples, Pears, Oranges) and Veggies</i>.</div>+</div>+<<===== 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 =====<<+++++>>===== INPUT =====>>+[+ {+ "author": [+ {+ "family": "Doe",+ "given": "John"+ }+ ],+ "id": "doeA",+ "title": "Fruits (apples, pears, oranges) and veggies",+ "type": "book"+ }+]+<<===== INPUT =====<<+++>>===== VERSION =====>>+1.0+<<===== VERSION =====<<+