pandoc-citeproc 0.12.2.5 → 0.13
raw patch · 155 files changed
+2317/−1887 lines, 155 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Text.CSL.Reference: mkRefDate :: Literal -> Parser [RefDate]
+ Text.CSL.Reference: instance Text.CSL.Util.AddYaml Text.CSL.Reference.Literal
+ Text.CSL.Reference: instance Text.CSL.Util.AddYaml Text.CSL.Reference.RefDate
+ Text.CSL.Reference: parseEDTFDate :: String -> [RefDate]
+ Text.CSL.Style: instance Text.CSL.Util.AddYaml Text.CSL.Style.Formatted
- Text.CSL: readBiblioFile :: FilePath -> IO [Reference]
+ Text.CSL: readBiblioFile :: (String -> Bool) -> FilePath -> IO [Reference]
- Text.CSL: readBiblioString :: BibFormat -> String -> IO [Reference]
+ Text.CSL: readBiblioString :: (String -> Bool) -> BibFormat -> String -> IO [Reference]
- Text.CSL.Eval.Date: longOrdinal :: [CslTerm] -> String -> String -> String
+ Text.CSL.Eval.Date: longOrdinal :: [CslTerm] -> String -> Int -> String
- Text.CSL.Eval.Date: ordinal :: [CslTerm] -> String -> String -> String
+ Text.CSL.Eval.Date: ordinal :: [CslTerm] -> String -> Int -> String
- Text.CSL.Input.Bibtex: readBibtex :: Bool -> Bool -> FilePath -> IO [Reference]
+ Text.CSL.Input.Bibtex: readBibtex :: (String -> Bool) -> Bool -> Bool -> FilePath -> IO [Reference]
- Text.CSL.Input.Bibtex: readBibtexString :: Bool -> Bool -> String -> IO [Reference]
+ Text.CSL.Input.Bibtex: readBibtexString :: (String -> Bool) -> Bool -> Bool -> String -> IO [Reference]
- Text.CSL.Input.Bibutils: readBiblioFile :: FilePath -> IO [Reference]
+ Text.CSL.Input.Bibutils: readBiblioFile :: (String -> Bool) -> FilePath -> IO [Reference]
- Text.CSL.Input.Bibutils: readBiblioString :: BibFormat -> String -> IO [Reference]
+ Text.CSL.Input.Bibutils: readBiblioString :: (String -> Bool) -> BibFormat -> String -> IO [Reference]
- Text.CSL.Reference: RefDate :: Literal -> Literal -> Literal -> Literal -> Literal -> Bool -> RefDate
+ Text.CSL.Reference: RefDate :: Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int -> Literal -> Bool -> RefDate
- Text.CSL.Reference: [day] :: RefDate -> Literal
+ Text.CSL.Reference: [day] :: RefDate -> Maybe Int
- Text.CSL.Reference: [month] :: RefDate -> Literal
+ Text.CSL.Reference: [month] :: RefDate -> Maybe Int
- Text.CSL.Reference: [season] :: RefDate -> Literal
+ Text.CSL.Reference: [season] :: RefDate -> Maybe Int
- Text.CSL.Reference: [year] :: RefDate -> Literal
+ Text.CSL.Reference: [year] :: RefDate -> Maybe Int
Files
- changelog +33/−0
- man/man1/pandoc-citeproc.1 +3/−3
- pandoc-citeproc.cabal +1/−1
- pandoc-citeproc.hs +85/−78
- src/Text/CSL.hs +7/−7
- src/Text/CSL/Data.hs +14/−12
- src/Text/CSL/Data/Embedded.hs +1/−1
- src/Text/CSL/Eval.hs +71/−62
- src/Text/CSL/Eval/Common.hs +10/−10
- src/Text/CSL/Eval/Date.hs +70/−75
- src/Text/CSL/Eval/Names.hs +59/−53
- src/Text/CSL/Eval/Output.hs +25/−24
- src/Text/CSL/Exception.hs +3/−3
- src/Text/CSL/Input/Bibtex.hs +383/−424
- src/Text/CSL/Input/Bibutils.hs +99/−54
- src/Text/CSL/Output/Pandoc.hs +10/−8
- src/Text/CSL/Output/Plain.hs +4/−4
- src/Text/CSL/Pandoc.hs +71/−58
- src/Text/CSL/Parser.hs +43/−46
- src/Text/CSL/Proc.hs +39/−36
- src/Text/CSL/Proc/Collapse.hs +20/−20
- src/Text/CSL/Proc/Disamb.hs +18/−18
- src/Text/CSL/Reference.hs +236/−192
- src/Text/CSL/Style.hs +70/−55
- src/Text/CSL/Util.hs +82/−48
- stack.yaml +4/−1
- tests/JSON.hs +5/−5
- tests/biblio2yaml/aksin.biblatex +1/−1
- tests/biblio2yaml/almendro.biblatex +1/−1
- tests/biblio2yaml/angenendt.biblatex +1/−1
- tests/biblio2yaml/aristotle-anima.biblatex +1/−1
- tests/biblio2yaml/aristotle-physics.biblatex +1/−1
- tests/biblio2yaml/aristotle-poetics.biblatex +1/−1
- tests/biblio2yaml/aristotle-rhetoric.biblatex +1/−1
- tests/biblio2yaml/article.biblatex +9/−9
- tests/biblio2yaml/augustine.biblatex +1/−1
- tests/biblio2yaml/averroes-bland.biblatex +1/−1
- tests/biblio2yaml/averroes-hannes.biblatex +1/−1
- tests/biblio2yaml/averroes-hercz.biblatex +1/−1
- tests/biblio2yaml/baez-article.biblatex +1/−1
- tests/biblio2yaml/baez-online.biblatex +3/−3
- tests/biblio2yaml/basic.bibtex +3/−3
- tests/biblio2yaml/bertram.biblatex +1/−1
- tests/biblio2yaml/book-averroes.biblatex +3/−3
- tests/biblio2yaml/book-coleridge.biblatex +1/−1
- tests/biblio2yaml/book-title-maintitle-series.biblatex +1/−1
- tests/biblio2yaml/book-vazques-de-parga.biblatex +1/−1
- tests/biblio2yaml/brandt.biblatex +1/−1
- tests/biblio2yaml/britannica.biblatex +1/−1
- tests/biblio2yaml/chiu.biblatex +1/−1
- tests/biblio2yaml/cicero.biblatex +1/−1
- tests/biblio2yaml/cms.biblatex +1/−1
- tests/biblio2yaml/coleridge.biblatex +1/−1
- tests/biblio2yaml/companion.biblatex +1/−1
- tests/biblio2yaml/cotton.biblatex +1/−1
- tests/biblio2yaml/crossref-inbook-mvbook.biblatex +3/−3
- tests/biblio2yaml/crossref-nested.biblatex +5/−5
- tests/biblio2yaml/ctan.biblatex +4/−4
- tests/biblio2yaml/dates.biblatex +83/−83
- tests/biblio2yaml/doody.biblatex +2/−2
- tests/biblio2yaml/edtf-date.biblatex +23/−23
- tests/biblio2yaml/gaonkar-in.biblatex +1/−1
- tests/biblio2yaml/gaonkar.biblatex +1/−1
- tests/biblio2yaml/geer.biblatex +1/−1
- tests/biblio2yaml/gerhardt.biblatex +1/−1
- tests/biblio2yaml/gillies.biblatex +1/−1
- tests/biblio2yaml/glashow.biblatex +1/−1
- tests/biblio2yaml/gonzalez.biblatex +1/−1
- tests/biblio2yaml/hammond.biblatex +1/−1
- tests/biblio2yaml/herrmann.biblatex +1/−1
- tests/biblio2yaml/hyman.biblatex +1/−1
- tests/biblio2yaml/iliad.biblatex +1/−1
- tests/biblio2yaml/inbook-title-booktitle-maintitle-series-2.biblatex +1/−1
- tests/biblio2yaml/inbook-title-booktitle-maintitle-series.biblatex +1/−1
- tests/biblio2yaml/inbook.biblatex +3/−3
- tests/biblio2yaml/incollection-2.biblatex +3/−3
- tests/biblio2yaml/incollection.biblatex +3/−3
- tests/biblio2yaml/inproceedings.biblatex +9/−9
- tests/biblio2yaml/issue288.biblatex +2/−2
- tests/biblio2yaml/itzhaki.biblatex +3/−3
- tests/biblio2yaml/jaffe.biblatex +2/−2
- tests/biblio2yaml/jcg.biblatex +1/−1
- tests/biblio2yaml/kant-kpv.biblatex +1/−1
- tests/biblio2yaml/kant-ku.biblatex +1/−1
- tests/biblio2yaml/kastenholz.biblatex +1/−1
- tests/biblio2yaml/knuth-ct-a.biblatex +1/−1
- tests/biblio2yaml/knuth-ct-b.biblatex +1/−1
- tests/biblio2yaml/knuth-ct-c.biblatex +1/−1
- tests/biblio2yaml/knuth-ct-d.biblatex +1/−1
- tests/biblio2yaml/knuth-ct-e.biblatex +1/−1
- tests/biblio2yaml/knuth-ct-related.biblatex +2/−2
- tests/biblio2yaml/knuth-ct.biblatex +2/−2
- tests/biblio2yaml/kowalik.biblatex +3/−3
- tests/biblio2yaml/kullback-related.biblatex +1/−1
- tests/biblio2yaml/kullback-reprint.biblatex +2/−2
- tests/biblio2yaml/kullback.biblatex +1/−1
- tests/biblio2yaml/laufenberg.biblatex +3/−3
- tests/biblio2yaml/loh.biblatex +1/−1
- tests/biblio2yaml/malinowski.biblatex +1/−1
- tests/biblio2yaml/manual.biblatex +1/−1
- tests/biblio2yaml/markey.biblatex +6/−6
- tests/biblio2yaml/maron.biblatex +1/−1
- tests/biblio2yaml/massa.biblatex +1/−1
- tests/biblio2yaml/moore-related.biblatex +1/−1
- tests/biblio2yaml/moore.biblatex +1/−1
- tests/biblio2yaml/moraux.biblatex +2/−2
- tests/biblio2yaml/murray.biblatex +1/−1
- tests/biblio2yaml/nietzsche-historie.biblatex +1/−1
- tests/biblio2yaml/nietzsche-ksa.biblatex +1/−1
- tests/biblio2yaml/nietzsche-ksa1.biblatex +1/−1
- tests/biblio2yaml/nussbaum.biblatex +1/−1
- tests/biblio2yaml/online.biblatex +10/−10
- tests/biblio2yaml/options-url-false-doi-false.biblatex +2/−2
- tests/biblio2yaml/padhye.biblatex +1/−1
- tests/biblio2yaml/pandoc-2/ctan.biblatex +4/−4
- tests/biblio2yaml/pandoc-2/jaffe.biblatex +2/−2
- tests/biblio2yaml/pandoc-2/kastenholz.biblatex +1/−1
- tests/biblio2yaml/pandoc-2/online.biblatex +10/−10
- tests/biblio2yaml/pandoc-2/sigfridsson.biblatex +1/−1
- tests/biblio2yaml/patent.biblatex +10/−10
- tests/biblio2yaml/periodical.biblatex +1/−1
- tests/biblio2yaml/piccato.biblatex +1/−1
- tests/biblio2yaml/pines.biblatex +1/−1
- tests/biblio2yaml/quotes.biblatex +1/−1
- tests/biblio2yaml/reese.biblatex +1/−1
- tests/biblio2yaml/report.biblatex +2/−2
- tests/biblio2yaml/salam.biblatex +7/−7
- tests/biblio2yaml/sarfraz.biblatex +1/−1
- tests/biblio2yaml/shore.biblatex +2/−2
- tests/biblio2yaml/sigfridsson.biblatex +1/−1
- tests/biblio2yaml/sorace.biblatex +3/−3
- tests/biblio2yaml/spiegelberg.biblatex +1/−1
- tests/biblio2yaml/springer.biblatex +1/−1
- tests/biblio2yaml/strings.biblatex +1/−1
- tests/biblio2yaml/test-case-conversion.biblatex +1/−1
- tests/biblio2yaml/thesis.biblatex +2/−2
- tests/biblio2yaml/vangennep-related.biblatex +1/−1
- tests/biblio2yaml/vangennep-trans.biblatex +1/−1
- tests/biblio2yaml/vangennep.biblatex +1/−1
- tests/biblio2yaml/vazques-de-parga-mvbook.biblatex +1/−1
- tests/biblio2yaml/vazques-de-parga.biblatex +1/−1
- tests/biblio2yaml/vizedom-related.biblatex +1/−1
- tests/biblio2yaml/wassenberg.biblatex +3/−3
- tests/biblio2yaml/weinberg.biblatex +1/−1
- tests/biblio2yaml/westfahl-frontier.biblatex +1/−1
- tests/biblio2yaml/westfahl-space.biblatex +2/−2
- tests/biblio2yaml/wilde.biblatex +1/−1
- tests/biblio2yaml/worman.biblatex +1/−1
- tests/biblio2yaml/yoon.biblatex +1/−1
- tests/issue250.expected.native +5/−0
- tests/issue250.in.native +2/−0
- tests/jats.csl +0/−208
- tests/modern-language-association-7th-edition.csl +460/−0
- tests/test-citeproc.hs +36/−33
- tests/test-pandoc-citeproc.hs +21/−21
changelog view
@@ -1,3 +1,36 @@+pandoc-citeproc (0.13)++ * Made bibliography parsing more efficient. (API change)+ This commit adds an extra parameter to the bibliography parsing+ functions: readBibtex, readBibtexString, readBiblioString,+ readBiblioFile. The extra (first) parameter is a function+ from strings to booleans that acts as a filter on citation+ identifiers, so that non-matching identifiers are not parsed+ in full. pandoc-citeproc now gets a list of the citation+ identifiers in a document and passes it to readBiblio*,+ which gives a very substantial speed increase with large+ bibliographies. This is most noticable with bibtex,+ biblatex, and yaml bibliographies.++ * Improved RefDate type (#313, API change). RefDate fields+ (month, day, season, year) were previously strings; they've+ been changed to Maybe Int. In addition, the AddYaml class+ is exported from Text.CSL.Util; (&=) is now a method of that+ class. Finally, parseEDTFDate is exported from Text.CSL.Reference,+ and is used instead of the old date parsing code in+ Text.CSL.Input.Bibtex.++ * Link to bibliographies in undated citations, like+ (Doe, n.d.) (#250).++ * Bibtex parser: a few efficiency improvements.++ * pandoc-citeproc.hs - better exception messages for -y and -j.++ * Added needed import of fromMaybe without embed_data_files.+ This makes it possible to build pandoc-citeproc without+ the embed_data_files flag again.+ pandoc-citeproc (0.12.2.5) * Fixed spurious disambiguation on some date ranges (#312).
man/man1/pandoc-citeproc.1 view
@@ -1,14 +1,14 @@ .\"t-.\" Automatically generated by Pandoc 2.0+.\" Automatically generated by Pandoc 2.1 .\"-.TH "pandoc\-citeproc" "1" "2017-06-04" "pandoc-citeproc 0.10.5" ""+.TH "pandoc\-citeproc" "1" "2018-01-09" "pandoc-citeproc 0.13" "" .hy .SH NAME .PP pandoc\-citeproc \- filter to resolve citations in a pandoc document. .SH SYNOPSIS .PP-pandoc\-citeproc options (#options) [file..]+pandoc\-citeproc options [file..] .SH DESCRIPTION .PP The \f[C]pandoc\-citeproc\f[] executable has two modes, filter mode and
pandoc-citeproc.cabal view
@@ -1,5 +1,5 @@ name: pandoc-citeproc-version: 0.12.2.5+version: 0.13 cabal-version: >= 1.12 synopsis: Supports using pandoc with citeproc
pandoc-citeproc.hs view
@@ -1,34 +1,38 @@-{-# LANGUAGE CPP, ScopedTypeVariables #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ScopedTypeVariables #-} module Main where-import Text.CSL.Input.Bibutils (readBiblioString, BibFormat(..))-import Text.CSL.Reference (Reference(refId), Literal(..))-import Text.CSL.Exception-import Data.List (group, sort)-import Data.Char (chr, toLower)-import Data.Yaml.Builder (toByteString)-import Control.Applicative ((<|>), many)-import qualified Data.ByteString as B-import qualified Data.ByteString.Lazy as BL-import qualified Data.ByteString.Char8 as B8-import Data.Attoparsec.ByteString.Char8 as Attoparsec-import qualified Data.Text as T-import Data.Text.Encoding (encodeUtf8)-import Data.Aeson.Encode.Pretty (encodePretty', defConfig, Config(..),- Indent(Spaces), NumberFormat(Generic))-import System.Console.GetOpt-import Control.Exception as E-import Control.Monad-import System.IO-import System.FilePath (takeExtension)-import System.Environment (getArgs)-import System.Exit-import Data.Version (showVersion)-import Paths_pandoc_citeproc (version)-import Text.CSL.Pandoc (processCites')-import Text.CSL.Data (getManPage, getLicense)-import Text.Pandoc.JSON hiding (Format)-import Text.Pandoc.Walk-import qualified Text.Pandoc.UTF8 as UTF8+import Control.Applicative (many, (<|>))+import Control.Exception as E+import Control.Monad+import Data.Aeson.Encode.Pretty (Config (..), Indent (Spaces),+ NumberFormat (Generic),+ defConfig, encodePretty')+import Data.Attoparsec.ByteString.Char8 as Attoparsec+import qualified Data.ByteString as B+import qualified Data.ByteString.Char8 as B8+import qualified Data.ByteString.Lazy as BL+import Data.Char (chr, toLower)+import Data.List (group, sort)+import qualified Data.Text as T+import Data.Text.Encoding (encodeUtf8)+import Data.Version (showVersion)+import Data.Yaml.Builder (toByteString)+import Paths_pandoc_citeproc (version)+import System.Console.GetOpt+import System.Environment (getArgs)+import System.Exit+import System.FilePath (takeExtension)+import System.IO+import Text.CSL.Data (getLicense, getManPage)+import Text.CSL.Exception+import Text.CSL.Input.Bibutils (BibFormat (..),+ readBiblioString)+import Text.CSL.Pandoc (processCites')+import Text.CSL.Reference (Literal (..),+ Reference (refId))+import Text.Pandoc.JSON hiding (Format)+import qualified Text.Pandoc.UTF8 as UTF8+import Text.Pandoc.Walk main :: IO () main = do@@ -40,69 +44,71 @@ exitWith $ ExitFailure 1 when (Version `elem` flags) $ do UTF8.putStrLn $ "pandoc-citeproc " ++ showVersion version- exitWith ExitSuccess+ exitSuccess when (Help `elem` flags) $ do UTF8.putStrLn $ usageInfo header options- exitWith ExitSuccess+ exitSuccess when (Man `elem` flags) $ do getManPage >>= BL.putStr- exitWith ExitSuccess+ exitSuccess when (License `elem` flags) $ do getLicense >>= BL.putStr- exitWith ExitSuccess- if Bib2YAML `elem` flags || Bib2JSON `elem` flags- then do- let mbformat = case [f | Format f <- flags] of- [x] -> readFormat x- _ -> Nothing- bibformat <- case mbformat <|>- msum (map formatFromExtension args) of- Just f -> return f- Nothing -> do- UTF8.hPutStrLn stderr $ usageInfo- ("Unknown format\n" ++ header) options- exitWith $ ExitFailure 3- bibstring <- case args of- [] -> UTF8.getContents- xs -> mconcat <$> mapM UTF8.readFile xs- readBiblioString bibformat bibstring >>=- warnDuplicateKeys >>=- if Bib2YAML `elem` flags- then outputYamlBlock .- B8.intercalate (B.singleton 10) .- map (unescapeTags . toByteString . (:[]))- else B8.putStrLn . unescapeUnicode . B.concat . BL.toChunks .- encodePretty' defConfig{ confIndent = Spaces 2- , confCompare = compare- , confNumFormat = Generic }- else E.catch (toJSONFilter doCites)- (\(e :: CiteprocException) -> do- UTF8.hPutStrLn stderr $ renderError e- exitWith (ExitFailure 1))+ exitSuccess + E.handle+ (\(e :: CiteprocException) -> do+ UTF8.hPutStrLn stderr $ renderError e+ exitWith (ExitFailure 1)) $+ if Bib2YAML `elem` flags || Bib2JSON `elem` flags+ then do+ let mbformat = case [f | Format f <- flags] of+ [x] -> readFormat x+ _ -> Nothing+ bibformat <- case mbformat <|>+ msum (map formatFromExtension args) of+ Just f -> return f+ Nothing -> do+ UTF8.hPutStrLn stderr $ usageInfo+ ("Unknown format\n" ++ header) options+ exitWith $ ExitFailure 3+ bibstring <- case args of+ [] -> UTF8.getContents+ xs -> mconcat <$> mapM UTF8.readFile xs+ readBiblioString (const True) bibformat bibstring >>=+ warnDuplicateKeys >>=+ if Bib2YAML `elem` flags+ then outputYamlBlock .+ B8.intercalate (B.singleton 10) .+ map (unescapeTags . toByteString . (:[]))+ else B8.putStrLn . unescapeUnicode . B.concat . BL.toChunks .+ encodePretty' defConfig{ confIndent = Spaces 2+ , confCompare = compare+ , confNumFormat = Generic }+ else toJSONFilter doCites+ formatFromExtension :: FilePath -> Maybe BibFormat formatFromExtension = readFormat . dropWhile (=='.') . takeExtension readFormat :: String -> Maybe BibFormat readFormat = go . map toLower- where go "biblatex" = Just BibLatex- go "bib" = Just BibLatex- go "bibtex" = Just Bibtex- go "json" = Just Json- go "yaml" = Just Yaml+ where go "biblatex" = Just BibLatex+ go "bib" = Just BibLatex+ go "bibtex" = Just Bibtex+ go "json" = Just Json+ go "yaml" = Just Yaml #ifdef USE_BIBUTILS- go "ris" = Just Ris- go "endnote" = Just Endnote- go "enl" = Just Endnote+ go "ris" = Just Ris+ go "endnote" = Just Endnote+ go "enl" = Just Endnote go "endnotexml" = Just EndnotXml- go "xml" = Just EndnotXml- go "wos" = Just Isi- go "isi" = Just Isi- go "medline" = Just Medline- go "copac" = Just Copac- go "mods" = Just Mods+ go "xml" = Just EndnotXml+ go "wos" = Just Isi+ go "isi" = Just Isi+ go "medline" = Just Medline+ go "copac" = Just Copac+ go "mods" = Just Mods #endif- go _ = Nothing+ go _ = Nothing doCites :: Pandoc -> IO Pandoc@@ -191,3 +197,4 @@ regchar :: Attoparsec.Parser B.ByteString regchar = B8.singleton <$> anyChar+
src/Text/CSL.hs view
@@ -63,13 +63,13 @@ , renderPandoc' ) where -import Text.CSL.Proc-import Text.CSL.Reference-import Text.CSL.Style-import Text.CSL.Parser-import Text.CSL.Input.Bibutils-import Text.CSL.Output.Pandoc-import Text.CSL.Output.Plain+import Text.CSL.Input.Bibutils+import Text.CSL.Output.Pandoc+import Text.CSL.Output.Plain+import Text.CSL.Parser+import Text.CSL.Proc+import Text.CSL.Reference+import Text.CSL.Style -- $intro
src/Text/CSL/Data.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE CPP #-}+{-# LANGUAGE CPP #-} {-# LANGUAGE DeriveDataTypeable #-} ----------------------------------------------------------------------------- -- |@@ -21,16 +21,17 @@ , langBase ) where -import System.FilePath ()-import Data.Typeable-import qualified Data.ByteString.Lazy as L-import qualified Control.Exception as E+import qualified Control.Exception as E+import qualified Data.ByteString.Lazy as L+import Data.Typeable+import System.FilePath ()+import Data.Maybe (fromMaybe) #ifdef EMBED_DATA_FILES-import Data.Maybe (fromMaybe)-import Text.CSL.Data.Embedded (localeFiles, defaultCSL, manpage, license)+import Text.CSL.Data.Embedded (defaultCSL, license, localeFiles,+ manpage) #else-import Paths_pandoc_citeproc (getDataFileName)-import System.Directory (doesFileExist)+import Paths_pandoc_citeproc (getDataFileName)+import System.Directory (doesFileExist) #endif data CSLLocaleException =@@ -38,7 +39,7 @@ | CSLLocaleReadError E.IOException deriving Typeable instance Show CSLLocaleException where- show (CSLLocaleNotFound s) = "Could not find locale data for " ++ s+ show (CSLLocaleNotFound s) = "Could not find locale data for " ++ s show (CSLLocaleReadError e) = show e instance E.Exception CSLLocaleException @@ -67,12 +68,12 @@ f <- case length s of 0 -> return "locales/locales-en-US.xml" 2 -> getDataFileName ("locales/locales-" ++- maybe s id (lookup s langBase) ++ ".xml")+ fromMaybe s (lookup s langBase) ++ ".xml") _ -> getDataFileName ("locales/locales-" ++ take 5 s ++ ".xml") exists <- doesFileExist f if not exists && length s > 2 then getLocale $ take 2 s -- try again with base locale- else E.handle (\e -> E.throwIO (CSLLocaleReadError e)) $ L.readFile f+ else E.handle (E.throwIO . CSLLocaleReadError) $ L.readFile f #endif getDefaultCSL :: IO L.ByteString@@ -142,3 +143,4 @@ ,("vi", "vi-VN") ,("zh", "zh-CN") ]+
src/Text/CSL/Data/Embedded.hs view
@@ -2,8 +2,8 @@ module Text.CSL.Data.Embedded (localeFiles, defaultCSL, manpage, license) where-import Data.FileEmbed import qualified Data.ByteString.Char8 as S+import Data.FileEmbed localeFiles :: [(FilePath, S.ByteString)] localeFiles = $(embedDir "locales")
src/Text/CSL/Eval.hs view
@@ -1,4 +1,6 @@-{-# LANGUAGE PatternGuards, FlexibleContexts, ScopedTypeVariables #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE ScopedTypeVariables #-} ----------------------------------------------------------------------------- -- | -- Module : Text.CSL.Eval@@ -20,28 +22,28 @@ , module Text.CSL.Eval.Output ) where -import Control.Arrow-import Control.Monad.State-import qualified Control.Exception as E-import Data.Monoid (Any(..))-import Data.Char ( toLower, isDigit, isLetter )-import Data.Maybe-import Data.String ( fromString )-import Text.Pandoc.Definition (Inline(Str, Link), nullAttr)-import Text.Pandoc.Walk (walk)-import Text.Pandoc.Shared (stringify)-import qualified Data.Text as T+import Control.Arrow+import qualified Control.Exception as E+import Control.Monad.State+import Data.Char (isDigit, isLetter, toLower)+import Data.Maybe+import Data.Monoid (Any (..))+import Data.String (fromString)+import qualified Data.Text as T+import Text.Pandoc.Definition (Inline (Link, Str), nullAttr)+import Text.Pandoc.Shared (stringify)+import Text.Pandoc.Walk (walk) -import Text.CSL.Exception-import Text.CSL.Eval.Common-import Text.CSL.Eval.Output-import Text.CSL.Eval.Date-import Text.CSL.Eval.Names-import Text.CSL.Output.Plain-import Text.CSL.Reference-import Text.CSL.Style hiding (Any)-import Text.CSL.Util ( readNum, last', proc, proc', query, betterThan,- safeRead, isRange )+import Text.CSL.Eval.Common+import Text.CSL.Eval.Date+import Text.CSL.Eval.Names+import Text.CSL.Eval.Output+import Text.CSL.Exception+import Text.CSL.Output.Plain+import Text.CSL.Reference+import Text.CSL.Style hiding (Any)+import Text.CSL.Util (betterThan, isRange, last', proc,+ proc', query, readNum, safeRead) -- | Produce the output with a 'Layout', the 'EvalMode', a 'Bool' -- 'True' if the evaluation happens for disambiguation purposes, the@@ -80,8 +82,8 @@ = map (format . sorting) ss where render = renderPlain . formatOutputList . proc removeDelimAndLabel- removeDelimAndLabel (OLabel{}) = ONull- removeDelimAndLabel (ODel{}) = ONull+ removeDelimAndLabel OLabel{} = ONull+ removeDelimAndLabel ODel{} = ONull removeDelimAndLabel x = x format (s,e) = applaySort s . render $ uncurry eval e eval o e = evalLayout (Layout emptyFormatting [] [e]) m False l ms o as mbr@@ -118,9 +120,9 @@ then getLocVar >>= formatRange fm . snd else formatNumber f fm s =<< getStringVar s- | Variable s f fm d <- el = return . addDelim d =<< concatMapM (getVariable f fm) s+ | Variable s f fm d <- el = addDelim d <$> concatMapM (getVariable f fm) s | Group fm d l <- el = outputList fm d <$> tryGroup l- | Date _ _ _ _ _ _ <- el = evalDate el+ | Date{} <- el = evalDate el | Label s f fm _ <- el = formatLabel f fm True s -- FIXME !! | Term s f fm p <- el = formatTerm f fm p s | Names s n fm d sub <- el = modify (\st -> st { contNum = [] }) >>@@ -151,7 +153,7 @@ where addSpaces strng = (if take 1 strng == " " then (OSpace:) else id) . (if last' strng == " " then (++[OSpace]) else id)- substituteWith e = head <$> gets (names . env) >>= \(Names _ ns fm d _) -> do+ substituteWith e = head <$> gets (names . env) >>= \(Names _ ns fm d _) -> case e of Names rs [Name NotSet fm'' [] [] []] fm' d' [] -> let nfm = mergeFM fm'' $ mergeFM fm' fm in@@ -177,8 +179,8 @@ nums <- mapM getStringVar numVars let pluralizeTerm (Term s f fm _) = Term s f fm $ case numVars of- ["number-of-volumes"] -> not $ any (== "1") nums- ["number-of-pages"] -> not $ any (== "1") nums+ ["number-of-volumes"] -> "1" `notElem` nums+ ["number-of-pages"] -> "1" `notElem` nums _ -> any isRange nums pluralizeTerm x = x if null res@@ -197,7 +199,7 @@ | Const {} <- e = True | otherwise = False - ifEmpty p t e = p >>= \r -> if r == [] then t else return (e r)+ ifEmpty p t e = p >>= \r -> if null r then t else return (e r) withNames e n f = modify (\s -> s { authSub = e ++ authSub s , env = (env s)@@ -269,14 +271,16 @@ in getVar False chk "ref-type" chkNumeric v = do val <- getStringVar v as <- gets (abbrevs . env)- let val' = if getAbbreviation as v val == [] then val else getAbbreviation as v val+ let val' = if null (getAbbreviation as v val)+ then val+ else getAbbreviation as v val return (isNumericString val')- chkDate v = getDateVar v >>= return . not . null . filter circa+ chkDate v = any circa <$> getDateVar v chkPosition s = if s == "near-note" then gets (nearNote . cite . env)- else gets (citePosition . cite . env) >>= return . compPosition s- chkDisambiguate s = gets disamb >>= return . (==) (formatVariable s) . map toLower . show- chkLocator v = getLocVar >>= return . (==) v . fst+ else compPosition s <$> gets (citePosition . cite . env)+ chkDisambiguate s = (==) (formatVariable s) . map toLower . show <$> gets disamb+ chkLocator v = (==) v . fst <$> getLocVar isIbid s = not (s == "first" || s == "subsequent") compPosition a b | "first" <- a = b == "first"@@ -290,13 +294,13 @@ | Just v <- fromValue val :: Maybe Formatted = if v == mempty then []- else let ys = maybe (unFormatted v) (unFormatted . fromString)+ else let ys = unFormatted . maybe v fromString $ getAbbr (stringify $ unFormatted v) in if null ys then [] else [Output [OPan $ walk value' ys] fm]- | Just v <- fromValue val :: Maybe String = (:[]) . flip OStr fm . maybe v id . getAbbr $ value v- | Just v <- fromValue val :: Maybe Literal = (:[]) . flip OStr fm . maybe (unLiteral v) id . getAbbr $ value $ unLiteral v+ | Just v <- fromValue val :: Maybe String = (:[]) . flip OStr fm . Data.Maybe.fromMaybe v . getAbbr $ value v+ | Just v <- fromValue val :: Maybe Literal = (:[]) . flip OStr fm . Data.Maybe.fromMaybe (unLiteral v) . getAbbr $ value $ unLiteral v | Just v <- fromValue val :: Maybe Int = output fm (if v == 0 then [] else show v) | Just v <- fromValue val :: Maybe Int = output fm (if v == 0 then [] else show v) | Just v <- fromValue val :: Maybe CNum = if v == 0 then [] else [OCitNum (unCNum v) fm]@@ -311,8 +315,8 @@ value' x = x getAbbr v = if f == Short then case getAbbreviation as s v of- [] -> Nothing- y -> Just y+ [] -> Nothing+ y -> Just y else Nothing nameOpts = ("name-as-sort-order","all") : o sortDate = [ DatePart "year" "numeric-leading-zeros" "" emptyFormatting@@ -323,10 +327,10 @@ formatTitle s f fm | Short <- f , isTitleVar s = try (getIt $ s ++ "-short") $ getIt s- | isTitleShortVar s = try (getIt s) $ return . (:[]) . flip OStr fm =<< getTitleShort s+ | isTitleShortVar s = try (getIt s) $ (:[]) . flip OStr fm <$> getTitleShort s | otherwise = getIt s where- try g h = g >>= \r -> if r == [] then h else return r+ try g h = g >>= \r -> if null r then h else return r getIt x = do o <- gets (options . env) a <- gets (abbrevs . env)@@ -336,24 +340,29 @@ formatNumber f fm v n = gets (abbrevs . env) >>= \as -> if isNumericString (getAbbr as n)- then gets (terms . env) >>=- return . output fm . flip process (getAbbr as n)+ then output fm . flip process (getAbbr as n) <$> gets (terms . env) else return . output fm . getAbbr as $ n where- getAbbr as = if getAbbreviation as v n == [] then id else getAbbreviation as v+ getAbbr as = if null (getAbbreviation as v n)+ then id+ else getAbbreviation as v checkRange' ts = if v == "page" then checkRange ts else id process ts = checkRange' ts . printNumStr . map (renderNumber ts) . breakNumericString . words renderNumber ts x = if isTransNumber x then format ts x else x format tm = case f of- Ordinal -> ordinal tm v- LongOrdinal -> longOrdinal tm v- Roman -> if readNum n < 6000 then roman else id- _ -> id+ Ordinal -> maybe "" (ordinal tm v) . safeRead+ LongOrdinal -> maybe "" (longOrdinal tm v) . safeRead+ Roman -> maybe ""+ (\x -> if x < 6000 then roman x else show x) .+ safeRead+ _ -> maybe "" show . (safeRead :: String -> Maybe Int) + roman :: Int -> String roman = foldr (++) [] . reverse . map (uncurry (!!)) . zip romanList .- map (readNum . return) . take 4 . reverse+ map (readNum . return) . take 4 .+ reverse . show romanList = [[ "", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix" ] ,[ "", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc" ] ,[ "", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm" ]@@ -369,7 +378,7 @@ printNumStr :: [String] -> String printNumStr [] = []-printNumStr (x:[]) = x+printNumStr [x] = x printNumStr (x:"-":y:xs) = x ++ "-" ++ y ++ printNumStr xs printNumStr (x:",":y:xs) = x ++ ", " ++ y ++ printNumStr xs printNumStr (x:xs)@@ -388,9 +397,9 @@ isSpecialChar = all (`elem` "&-,.\x2013") isNumber cs = case [c | c <- cs , not (isLetter c)- , not (c `elem` "&-.,\x2013")] of- [] -> False- xs -> all isDigit xs+ , c `notElem` "&-.,\x2013"] of+ [] -> False+ xs -> all isDigit xs breakNumericString :: [String] -> [String] breakNumericString [] = []@@ -411,7 +420,7 @@ pages = tupleRange . breakNumericString . words $ p tupleRange [] = []- tupleRange (x:cs:[] )+ tupleRange [x, cs] | cs `elem` ["-", "--", "\x2013"] = return (x,[]) tupleRange (x:cs:y:xs) | cs `elem` ["-", "--", "\x2013"] = (x, y) : tupleRange xs@@ -421,12 +430,12 @@ joinRange (a, b) = a ++ "-" ++ b process = checkRange ts . printNumStr . case opt of- "expanded" -> map (joinRange . expandedRange)- "chicago" -> map (joinRange . chicagoRange )- "minimal" -> map (joinRange . minimalRange 1)- "minimal-two" -> map (joinRange . minimalRange 2)- _ -> map joinRange- return [flip OLoc fm $ [OStr (process pages) emptyFormatting]]+ "expanded" -> map (joinRange . expandedRange)+ "chicago" -> map (joinRange . chicagoRange )+ "minimal" -> map (joinRange . minimalRange 1)+ "minimal-two" -> map (joinRange . minimalRange 2)+ _ -> map joinRange+ return [OLoc [OStr (process pages) emptyFormatting] fm] -- Abbreviated page ranges are expanded to their non-abbreviated form: -- 42–45, 321–328, 2787–2816@@ -446,7 +455,7 @@ -- a minimum number of digits for the second number; thus, with -- minDigits = 2, we have 328-28. minimalRange :: Int -> (String, String) -> (String, String)-minimalRange minDigits ((a:as), (b:bs))+minimalRange minDigits (a:as, b:bs) | a == b , length as == length bs , length bs >= minDigits =
src/Text/CSL/Eval/Common.hs view
@@ -18,18 +18,18 @@ module Text.CSL.Eval.Common where -import Control.Arrow ( (&&&), (>>>) )-import Control.Monad.State-import Data.Char ( toLower )-import Data.List ( elemIndex )-import qualified Data.Map as M-import Data.Maybe+import Control.Arrow ((&&&), (>>>))+import Control.Monad.State+import Data.Char (toLower)+import Data.List (elemIndex)+import qualified Data.Map as M+import Data.Maybe -import Text.Pandoc.Shared ( stringify )-import Text.CSL.Reference-import Text.CSL.Style+import Text.CSL.Reference+import Text.CSL.Style+import Text.Pandoc.Shared (stringify) -import Debug.Trace+import Debug.Trace data EvalState = EvalState
src/Text/CSL/Eval/Date.hs view
@@ -15,19 +15,21 @@ module Text.CSL.Eval.Date where -import Control.Monad.State-import qualified Control.Exception as E+import qualified Control.Exception as E+import Control.Monad.State -import Data.List-import Data.List.Split+import Data.List+import Data.List.Split+import Data.Maybe (fromMaybe, isNothing) -import Text.CSL.Exception-import Text.CSL.Eval.Common-import Text.CSL.Eval.Output-import Text.CSL.Style-import Text.CSL.Reference-import Text.CSL.Util ( readNum, toRead, last')-import Text.Pandoc.Definition ( Inline (Str) )+import Text.CSL.Exception+import Text.CSL.Eval.Common+import Text.CSL.Eval.Output+import Text.CSL.Style+import Text.CSL.Reference+import Text.CSL.Util ( toRead, last' )+import Text.Pandoc.Definition ( Inline (Str) )+import Text.Printf (printf) evalDate :: Element -> State EvalState [Output] evalDate (Date s f fm dl dp dp') = do@@ -48,8 +50,8 @@ al am an ahl updateS a b = if b /= a && b /= [] then b else a case f of- NoFormDate -> mapM getDateVar s >>= return . outputList fm dl .- concatMap (formatDate em k tm dp)+ NoFormDate -> outputList fm dl .+ concatMap (formatDate em k tm dp) <$> mapM getDateVar s _ -> do Date _ _ lfm ldl ldp _ <- getDate f let go dps = return . outputList (updateFM fm lfm) (if ldl /= [] then ldl else dl) . concatMap (formatDate em k tm dps)@@ -81,8 +83,8 @@ | (a:b:_) <- date = addODate . concat $ doRange a b | otherwise = [] where- addODate [] = []- addODate xs = [ODate xs]+ addODate [] = []+ addODate xs = [ODate xs] splitDate a b = case split (onSublist $ diff a b dp) dp of [x,y,z] -> (x,y,z) _ -> E.throw ErrorSplittingDate@@ -111,7 +113,7 @@ case () of _ | ya /= yb -> ["year","month","day"] | ma /= mb || sa /= sb ->- if da == mempty && db == mempty+ if isNothing da && isNothing db then ["month"] else ["month","day"] | da /= db -> ["day"]@@ -122,16 +124,12 @@ else Long in maybe [] termPlural $ findTerm t f' tm - addZero n = if length n == 1 then '0' : n else n- addZeros = reverse . take 5 . flip (++) (repeat '0') . reverse- formatDatePart (RefDate (Literal y) (Literal m)- (Literal e) (Literal d) (Literal o) _) (DatePart n f _ fm)- | "year" <- n, y /= mempty = return $ OYear (formatYear f y) k fm- | "month" <- n, m /= mempty = output fm (formatMonth f fm m)- | "day" <- n, d /= mempty = output fm (formatDay f m d)- | "month" <- n, m == mempty- , e /= mempty = output fm $ term f ("season-0" ++ e)- | "year" <- n, o /= mempty = output fm o+ formatDatePart (RefDate y m e d o _) (DatePart n f _ fm)+ | "year" <- n, Just y' <- y = return $ OYear (formatYear f y') k fm+ | "month" <- n, Just m' <- m = output fm (formatMonth f fm m')+ | "month" <- n, Just e' <- e = output fm $ term f (printf "season-%02d" e')+ | "day" <- n, Just d' <- d = output fm (formatDay f m d')+ | "year" <- n, o /= mempty = output fm (unLiteral o) | otherwise = [] withDelim xs o1 o2@@ -142,81 +140,78 @@ _ -> []) ++ o2 formatYear f y- | "short" <- f = drop 2 y+ | "short" <- f = printf "%02d" y | isSorting em- , iy < 0 = '-' : addZeros (tail y)- | isSorting em = addZeros y- | iy < 0 = show (abs iy) ++ term [] "bc"- | length y < 4- , iy /= 0 = y ++ term [] "ad"- | iy == 0 = []- | otherwise = y- where- iy = readNum y+ , y < 0 = printf "-%04d" (abs y)+ | isSorting em = printf "%04d" y+ | y < 0 = printf "%d" (abs y) ++ term [] "bc"+ | y < 1000+ , y > 0 = printf "%d" y ++ term [] "ad"+ | y == 0 = ""+ | otherwise = printf "%d" y+ formatMonth f fm m | "short" <- f = getMonth $ period . termPlural | "long" <- f = getMonth termPlural- | "numeric" <- f = m- | otherwise = addZero m+ | "numeric" <- f = printf "%d" m+ | otherwise = printf "%02d" m where period = if stripPeriods fm then filter (/= '.') else id- getMonth g = maybe m g $ findTerm ("month-" ++ addZero m) (read $ toRead f) tm+ getMonth g = maybe (show m) g $ findTerm ("month-" ++ printf "%02d" m) (read $ toRead f) tm+ formatDay f m d- | "numeric-leading-zeros" <- f = addZero d- | "ordinal" <- f = ordinal tm ("month-" ++ addZero m) d- | otherwise = d+ | "numeric-leading-zeros" <- f = printf "%02d" d+ | "ordinal" <- f = ordinal tm ("month-" ++ maybe "0" (printf "%02d") m) d+ | otherwise = printf "%d" d -ordinal :: [CslTerm] -> String -> String -> String-ordinal _ _ [] = []+ordinal :: [CslTerm] -> String -> Int -> String ordinal ts v s- | length s == 1 = let a = termPlural (getWith1 s) in- if a == [] then setOrd (term []) else s ++ a- | length s == 2 = let a = termPlural (getWith2 s)- b = getWith1 [last s] in+ | s < 10 = let a = termPlural (getWith1 (show s)) in+ if a == [] then setOrd (term []) else show s ++ a+ | s < 100 = let a = termPlural (getWith2 (show s))+ b = getWith1 [last (show s)] in if a /= []- then s ++ a+ then show s ++ a else if termPlural b == [] || (termMatch b /= [] && termMatch b /= "last-digit") then setOrd (term []) else setOrd b | otherwise = let a = getWith2 last2- b = getWith1 [last s] in+ b = getWith1 [last (show s)] in if termPlural a /= [] && termMatch a /= "whole-number" then setOrd a- else if termPlural b == [] || (termMatch b /= [] && termMatch b /= "last-digit")- then setOrd (term []) else setOrd b+ else if null (termPlural b) ||+ (termMatch b /= [] &&+ termMatch b /= "last-digit")+ then setOrd (term [])+ else setOrd b where- setOrd = (++) s . termPlural+ setOrd = (++) (show s) . termPlural getWith1 = term . (++) "-0" getWith2 = term . (++) "-"- last2 = reverse . take 2 . reverse $ s+ last2 = reverse . take 2 . reverse $ show s term t = getOrdinal v ("ordinal" ++ t) ts -longOrdinal :: [CslTerm] -> String -> String -> String-longOrdinal _ _ [] = []+longOrdinal :: [CslTerm] -> String -> Int -> String longOrdinal ts v s- | num > 10 ||- num == 0 = ordinal ts v s- | otherwise = case last s of- '1' -> term "01"- '2' -> term "02"- '3' -> term "03"- '4' -> term "04"- '5' -> term "05"- '6' -> term "06"- '7' -> term "07"- '8' -> term "08"- '9' -> term "09"- _ -> term "10"+ | s > 10 ||+ s == 0 = ordinal ts v s+ | otherwise = case s `mod` 10 of+ 1 -> term "01"+ 2 -> term "02"+ 3 -> term "03"+ 4 -> term "04"+ 5 -> term "05"+ 6 -> term "06"+ 7 -> term "07"+ 8 -> term "08"+ 9 -> term "09"+ _ -> term "10" where- num = readNum s term t = termPlural $ getOrdinal v ("long-ordinal-" ++ t) ts getOrdinal :: String -> String -> [CslTerm] -> CslTerm getOrdinal v s ts- = case findTerm' s Long gender ts of- Just x -> x- Nothing -> case findTerm' s Long Neuter ts of- Just x -> x- Nothing -> newTerm+ = fromMaybe newTerm $ findTerm' s Long gender ts `mplus`+ findTerm' s Long Neuter ts where gender = if v `elem` numericVars || "month" `isPrefixOf` v then maybe Neuter termGender $ findTerm v Long ts
src/Text/CSL/Eval/Names.hs view
@@ -1,4 +1,5 @@-{-# LANGUAGE PatternGuards, FlexibleContexts #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE PatternGuards #-} ----------------------------------------------------------------------------- -- | -- Module : Text.CSL.Eval.Names@@ -15,20 +16,20 @@ module Text.CSL.Eval.Names where -import Control.Monad.State-import Data.Char ( isLower, isUpper, isLetter )-import Data.List ( nub, intersperse )-import Data.List.Split ( wordsBy )-import Data.Maybe ( isJust )+import Control.Monad.State+import Data.Char (isLetter, isLower, isUpper)+import Data.List (intersperse, nub)+import Data.List.Split (wordsBy)+import Data.Maybe (isJust) -import Text.CSL.Eval.Common-import Text.CSL.Eval.Output-import Text.CSL.Util ( headInline, lastInline, readNum, (<^>), query, toRead,- splitStrWhen, isRange )-import Text.CSL.Style-import Text.Pandoc.Definition-import Text.Pandoc.Shared ( stringify )-import qualified Text.Pandoc.Builder as B+import Text.CSL.Eval.Common+import Text.CSL.Eval.Output+import Text.CSL.Style+import Text.CSL.Util (headInline, isRange, lastInline, query,+ readNum, splitStrWhen, toRead, (<^>))+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Definition+import Text.Pandoc.Shared (stringify) evalNames :: Bool -> [String] -> [Name] -> String -> State EvalState [Output] evalNames skipEdTrans ns nl d@@ -55,7 +56,7 @@ if null res then return [] else let role = if aus == ["author"] then "authorsub" else s- in return . return . OContrib k role res fb =<< gets etal+ in return . OContrib k role res fb <$> gets etal r' <- evalNames skipEdTrans xs nl d num <- gets contNum return $ if r /= [] && r' /= []@@ -64,7 +65,7 @@ | otherwise = return [] where agents p s a = concatMapM (formatNames (hasEtAl nl) d p s a) nl- delim ops = if d == [] then getOptionVal "names-delimiter" ops else d+ delim ops = if null d then getOptionVal "names-delimiter" ops else d resetEtal = modify (\s -> s { etal = [] }) count num x = if hasCount nl && num /= [] -- FIXME!! le zero!! then [OContrib [] [] [ONum (length num) emptyFormatting] [] []]@@ -81,16 +82,19 @@ formatNames ea del p s as n | Name f _ ns _ _ <- n, Count <- f = do b <- isBib <$> gets mode- o <- gets (options . env) >>= return . mergeOptions ns+ o <- mergeOptions ns <$> gets (options . env) modify $ \st -> st { contNum = nub $ (++) (take (snd $ isEtAl b o p as) as) $ contNum st } return [] | Name f fm ns d np <- n = do b <- isBib <$> gets mode- o <- gets (options . env) >>= return . mergeOptions ns+ o <- mergeOptions ns <$> gets (options . env) m <- gets mode let odel = if del /= [] then del else getOptionVal "name-delimiter" o- del' = if d /= [] then d else if odel == [] then ", " else odel+ del'+ | d /= [] = d+ | null odel = ", "+ | otherwise = odel (_,i) = isEtAl b o p as form = case f of NotSet -> case getOptionVal "name-form" o of@@ -100,8 +104,11 @@ genName x = do etal' <- formatEtAl o ea "et-al" fm del' x if null etal' then do t <- getTerm False Long "and"- return $ delim t o del' $ format m o form fm np x- else return $ (addDelim del' $ format m o form fm np x) ++ etal'+ return $ delim t o del'+ $ format m o form fm np x+ else return $+ addDelim del' (format m o form fm np x)+ ++ etal' setLastName o $ formatName m False f fm o np (last as) updateEtal =<< mapM genName [1 + i .. length as] genName i@@ -136,8 +143,8 @@ updateEtal x = modify $ \st -> let x' = if length x == 1 then repeat $ head x else x in st { etal = case etal st of- [] -> x- ys -> zipWith (++) ys x'+ [] -> x+ ys -> zipWith (++) ys x' } isWithLastName os | "true" <- getOptionVal "et-al-use-last" os@@ -166,7 +173,7 @@ | "text" <- getOptionVal "and" os = " " ++ t ++ " " | "symbol" <- getOptionVal "and" os = " & " | otherwise = []- andStr' t d os = if andStr t os == [] then d else andStr t os+ andStr' t d os = if null (andStr t os) then d else andStr t os formatEtAl o b t fm d i = do ln <- gets lastName@@ -177,8 +184,8 @@ | otherwise -> return [] else et_al o b t fm d i et_al o b t fm d i- = when' (gets mode >>= return . not . isSorting) $- if (b || length as <= i)+ = when' ( not . isSorting <$> gets mode) $+ if b || length as <= i then return [] else do x <- getTerm False Long t when' (return $ x /= []) $@@ -217,7 +224,7 @@ etAlMin' x y = if b then etAlMin x else read $ getOptionVal' x y isOptionSet' s1 s2 = if b then isOptionSet s1 os- else or $ (isOptionSet s1 os) : [(isOptionSet s2 os)]+ else or $ isOptionSet s1 os : [isOptionSet s2 os] getOptionVal' s1 s2 = if null (getOptionVal s1 os) then getOptionVal s2 os else getOptionVal s1 os@@ -264,10 +271,9 @@ Nothing | isInit x -> addIn x [Space] -- default _ -> Space : x ++ [Space]- addIn x i = foldr hyphenate []- $ map (\z -> Str (headInline z) : i)- $ wordsBy (== Str "-")- $ splitStrWhen (=='-') x+ addIn x i = foldr (hyphenate . (\z -> Str (headInline z) : i)) []+ $ wordsBy (== Str "-")+ $ splitStrWhen (=='-') x sortSep g s = when_ g $ separator ++ addAffixes (g <+> s) "given" mempty separator = if null (getOptionVal "sort-separator" ops)@@ -281,13 +287,13 @@ oPan' (unFormatted $ nameSuffix n) fm suffNoCom = when_ (nameSuffix n) $ OSpace : oPan' (unFormatted $ nameSuffix n) fm - onlyGiven = not (givenName n == mempty) && family == mempty+ onlyGiven = givenName n /= mempty && family == mempty given = if onlyGiven then givenLong else when_ (givenName n) . Formatted . trimsp . fixsp . concatMap initial $ givenName n fixsp (Space:Space:xs) = fixsp (Space:xs)- fixsp (x:xs) = x : fixsp xs- fixsp [] = []+ fixsp (x:xs) = x : fixsp xs+ fixsp [] = [] trimsp = reverse . dropWhile (==Space) . reverse . dropWhile (==Space) givenLong = when_ (givenName n) . mconcat . intersperse (Formatted [Space]) $ givenName n family = familyName n@@ -298,23 +304,23 @@ c <= '\x5FF' || (c >= '\x1e00' && c <= '\x1fff') shortName = oPan' (unFormatted $ nondropping <+> family) (form "family")- longName g = if isSorting m- then let firstPart = case getOptionVal "demote-non-dropping-particle" ops of++ longName g+ | isSorting m = let firstPart = case getOptionVal "demote-non-dropping-particle" ops of "never" -> nondropping <+> family <+> dropping _ -> family <+> dropping <+> nondropping in oPan' (unFormatted firstPart) (form "family") <++> oPan' (unFormatted g) (form "given") <> suffCom- else if (b && getOptionVal "name-as-sort-order" ops == "first") ||- getOptionVal "name-as-sort-order" ops == "all"- then let (fam,par) = case getOptionVal "demote-non-dropping-particle" ops of- "never" -> (nondropping <+> family, dropping)- "sort-only" -> (nondropping <+> family, dropping)- _ -> (family, dropping <+> nondropping)- in oPan' (unFormatted fam) (form "family") <> sortSep g par <> suffCom- else let fam = addAffixes (dropping <+> nondropping <+> family) "family" suff- gvn = oPan' (unFormatted g) (form "given")- in if all isByzantine $ stringify $ unFormatted family- then gvn <++> fam- else fam <> gvn+ | (b && getOptionVal "name-as-sort-order" ops == "first") ||+ getOptionVal "name-as-sort-order" ops == "all" = let (fam,par) = case getOptionVal "demote-non-dropping-particle" ops of+ "never" -> (nondropping <+> family, dropping)+ "sort-only" -> (nondropping <+> family, dropping)+ _ -> (family, dropping <+> nondropping)+ in oPan' (unFormatted fam) (form "family") <> sortSep g par <> suffCom+ | otherwise = let fam = addAffixes (dropping <+> nondropping <+> family) "family" suff+ gvn = oPan' (unFormatted g) (form "given")+ in if all isByzantine $ stringify $ unFormatted family+ then gvn <++> fam+ else fam <> gvn disWithGiven = getOptionVal "disambiguate-add-givenname" ops == "true" initialize = isJust (lookup "initialize-with" ops) && not onlyGiven@@ -349,7 +355,7 @@ formatLabel :: Form -> Formatting -> Bool -> String -> State EvalState [Output] formatLabel f fm p s- | "locator" <- s = when' (gets (citeLocator . cite . env) >>= return . (/=) []) $ do+ | "locator" <- s = when' ( (/=) [] <$> gets (citeLocator . cite . env)) $ do (l,v) <- getLocVar form (\fm' -> return . flip OLoc emptyFormatting . output fm') id l (isRange v) | "page" <- s = checkPlural@@ -372,7 +378,7 @@ v <- getStringVar s format s (isRange v) format = form output id- form o g t b = return . o fm =<< g . period <$> getTerm (b && p) f t+ form o g t b = o fm . g . period <$> getTerm (b && p) f t period = if stripPeriods fm then filter (/= '.') else id (<+>) :: Formatted -> Formatted -> Formatted@@ -380,9 +386,9 @@ s <+> Formatted [] = s Formatted xs <+> Formatted ys = case lastInline xs of- "’" -> Formatted (xs ++ ys)- "-" -> Formatted (xs ++ ys)- _ -> Formatted (xs ++ [Space] ++ ys)+ "’" -> Formatted (xs ++ ys)+ "-" -> Formatted (xs ++ ys)+ _ -> Formatted (xs ++ [Space] ++ ys) (<++>) :: [Output] -> [Output] -> [Output] [] <++> o = o
src/Text/CSL/Eval/Output.hs view
@@ -15,15 +15,16 @@ module Text.CSL.Eval.Output where -import Text.CSL.Output.Pandoc (lastInline)-import Text.CSL.Style-import Data.Char (toLower, toUpper)-import Text.CSL.Util (capitalize, titlecase, unTitlecase, isPunct)-import Text.Pandoc.Definition-import Text.Pandoc.Walk (walk)-import Data.String (fromString)-import Data.Maybe (mapMaybe)-import Text.Parsec+import Data.Char (toLower, toUpper)+import Data.Maybe (mapMaybe)+import Data.String (fromString)+import Text.CSL.Output.Pandoc (lastInline)+import Text.CSL.Style+import Text.CSL.Util (capitalize, isPunct, titlecase,+ unTitlecase)+import Text.Pandoc.Definition+import Text.Pandoc.Walk (walk)+import Text.Parsec -- Parse affix or delimiter into Formatted, splitting out -- raw components in @{{format}}...{{/format}}@.@@ -57,15 +58,15 @@ | otherwise = [OStr s fm] appendOutput :: Formatting -> [Output] -> [Output]-appendOutput fm xs = if xs /= [] then [Output xs fm] else []+appendOutput fm xs = [Output xs fm | xs /= []] outputList :: Formatting -> Delimiter -> [Output] -> [Output] outputList fm d = appendOutput fm . addDelim d . mapMaybe cleanOutput' where cleanOutput' o | Output xs f <- o = case cleanOutput xs of- [] -> Nothing- ys -> Just (Output ys f)+ [] -> Nothing+ ys -> Just (Output ys f) | otherwise = rmEmptyOutput o cleanOutput :: [Output] -> [Output]@@ -115,7 +116,7 @@ oPan ils = [OPan ils] oPan' :: [Inline] -> Formatting -> [Output]-oPan' [] _ = []+oPan' [] _ = [] oPan' ils f = [Output [OPan ils] f] formatOutputList :: [Output] -> Formatted@@ -199,17 +200,17 @@ | otherwise = Formatted $ font_variant . font_style . font_weight $ ils font_variant ils = case fontVariant f of- "small-caps" -> [SmallCaps ils]- _ -> ils+ "small-caps" -> [SmallCaps ils]+ _ -> ils font_style ils = case fontStyle f of- "italic" -> [Emph ils]- "oblique" -> [Emph ils]- _ -> ils+ "italic" -> [Emph ils]+ "oblique" -> [Emph ils]+ _ -> ils font_weight ils = case fontWeight f of- "bold" -> [Strong ils]- _ -> ils+ "bold" -> [Strong ils]+ _ -> ils text_case (Formatted []) = Formatted [] text_case (Formatted ils@(i:is))@@ -224,10 +225,10 @@ "sentence" -> unTitlecase ils _ -> ils - lowercaseStr (Str xs) = Str $ map toLower xs- lowercaseStr x = x- uppercaseStr (Str xs) = Str $ map toUpper xs- uppercaseStr x = x+ lowercaseStr (Str xs) = Str $ map toLower xs+ lowercaseStr x = x+ uppercaseStr (Str xs) = Str $ map toUpper xs+ uppercaseStr x = x capitalizeStr (Str xs) = Str $ capitalize xs capitalizeStr x = x
src/Text/CSL/Exception.hs view
@@ -1,8 +1,8 @@-{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE DeriveDataTypeable #-}+ module Text.CSL.Exception (CiteprocException(..), renderError) where-import Control.Exception (Exception)-import Data.Data+import Control.Exception (Exception)+import Data.Data data CiteprocException = ErrorParsingReferences String
src/Text/CSL/Input/Bibtex.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleContexts #-} {-# OPTIONS_GHC -fno-warn-unused-do-bind #-} ----------------------------------------------------------------------------- -- |@@ -20,35 +21,37 @@ ) where -import Text.Parsec hiding (optional, (<|>), many, State)-import Control.Applicative-import qualified Control.Exception as E-import Text.CSL.Compat.Pandoc (readLaTeX)-import Text.CSL.Exception- (CiteprocException (ErrorReadingBib, ErrorReadingBibFile))-import Text.Pandoc.Definition-import Text.Pandoc.Generic (bottomUp)-import Data.List.Split (splitOn, splitWhen, wordsBy)-import Data.List (intercalate, foldl')-import Data.Maybe-import Data.Char (toLower, isUpper, toUpper, isDigit, isAlphaNum)-import Control.Monad-import Control.Monad.RWS-import System.Environment (getEnvironment)-import Text.CSL.Reference-import Text.CSL.Style (Formatted(..), Locale(..), CslTerm(..), Agent(..))-import Text.CSL.Util (trim, onBlocks, unTitlecase, protectCase, splitStrWhen,- safeRead)-import Text.CSL.Parser (parseLocale)-import qualified Text.Pandoc.Walk as Walk-import qualified Text.Pandoc.UTF8 as UTF8+import Control.Applicative+import qualified Control.Exception as E+import Control.Monad+import Control.Monad.RWS+import Data.Char (isAlphaNum, isDigit, isUpper, toLower,+ toUpper)+import Data.List (foldl', intercalate)+import Data.List.Split (splitOn, splitWhen, wordsBy)+import qualified Data.Map as Map+import Data.Maybe+import System.Environment (getEnvironment)+import Text.CSL.Compat.Pandoc (readLaTeX)+import Text.CSL.Exception (CiteprocException (ErrorReadingBib, ErrorReadingBibFile))+import Text.CSL.Parser (parseLocale)+import Text.CSL.Reference+import Text.CSL.Style (Agent (..), CslTerm (..),+ Formatted (..), Locale (..))+import Text.CSL.Util (onBlocks, protectCase, safeRead,+ splitStrWhen, trim, unTitlecase)+import Text.Pandoc.Definition+import Text.Pandoc.Generic (bottomUp)+import qualified Text.Pandoc.UTF8 as UTF8+import qualified Text.Pandoc.Walk as Walk+import Text.Parsec hiding (State, many, (<|>)) blocksToFormatted :: [Block] -> Bib Formatted blocksToFormatted bs = case bs of- [Plain xs] -> inlinesToFormatted xs- [Para xs] -> inlinesToFormatted xs- _ -> inlinesToFormatted $ Walk.query (:[]) bs+ [Plain xs] -> inlinesToFormatted xs+ [Para xs] -> inlinesToFormatted xs+ _ -> inlinesToFormatted $ Walk.query (:[]) bs adjustSpans :: Lang -> Inline -> [Inline] adjustSpans _ (Span ("",[],[]) xs) = xs@@ -73,10 +76,10 @@ f "mkbibparens" ils = [Str "("] ++ ils ++ [Str ")"] -- TODO: ... f "mkbibbrackets" ils = [Str "["] ++ ils ++ [Str "]"] -- TODO: ... -- ... both should be nestable & should work in year fields- f "autocap" ils = ils -- TODO: should work in year fields- f "textnormal" ils = [Span ("",["nodecor"],[]) ils]+ f "autocap" ils = ils -- TODO: should work in year fields+ f "textnormal" ils = [Span ("",["nodecor"],[]) ils] f "bibstring" [Str s] = [Str $ resolveKey' lang s]- f _ ils = [Span nullAttr ils]+ f _ ils = [Span nullAttr ils] parseRawLaTeX _ _ = [] inlinesToFormatted :: [Inline] -> Bib Formatted@@ -86,7 +89,7 @@ data Item = Item{ identifier :: String , entryType :: String- , fields :: [(String, String)]+ , fields :: Map.Map String String } -- | Get 'Lang' from the environment variable LANG, defaulting to en-US.@@ -95,72 +98,73 @@ env <- getEnvironment return $ case lookup "LANG" env of Just x -> case splitWhen (\c -> c == '.' || c == '_' || c == '-') x of- (w:z:_) -> Lang w z- [w] | not (null w) -> Lang w mempty- _ -> Lang "en" "US"+ (w:z:_) -> Lang w z+ [w] | not (null w) -> Lang w mempty+ _ -> Lang "en" "US" Nothing -> Lang "en" "US" -- | Parse a BibTeX or BibLaTeX file into a list of 'Reference's.--- If the first parameter is true, the file will be treated as--- BibTeX; otherwse as BibLaTeX. If the second parameter is+-- The first parameter is a predicate to filter identifiers.+-- If the second parameter is true, the file will be treated as+-- BibTeX; otherwse as BibLaTeX. If the third parameter is -- true, an "untitlecase" transformation will be performed.-readBibtex :: Bool -> Bool -> FilePath -> IO [Reference]-readBibtex isBibtex caseTransform f = do+readBibtex :: (String -> Bool) -> Bool -> Bool -> FilePath -> IO [Reference]+readBibtex idpred isBibtex caseTransform f = do contents <- UTF8.readFile f- E.catch (readBibtexString isBibtex caseTransform contents)+ E.catch (readBibtexString idpred isBibtex caseTransform contents) (\e -> case e of ErrorReadingBib es -> E.throwIO $ ErrorReadingBibFile f es- _ -> E.throwIO e)+ _ -> E.throwIO e) -- | Like 'readBibtex' but operates on a String rather than a file.-readBibtexString :: Bool -> Bool -> String -> IO [Reference]-readBibtexString isBibtex caseTransform contents = do+readBibtexString :: (String -> Bool) -> Bool -> Bool -> String+ -> IO [Reference]+readBibtexString idpred isBibtex caseTransform contents = do lang <- getLangFromEnv locale <- parseLocale (langToLocale lang)- case runParser (bibEntries <* eof) [] "stdin" contents of+ case runParser (bibEntries <* eof) (Map.empty) "stdin" contents of -- drop 8 to remove "stdin" + space Left err -> E.throwIO $ ErrorReadingBib $ drop 8 $ show err Right xs -> return $ mapMaybe (itemToReference lang locale isBibtex caseTransform)- (resolveCrossRefs isBibtex xs)+ (filter (idpred . identifier)+ (resolveCrossRefs isBibtex+ xs)) -type BibParser = Parsec [Char] [(String, String)]+type BibParser = Parsec String (Map.Map String String) bibEntries :: BibParser [Item] bibEntries = do skipMany nonEntry- items <- many (bibItem <* skipMany nonEntry)- return items- where nonEntry = bibSkip <|> bibComment <|> bibPreamble <|> bibString+ many (bibItem <* skipMany nonEntry)+ where nonEntry = bibSkip <|>+ try (char '@' >>+ (bibComment <|> bibPreamble <|> bibString)) bibSkip :: BibParser () bibSkip = skipMany1 (satisfy (/='@')) bibComment :: BibParser ()-bibComment = try $ do- char '@'+bibComment = do cistring "comment" spaces void inBraces <|> bibSkip <|> return () bibPreamble :: BibParser ()-bibPreamble = try $ do- char '@'+bibPreamble = do cistring "preamble" spaces void inBraces bibString :: BibParser ()-bibString = try $ do- char '@'+bibString = do cistring "string" spaces char '{' spaces- f <- entField- spaces+ (k,v) <- entField char '}'- updateState $ (f:)+ updateState (Map.insert k v) return () inBraces :: BibParser String@@ -187,7 +191,7 @@ ) (char '"') fieldName :: BibParser String-fieldName = (map toLower) <$> many1 (letter <|> digit <|> oneOf "-_:+")+fieldName = map toLower <$> many1 (letter <|> digit <|> oneOf "-_:+") isBibtexKeyChar :: Char -> Bool isBibtexKeyChar c = isAlphaNum c || c `elem` ".:;?!`'()/*@_+=-[]*&"@@ -203,20 +207,19 @@ spaces char ',' spaces- entfields <- entField `sepEndBy` (char ',')+ entfields <- entField `sepEndBy` (char ',' >> spaces) spaces char '}'- return $ Item entid enttype entfields+ return $ Item entid enttype (Map.fromList entfields) entField :: BibParser (String, String)-entField = try $ do- spaces+entField = do k <- fieldName spaces char '=' spaces vs <- (expandString <|> inQuotes <|> inBraces <|> rawWord) `sepBy`- (try $ spaces >> char '#' >> spaces)+ try (spaces >> char '#' >> spaces) spaces return (k, concat vs) @@ -227,16 +230,17 @@ expandString = do k <- fieldName strs <- getState- case lookup k strs of+ case Map.lookup k strs of Just v -> return v Nothing -> return k -- return raw key if not found cistring :: String -> BibParser String-cistring [] = return []-cistring (c:cs) = do- x <- (char (toLower c) <|> char (toUpper c))- xs <- cistring cs- return (x:xs)+cistring s = try (go s)+ where go [] = return []+ go (c:cs) = do+ x <- char (toLower c) <|> char (toUpper c)+ xs <- go cs+ return (x:xs) resolveCrossRefs :: Bool -> [Item] -> [Item] resolveCrossRefs isBibtex entries =@@ -249,27 +253,29 @@ getXrefFields isBibtex baseEntry entries keys = do let keys' = splitKeys keys xrefEntry <- [e | e <- entries, identifier e `elem` keys']- (k, v) <- fields xrefEntry+ (k, v) <- Map.toList $ fields xrefEntry if k == "crossref" || k == "xdata" then do xs <- mapM (getXrefFields isBibtex baseEntry entries) (splitKeys v) (x, y) <- xs- guard $ isNothing $ lookup x $ fields xrefEntry+ guard $ isNothing $ Map.lookup x $ fields xrefEntry return (x, y) else do k' <- if isBibtex then return k else transformKey (entryType xrefEntry) (entryType baseEntry) k- guard $ isNothing $ lookup k' $ fields baseEntry+ guard $ isNothing $ Map.lookup k' $ fields baseEntry return (k',v) resolveCrossRef :: Bool -> [Item] -> Item -> Item-resolveCrossRef isBibtex entries entry = foldr go entry (fields entry)- where go (key, val) entry' =+resolveCrossRef isBibtex entries entry =+ Map.foldrWithKey go entry (fields entry)+ where go key val entry' = if key == "crossref" || key == "xdata"- then entry'{ fields = fields entry' ++- getXrefFields isBibtex entry entries val }+ then entry'{ fields = fields entry' <>+ Map.fromList (getXrefFields isBibtex+ entry entries val) } else entry' -- transformKey source target key@@ -409,38 +415,38 @@ case map toLower k of -- "inpreparation" -> "" -- missing -- "submitted" -> "" -- missing- "forthcoming" -> "kommende" -- csl- "inpress" -> "i tryk" -- csl+ "forthcoming" -> "kommende" -- csl+ "inpress" -> "i tryk" -- csl -- "prepublished" -> "" -- missing- "mathesis" -> "speciale"- "phdthesis" -> "ph.d.-afhandling"- "candthesis" -> "kandidatafhandling"- "techreport" -> "teknisk rapport"- "resreport" -> "forskningsrapport"- "software" -> "software"- "datacd" -> "data-cd"- "audiocd" -> "lyd-cd"- "patent" -> "patent"- "patentde" -> "tysk patent"- "patenteu" -> "europæisk patent"- "patentfr" -> "fransk patent"- "patentuk" -> "britisk patent"- "patentus" -> "amerikansk patent"- "patreq" -> "ansøgning om patent"- "patreqde" -> "ansøgning om tysk patent"- "patreqeu" -> "ansøgning om europæisk patent"- "patreqfr" -> "ansøgning om fransk patent"- "patrequk" -> "ansøgning om britisk patent"- "patrequs" -> "ansøgning om amerikansk patent"- "countryde" -> "Tyskland"- "countryeu" -> "Europæiske Union"- "countryep" -> "Europæiske Union"- "countryfr" -> "Frankrig"- "countryuk" -> "Storbritanien"- "countryus" -> "USA"- "newseries" -> "ny serie"- "oldseries" -> "gammel serie"- _ -> k+ "mathesis" -> "speciale"+ "phdthesis" -> "ph.d.-afhandling"+ "candthesis" -> "kandidatafhandling"+ "techreport" -> "teknisk rapport"+ "resreport" -> "forskningsrapport"+ "software" -> "software"+ "datacd" -> "data-cd"+ "audiocd" -> "lyd-cd"+ "patent" -> "patent"+ "patentde" -> "tysk patent"+ "patenteu" -> "europæisk patent"+ "patentfr" -> "fransk patent"+ "patentuk" -> "britisk patent"+ "patentus" -> "amerikansk patent"+ "patreq" -> "ansøgning om patent"+ "patreqde" -> "ansøgning om tysk patent"+ "patreqeu" -> "ansøgning om europæisk patent"+ "patreqfr" -> "ansøgning om fransk patent"+ "patrequk" -> "ansøgning om britisk patent"+ "patrequs" -> "ansøgning om amerikansk patent"+ "countryde" -> "Tyskland"+ "countryeu" -> "Europæiske Union"+ "countryep" -> "Europæiske Union"+ "countryfr" -> "Frankrig"+ "countryuk" -> "Storbritanien"+ "countryus" -> "USA"+ "newseries" -> "ny serie"+ "oldseries" -> "gammel serie"+ _ -> k resolveKey' (Lang "de" "DE") k = case map toLower k of "inpreparation" -> "in Vorbereitung"@@ -524,79 +530,79 @@ "submitted" -> "submitted" "techreport" -> "technical report" "volume" -> "vol."- _ -> k+ _ -> k resolveKey' (Lang "es" "ES") k = case map toLower k of -- "inpreparation" -> "" -- missing -- "submitted" -> "" -- missing- "forthcoming" -> "previsto" -- csl- "inpress" -> "en imprenta" -- csl+ "forthcoming" -> "previsto" -- csl+ "inpress" -> "en imprenta" -- csl -- "prepublished" -> "" -- missing- "mathesis" -> "Tesis de licenciatura"- "phdthesis" -> "Tesis doctoral"+ "mathesis" -> "Tesis de licenciatura"+ "phdthesis" -> "Tesis doctoral" -- "candthesis" -> "" -- missing- "techreport" -> "informe técnico"+ "techreport" -> "informe técnico" -- "resreport" -> "" -- missing -- "software" -> "" -- missing -- "datacd" -> "" -- missing -- "audiocd" -> "" -- missing- "patent" -> "patente"- "patentde" -> "patente alemana"- "patenteu" -> "patente europea"- "patentfr" -> "patente francesa"- "patentuk" -> "patente británica"- "patentus" -> "patente americana"- "patreq" -> "solicitud de patente"- "patreqde" -> "solicitud de patente alemana"- "patreqeu" -> "solicitud de patente europea"- "patreqfr" -> "solicitud de patente francesa"- "patrequk" -> "solicitud de patente británica"- "patrequs" -> "solicitud de patente americana"- "countryde" -> "Alemania"- "countryeu" -> "Unión Europea"- "countryep" -> "Unión Europea"- "countryfr" -> "Francia"- "countryuk" -> "Reino Unido"- "countryus" -> "Estados Unidos de América"- "newseries" -> "nueva época"- "oldseries" -> "antigua época"- _ -> k+ "patent" -> "patente"+ "patentde" -> "patente alemana"+ "patenteu" -> "patente europea"+ "patentfr" -> "patente francesa"+ "patentuk" -> "patente británica"+ "patentus" -> "patente americana"+ "patreq" -> "solicitud de patente"+ "patreqde" -> "solicitud de patente alemana"+ "patreqeu" -> "solicitud de patente europea"+ "patreqfr" -> "solicitud de patente francesa"+ "patrequk" -> "solicitud de patente británica"+ "patrequs" -> "solicitud de patente americana"+ "countryde" -> "Alemania"+ "countryeu" -> "Unión Europea"+ "countryep" -> "Unión Europea"+ "countryfr" -> "Francia"+ "countryuk" -> "Reino Unido"+ "countryus" -> "Estados Unidos de América"+ "newseries" -> "nueva época"+ "oldseries" -> "antigua época"+ _ -> k resolveKey' (Lang "fi" "FI") k = case map toLower k of -- "inpreparation" -> "" -- missing -- "submitted" -> "" -- missing- "forthcoming" -> "tulossa" -- csl- "inpress" -> "painossa" -- csl+ "forthcoming" -> "tulossa" -- csl+ "inpress" -> "painossa" -- csl -- "prepublished" -> "" -- missing- "mathesis" -> "tutkielma"- "phdthesis" -> "tohtorinväitöskirja"- "candthesis" -> "kandidat"- "techreport" -> "tekninen raportti"- "resreport" -> "tutkimusraportti"- "software" -> "ohjelmisto"- "datacd" -> "data-CD"- "audiocd" -> "ääni-CD"- "patent" -> "patentti"- "patentde" -> "saksalainen patentti"- "patenteu" -> "Euroopan Unionin patentti"- "patentfr" -> "ranskalainen patentti"- "patentuk" -> "englantilainen patentti"- "patentus" -> "yhdysvaltalainen patentti"- "patreq" -> "patenttihakemus"- "patreqde" -> "saksalainen patenttihakemus"- "patreqeu" -> "Euroopan Unionin patenttihakemus"- "patreqfr" -> "ranskalainen patenttihakemus"- "patrequk" -> "englantilainen patenttihakemus"- "patrequs" -> "yhdysvaltalainen patenttihakemus"- "countryde" -> "Saksa"- "countryeu" -> "Euroopan Unioni"- "countryep" -> "Euroopan Unioni"- "countryfr" -> "Ranska"- "countryuk" -> "Iso-Britannia"- "countryus" -> "Yhdysvallat"- "newseries" -> "uusi sarja"- "oldseries" -> "vanha sarja"- _ -> k+ "mathesis" -> "tutkielma"+ "phdthesis" -> "tohtorinväitöskirja"+ "candthesis" -> "kandidat"+ "techreport" -> "tekninen raportti"+ "resreport" -> "tutkimusraportti"+ "software" -> "ohjelmisto"+ "datacd" -> "data-CD"+ "audiocd" -> "ääni-CD"+ "patent" -> "patentti"+ "patentde" -> "saksalainen patentti"+ "patenteu" -> "Euroopan Unionin patentti"+ "patentfr" -> "ranskalainen patentti"+ "patentuk" -> "englantilainen patentti"+ "patentus" -> "yhdysvaltalainen patentti"+ "patreq" -> "patenttihakemus"+ "patreqde" -> "saksalainen patenttihakemus"+ "patreqeu" -> "Euroopan Unionin patenttihakemus"+ "patreqfr" -> "ranskalainen patenttihakemus"+ "patrequk" -> "englantilainen patenttihakemus"+ "patrequs" -> "yhdysvaltalainen patenttihakemus"+ "countryde" -> "Saksa"+ "countryeu" -> "Euroopan Unioni"+ "countryep" -> "Euroopan Unioni"+ "countryfr" -> "Ranska"+ "countryuk" -> "Iso-Britannia"+ "countryus" -> "Yhdysvallat"+ "newseries" -> "uusi sarja"+ "oldseries" -> "vanha sarja"+ _ -> k resolveKey' (Lang "fr" "FR") k = case map toLower k of@@ -638,38 +644,38 @@ case map toLower k of -- "inpreparation" -> "" -- missing -- "submitted" -> "" -- missing- "forthcoming" -> "futuro" -- csl- "inpress" -> "in stampa"+ "forthcoming" -> "futuro" -- csl+ "inpress" -> "in stampa" -- "prepublished" -> "" -- missing- "mathesis" -> "tesi di laurea magistrale"- "phdthesis" -> "tesi di dottorato"+ "mathesis" -> "tesi di laurea magistrale"+ "phdthesis" -> "tesi di dottorato" -- "candthesis" -> "" -- missing- "techreport" -> "rapporto tecnico"- "resreport" -> "rapporto di ricerca"+ "techreport" -> "rapporto tecnico"+ "resreport" -> "rapporto di ricerca" -- "software" -> "" -- missing -- "datacd" -> "" -- missing -- "audiocd" -> "" -- missing- "patent" -> "brevetto"- "patentde" -> "brevetto tedesco"- "patenteu" -> "brevetto europeo"- "patentfr" -> "brevetto francese"- "patentuk" -> "brevetto britannico"- "patentus" -> "brevetto americano"- "patreq" -> "brevetto richiesto"- "patreqde" -> "brevetto tedesco richiesto"- "patreqeu" -> "brevetto europeo richiesto"- "patreqfr" -> "brevetto francese richiesto"- "patrequk" -> "brevetto britannico richiesto"- "patrequs" -> "brevetto U.S.A. richiesto"- "countryde" -> "Germania"- "countryeu" -> "Unione Europea"- "countryep" -> "Unione Europea"- "countryfr" -> "Francia"- "countryuk" -> "Regno Unito"- "countryus" -> "Stati Uniti d’America"- "newseries" -> "nuova serie"- "oldseries" -> "vecchia serie"- _ -> k+ "patent" -> "brevetto"+ "patentde" -> "brevetto tedesco"+ "patenteu" -> "brevetto europeo"+ "patentfr" -> "brevetto francese"+ "patentuk" -> "brevetto britannico"+ "patentus" -> "brevetto americano"+ "patreq" -> "brevetto richiesto"+ "patreqde" -> "brevetto tedesco richiesto"+ "patreqeu" -> "brevetto europeo richiesto"+ "patreqfr" -> "brevetto francese richiesto"+ "patrequk" -> "brevetto britannico richiesto"+ "patrequs" -> "brevetto U.S.A. richiesto"+ "countryde" -> "Germania"+ "countryeu" -> "Unione Europea"+ "countryep" -> "Unione Europea"+ "countryfr" -> "Francia"+ "countryuk" -> "Regno Unito"+ "countryus" -> "Stati Uniti d’America"+ "newseries" -> "nuova serie"+ "oldseries" -> "vecchia serie"+ _ -> k resolveKey' (Lang "nl" "NL") k = case map toLower k of "inpreparation" -> "in voorbereiding"@@ -741,38 +747,38 @@ resolveKey' (Lang "pt" "PT") k = case map toLower k of -- "candthesis" -> "" -- missing- "techreport" -> "relatório técnico"- "resreport" -> "relatório de pesquisa"- "software" -> "software"- "datacd" -> "CD-ROM"- "patent" -> "patente"- "patentde" -> "patente alemã"- "patenteu" -> "patente européia"- "patentfr" -> "patente francesa"- "patentuk" -> "patente britânica"- "patentus" -> "patente americana"- "patreq" -> "pedido de patente"- "patreqde" -> "pedido de patente alemã"- "patreqeu" -> "pedido de patente européia"- "patreqfr" -> "pedido de patente francesa"- "patrequk" -> "pedido de patente britânica"- "patrequs" -> "pedido de patente americana"- "countryde" -> "Alemanha"- "countryeu" -> "União Europeia"- "countryep" -> "União Europeia"- "countryfr" -> "França"- "countryuk" -> "Reino Unido"- "countryus" -> "Estados Unidos da América"- "newseries" -> "nova série"- "oldseries" -> "série antiga"+ "techreport" -> "relatório técnico"+ "resreport" -> "relatório de pesquisa"+ "software" -> "software"+ "datacd" -> "CD-ROM"+ "patent" -> "patente"+ "patentde" -> "patente alemã"+ "patenteu" -> "patente européia"+ "patentfr" -> "patente francesa"+ "patentuk" -> "patente britânica"+ "patentus" -> "patente americana"+ "patreq" -> "pedido de patente"+ "patreqde" -> "pedido de patente alemã"+ "patreqeu" -> "pedido de patente européia"+ "patreqfr" -> "pedido de patente francesa"+ "patrequk" -> "pedido de patente britânica"+ "patrequs" -> "pedido de patente americana"+ "countryde" -> "Alemanha"+ "countryeu" -> "União Europeia"+ "countryep" -> "União Europeia"+ "countryfr" -> "França"+ "countryuk" -> "Reino Unido"+ "countryus" -> "Estados Unidos da América"+ "newseries" -> "nova série"+ "oldseries" -> "série antiga" -- "inpreparation" -> "" -- missing- "forthcoming" -> "a publicar" -- csl- "inpress" -> "na imprensa"+ "forthcoming" -> "a publicar" -- csl+ "inpress" -> "na imprensa" -- "prepublished" -> "" -- missing- "mathesis" -> "tese de mestrado"- "phdthesis" -> "tese de doutoramento"- "audiocd" -> "CD áudio"- _ -> k+ "mathesis" -> "tese de mestrado"+ "phdthesis" -> "tese de doutoramento"+ "audiocd" -> "CD áudio"+ _ -> k resolveKey' (Lang "pt" "BR") k = case map toLower k of -- "candthesis" -> "" -- missing@@ -812,60 +818,60 @@ case map toLower k of -- "inpreparation" -> "" -- missing -- "submitted" -> "" -- missing- "forthcoming" -> "kommande" -- csl- "inpress" -> "i tryck" -- csl+ "forthcoming" -> "kommande" -- csl+ "inpress" -> "i tryck" -- csl -- "prepublished" -> "" -- missing- "mathesis" -> "examensarbete"- "phdthesis" -> "doktorsavhandling"- "candthesis" -> "kandidatavhandling"- "techreport" -> "teknisk rapport"- "resreport" -> "forskningsrapport"- "software" -> "datorprogram"- "datacd" -> "data-cd"- "audiocd" -> "ljud-cd"- "patent" -> "patent"- "patentde" -> "tyskt patent"- "patenteu" -> "europeiskt patent"- "patentfr" -> "franskt patent"- "patentuk" -> "brittiskt patent"- "patentus" -> "amerikanskt patent"- "patreq" -> "patentansökan"- "patreqde" -> "ansökan om tyskt patent"- "patreqeu" -> "ansökan om europeiskt patent"- "patreqfr" -> "ansökan om franskt patent"- "patrequk" -> "ansökan om brittiskt patent"- "patrequs" -> "ansökan om amerikanskt patent"- "countryde" -> "Tyskland"- "countryeu" -> "Europeiska unionen"- "countryep" -> "Europeiska unionen"- "countryfr" -> "Frankrike"- "countryuk" -> "Storbritannien"- "countryus" -> "USA"- "newseries" -> "ny följd"- "oldseries" -> "gammal följd"- _ -> k+ "mathesis" -> "examensarbete"+ "phdthesis" -> "doktorsavhandling"+ "candthesis" -> "kandidatavhandling"+ "techreport" -> "teknisk rapport"+ "resreport" -> "forskningsrapport"+ "software" -> "datorprogram"+ "datacd" -> "data-cd"+ "audiocd" -> "ljud-cd"+ "patent" -> "patent"+ "patentde" -> "tyskt patent"+ "patenteu" -> "europeiskt patent"+ "patentfr" -> "franskt patent"+ "patentuk" -> "brittiskt patent"+ "patentus" -> "amerikanskt patent"+ "patreq" -> "patentansökan"+ "patreqde" -> "ansökan om tyskt patent"+ "patreqeu" -> "ansökan om europeiskt patent"+ "patreqfr" -> "ansökan om franskt patent"+ "patrequk" -> "ansökan om brittiskt patent"+ "patrequs" -> "ansökan om amerikanskt patent"+ "countryde" -> "Tyskland"+ "countryeu" -> "Europeiska unionen"+ "countryep" -> "Europeiska unionen"+ "countryfr" -> "Frankrike"+ "countryuk" -> "Storbritannien"+ "countryus" -> "USA"+ "newseries" -> "ny följd"+ "oldseries" -> "gammal följd"+ _ -> k resolveKey' _ k = resolveKey' (Lang "en" "US") k -parseMonth :: String -> String+parseMonth :: String -> Maybe Int parseMonth s = case map toLower s of- "jan" -> "1"- "feb" -> "2"- "mar" -> "3"- "apr" -> "4"- "may" -> "5"- "jun" -> "6"- "jul" -> "7"- "aug" -> "8"- "sep" -> "9"- "oct" -> "10"- "nov" -> "11"- "dec" -> "12"- _ -> s+ "jan" -> Just 1+ "feb" -> Just 2+ "mar" -> Just 3+ "apr" -> Just 4+ "may" -> Just 5+ "jun" -> Just 6+ "jul" -> Just 7+ "aug" -> Just 8+ "sep" -> Just 9+ "oct" -> Just 10+ "nov" -> Just 11+ "dec" -> Just 12+ _ -> safeRead s data BibState = BibState{- untitlecase :: Bool- , localeLanguage :: Lang+ untitlecase :: Bool+ , localeLanguage :: Lang } type Bib = RWST Item () BibState Maybe@@ -876,21 +882,21 @@ getField :: String -> Bib Formatted getField f = do fs <- asks fields- case lookup f fs of+ case Map.lookup f fs of Just x -> latex x Nothing -> notFound f getPeriodicalTitle :: String -> Bib Formatted getPeriodicalTitle f = do fs <- asks fields- case lookup f fs of+ case Map.lookup f fs of Just x -> blocksToFormatted $ onBlocks protectCase $ latex' $ trim x Nothing -> notFound f getTitle :: String -> Bib Formatted getTitle f = do fs <- asks fields- case lookup f fs of+ case Map.lookup f fs of Just x -> latexTitle x Nothing -> notFound f @@ -899,7 +905,7 @@ fs <- asks fields utc <- gets untitlecase let processTitle = if utc then onBlocks unTitlecase else id- case lookup f fs of+ case Map.lookup f fs of Just x -> case processTitle $ latex' x of bs | not requireColon || containsColon bs -> blocksToFormatted $ upToColon bs@@ -907,67 +913,17 @@ Nothing -> notFound f containsColon :: [Block] -> Bool-containsColon [Para xs] = (Str ":") `elem` xs+containsColon [Para xs] = Str ":" `elem` xs containsColon [Plain xs] = containsColon [Para xs] containsColon _ = False upToColon :: [Block] -> [Block]-upToColon [Para xs] = [Para $ takeWhile (/= (Str ":")) xs]+upToColon [Para xs] = [Para $ takeWhile (/= Str ":") xs] upToColon [Plain xs] = upToColon [Para xs] upToColon bs = bs getDates :: String -> Bib [RefDate]-getDates f = getRawField f >>= parseDates--parseDates :: Monad m => String-> m [RefDate]-parseDates s- | '/' `elem` s = mapM parseDate . splitWhen (== '/') $ s- -- 199u EDTF format for a range:- | 'u' `elem` s = let s1 = map (\c -> if c == 'u' then '0' else c) s- s2 = map (\c -> if c == 'u' then '9' else c) s- in mapM parseDate [s1, s2]- | otherwise = mapM parseDate [s]--parseDate :: Monad m => String -> m RefDate--- EDTF format for year of more than 4 digits, starts with 'y':-parseDate ('y':xs) = parseDate xs-parseDate "open" = return RefDate { year = mempty,- month = mempty, season = mempty, day = mempty,- other = mempty, circa = False }-parseDate "unknown" = return RefDate { year = mempty,- month = mempty, season = mempty, day = mempty,- other = mempty, circa = False }-parseDate s = do- let circa' = '~' `elem` s- let (year', month', day') =- case splitWhen (== '-') $ filter (`notElem` "~?")- -- drop time component:- $ takeWhile (/='T') s of- -- initial - is negative year:- ["",y] -> ('-':y, mempty, mempty)- ["",y,m] -> ('-':y, m, mempty)- ["",y,m,d] -> ('-':y, m, d)- [y] -> (y, mempty, mempty)- [y,m] -> (y, m, mempty)- [y,m,d] -> (y, m, d)- _ -> (mempty, mempty, mempty)- let year'' = case safeRead year' of- -- EDTF 0 == CSL JSON -1 (1 BCE)- Just (n :: Integer) | n <= 0 -> show (n - 1)- _ -> year'- let (season'', month'') = case month' of- "21" -> ("1","")- "22" -> ("2","")- "23" -> ("3","")- "24" -> ("4","")- _ -> ("", month')- return RefDate { year = Literal $ dropWhile (=='0') year''- , month = Literal $ dropWhile (=='0') month''- , season = Literal season''- , day = Literal $ dropWhile (=='0') day'- , other = mempty- , circa = circa'- }+getDates f = parseEDTFDate <$> getRawField f isNumber :: String -> Bool isNumber ('-':d:ds) = all isDigit (d:ds)@@ -982,49 +938,50 @@ getOldDates :: String -> Bib [RefDate] getOldDates prefix = do- year' <- fixLeadingDash <$> getRawField (prefix ++ "year")+ year' <- fixLeadingDash <$> getRawField (prefix ++ "year") <|> return "" month' <- (parseMonth- <$> getRawField (prefix ++ "month")) <|> return ""- day' <- getRawField (prefix ++ "day") <|> return mempty- endyear' <- fixLeadingDash <$> getRawField (prefix ++ "endyear") <|> return ""- endmonth' <- (parseMonth <$> getRawField (prefix ++ "endmonth")) <|> return ""- endday' <- getRawField (prefix ++ "endday") <|> return ""- let start' = RefDate { year = Literal $ if isNumber year' then year' else ""- , month = Literal $ month'- , season = mempty- , day = Literal day'+ <$> getRawField (prefix ++ "month")) <|> return Nothing+ day' <- (safeRead <$> getRawField (prefix ++ "day")) <|> return Nothing+ endyear' <- (fixLeadingDash <$> getRawField (prefix ++ "endyear"))+ <|> return ""+ endmonth' <- (parseMonth <$> getRawField (prefix ++ "endmonth"))+ <|> return Nothing+ endday' <- (safeRead <$> getRawField (prefix ++ "endday")) <|> return Nothing+ let start' = RefDate { year = safeRead year'+ , month = month'+ , season = Nothing+ , day = day' , other = Literal $ if isNumber year' then "" else year' , circa = False }- let end' = if null endyear'- then []- else [RefDate { year = Literal $ if isNumber endyear' then endyear' else ""- , month = Literal $ endmonth'- , day = Literal $ endday'- , season = mempty- , other = Literal $ if isNumber endyear' then "" else endyear'- , circa = False- }]- return (start':end')+ let end' = RefDate { year = safeRead endyear'+ , month = endmonth'+ , day = endday'+ , season = Nothing+ , other = Literal $ if isNumber endyear' then "" else endyear'+ , circa = False+ }+ let hasyear r = isJust (year r)+ return $ filter hasyear [start', end'] getRawField :: String -> Bib String getRawField f = do fs <- asks fields- case lookup f fs of+ case Map.lookup f fs of Just x -> return x Nothing -> notFound f getAuthorList :: Options -> String -> Bib [Agent] getAuthorList opts f = do fs <- asks fields- case lookup f fs of+ case Map.lookup f fs of Just x -> latexAuthors opts x Nothing -> notFound f getLiteralList :: String -> Bib [Formatted] getLiteralList f = do fs <- asks fields- case lookup f fs of+ case Map.lookup f fs of Just x -> toLiteralList $ latex' x Nothing -> notFound f @@ -1049,7 +1006,8 @@ toAuthorList _ _ = mzero toAuthor :: Options -> [Inline] -> Bib Agent-toAuthor _ [Str "others"] = return $+toAuthor _ [Str "others"] =+ return Agent { givenName = [] , droppingPart = mempty , nonDroppingPart = mempty@@ -1060,7 +1018,7 @@ , parseNames = False } toAuthor _ [Span ("",[],[]) ils] =- return $ -- corporate author+ return -- corporate author Agent { givenName = [] , droppingPart = mempty , nonDroppingPart = mempty@@ -1104,17 +1062,18 @@ let (von, lastname) = if bibtex then case span isCapitalized $ reverse vonlast of- ([],(w:ws)) -> (reverse ws, [w])- (vs, ws) -> (reverse ws, reverse vs)- else case span (not . isCapitalized) vonlast of+ ([],w:ws) -> (reverse ws, [w])+ (vs, ws) -> (reverse ws, reverse vs)+ else case break isCapitalized vonlast of (vs@(_:_), []) -> (init vs, [last vs]) (vs, ws) -> (vs, ws) let prefix = Formatted $ intercalate [Space] von let family = Formatted $ intercalate [Space] lastname let suffix = Formatted $ intercalate [Space] jr let givens = map Formatted first- return $- Agent { givenName = givens++ return Agent+ { givenName = givens , droppingPart = if useprefix then mempty else prefix , nonDroppingPart = if useprefix then prefix else mempty , familyName = family@@ -1144,7 +1103,7 @@ removeSoftBreak :: Inline -> Inline removeSoftBreak SoftBreak = Space-removeSoftBreak x = x+removeSoftBreak x = x latex :: String -> Bib Formatted latex s = blocksToFormatted $ latex' $ trim s@@ -1159,70 +1118,70 @@ latexAuthors opts = toAuthorList opts . latex' . trim bib :: Bib Reference -> Item -> Maybe Reference-bib m entry = fmap fst $ evalRWST m entry (BibState True (Lang "en" "US"))+bib m entry = fst Control.Applicative.<$> evalRWST m entry (BibState True (Lang "en" "US")) toLocale :: String -> String-toLocale "english" = "en-US" -- "en-EN" unavailable in CSL-toLocale "usenglish" = "en-US"-toLocale "american" = "en-US"-toLocale "british" = "en-GB"-toLocale "ukenglish" = "en-GB"-toLocale "canadian" = "en-US" -- "en-CA" unavailable in CSL-toLocale "australian" = "en-GB" -- "en-AU" unavailable in CSL-toLocale "newzealand" = "en-GB" -- "en-NZ" unavailable in CSL-toLocale "afrikaans" = "af-ZA"-toLocale "arabic" = "ar"-toLocale "basque" = "eu"-toLocale "bulgarian" = "bg-BG"-toLocale "catalan" = "ca-AD"-toLocale "croatian" = "hr-HR"-toLocale "czech" = "cs-CZ"-toLocale "danish" = "da-DK"-toLocale "dutch" = "nl-NL"-toLocale "estonian" = "et-EE"-toLocale "finnish" = "fi-FI"-toLocale "canadien" = "fr-CA"-toLocale "acadian" = "fr-CA"-toLocale "french" = "fr-FR"-toLocale "francais" = "fr-FR"-toLocale "austrian" = "de-AT"-toLocale "naustrian" = "de-AT"-toLocale "german" = "de-DE"-toLocale "germanb" = "de-DE"-toLocale "ngerman" = "de-DE"-toLocale "greek" = "el-GR"+toLocale "english" = "en-US" -- "en-EN" unavailable in CSL+toLocale "usenglish" = "en-US"+toLocale "american" = "en-US"+toLocale "british" = "en-GB"+toLocale "ukenglish" = "en-GB"+toLocale "canadian" = "en-US" -- "en-CA" unavailable in CSL+toLocale "australian" = "en-GB" -- "en-AU" unavailable in CSL+toLocale "newzealand" = "en-GB" -- "en-NZ" unavailable in CSL+toLocale "afrikaans" = "af-ZA"+toLocale "arabic" = "ar"+toLocale "basque" = "eu"+toLocale "bulgarian" = "bg-BG"+toLocale "catalan" = "ca-AD"+toLocale "croatian" = "hr-HR"+toLocale "czech" = "cs-CZ"+toLocale "danish" = "da-DK"+toLocale "dutch" = "nl-NL"+toLocale "estonian" = "et-EE"+toLocale "finnish" = "fi-FI"+toLocale "canadien" = "fr-CA"+toLocale "acadian" = "fr-CA"+toLocale "french" = "fr-FR"+toLocale "francais" = "fr-FR"+toLocale "austrian" = "de-AT"+toLocale "naustrian" = "de-AT"+toLocale "german" = "de-DE"+toLocale "germanb" = "de-DE"+toLocale "ngerman" = "de-DE"+toLocale "greek" = "el-GR" toLocale "polutonikogreek" = "el-GR"-toLocale "hebrew" = "he-IL"-toLocale "hungarian" = "hu-HU"-toLocale "icelandic" = "is-IS"-toLocale "italian" = "it-IT"-toLocale "japanese" = "ja-JP"-toLocale "latvian" = "lv-LV"-toLocale "lithuanian" = "lt-LT"-toLocale "magyar" = "hu-HU"-toLocale "mongolian" = "mn-MN"-toLocale "norsk" = "nb-NO"-toLocale "nynorsk" = "nn-NO"-toLocale "farsi" = "fa-IR"-toLocale "polish" = "pl-PL"-toLocale "brazil" = "pt-BR"-toLocale "brazilian" = "pt-BR"-toLocale "portugues" = "pt-PT"-toLocale "portuguese" = "pt-PT"-toLocale "romanian" = "ro-RO"-toLocale "russian" = "ru-RU"-toLocale "serbian" = "sr-RS"-toLocale "serbianc" = "sr-RS"-toLocale "slovak" = "sk-SK"-toLocale "slovene" = "sl-SL"-toLocale "spanish" = "es-ES"-toLocale "swedish" = "sv-SE"-toLocale "thai" = "th-TH"-toLocale "turkish" = "tr-TR"-toLocale "ukrainian" = "uk-UA"-toLocale "vietnamese" = "vi-VN"-toLocale "latin" = "la"-toLocale x = x+toLocale "hebrew" = "he-IL"+toLocale "hungarian" = "hu-HU"+toLocale "icelandic" = "is-IS"+toLocale "italian" = "it-IT"+toLocale "japanese" = "ja-JP"+toLocale "latvian" = "lv-LV"+toLocale "lithuanian" = "lt-LT"+toLocale "magyar" = "hu-HU"+toLocale "mongolian" = "mn-MN"+toLocale "norsk" = "nb-NO"+toLocale "nynorsk" = "nn-NO"+toLocale "farsi" = "fa-IR"+toLocale "polish" = "pl-PL"+toLocale "brazil" = "pt-BR"+toLocale "brazilian" = "pt-BR"+toLocale "portugues" = "pt-PT"+toLocale "portuguese" = "pt-PT"+toLocale "romanian" = "ro-RO"+toLocale "russian" = "ru-RU"+toLocale "serbian" = "sr-RS"+toLocale "serbianc" = "sr-RS"+toLocale "slovak" = "sk-SK"+toLocale "slovene" = "sl-SL"+toLocale "spanish" = "es-ES"+toLocale "swedish" = "sv-SE"+toLocale "thai" = "th-TH"+toLocale "turkish" = "tr-TR"+toLocale "ukrainian" = "uk-UA"+toLocale "vietnamese" = "vi-VN"+toLocale "latin" = "la"+toLocale x = x concatWith :: Char -> [Formatted] -> Formatted concatWith sep = Formatted . foldl' go mempty . map unFormatted@@ -1365,8 +1324,8 @@ editor'' <- getAuthorList' "editor" <|> return [] director'' <- getAuthorList' "director" <|> return [] let (editor', director') = case editortype of- "director" -> ([], editor'')- _ -> (editor'', director'')+ "director" -> ([], editor'')+ _ -> (editor'', director'') -- FIXME: add same for editora, editorb, editorc -- titles@@ -1374,7 +1333,7 @@ let isPeriodical = et == "periodical" let isChapterlike = et `elem` ["inbook","incollection","inproceedings","inreference","bookinbook"]- hasMaintitle <- (True <$ (getRawField "maintitle")) <|> return False+ hasMaintitle <- (True <$ getRawField "maintitle") <|> return False let hyphenation' = if null hyphenation then defaultHyphenation else hyphenation@@ -1432,7 +1391,7 @@ shortTitle' <- (guard (not hasMaintitle || isChapterlike) >> getTitle "shorttitle") <|> if (subtitle' /= mempty || titleaddon' /= mempty) &&- (not hasMaintitle)+ not hasMaintitle then getShortTitle False "title" else getShortTitle True "title" <|> return mempty@@ -1447,7 +1406,7 @@ else getLiteralList' f) <|> return Nothing) ["school","institution","organization", "howpublished","publisher"]- let publisher' = concatWith ';' [p | Just p <- pubfields]+ let publisher' = concatWith ';' $ catMaybes pubfields origpublisher' <- getField "origpublisher" <|> return mempty -- places@@ -1524,7 +1483,7 @@ keywords' <- getField "keywords" <|> return mempty note' <- if et == "periodical" then return mempty- else (getField "note" <|> return mempty)+ else getField "note" <|> return mempty addendum' <- if bibtex then return mempty else getField "addendum"@@ -1542,8 +1501,8 @@ let takeDigits (Str xs : _) = case takeWhile isDigit xs of- [] -> []- ds -> [Str ds]+ [] -> []+ ds -> [Str ds] takeDigits x = x return $ emptyReference
src/Text/CSL/Input/Bibutils.hs view
@@ -1,4 +1,6 @@-{-# LANGUAGE CPP, ForeignFunctionInterface, PatternGuards #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE PatternGuards #-} ----------------------------------------------------------------------------- -- | -- Module : Text.CSL.Input.Bibutils@@ -18,51 +20,60 @@ , convertRefs ) where -import qualified Text.Pandoc.UTF8 as UTF8-import Text.Pandoc hiding (readMarkdown)-import Text.CSL.Compat.Pandoc (readMarkdown)-import Data.Char-import System.FilePath ( takeExtension )-import Text.CSL.Exception-import Text.CSL.Reference hiding ( Value )-import Text.CSL.Input.Bibtex-import qualified Data.ByteString.Lazy as BL-import qualified Data.Map as M-import Data.Aeson-import qualified Control.Exception as E+import qualified Control.Exception as E+import Data.Aeson+import qualified Data.ByteString.Lazy as BL+import qualified Data.ByteString as BS+import qualified Data.HashMap.Strict as HM+import qualified Data.Text as T+import qualified Data.Yaml as Yaml+import qualified Data.Vector as V+import Data.Char+import qualified Data.Map as M+import System.FilePath (takeExtension)+import Text.CSL.Compat.Pandoc (readMarkdown)+import Text.CSL.Exception+import Text.CSL.Input.Bibtex+import Text.CSL.Reference hiding (Value)+import Text.CSL.Util (parseString)+import Text.Pandoc hiding (readMarkdown)+import qualified Text.Pandoc.UTF8 as UTF8 #ifdef USE_BIBUTILS-import Control.Exception ( bracket, catch )-import Control.Monad.Trans ( liftIO )-import System.FilePath ( (</>), (<.>) )-import System.IO.Error ( isAlreadyExistsError )-import System.Directory-import Text.Bibutils+import Control.Exception (bracket, catch)+import Control.Monad.Trans (liftIO)+import System.Directory+import System.FilePath ((<.>), (</>))+import System.IO.Error (isAlreadyExistsError)+import Text.Bibutils #endif -- | Read a file with a bibliographic database. The database format--- is recognized by the file extension.+-- is recognized by the file extension. The first argument is+-- a predicate to filter citation identifiers. -- -- Supported formats are: @json@, @mods@, @bibtex@, @biblatex@, @ris@, -- @endnote@, @endnotexml@, @isi@, @medline@, and @copac@.-readBiblioFile :: FilePath -> IO [Reference]-readBiblioFile f+readBiblioFile :: (String -> Bool) -> FilePath -> IO [Reference]+readBiblioFile idpred f = case getExt f of ".json" -> BL.readFile f >>= either- (E.throwIO . ErrorReadingBibFile f) return . eitherDecode+ (E.throwIO . ErrorReadingBibFile f)+ (return . filterEntries idpred) . eitherDecode ".yaml" -> UTF8.readFile f >>= either- (E.throwIO . ErrorReadingBibFile f) return . readYamlBib- ".bib" -> readBibtex False True f- ".bibtex" -> readBibtex True True f- ".biblatex" -> readBibtex False True f+ (E.throwIO . ErrorReadingBibFile f) return .+ readYamlBib idpred+ ".bib" -> readBibtex idpred False True f+ ".bibtex" -> readBibtex idpred True True f+ ".biblatex" -> readBibtex idpred False True f #ifdef USE_BIBUTILS- ".mods" -> readBiblioFile' f mods_in- ".ris" -> readBiblioFile' f ris_in- ".enl" -> readBiblioFile' f endnote_in- ".xml" -> readBiblioFile' f endnotexml_in- ".wos" -> readBiblioFile' f isi_in- ".medline" -> readBiblioFile' f medline_in- ".copac" -> readBiblioFile' f copac_in+ ".mods" -> readBiblioFile' idpred f mods_in+ ".ris" -> readBiblioFile' idpred f ris_in+ ".enl" -> readBiblioFile' idpred f endnote_in+ ".xml" -> readBiblioFile' idpred f endnotexml_in+ ".wos" -> readBiblioFile' idpred f isi_in+ ".medline" -> readBiblioFile' idpred f medline_in+ ".copac" -> readBiblioFile' idpred f copac_in _ -> E.throwIO $ ErrorReadingBibFile f "the format of the bibliographic database could not be recognized from the file extension" #else _ -> E.throwIO $ ErrorReadingBibFile f "bibliography format not supported"@@ -84,14 +95,14 @@ #endif deriving Show -readBiblioString :: BibFormat -> String -> IO [Reference]-readBiblioString b s+readBiblioString :: (String -> Bool) -> BibFormat -> String -> IO [Reference]+readBiblioString idpred b s | Json <- b = either (E.throwIO . ErrorReadingBib) return $ eitherDecode $ UTF8.fromStringLazy s | Yaml <- b = either (E.throwIO . ErrorReadingBib)- return $ readYamlBib s- | Bibtex <- b = readBibtexString True True s- | BibLatex <- b = readBibtexString False True s+ return $ readYamlBib idpred s+ | Bibtex <- b = readBibtexString idpred True True s+ | BibLatex <- b = readBibtexString idpred False True s #ifdef USE_BIBUTILS | Ris <- b = go ris_in | Endnote <- b = go endnote_in@@ -108,13 +119,13 @@ go f = withTempDir "citeproc" $ \tdir -> do let tfile = tdir </> "bibutils-tmp.biblio" UTF8.writeFile tfile s- readBiblioFile' tfile f+ readBiblioFile' idpred tfile f #endif #ifdef USE_BIBUTILS-readBiblioFile' :: FilePath -> BiblioIn -> IO [Reference]-readBiblioFile' fin bin- | bin == biblatex_in = readBibtex False True fin+readBiblioFile' :: (String -> Bool) -> FilePath -> BiblioIn -> IO [Reference]+readBiblioFile' idpred fin bin+ | bin == biblatex_in = readBibtex idpred False True fin | otherwise = withTempDir "citeproc" $ \tdir -> do let tfile = tdir </> "bibutils-tmp"@@ -128,7 +139,7 @@ _ <- bibl_write param bibl tfile bibl_free bibl bibl_freeparams param- refs <- readBibtex True False tfile+ refs <- readBibtex idpred True False tfile return $! refs where handleBibfileError :: E.SomeException -> IO () handleBibfileError e = E.throwIO $ ErrorReadingBibFile fin (show e)@@ -152,11 +163,44 @@ getExt :: String -> String getExt = takeExtension . map toLower -readYamlBib :: String -> Either String [Reference]-readYamlBib s =- case readMarkdown s of+readYamlBib :: (String -> Bool) -> String -> Either String [Reference]+readYamlBib idpred s =+ case readMarkdown s' of (Pandoc meta _) -> convertRefs (lookupMeta "references" meta)+ where s' = addTop $ addBottom+ $ UTF8.toString+ $ selectEntries idpred+ $ UTF8.fromString+ $ s+ addTop = ("---\n" ++)+ addBottom = (++ "...\n") +selectEntries :: (String -> Bool) -> BS.ByteString -> BS.ByteString+selectEntries idpred bs =+ case Yaml.decodeEither bs of+ Right (Array vs) -> Yaml.encode (filterObjects $ V.toList vs)+ Right (Object o) ->+ case HM.lookup (T.pack "references") o of+ Just (Array vs) ->+ Yaml.encode (HM.insert (T.pack "references")+ (filterObjects $ V.toList vs) mempty)+ _ -> BS.empty+ Right _ -> BS.empty+ Left e -> E.throw $ ErrorParsingReferences e+ where filterObjects = filter+ (\x -> case x of+ Object o ->+ case HM.lookup (T.pack "id") o of+ Just i ->+ case Yaml.parseMaybe parseString i of+ Just s -> idpred s+ Nothing -> False+ _ -> False+ _ -> False)++filterEntries :: (String -> Bool) -> [Reference] -> [Reference]+filterEntries idpred = filter (\r -> idpred (unLiteral (refId r)))+ convertRefs :: Maybe MetaValue -> Either String [Reference] convertRefs Nothing = Right [] convertRefs (Just v) =@@ -167,14 +211,15 @@ -- references: -- ... case fromJSON (metaValueToJSON v) of- Success "" -> Right []- _ -> Left s+ Success "" -> Right []+ _ -> Left s Success x -> Right x metaValueToJSON :: MetaValue -> Value-metaValueToJSON (MetaMap m) = toJSON $ M.map metaValueToJSON m-metaValueToJSON (MetaList xs) = toJSON $ map metaValueToJSON xs-metaValueToJSON (MetaString t) = toJSON t-metaValueToJSON (MetaBool b) = toJSON b+metaValueToJSON (MetaMap m) = toJSON $ M.map metaValueToJSON m+metaValueToJSON (MetaList xs) = toJSON $ map metaValueToJSON xs+metaValueToJSON (MetaString t) = toJSON t+metaValueToJSON (MetaBool b) = toJSON b metaValueToJSON (MetaInlines ils) = toJSON ils-metaValueToJSON (MetaBlocks bs) = toJSON bs+metaValueToJSON (MetaBlocks bs) = toJSON bs+
src/Text/CSL/Output/Pandoc.hs view
@@ -1,4 +1,5 @@-{-# LANGUAGE PatternGuards, DeriveDataTypeable #-}++{-# LANGUAGE PatternGuards #-} ----------------------------------------------------------------------------- -- | -- Module : Text.CSL.Output.Pandoc@@ -24,12 +25,13 @@ , toCapital ) where -import Text.CSL.Util ( proc, proc', tailInline, lastInline,- initInline, tailFirstInlineStr, headInline, toCapital )-import Data.Maybe ( fromMaybe )-import Text.CSL.Style-import Text.Pandoc.Definition-import Text.Pandoc.XML (fromEntities)+import Data.Maybe (fromMaybe)+import Text.CSL.Style+import Text.CSL.Util (headInline, initInline, lastInline,+ proc, proc', tailFirstInlineStr,+ tailInline, toCapital)+import Text.Pandoc.Definition+import Text.Pandoc.XML (fromEntities) renderPandoc :: Style -> Formatted -> [Inline] renderPandoc sty@@ -47,7 +49,7 @@ clean' :: Style -> [Inline] -> [Inline] clean' _ [] = [] clean' sty (i:is) =- case (i:is) of+ case i:is of (Str "" : rest) -> clean' sty rest (Str xs : Str ys : rest) -> clean' sty $ Str (xs ++ ys) : rest (Link a1 lab1 ('#':r1, "") : Str "\8211" : Link a2 lab2 ('#':r2, "") : rest)
src/Text/CSL/Output/Plain.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE PatternGuards #-}+ ----------------------------------------------------------------------------- -- | -- Module : Text.CSL.Output.Plain@@ -17,9 +17,9 @@ ( renderPlain ) where -import Text.CSL.Style-import Text.CSL.Compat.Pandoc (writePlain)-import Text.Pandoc (Block(Plain), Pandoc(..), nullMeta)+import Text.CSL.Compat.Pandoc (writePlain)+import Text.CSL.Style+import Text.Pandoc (Block (Plain), Pandoc (..), nullMeta) -- | Render the 'Formatted' into a plain text string. renderPlain :: Formatted -> String
src/Text/CSL/Pandoc.hs view
@@ -1,41 +1,46 @@-{-# LANGUAGE PatternGuards, OverloadedStrings, FlexibleInstances,- ScopedTypeVariables, CPP #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE ScopedTypeVariables #-} module Text.CSL.Pandoc (processCites, processCites') where -import Text.Pandoc-import Text.Pandoc.Walk-import Text.Pandoc.Builder (setMeta, deleteMeta)-import Text.Pandoc.Shared (stringify)-import Text.HTML.TagSoup.Entity (lookupEntity)-import qualified Data.ByteString.Lazy as L-import System.SetEnv (setEnv)-import System.Environment (getEnv)-import Control.Applicative ((<|>))-import Data.Aeson-import Data.Char ( isDigit, isPunctuation, toLower, isSpace )-import qualified Data.Map as M-import Text.CSL.Reference hiding (processCites, Value)-import Text.CSL.Input.Bibutils (readBiblioFile, convertRefs)-import Text.CSL.Style hiding (Cite(..), Citation(..))-import Text.CSL.Proc-import Text.CSL.Output.Pandoc (renderPandoc, renderPandoc')-import qualified Text.CSL.Style as CSL-import Text.CSL.Parser-import Text.CSL.Output.Pandoc ( headInline, tailInline, initInline,- toCapital )-import Text.CSL.Data (getDefaultCSL)-import Text.Parsec hiding (State, (<|>))-import Control.Monad-import qualified Control.Exception as E-import Control.Monad.State-import System.FilePath-import System.Directory (getAppUserDataDirectory)-import Text.CSL.Util (findFile, splitStrWhen, tr', parseRomanNumeral, trim,- lastInline)-import Text.CSL.Exception-import System.IO.Error (isDoesNotExistError)-import Data.Maybe (fromMaybe)+import Control.Applicative ((<|>))+import qualified Control.Exception as E+import Control.Monad+import Control.Monad.State+import Data.Aeson+import qualified Data.ByteString.Lazy as L+import Data.Char (isDigit, isPunctuation, isSpace,+ toLower)+import qualified Data.Map as M+import qualified Data.Set as Set+import Data.Maybe (fromMaybe)+import System.Directory (getAppUserDataDirectory)+import System.Environment (getEnv)+import System.FilePath+import System.IO.Error (isDoesNotExistError)+import System.SetEnv (setEnv)+import Text.CSL.Data (getDefaultCSL)+import Text.CSL.Exception+import Text.CSL.Input.Bibutils (convertRefs, readBiblioFile)+import Text.CSL.Output.Pandoc (renderPandoc, renderPandoc',+ headInline, initInline, tailInline, toCapital)+import Text.CSL.Parser+import Text.CSL.Proc+import Text.CSL.Reference hiding (Value, processCites)+import Text.CSL.Style hiding (Citation (..), Cite (..))+import qualified Text.CSL.Style as CSL+import Text.CSL.Util (findFile, lastInline,+ parseRomanNumeral, splitStrWhen, tr',+ trim)+import Text.HTML.TagSoup.Entity (lookupEntity)+import Text.Pandoc+import Text.Pandoc.Builder (deleteMeta, setMeta)+import Text.Pandoc.Shared (stringify)+import Text.Pandoc.Walk+import Text.Parsec hiding (State, (<|>)) -- | Process a 'Pandoc' document by adding citations formatted -- according to a CSL style. Add a bibliography (if one is called@@ -75,7 +80,7 @@ (bs', True) -> bs' (_, False) -> case reverse bs of- (Header lev (id',classes,kvs) ys) : xs ->+ Header lev (id',classes,kvs) ys : xs -> reverse xs ++ [Header lev (id',addUnNumbered classes,kvs) ys, Div ("refs",["references"],[]) refs]@@ -121,7 +126,7 @@ -- create a cite with to all the references. mkNociteWildcards :: [Reference] -> [[Citation]] -> [[Citation]] mkNociteWildcards refs nocites =- map (\citgrp -> expandStar citgrp) nocites+ map expandStar nocites where expandStar cs = case [c | c <- cs , citationId c == "*"] of@@ -137,7 +142,7 @@ removeNocaseSpans :: Inline -> [Inline] removeNocaseSpans (Span ("",["nocase"],[]) xs) = xs-removeNocaseSpans x = [x]+removeNocaseSpans x = [x] -- | Process a 'Pandoc' document by adding citations formatted -- according to a CSL style. The style filename is derived from@@ -183,10 +188,14 @@ -- Note that LANG needs to be set for bibtex conversion: setEnv "LANG" "en-US.UTF-8" setEnv "LC_ALL" "en-US.UTF-8"- else do+ else setEnv "LC_ALL" envlang- bibRefs <- getBibRefs $ maybe (MetaList []) id- $ lookupMeta "bibliography" meta+ let citids = query getCitationIds (Pandoc meta blocks)+ let idpred = if "*" `Set.member` citids+ then const True+ else (`Set.member` citids)+ bibRefs <- getBibRefs idpred $ Data.Maybe.fromMaybe (MetaList [])+ $ lookupMeta "bibliography" meta let refs = inlineRefs ++ bibRefs let cslAbbrevFile = lookupMeta "citation-abbreviations" meta >>= toPath let skipLeadingSpace = L.dropWhile (\s -> s == 32 || (s >= 9 && s <= 13))@@ -208,13 +217,13 @@ toPath (MetaInlines ils) = Just $ stringify ils toPath _ = Nothing -getBibRefs :: MetaValue -> IO [Reference]-getBibRefs (MetaList xs) = concat `fmap` mapM getBibRefs xs-getBibRefs (MetaInlines xs) = getBibRefs (MetaString $ stringify xs)-getBibRefs (MetaString s) = do+getBibRefs :: (String -> Bool) -> MetaValue -> IO [Reference]+getBibRefs idpred (MetaList xs) = concat `fmap` mapM (getBibRefs idpred) xs+getBibRefs idpred (MetaInlines xs) = getBibRefs idpred (MetaString $ stringify xs)+getBibRefs idpred (MetaString s) = do path <- findFile ["."] s >>= maybe (E.throwIO $ CouldNotFindBibFile s) return- map unescapeRefId `fmap` readBiblioFile path-getBibRefs _ = return []+ map unescapeRefId `fmap` readBiblioFile idpred path+getBibRefs _ _ = return [] -- unescape reference ids, which may contain XML entities, so -- that we can do lookups with regular string equality@@ -248,19 +257,19 @@ processCite _ _ x = x isNote :: Inline -> Bool-isNote (Note _) = True+isNote (Note _) = True isNote (Cite _ [Note _]) = True-isNote _ = False+isNote _ = False mvPunctInsideQuote :: Inline -> Inline -> [Inline] mvPunctInsideQuote (Quoted qt ils) (Str s) | s `elem` [".", ","] =- [Quoted qt (init ils ++ (mvPunctInsideQuote (last ils) (Str s)))]+ [Quoted qt (init ils ++ mvPunctInsideQuote (last ils) (Str s))] mvPunctInsideQuote il il' = [il, il'] isSpacy :: Inline -> Bool-isSpacy Space = True+isSpacy Space = True isSpacy SoftBreak = True-isSpacy _ = False+isSpacy _ = False mvPunct :: Bool -> Style -> [Inline] -> [Inline] mvPunct _ _ (x : Space : xs)@@ -306,7 +315,7 @@ where isEndPunct c = c `elem` (".,;:!?" :: String) startWithPunct :: [Inline] -> Bool-startWithPunct = and . map (`elem` (".,;:!?" :: String)) . headInline+startWithPunct = all (`elem` (".,;:!?" :: String)) . headInline deNote :: Pandoc -> Pandoc deNote = topDown go@@ -338,6 +347,10 @@ getCitation i | Cite t _ <- i = [t] | otherwise = [] +getCitationIds :: Inline -> Set.Set String+getCitationIds (Cite cs _) = Set.fromList (map citationId cs)+getCitationIds _ = mempty+ setHashes :: Inline -> State Int Inline setHashes i | Cite t ils <- i = do t' <- mapM setHash t return $ Cite t' ils@@ -355,7 +368,7 @@ s' = case (la,lo,s) of -- treat a bare locator as if it begins with space -- so @item1 [blah] is like [@item1, blah]- ("","",(x:_))+ ("","",x:_) | not (isPunct x) -> Space : s _ -> s isPunct (Str (x:_)) = isPunctuation x@@ -375,8 +388,8 @@ locatorWords locMap inp = case parse (pLocatorWords locMap) "suffix" $ splitStrWhen (\c -> isLocatorPunct c || isSpace c) inp of- Right r -> r- Left _ -> ("","",inp)+ Right r -> r+ Left _ -> ("","",inp) pLocatorWords :: LocatorMap -> Parsec [Inline] st (String, String, [Inline]) pLocatorWords locMap = do@@ -437,12 +450,12 @@ t <- anyToken case t of Str (d:_) | isDigit d -> return ()- _ -> mzero+ _ -> mzero pLocatorPunct :: Parsec [Inline] st Inline pLocatorPunct = pMatch isLocatorPunct' where isLocatorPunct' (Str [c]) = isLocatorPunct c- isLocatorPunct' _ = False+ isLocatorPunct' _ = False isLocatorPunct :: Char -> Bool isLocatorPunct ':' = False
src/Text/CSL/Parser.hs view
@@ -1,4 +1,5 @@-{-# LANGUAGE OverloadedStrings, TupleSections #-}+{-# LANGUAGE OverloadedStrings #-}+ ----------------------------------------------------------------------------- -- | -- Module : Text.CSL.Parser@@ -15,25 +16,25 @@ module Text.CSL.Parser (readCSLFile, parseCSL, parseCSL', parseLocale, localizeCSL) where-import qualified Data.Text as T-import qualified Data.ByteString.Lazy as L-import qualified Data.Map as M-import qualified Control.Exception as E-import Control.Monad (when)-import Data.Either (lefts, rights)-import Data.Text (Text, unpack)-import Text.CSL.Style hiding (parseNames)-import Text.CSL.Util (toRead, findFile)-import System.Directory (getAppUserDataDirectory)-import qualified Text.XML as X-import Data.Default-import Text.Pandoc.Shared (safeRead)-import Text.XML.Cursor-import Data.Maybe (listToMaybe, fromMaybe)-import Text.Pandoc.UTF8 (fromStringLazy)-import Text.CSL.Compat.Pandoc (fetchItem)-import Text.CSL.Data (getLocale)-import Text.CSL.Exception+import qualified Control.Exception as E+import Control.Monad (when)+import qualified Data.ByteString.Lazy as L+import Data.Default+import Data.Either (lefts, rights)+import qualified Data.Map as M+import Data.Maybe (fromMaybe, listToMaybe)+import Data.Text (Text, unpack)+import qualified Data.Text as T+import System.Directory (getAppUserDataDirectory)+import Text.CSL.Compat.Pandoc (fetchItem)+import Text.CSL.Data (getLocale)+import Text.CSL.Exception+import Text.CSL.Style hiding (parseNames)+import Text.CSL.Util (findFile, toRead)+import Text.Pandoc.Shared (safeRead)+import Text.Pandoc.UTF8 (fromStringLazy)+import qualified Text.XML as X+import Text.XML.Cursor -- | Parse a 'String' into a 'Style' (with default locale). parseCSL :: String -> Style@@ -65,15 +66,15 @@ let pickParentCur = get "link" >=> attributeIs (X.Name "rel" Nothing Nothing) "independent-parent" let parentCur = cur $/ get "info" &/ pickParentCur let parent' = concatMap (stringAttr "href") parentCur- when (parent' == src) $ do+ when (parent' == src) $ E.throwIO $ DependentStyleHasItselfAsParent src case parent' of "" -> localizeCSL mbLocale $ parseCSLCursor cur y -> do -- note, we insert locale from the dependent style: let mbLocale' = case stringAttr "default-locale" cur of- "" -> mbLocale- x -> Just x+ "" -> mbLocale+ x -> Just x readCSLFile mbLocale' y parseCSL' :: L.ByteString -> Style@@ -104,7 +105,7 @@ defaultLocale = case cur $| laxAttribute "default-locale" of (x:_) -> unpack x [] -> "en-US"- author = case (cur $// get "info" &/ get "author") of+ author = case cur $// get "info" &/ get "author" of (x:_) -> CSAuthor (x $/ get "name" &/ string) (x $/ get "email" &/ string) (x $/ get "uri" &/ string)@@ -129,9 +130,7 @@ attrWithDefault :: Read a => Text -> a -> Cursor -> a attrWithDefault t d cur =- case safeRead (toRead $ stringAttr t cur) of- Just x -> x- Nothing -> d+ fromMaybe d $ safeRead (toRead $ stringAttr t cur) stringAttr :: Text -> Cursor -> String stringAttr t cur =@@ -178,16 +177,16 @@ case node cur of X.NodeElement e -> case X.nameLocalName $ X.elementName e of- "term" -> parseTerm cur- "text" -> parseText cur- "choose" -> parseChoose cur- "group" -> parseGroup cur- "label" -> parseLabel cur- "number" -> parseNumber cur+ "term" -> parseTerm cur+ "text" -> parseText cur+ "choose" -> parseChoose cur+ "group" -> parseGroup cur+ "label" -> parseLabel cur+ "number" -> parseNumber cur "substitute" -> parseSubstitute cur- "names" -> parseNames cur- "date" -> parseDate cur- _ -> []+ "names" -> parseNames cur+ "date" -> parseDate cur+ _ -> [] _ -> [] getFormatting :: Cursor -> Formatting@@ -220,7 +219,7 @@ _ -> NoFormDate format = getFormatting cur delim = stringAttr "delimiter" cur- parts = cur $/ get "date-part" &| (parseDatePart form)+ parts = cur $/ get "date-part" &| parseDatePart form partsAttr = stringAttr "date-parts" cur parseDatePart :: DateForm -> Cursor -> DatePart@@ -228,13 +227,13 @@ DatePart { dpName = stringAttr "name" cur , dpForm = case stringAttr "form" cur of "" -> case defaultForm of- TextDate -> "long"+ TextDate -> "long" NumericDate -> "numeric"- _ -> "long"+ _ -> "long" x -> x , dpRangeDelim = case stringAttr "range-delimiter" cur of- "" -> "-"- x -> x+ "" -> "-"+ x -> x , dpFormatting = getFormatting cur } @@ -314,9 +313,7 @@ then [Macro macro formatting] else if not (null variable) then [Variable (words variable) textForm formatting delim]- else if not (null value)- then [Const value formatting]- else []+ else [Const value formatting | not (null value)] parseChoose :: Cursor -> [Element] parseChoose cur =@@ -390,8 +387,8 @@ (stringAttr "names-use-last" cur)] x -> [SortVariable x sorting] where sorting = case stringAttr "sort" cur of- "descending" -> Descending ""- _ -> Ascending ""+ "descending" -> Descending ""+ _ -> Ascending "" parseBiblio :: Cursor -> Bibliography parseBiblio cur =
src/Text/CSL/Proc.hs view
@@ -1,4 +1,5 @@-{-# LANGUAGE PatternGuards, OverloadedStrings #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards #-} ----------------------------------------------------------------------------- -- | -- Module : Text.CSL.Proc@@ -16,24 +17,24 @@ module Text.CSL.Proc where -import Control.Arrow ( (&&&), (>>>), second )-import Data.Char ( toLower, isLetter, isDigit )-import Data.List-import Data.Ord ( comparing )-import Data.Maybe ( mapMaybe )-import Text.CSL.Eval-import Text.CSL.Util ( proc, proc', query, uncamelize, tr' )-import Text.CSL.Proc.Collapse-import Text.CSL.Proc.Disamb-import Text.CSL.Reference-import Text.CSL.Style-import Data.Aeson-import Control.Applicative ((<|>))-import Text.Pandoc.Definition (Inline(Space, Str, Note), Block(Para))-+import Control.Applicative ((<|>))+import Control.Arrow (second, (&&&), (>>>))+import Data.Aeson+import Data.Char (isDigit, isLetter, toLower)+import Data.List+import Data.Maybe (mapMaybe)+import Data.Ord (comparing)+import Text.CSL.Eval+import Text.CSL.Proc.Collapse+import Text.CSL.Proc.Disamb+import Text.CSL.Reference+import Text.CSL.Style+import Text.CSL.Util (proc, proc', query, tr', uncamelize)+import Text.Pandoc.Definition (Block (Para),+ Inline (Note, Space, Str)) data ProcOpts = ProcOpts- { bibOpts :: BibOpts+ { bibOpts :: BibOpts , linkCitations :: Bool } deriving ( Show, Read, Eq )@@ -125,13 +126,15 @@ OCitNum n f{hyperlink = "#ref-" ++ citeid} addLink' citeid (OCitLabel l f) = OCitLabel l f{hyperlink = "#ref-" ++ citeid}+ addLink' citeid (Output xs@(OStr _ _: _) f) =+ Output xs f{hyperlink = "#ref-" ++ citeid} addLink' _ x = x -- | Given the CSL 'Style' and the list of 'Reference's sort the list -- according to the 'Style' and assign the citation number to each -- 'Reference'. procRefs :: Style -> [Reference] -> [Reference]-procRefs (Style {biblio = mb, csMacros = ms , styleLocale = l, styleAbbrevs = as, csOptions = opts}) rs+procRefs Style {biblio = mb, csMacros = ms , styleLocale = l, styleAbbrevs = as, csOptions = opts} rs = maybe (setCNum rs) process mb where opts' b = mergeOptions (bibOptions b) opts@@ -156,8 +159,8 @@ -- | With a 'Style' and a sorted list of 'Reference's produce the -- evaluated output for the bibliography. procBiblio :: BibOpts -> Style -> [Reference] -> [[Output]]-procBiblio bos (Style {biblio = mb, csMacros = ms , styleLocale = l,- styleAbbrevs = as, csOptions = opts}) rs+procBiblio bos Style {biblio = mb, csMacros = ms , styleLocale = l,+ styleAbbrevs = as, csOptions = opts} rs = map addSpaceAfterCitNum $ maybe [] process mb where -- handle second-field-align (sort of)@@ -196,7 +199,7 @@ getPartialEach x xs = concat . take 1 . map fst . sortBy (flip (comparing $ length . snd)) . filter ((<) 0 . length . snd) .- zip xs . map (takeWhile id . map (uncurry (==)) . zip x) $ xs+ zip xs . map (takeWhile id . zipWith (==) x) $ xs chkCreator = if subAuthRule == "partial-each" then chPartialEach [] else chkCr [] @@ -264,15 +267,15 @@ | otherwise = refs where quash [] _ = True- quash q r = not . and . flip map q $ \(f,v) -> lookup_ r f v- select s r = and . flip map s $ \(f,v) -> lookup_ r f v- include i r = or . flip map i $ \(f,v) -> lookup_ r f v- exclude e r = and . flip map e $ \(f,v) -> not $ lookup_ r f v- lookup_ r f v = case f of- "type" -> look "ref-type"- "id" -> look "ref-id"- "categories" -> look "categories"- x -> look x+ quash q r = not $ all (lookup_ r) q+ select s r = all (lookup_ r) s+ include i r = any (lookup_ r) i+ exclude e r = all (not . lookup_ r) e+ lookup_ r (f, v) = case f of+ "type" -> look "ref-type"+ "id" -> look "ref-id"+ "categories" -> look "categories"+ x -> look x where look s = case lookup s (mkRefMap (Just r)) of Just x | Just v' <- (fromValue x :: Maybe RefType ) -> v == uncamelize (show v')@@ -286,8 +289,8 @@ -- 'Reference's, generate a 'CitationGroup'. The citations are sorted -- according to the 'Style'. procGroup :: Style -> [(Cite, Maybe Reference)] -> CitationGroup-procGroup (Style {citation = ct, csMacros = ms , styleLocale = l,- styleAbbrevs = as, csOptions = opts}) cr+procGroup Style {citation = ct, csMacros = ms , styleLocale = l,+ styleAbbrevs = as, csOptions = opts} cr = CG authIn (layFormat $ citLayout ct) (layDelim $ citLayout ct) (authIn ++ co) where (co, authIn) = case cr of@@ -318,10 +321,10 @@ combine (Formatted []) ys = ys combine xs ys = case ys of- Formatted [] -> xs+ Formatted [] -> xs Formatted (Note _ : _) -> xs <> ys- Formatted (Str [c]:_) | c `elem` (", ;:" :: String) -> xs <> ys- _ -> xs <> Formatted [Space] <> ys+ Formatted (Str [c]:_) | c `elem` (", ;:" :: String) -> xs <> ys+ _ -> xs <> Formatted [Space] <> ys formatAuth = formatOutput . localMod formatCits = (if isNote then toNote else id) . formatOutputList . appendOutput formatting . addAffixes f .@@ -331,7 +334,7 @@ verticalAlign = if isAuthorInText cs then "" else verticalAlign f }- isAuthorInText [] = False+ isAuthorInText [] = False isAuthorInText ((c,_):_) = authorInText c localMod = uncurry $ localModifiers s (not $ null co) setAsSupAu h = map $ \(c,o) -> if (citeId c, citeHash c) == h
src/Text/CSL/Proc/Collapse.hs view
@@ -16,16 +16,16 @@ module Text.CSL.Proc.Collapse where -import Data.Ord (comparing)-import Data.Monoid (Any(..))-import Control.Arrow ( (&&&), (>>>), second )-import Data.Char-import Data.List ( groupBy, sortBy )-import Text.CSL.Util ( query, proc, proc', betterThan )-import Text.CSL.Eval-import Text.CSL.Proc.Disamb-import Text.CSL.Style hiding (Any)-import Text.Pandoc.Definition ( Inline (Str) )+import Control.Arrow (second, (&&&), (>>>))+import Data.Char+import Data.List (groupBy, sortBy)+import Data.Monoid (Any (..))+import Data.Ord (comparing)+import Text.CSL.Eval+import Text.CSL.Proc.Disamb+import Text.CSL.Style hiding (Any)+import Text.CSL.Util (betterThan, proc, proc', query)+import Text.Pandoc.Definition (Inline (Str)) -- | Collapse citations according to the style options. collapseCitGroups :: Style -> [CitationGroup] -> [CitationGroup]@@ -56,7 +56,7 @@ citNums (OCitNum i _) = [i] citNums (Output xs _) = concatMap citNums xs citNums _ = []- numOf = foldr (\x _ -> x) 0 . citNums+ numOf = foldr const 0 . citNums process xs = if hasLocator xs then xs else flip concatMap (groupConsecWith numOf xs)@@ -129,7 +129,7 @@ uncurry zip . second format . unzip $ a doCollapse [] = []- doCollapse (x:[]) = [collapsYS x]+ doCollapse [x] = [collapsYS x] doCollapse (x:xs) = let (a,b) = collapsYS x in if length x > 1 then (a, Output (b : [ODel afterColDel]) emptyFormatting) : doCollapse xs@@ -166,10 +166,10 @@ null (citeLocator $ fst b) getYS [] = []- getYS (x:[]) = return $ uncurry addCiteAffixes x+ getYS [x] = return $ uncurry addCiteAffixes x getYS (x:xs) = if ranged- then proc rmOYearSuf (snd x) : addDelim ysd (processYS $ (snd x) : query rmOYear (map snd xs))- else addDelim ysd $ (snd x) : (processYS $ query rmOYear (map snd xs))+ then proc rmOYearSuf (snd x) : addDelim ysd (processYS $ snd x : query rmOYear (map snd xs))+ else addDelim ysd $ snd x : processYS (query rmOYear (map snd xs)) rmOYearSuf o | OYearSuf {} <- o = ONull | otherwise = o@@ -183,7 +183,7 @@ getOYS o | OYearSuf s _ _ f <- o = [(if s /= [] then ord (head s) else 0, f)] | otherwise = []- sufOf = foldr (\x _ -> x) (0,emptyFormatting) . query getOYS+ sufOf = foldr const (0,emptyFormatting) . query getOYS newSuf = map sufOf >>> (map fst >>> groupConsec) &&& map snd >>> uncurry zip process xs = flip concatMap (newSuf xs) $ \(x,f) -> if length x > 2@@ -215,7 +215,7 @@ isNumStyle :: [Output] -> Bool isNumStyle = getAny . query ocitnum where- ocitnum (OCitNum {}) = Any True+ ocitnum OCitNum {} = Any True ocitnum _ = Any False -- | Group consecutive integers:@@ -227,7 +227,7 @@ groupConsecWith :: (a -> Int) -> [a] -> [[a]] groupConsecWith f = foldr go [] . sortBy (comparing f) where go x [] = [[x]]- go x ((y:ys):gs) = if (f x + 1) == (f y)- then ((x:y:ys):gs)- else ([x]:(y:ys):gs)+ go x ((y:ys):gs) = if (f x + 1) == f y+ then (x:y:ys):gs+ else [x]:(y:ys):gs go _ ([]:_) = error "groupConsec: head of list is empty"
src/Text/CSL/Proc/Disamb.hs view
@@ -21,16 +21,16 @@ module Text.CSL.Proc.Disamb where -import Control.Arrow ( (&&&), (>>>), second )-import Data.List ( elemIndex, find, findIndex, sortBy, mapAccumL- , nub, nubBy, groupBy, isPrefixOf )-import Data.Maybe-import Data.Ord ( comparing )+import Control.Arrow (second, (&&&), (>>>))+import Data.List (elemIndex, find, findIndex, groupBy,+ isPrefixOf, mapAccumL, nub, nubBy, sortBy)+import Data.Maybe+import Data.Ord (comparing) -import Text.CSL.Eval-import Text.CSL.Reference-import Text.CSL.Style-import Text.CSL.Util (query, proc)+import Text.CSL.Eval+import Text.CSL.Reference+import Text.CSL.Style+import Text.CSL.Util (proc, query) -- | Given the 'Style', the list of references and the citation -- groups, disambiguate citations according to the style options.@@ -58,12 +58,12 @@ hasYSuffOpt = "disambiguate-add-year-suffix" `elem` disOpts giveNameDisamb = case getOptionVal "givenname-disambiguation-rule" (citOptions (citation s)) of- "by-cite" -> ByCite- "all-names" -> AllNames- "all-names-with-initials" -> AllNames- "primary-name" -> PrimaryName+ "by-cite" -> ByCite+ "all-names" -> AllNames+ "all-names-with-initials" -> AllNames+ "primary-name" -> PrimaryName "primary-name-with-initials" -> PrimaryName- _ -> ByCite -- default as of CSL 1.0+ _ -> ByCite -- default as of CSL 1.0 clean = if hasGNameOpt then id else proc rmHashAndGivenNames withNames = flip map duplics $ same . clean . map (if hasNamesOpt then disambData else return . disambYS)@@ -234,8 +234,8 @@ -- allow title to disambiguate xs -> xs years o = case query getYears o of- [] -> [([],[])]- r -> r+ [] -> [([],[])]+ r -> r zipData = uncurry . zipWith $ \c y -> if key c /= [] then c {citYear = snd y} else c {key = fst y@@ -408,11 +408,11 @@ -- | Removes all given names and name hashes from OName elements. rmHashAndGivenNames :: Output -> Output rmHashAndGivenNames (OName _ s _ f) = OName emptyAgent s [] f-rmHashAndGivenNames o = o+rmHashAndGivenNames o = o rmGivenNames :: Output -> Output rmGivenNames (OName a s _ f) = OName a s [] f-rmGivenNames o = o+rmGivenNames o = o -- | Add, with 'proc', a give name to the family name. Needed for -- disambiguation.
src/Text/CSL/Reference.hs view
@@ -1,11 +1,17 @@-{-# LANGUAGE GeneralizedNewtypeDeriving, PatternGuards, OverloadedStrings,- DeriveDataTypeable, ExistentialQuantification, FlexibleInstances,- ScopedTypeVariables, GeneralizedNewtypeDeriving, IncoherentInstances,- DeriveGeneric, CPP #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE IncoherentInstances #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE ScopedTypeVariables #-} #if MIN_VERSION_base(4,8,0) #define OVERLAPS {-# OVERLAPPING #-} #else-{-# LANGUAGE OverlappingInstances #-}+{-# LANGUAGE OverlappingInstances #-} #define OVERLAPS #endif -----------------------------------------------------------------------------@@ -33,7 +39,6 @@ , handleLiteral , toDatePart , setCirca- , mkRefDate , RefType(..) , CNum(..) , CLabel(..)@@ -44,39 +49,44 @@ , processCites , setPageFirst , setNearNote+ , parseEDTFDate ) where -import Control.Monad ( guard, mplus )-import Data.List ( elemIndex, intercalate )-import Data.List.Split ( splitWhen )-import Data.Maybe ( fromMaybe, isJust, isNothing )-import Data.Generics hiding (Generic)-import GHC.Generics (Generic)-import Data.Aeson hiding (Value)-import qualified Data.Aeson as Aeson-import Data.Aeson.Types (Parser)-import qualified Data.Yaml.Builder as Y-import Data.Yaml.Builder (ToYaml(..))-import Data.Either (lefts, rights)-import Control.Applicative ((<|>))-import qualified Data.Text as T-import Data.Text (Text)-import qualified Data.Vector as V-import Data.Char (toLower, isDigit)-import Text.CSL.Style hiding (Number)-import Text.CSL.Util (parseString, parseInt, parseBool, safeRead, readNum,- inlinesToString, capitalize, camelize, uncamelize,- (&=), mapping')-import Text.Pandoc (Inline(Str))-import Data.String-import qualified Text.Parsec as P-import qualified Text.Parsec.String as P+import Control.Applicative ((<|>))+import Control.Monad (guard, mplus)+import Data.Aeson hiding (Value)+import qualified Data.Aeson as Aeson+import Data.Aeson.Types (Parser)+import Data.Char (isDigit, toLower)+import Data.Either (lefts, rights)+import Data.Generics hiding (Generic) import qualified Data.HashMap.Strict as H+import Data.List (elemIndex, intercalate)+import Data.List.Split (splitWhen)+import Data.Maybe (fromMaybe, isNothing)+import Data.String+import Data.Text (Text)+import qualified Data.Text as T+import qualified Data.Vector as V+import Data.Yaml.Builder (ToYaml (..))+import qualified Data.Yaml.Builder as Y+import GHC.Generics (Generic)+import Text.CSL.Style hiding (Number)+import Text.CSL.Util (camelize, capitalize, inlinesToString,+ mapping', parseBool, parseInt, parseMaybeInt,+ parseString, readNum, safeRead, trim,+ uncamelize, AddYaml(..))+import Text.Pandoc (Inline (Str))+import qualified Text.Parsec as P+import qualified Text.Parsec.String as P newtype Literal = Literal { unLiteral :: String } deriving ( Show, Read, Eq, Data, Typeable, Monoid, Generic ) +instance AddYaml Literal+ where x &= (Literal y) = x &= (T.pack y)+ instance FromJSON Literal where parseJSON v = Literal `fmap` parseString v @@ -123,41 +133,46 @@ data Empty = Empty deriving ( Typeable, Data, Generic ) data RefDate =- RefDate { year :: Literal- , month :: Literal- , season :: Literal- , day :: Literal+ RefDate { year :: Maybe Int+ , month :: Maybe Int+ , season :: Maybe Int+ , day :: Maybe Int , other :: Literal , circa :: Bool } deriving ( Show, Read, Eq, Typeable, Data, Generic ) +instance AddYaml RefDate where+ _ &= (RefDate Nothing Nothing Nothing Nothing o _) | o == mempty = id+ x &= y = x &= y+ instance FromJSON RefDate where parseJSON (Array v) = handlePseudoMonths <$> case fromJSON (Array v) of- Success [y] -> RefDate <$> parseJSON y <*>- pure "" <*> pure "" <*> pure "" <*> pure "" <*> pure False- Success [y,m] -> RefDate <$> parseJSON y <*> parseJSON m <*>- pure "" <*> pure "" <*> pure "" <*> pure False- Success [y,m,d] -> RefDate <$> parseJSON y <*> parseJSON m <*>- pure "" <*> parseJSON d <*> pure "" <*> pure False+ Success [y] -> RefDate <$> parseMaybeInt y <*>+ pure Nothing <*> pure Nothing <*> pure Nothing <*>+ pure "" <*> pure False+ Success [y,m] -> RefDate <$> parseMaybeInt y <*> parseMaybeInt m <*>+ pure Nothing <*> pure Nothing <*> pure "" <*> pure False+ Success [y,m,d] -> RefDate <$> parseMaybeInt y <*> parseMaybeInt m <*>+ pure Nothing <*> parseMaybeInt d <*> pure "" <*> pure False Error e -> fail $ "Could not parse RefDate: " ++ e _ -> fail "Could not parse RefDate" where handlePseudoMonths r =- case unLiteral (month r) of- "13" -> r{ month = mempty, season = Literal "1" }- "14" -> r{ month = mempty, season = Literal "2" }- "15" -> r{ month = mempty, season = Literal "3" }- "16" -> r{ month = mempty, season = Literal "4" }- "21" -> r{ month = mempty, season = Literal "1" }- "22" -> r{ month = mempty, season = Literal "2" }- "23" -> r{ month = mempty, season = Literal "3" }- "24" -> r{ month = mempty, season = Literal "4" }+ case month r of+ Just 13 -> r{ month = Nothing, season = Just 1 }+ Just 14 -> r{ month = Nothing, season = Just 2 }+ Just 15 -> r{ month = Nothing, season = Just 3 }+ Just 16 -> r{ month = Nothing, season = Just 4 }+ Just 21 -> r{ month = Nothing, season = Just 1 }+ Just 22 -> r{ month = Nothing, season = Just 2 }+ Just 23 -> r{ month = Nothing, season = Just 3 }+ Just 24 -> r{ month = Nothing, season = Just 4 } _ -> r parseJSON (Object v) = RefDate <$>- v .:? "year" .!= "" <*>- v .:? "month" .!= "" <*>- v .:? "season" .!= "" <*>- v .:? "day" .!= "" <*>+ (v .:? "year" >>= parseMaybeInt) <*>+ (v .:? "month" >>= parseMaybeInt) <*>+ (v .:? "season" >>= parseMaybeInt) <*>+ (v .:? "day" >>= parseMaybeInt) <*> v .:? "literal" .!= "" <*> ((v .: "circa" >>= parseBool) <|> pure False) parseJSON _ = fail "Could not parse RefDate"@@ -174,13 +189,14 @@ -} instance ToYaml RefDate where- toYaml r = mapping' [ "year" &= year r- , "month" &= month r- , "season" &= season r- , "day" &= day r- , "literal" &= other r- , "circa" &= T.pack (if circa r then "1" else "")- ]+ toYaml r = mapping'+ [ "year" &= year r+ , "month" &= month r+ , "season" &= season r+ , "day" &= day r+ , "literal" &= other r+ , "circa" &= circa r+ ] instance OVERLAPS FromJSON [RefDate] where@@ -191,61 +207,55 @@ circa' <- (v .: "circa" >>= parseBool) <|> pure False season' <- v .:? "season" case dateParts of- Just (Array xs) | not (isJust raw') && not (V.null xs)+ Just (Array xs) | isNothing raw' && not (V.null xs) -> mapM (fmap (setCirca circa' .- maybe id setSeason season') . parseJSON)+ maybe id setSeason season') . parseJSON) $ V.toList xs _ -> case raw' of Nothing -> handleLiteral <$> parseJSON (Object v) Just r -> return $ parseRawDate r parseJSON x = parseRawDate <$> parseJSON x +instance OVERLAPS+ ToJSON [RefDate] where+ toJSON [] = Array V.empty+ toJSON xs = object' $+ case filter (not . null) (map toDatePart xs) of+ [] -> ["literal" .= intercalate "; " (map (unLiteral . other) xs)]+ dps -> "date-parts" .= dps :+ ["circa" .= (1 :: Int) | any circa xs]++ -- Zotero doesn't properly support date ranges, so a common -- workaround is 2005_2007 or 2005_; support this as date range: handleLiteral :: RefDate -> [RefDate]-handleLiteral d@(RefDate (Literal "") (Literal "") (Literal "")- (Literal "") (Literal xs) b)+handleLiteral d@(RefDate Nothing Nothing Nothing Nothing (Literal xs) b) = case splitWhen (=='_') xs of [x,y] | all isDigit x && all isDigit y && not (null x) ->- [RefDate (Literal x) mempty mempty mempty mempty b,- RefDate (Literal y) mempty mempty mempty mempty b]+ [RefDate (safeRead x) Nothing Nothing Nothing mempty b,+ RefDate (safeRead y) Nothing Nothing Nothing mempty b] _ -> [d] handleLiteral d = [d] toDatePart :: RefDate -> [Int] toDatePart refdate =- case (safeRead (unLiteral $ year refdate),- safeRead (unLiteral $ month refdate)+ case (year refdate, month refdate `mplus`- ((+ 12) <$> safeRead (unLiteral $ season refdate)),- safeRead (unLiteral $ day refdate)) of+ ((+ 12) <$> season refdate),+ day refdate) of (Just (y :: Int), Just (m :: Int), Just (d :: Int)) -> [y, m, d] (Just y, Just m, Nothing) -> [y, m] (Just y, Nothing, Nothing) -> [y] _ -> [] -instance OVERLAPS- ToJSON [RefDate] where- toJSON [] = Array V.empty- toJSON xs = object' $- case filter (not . null) (map toDatePart xs) of- [] -> ["literal" .= intercalate "; " (map (unLiteral . other) xs)]- dps -> (["date-parts" .= dps ] ++- ["circa" .= (1 :: Int) | or (map circa xs)])- setCirca :: Bool -> RefDate -> RefDate setCirca circa' rd = rd{ circa = circa' } -setSeason :: Literal -> RefDate -> RefDate+setSeason :: Maybe Int -> RefDate -> RefDate setSeason season' rd = rd{ season = season' } -mkRefDate :: Literal -> Parser [RefDate]-mkRefDate z@(Literal xs)- | all isDigit xs = return [RefDate z mempty mempty mempty mempty False]- | otherwise = return [RefDate mempty mempty mempty mempty z False]- data RefType = NoType | Article@@ -292,12 +302,12 @@ -- found in one of the test cases: parseJSON (String "film") = return MotionPicture parseJSON (String t) =- (safeRead (capitalize . camelize . T.unpack $ t)) <|>+ safeRead (capitalize . camelize . T.unpack $ t) <|> fail ("'" ++ T.unpack t ++ "' is not a valid reference type") parseJSON v@(Array _) = fmap (capitalize . camelize . inlinesToString) (parseJSON v) >>= \t ->- (safeRead t <|>- fail ("'" ++ t ++ "' is not a valid reference type"))+ safeRead t <|>+ fail ("'" ++ t ++ "' is not a valid reference type") parseJSON _ = fail "Could not parse RefType" instance ToJSON RefType where@@ -308,11 +318,11 @@ -- For some reason, CSL is inconsistent about hyphens and underscores: handleSpecialCases :: String -> String-handleSpecialCases "motion-picture" = "motion_picture"-handleSpecialCases "musical-score" = "musical_score"+handleSpecialCases "motion-picture" = "motion_picture"+handleSpecialCases "musical-score" = "musical_score" handleSpecialCases "personal-communication" = "personal_communication"-handleSpecialCases "legal-case" = "legal_case"-handleSpecialCases x = x+handleSpecialCases "legal-case" = "legal_case"+handleSpecialCases x = x newtype CNum = CNum { unCNum :: Int } deriving ( Show, Read, Eq, Num, Typeable, Data, Generic ) @@ -343,81 +353,81 @@ -- | The 'Reference' record. data Reference = Reference- { refId :: Literal- , refType :: RefType+ { refId :: Literal+ , refType :: RefType - , author :: [Agent]- , editor :: [Agent]- , translator :: [Agent]- , recipient :: [Agent]- , interviewer :: [Agent]- , composer :: [Agent]- , director :: [Agent]- , illustrator :: [Agent]- , originalAuthor :: [Agent]- , containerAuthor :: [Agent]- , collectionEditor :: [Agent]- , editorialDirector :: [Agent]- , reviewedAuthor :: [Agent]+ , author :: [Agent]+ , editor :: [Agent]+ , translator :: [Agent]+ , recipient :: [Agent]+ , interviewer :: [Agent]+ , composer :: [Agent]+ , director :: [Agent]+ , illustrator :: [Agent]+ , originalAuthor :: [Agent]+ , containerAuthor :: [Agent]+ , collectionEditor :: [Agent]+ , editorialDirector :: [Agent]+ , reviewedAuthor :: [Agent] - , issued :: [RefDate]- , eventDate :: [RefDate]- , accessed :: [RefDate]- , container :: [RefDate]- , originalDate :: [RefDate]- , submitted :: [RefDate]+ , issued :: [RefDate]+ , eventDate :: [RefDate]+ , accessed :: [RefDate]+ , container :: [RefDate]+ , originalDate :: [RefDate]+ , submitted :: [RefDate] - , title :: Formatted- , titleShort :: Formatted- , reviewedTitle :: Formatted- , containerTitle :: Formatted- , volumeTitle :: Formatted- , collectionTitle :: Formatted- , containerTitleShort :: Formatted- , collectionNumber :: Formatted --Int- , originalTitle :: Formatted- , publisher :: Formatted- , originalPublisher :: Formatted- , publisherPlace :: Formatted- , originalPublisherPlace :: Formatted- , authority :: Formatted- , jurisdiction :: Formatted- , archive :: Formatted- , archivePlace :: Formatted- , archiveLocation :: Formatted- , event :: Formatted- , eventPlace :: Formatted- , page :: Formatted- , pageFirst :: Formatted- , numberOfPages :: Formatted- , version :: Formatted- , volume :: Formatted- , numberOfVolumes :: Formatted --Int- , issue :: Formatted- , chapterNumber :: Formatted- , medium :: Formatted- , status :: Formatted- , edition :: Formatted- , section :: Formatted- , source :: Formatted- , genre :: Formatted- , note :: Formatted- , annote :: Formatted- , abstract :: Formatted- , keyword :: Formatted- , number :: Formatted- , references :: Formatted- , url :: Literal- , doi :: Literal- , isbn :: Literal- , issn :: Literal- , pmcid :: Literal- , pmid :: Literal- , callNumber :: Literal- , dimensions :: Literal- , scale :: Literal- , categories :: [Literal]- , language :: Literal+ , title :: Formatted+ , titleShort :: Formatted+ , reviewedTitle :: Formatted+ , containerTitle :: Formatted+ , volumeTitle :: Formatted+ , collectionTitle :: Formatted+ , containerTitleShort :: Formatted+ , collectionNumber :: Formatted --Int+ , originalTitle :: Formatted+ , publisher :: Formatted+ , originalPublisher :: Formatted+ , publisherPlace :: Formatted+ , originalPublisherPlace :: Formatted+ , authority :: Formatted+ , jurisdiction :: Formatted+ , archive :: Formatted+ , archivePlace :: Formatted+ , archiveLocation :: Formatted+ , event :: Formatted+ , eventPlace :: Formatted+ , page :: Formatted+ , pageFirst :: Formatted+ , numberOfPages :: Formatted+ , version :: Formatted+ , volume :: Formatted+ , numberOfVolumes :: Formatted --Int+ , issue :: Formatted+ , chapterNumber :: Formatted+ , medium :: Formatted+ , status :: Formatted+ , edition :: Formatted+ , section :: Formatted+ , source :: Formatted+ , genre :: Formatted+ , note :: Formatted+ , annote :: Formatted+ , abstract :: Formatted+ , keyword :: Formatted+ , number :: Formatted+ , references :: Formatted+ , url :: Literal+ , doi :: Literal+ , isbn :: Literal+ , issn :: Literal+ , pmcid :: Literal+ , pmid :: Literal+ , callNumber :: Literal+ , dimensions :: Literal+ , scale :: Literal+ , categories :: [Literal]+ , language :: Literal , citationNumber :: CNum , firstReferenceNoteNumber :: Int@@ -505,8 +515,8 @@ v .:? "citation-label" .!= mempty) where takeFirstNum (Formatted (Str xs : _)) = case takeWhile isDigit xs of- [] -> mempty- ds -> Formatted [Str ds]+ [] -> mempty+ ds -> Formatted [Str ds] takeFirstNum x = x addPageFirst ref = if pageFirst ref == mempty && page ref /= mempty then ref{ pageFirst =@@ -858,7 +868,7 @@ = procGr [] cs where near_note = let nn = fromMaybe [] . lookup "near-note-distance" . citOptions . citation $ s- in if nn == [] then 5 else readNum nn+ in if null nn then 5 else readNum nn procGr _ [] = [] procGr a (x:xs) = let (a',res) = procCs a x in res : procGr a' xs@@ -876,38 +886,72 @@ parseRawDate :: String -> [RefDate] parseRawDate o = case P.parse rawDate "raw date" o of- Left _ -> [RefDate mempty mempty mempty mempty (Literal o) False]+ Left _ -> [RefDate Nothing Nothing Nothing Nothing (Literal o) False] Right ds -> ds rawDate :: P.Parser [RefDate] rawDate = rawDateISO <|> rawDateOld +parseEDTFDate :: String -> [RefDate]+parseEDTFDate o =+ case handleRanges (trim o) of+ [] -> []+ o' -> case P.parse rawDateISO "date" o' of+ Left _ -> []+ Right ds -> ds+ where handleRanges s =+ case splitWhen (=='/') s of+ -- 199u EDTF format for a range+ [x] | 'u' `elem` x ->+ map (\c -> if c == 'u' then '0' else c) x ++ "/" +++ map (\c -> if c == 'u' then '9' else c) x+ [x, "open"] -> x ++ "/" -- EDTF+ [x, "unknown"] -> x ++ "/" -- EDTF+ _ -> s+ rawDateISO :: P.Parser [RefDate] rawDateISO = do d1 <- isoDate- P.option [d1] (P.char '/' >> (\x -> [d1, x]) <$> isoDate)+ P.option [d1] (P.char '/' >>+ (\x -> [d1, x]) <$>+ ( isoDate <|> return emptydate )) <* P.eof+ where emptydate = RefDate Nothing Nothing Nothing Nothing mempty False isoDate :: P.Parser RefDate isoDate = P.try $ do+ extyear <- P.option False (True <$ P.char 'y') -- EDTF year > 4 digits+ -- needed for bibtex y <- do sign <- P.option "" (P.string "-") rest <- P.count 4 P.digit- return $ sign ++ rest+ extended <- if extyear+ then P.many P.digit+ else return []+ return $ case safeRead (sign ++ rest ++ extended) of+ Just x | x <= 0 -> Just (x - 1) -- 0 = -1 AD+ x -> x m' <- P.option Nothing $ Just <$> P.try (P.char '-' >> P.many1 P.digit) (m,s) <- case m' >>= safeRead of Just (n::Int)- | n >= 1 && n <= 12 -> return (show n, "")- | n >= 13 && n <= 16 -> return ("", show (n - 12))- | n >= 21 && n <= 24 -> return ("", show (n - 20))- Nothing | isNothing m' -> return ("", "")+ | n >= 1 && n <= 12 -> return (Just n, Nothing)+ | n >= 13 && n <= 16 -> return (Nothing, Just (n - 12))+ | n >= 21 && n <= 24 -> return (Nothing, Just (n - 20))+ Nothing | isNothing m' -> return (Nothing, Nothing) _ -> fail "Improper month"- d <- P.option Nothing $ Just <$> P.try (P.char '-' >> P.many1 P.digit)- guard $ isNothing d || case d >>= safeRead of- Just (n::Int) | n >= 1 && n <= 31 -> True- _ -> False+ d <- P.option Nothing $ safeRead <$> P.try (P.char '-' >> P.many1 P.digit)+ guard $ case d of+ Nothing -> True+ Just (n::Int) | n >= 1 && n <= 31 -> True+ _ -> False+ P.optional $ do+ _ <- P.char 'T'+ _ <- P.many (P.digit <|> P.char ':')+ P.optional $ (P.oneOf "+-" >> P.many1 (P.digit <|> P.char ':'))+ <|> P.string "Z"+ _ <- P.optional (P.char '?') c <- P.option False (True <$ P.char '~')- return RefDate{ year = Literal y, month = Literal m,- season = Literal s, day = maybe mempty Literal d,+ return RefDate{ year = y, month = m,+ season = s, day = d, other = mempty, circa = c } rawDateOld :: P.Parser [RefDate]@@ -919,43 +963,43 @@ xs <- P.many1 P.letter <|> P.many1 P.digit if all isDigit xs then case safeRead xs of- Just (n::Int) | n >= 1 && n <= 12 -> return (show n)+ Just (n::Int) | n >= 1 && n <= 12 -> return (Just n) _ -> fail "Improper month" else case elemIndex (map toLower $ take 3 xs) months of Nothing -> fail "Improper month"- Just n -> return (show (n+1))+ Just n -> return (Just (n+1)) let pseason = P.try $ do xs <- P.many1 P.letter case elemIndex (map toLower $ take 3 xs) seasons of Nothing -> fail "Improper season"- Just n -> return (show (n+1))+ Just n -> return (Just (n+1)) let pday = P.try $ do xs <- P.many1 P.digit case safeRead xs of- Just (n::Int) | n >= 1 && n <= 31 -> return (show n)+ Just (n::Int) | n >= 1 && n <= 31 -> return (Just n) _ -> fail "Improper day"- let pyear = P.many1 P.digit+ let pyear = safeRead <$> P.many1 P.digit let sep = P.oneOf [' ','/',','] >> P.spaces let rangesep = P.try $ P.spaces >> P.char '-' >> P.spaces- let refDate = RefDate mempty mempty mempty mempty mempty False+ let refDate = RefDate Nothing Nothing Nothing Nothing mempty False let date = P.choice $ map P.try [ (do s <- pseason sep y <- pyear- return refDate{ year = Literal y, season = Literal s })+ return refDate{ year = y, season = s }) , (do m <- pmonth sep d <- pday sep y <- pyear- return refDate{ year = Literal y, month = Literal m,- day = Literal d })+ return refDate{ year = y, month = m, day = d }) , (do m <- pmonth sep y <- pyear- return refDate{ year = Literal y, month = Literal m })+ return refDate{ year = y, month = m }) , (do y <- pyear- return refDate{ year = Literal y })+ return refDate{ year = y }) ] d1 <- date P.option [d1] ((\x -> [d1,x]) <$> (rangesep >> date))+
src/Text/CSL/Style.hs view
@@ -1,10 +1,16 @@-{-# LANGUAGE OverloadedStrings, PatternGuards, DeriveDataTypeable,- ScopedTypeVariables, FlexibleInstances, DeriveGeneric,- GeneralizedNewtypeDeriving, CPP, MultiParamTypeClasses #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE FlexibleInstances #-}++{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE ScopedTypeVariables #-} #if MIN_VERSION_base(4,8,0) #define OVERLAPS {-# OVERLAPPING #-} #else-{-# LANGUAGE OverlappingInstances #-}+{-# LANGUAGE OverlappingInstances #-} #define OVERLAPS #endif -----------------------------------------------------------------------------@@ -86,41 +92,43 @@ ) where -import Data.Aeson hiding (Number)-import GHC.Generics (Generic)-import Data.String-import Control.Arrow hiding (left, right)-import Control.Monad (liftM, mplus)-import Control.Applicative ((<|>))-import qualified Data.Aeson as Aeson-import Data.Aeson.Types (Pair)-import Data.List ( nubBy, isPrefixOf, isInfixOf, intersperse, intercalate )-import Data.List.Split ( splitWhen, wordsBy )-import Data.Generics ( Data, Typeable )-import Data.Maybe ( listToMaybe )-import qualified Data.Map as M-import Data.Char (isPunctuation, isUpper, isLetter)-import Text.CSL.Util (mb, parseBool, parseString, (.#?), (.#:), query,- betterThan, trimr, tailInline, headInline,- initInline, lastInline, splitStrWhen, mapping',- (&=))-import Data.Yaml.Builder(ToYaml(..))-import qualified Data.Yaml.Builder as Y-import Text.Pandoc.Definition hiding (Citation, Cite)-import Text.Pandoc (bottomUp)-import Text.CSL.Compat.Pandoc (readHtml, writeMarkdown)-import qualified Text.Pandoc.Walk as Walk-import qualified Text.Pandoc.Builder as B-import qualified Data.Text as T-import Text.Pandoc.XML (fromEntities)+import Control.Applicative ((<|>), (<$>))+import Control.Arrow hiding (left, right)+import Control.Monad (mplus)+import Data.Aeson hiding (Number)+import qualified Data.Aeson as Aeson+import Data.Aeson.Types (Pair)+import Data.Char (isLetter, isPunctuation, isUpper)+import Data.Generics (Data, Typeable)+import Data.List (intercalate, intersperse, isInfixOf,+ isPrefixOf, nubBy)+import Data.List.Split (splitWhen, wordsBy)+import qualified Data.Map as M+import Data.Maybe (listToMaybe, isNothing)+import Data.String+import qualified Data.Text as T+import Data.Yaml.Builder (ToYaml (..))+import qualified Data.Yaml.Builder as Y+import GHC.Generics (Generic)+import Text.CSL.Compat.Pandoc (readHtml, writeMarkdown)+import Text.CSL.Util (betterThan, headInline, initInline,+ lastInline, mapping', mb, parseBool,+ parseString, query, splitStrWhen,+ tailInline, trimr, (.#:), (.#?),+ AddYaml(..))+import Text.Pandoc (bottomUp)+import qualified Text.Pandoc.Builder as B+import Text.Pandoc.Definition hiding (Citation, Cite)+import qualified Text.Pandoc.Walk as Walk+import Text.Pandoc.XML (fromEntities) #ifdef UNICODE_COLLATION-import qualified Data.Text as T-import qualified Data.Text.ICU as T+import qualified Data.Text as T+import qualified Data.Text.ICU as T #else-import Data.RFC5051 (compareUnicode)+import Data.RFC5051 (compareUnicode) #endif-import qualified Data.Vector as V+import qualified Data.Vector as V -- Note: FromJSON reads HTML, ToJSON writes Markdown. -- This means that they aren't proper inverses of each other, which@@ -131,9 +139,9 @@ readCSLString :: String -> [Inline] readCSLString s = Walk.walk handleSmallCapsSpans $ case readHtml (adjustScTags s) of- Pandoc _ [Plain ils] -> ils- Pandoc _ [Para ils] -> ils- Pandoc _ x -> Walk.query (:[]) x+ Pandoc _ [Plain ils] -> ils+ Pandoc _ [Para ils] -> ils+ Pandoc _ x -> Walk.query (:[]) x -- this is needed for versions of pandoc that don't turn -- a span with font-variant:small-caps into a SmallCaps element: where handleSmallCapsSpans (Span ("",[],[("style",sty)]) ils)@@ -198,7 +206,7 @@ parseJSON v@(Array _) = Formatted <$> (parseJSON v <|> ((query (:[]) :: [Block] -> [Inline]) <$> parseJSON v))- parseJSON v = fmap (Formatted . readCSLString) $ parseString v+ parseJSON v = (Formatted . readCSLString) Control.Applicative.<$> parseString v instance ToJSON Formatted where toJSON = toJSON . writeCSLString . unFormatted@@ -209,6 +217,12 @@ instance IsString Formatted where fromString = Formatted . toStr +instance AddYaml Formatted where+ x &= (Formatted y) =+ \acc -> if null y+ then acc+ else (x Y..= Formatted y) : acc+ instance Monoid Formatted where mempty = Formatted [] mappend = appendWithPunct@@ -216,7 +230,7 @@ instance Walk.Walkable Inline Formatted where walk f = Formatted . Walk.walk f . unFormatted- walkM f = liftM Formatted . Walk.walkM f . unFormatted+ walkM f = fmap Formatted . Walk.walkM f . unFormatted query f = Walk.query f . unFormatted instance Walk.Walkable Formatted Formatted where@@ -241,7 +255,7 @@ appendWithPunct :: Formatted -> Formatted -> Formatted appendWithPunct (Formatted left) (Formatted right) = Formatted $- case concat [lastleft, firstright] of+ case lastleft ++ firstright of [' ',d] | d `elem` (",.:;" :: String) -> initInline left ++ right [c,d] | c `elem` (" ,.:;" :: String), d == c -> left ++ tailInline right [c,'.'] | c `elem` (",.!:;?" :: String) -> left ++ tailInline right@@ -324,7 +338,7 @@ findTerm'' :: String -> Form -> Maybe Gender -> [CslTerm] -> Maybe CslTerm findTerm'' s f mbg ts = listToMaybe [ t | t <- ts, cslTerm t == s, termForm t == f,- mbg == Nothing || mbg == Just (termGenderForm t) ]+ isNothing mbg || mbg == Just (termGenderForm t) ] `mplus` -- fallback: http://citationstyles.org/downloads/specification.html#terms case f of@@ -427,7 +441,7 @@ match :: Match -> [Bool] -> Bool match All = and match Any = or-match None = and . map not+match None = all not data DatePart = DatePart@@ -704,7 +718,7 @@ instance OVERLAPS FromJSON [[Cite]] where parseJSON (Array v) = mapM parseJSON $ V.toList v- parseJSON _ = return []+ parseJSON _ = return [] emptyCite :: Cite emptyCite = Cite [] mempty mempty [] [] [] [] False False False 0@@ -764,11 +778,11 @@ object' :: [Pair] -> Aeson.Value object' = object . filter (not . isempty)- where isempty (_, Array v) = V.null v- isempty (_, String t) = T.null t+ where isempty (_, Array v) = V.null v+ isempty (_, String t) = T.null t isempty ("first-reference-note-number", Aeson.Number n) = n == 0- isempty ("citation-number", Aeson.Number n) = n == 0- isempty (_, _) = False+ isempty ("citation-number", Aeson.Number n) = n == 0+ isempty (_, _) = False data Agent = Agent { givenName :: [Formatted]@@ -788,9 +802,9 @@ -- CSL JSON uses quotes to protect capitalization removeQuoted :: Formatted -> Formatted removeQuoted (Formatted ils) = Formatted (go ils)- where go [] = []+ where go [] = [] go (Quoted DoubleQuote ils' : xs) = ils' ++ go xs- go (x:xs) = x : go xs+ go (x:xs) = x : go xs instance FromJSON Agent where parseJSON (Object v) = nameTransform <$> (Agent <$>@@ -866,18 +880,18 @@ startWithCapital' :: Inline -> Bool startWithCapital' (Str (c:_)) = isUpper c && isLetter c-startWithCapital' _ = False+startWithCapital' _ = False startWithCapital :: Formatted -> Bool startWithCapital (Formatted (x:_)) = startWithCapital' x-startWithCapital _ = False+startWithCapital _ = False stripFinalComma :: Formatted -> (String, Formatted) stripFinalComma (Formatted ils) = case reverse $ splitStrWhen isPunctuation ils of- Str ",":xs -> (",", Formatted $ reverse xs)+ Str ",":xs -> (",", Formatted $ reverse xs) Str "!":Str ",":xs -> (",!", Formatted $ reverse xs)- _ -> ("", Formatted ils)+ _ -> ("", Formatted ils) suffixTransform :: Agent -> Agent suffixTransform ag@@ -915,7 +929,8 @@ FromJSON [Agent] where parseJSON (Array xs) = mapM parseJSON $ V.toList xs parseJSON (Object v) = (:[]) `fmap` parseJSON (Object v)- parseJSON _ = fail "Could not parse [Agent]"+ parseJSON _ = fail "Could not parse [Agent]" -- instance ToJSON [Agent] where -- toJSON xs = Array (V.fromList $ map toJSON xs)+
src/Text/CSL/Util.hs view
@@ -1,4 +1,8 @@-{-# LANGUAGE ScopedTypeVariables, PatternGuards, FlexibleContexts #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE PatternGuards #-}+{-# LANGUAGE ScopedTypeVariables #-} module Text.CSL.Util ( safeRead , readNum@@ -16,6 +20,7 @@ , parseBool , parseString , parseInt+ , parseMaybeInt , mb , (.#?) , (.#:)@@ -40,34 +45,35 @@ , mapHeadInline , tr' , findFile- , (&=)+ , AddYaml(..) , mapping' , parseRomanNumeral , isRange ) where-import Data.Aeson-import Data.Aeson.Types (Parser)-import Data.Text (Text)-import qualified Data.Text as T-import Data.Char (toLower, toUpper, isLower, isUpper, isPunctuation, isAscii)+import Control.Monad.State+import Data.Aeson+import Data.Aeson.Types (Parser)+import Data.Char (isAscii, isLower, isPunctuation, isUpper,+ toLower, toUpper)+import Data.Generics (Data, Typeable, everything, everywhere,+ everywhere', everywhereM, mkM, mkQ, mkT)+import Data.List.Split (wordsBy)+import qualified Data.Set as Set+import Data.Text (Text)+import qualified Data.Text as T import qualified Data.Traversable-import Text.Pandoc.Shared (safeRead, stringify)-import Text.Pandoc.Walk (walk)-import Text.Pandoc-import Data.List.Split (wordsBy)-import Control.Monad.State-import Data.Generics ( Typeable, Data, everywhere, everywhereM, mkM,- everywhere', everything, mkT, mkQ )-import qualified Data.Set as Set-import System.FilePath-import System.Directory (doesFileExist)-import qualified Data.Yaml.Builder as Y-import Data.Yaml.Builder (ToYaml(..), YamlBuilder)-import qualified Text.Parsec as P+import Data.Yaml.Builder (ToYaml (..), YamlBuilder)+import qualified Data.Yaml.Builder as Y+import System.Directory (doesFileExist)+import System.FilePath+import Text.Pandoc+import Text.Pandoc.Shared (safeRead, stringify)+import Text.Pandoc.Walk (walk)+import qualified Text.Parsec as P #ifdef TRACE import qualified Debug.Trace-import Text.Show.Pretty (ppShow)+import Text.Show.Pretty (ppShow) #endif #ifdef TRACE@@ -93,7 +99,7 @@ sa <^> sb = sa ++ sb capitalize :: String -> String-capitalize [] = []+capitalize [] = [] capitalize (c:cs) = toUpper c : cs isPunct :: Char -> Bool@@ -156,14 +162,28 @@ -- | Parse JSON value as Int. parseInt :: Value -> Parser Int-parseInt (String s) = case safeRead (T.unpack s) of- Just n -> return n- Nothing -> fail "Could not read Int" parseInt (Number n) = case fromJSON (Number n) of Success (x :: Int) -> return x- Error e -> fail $ "Could not read string: " ++ e-parseInt _ = fail "Could not read string"+ Error e -> fail $ "Could not read Int: " ++ e+parseInt x = parseString x >>= \s ->+ case safeRead s of+ Just n -> return n+ Nothing -> fail "Could not read Int" +-- | Parse JSON value as Maybe Int.+parseMaybeInt :: Maybe Value -> Parser (Maybe Int)+parseMaybeInt Nothing = return Nothing+parseMaybeInt (Just (Number n)) = case fromJSON (Number n) of+ Success (x :: Int) -> return (Just x)+ Error e -> fail $ "Could not read Int: " ++ e+parseMaybeInt (Just x) =+ parseString x >>= \s ->+ if null s+ then return Nothing+ else case safeRead s of+ Just n -> return (Just n)+ Nothing -> fail $ "Could not read as Int: " ++ show s+ mb :: Monad m => (b -> m a) -> (Maybe b -> m (Maybe a)) mb = Data.Traversable.mapM @@ -175,7 +195,7 @@ x .#: y = (x .: y) >>= parseString onBlocks :: ([Inline] -> [Inline]) -> [Block] -> [Block]-onBlocks f bs = walk f' bs+onBlocks f = walk f' where f' (Para ils) = Para (f ils) f' (Plain ils) = Plain (f ils) f' x = x@@ -189,7 +209,7 @@ splitUpStr ils = case reverse (combineInternalPeriods (splitStrWhen (\c -> isPunctuation c || c == '\160') ils)) of- [] -> []+ [] -> [] (x:xs) -> reverse $ Span ("",["lastword"],[]) [x] : xs -- We want to make sure that the periods in www.example.com, for@@ -259,7 +279,7 @@ | isMixedCase s -> Str s | otherwise -> Str (toUpper x:xs) SentenceBoundary ->- if isMixedCase (x:xs) || (all isUpperOrPunct (x:xs))+ if isMixedCase (x:xs) || all isUpperOrPunct (x:xs) then Str (x:xs) else Str (toUpper x : xs) _ -> Str (x:xs)@@ -304,9 +324,7 @@ | c `elem` "-/\x2013\x2014\160" = do put WordBoundary return $ Str [c] : acc- | isPunctuation c = do- -- leave state unchanged- return $ Str [c] : acc+ | isPunctuation c = return $ Str [c] : acc -- leave state unchanged go acc (Str []) = return acc go acc (Str xs) = do res <- xform (Str xs)@@ -316,7 +334,7 @@ b <- get case b of WordBoundary -> put LastWordBoundary- _ -> return ()+ _ -> return () go acc x go acc (Span ("",classes,[]) xs) | null classes || classes == ["nocase"] = do@@ -386,7 +404,7 @@ initInline :: [Inline] -> [Inline] initInline [] = []-initInline (i:[])+initInline [i] | Str s <- i = return $ Str (init' s) | Emph is <- i = return $ Emph (initInline is) | Strong is <- i = return $ Strong (initInline is)@@ -411,7 +429,7 @@ toCapital :: [Inline] -> [Inline] toCapital ils@(Span (_,["nocase"],_) _:_) = ils-toCapital ils = mapHeadInline capitalize ils+toCapital ils = mapHeadInline capitalize ils mapHeadInline :: (String -> String) -> [Inline] -> [Inline] mapHeadInline _ [] = []@@ -443,12 +461,28 @@ then return $ Just (p </> f) else findFile ps f -(&=) :: (ToYaml a, Monoid a, Eq a)- => Text -> a -> [(Text, YamlBuilder)] -> [(Text, YamlBuilder)]-x &= y = \acc -> if y == mempty- then acc- else (x Y..= y) : acc+class AddYaml a where+ (&=) :: Text -> a -> [(Text, YamlBuilder)] -> [(Text, YamlBuilder)] +instance ToYaml a => AddYaml [a] where+ x &= y = \acc -> if null y+ then acc+ else (x Y..= y) : acc++instance ToYaml a => AddYaml (Maybe a) where+ x &= y = \acc -> case y of+ Nothing -> acc+ Just z -> (x Y..= z) : acc++instance AddYaml Text where+ x &= y = \acc -> if T.null y+ then acc+ else (x Y..= y) : acc++instance AddYaml Bool where+ _ &= False = id+ x &= True = \acc -> (x Y..= Y.bool True) : acc+ mapping' :: [[(Text, YamlBuilder)] -> [(Text, YamlBuilder)]] -> YamlBuilder mapping' = Y.mapping . foldr ($) [] @@ -472,19 +506,19 @@ else lowercaseRomanDigits let [one, five, ten, fifty, hundred, fivehundred, thousand] = map P.char romanDigits- thousands <- P.many thousand >>= (return . (1000 *) . length)+ thousands <- ((1000 *) . length) <$> P.many thousand ninehundreds <- P.option 0 $ P.try $ hundred >> thousand >> return 900- fivehundreds <- P.many fivehundred >>= (return . (500 *) . length)+ fivehundreds <- ((500 *) . length) <$> P.many fivehundred fourhundreds <- P.option 0 $ P.try $ hundred >> fivehundred >> return 400- hundreds <- P.many hundred >>= (return . (100 *) . length)+ hundreds <- ((100 *) . length) <$> P.many hundred nineties <- P.option 0 $ P.try $ ten >> hundred >> return 90- fifties <- P.many fifty >>= (return . (50 *) . length)+ fifties <- ((50 *) . length) <$> P.many fifty forties <- P.option 0 $ P.try $ ten >> fifty >> return 40- tens <- P.many ten >>= (return . (10 *) . length)+ tens <- ((10 *) . length) <$> P.many ten nines <- P.option 0 $ P.try $ one >> ten >> return 9- fives <- P.many five >>= (return . (5 *) . length)+ fives <- ((5 *) . length) <$> P.many five fours <- P.option 0 $ P.try $ one >> five >> return 4- ones <- P.many one >>= (return . length)+ ones <- length <$> P.many one let total = thousands + ninehundreds + fivehundreds + fourhundreds + hundreds + nineties + fifties + forties + tens + nines + fives + fours + ones
stack.yaml view
@@ -10,4 +10,7 @@ - '.' extra-deps: - rfc5051-0.1.0.3-resolver: lts-10.0+- pandoc-2.1+- hslua-0.9.5+- skylighting-0.5.1+resolver: lts-10.2
tests/JSON.hs view
@@ -1,12 +1,12 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} -- ToJSON/FromJSON instances for Style module JSON where-import Data.Aeson-import Text.CSL.Style-import Text.CSL.Parser-import qualified Data.Text.Encoding as T+import Data.Aeson import qualified Data.ByteString.Lazy as L+import qualified Data.Text.Encoding as T+import Text.CSL.Parser+import Text.CSL.Style instance FromJSON Style where parseJSON (String s) = return $ parseCSL' $ L.fromChunks [T.encodeUtf8 s]- parseJSON _ = fail "Could not parse Style"+ parseJSON _ = fail "Could not parse Style"
tests/biblio2yaml/aksin.biblatex view
@@ -62,7 +62,7 @@ - family: Özkal given: Erhan issued:- - year: '2006'+ - year: 2006 title: Effect of immobilization on catalytic characteristics of saturated Pd-N-heterocyclic carbenes in Mizoroki-Heck reactions container-title: J. Organomet. Chem.
tests/biblio2yaml/almendro.biblatex view
@@ -54,7 +54,7 @@ - family: Nozal given: Fernando issued:- - year: '1998'+ - year: 1998 title: Elektromagnetisches Signalhorn jurisdiction: France; United Kingdom; Germany annote: This is a patent entry with a location field. The number is given in the
tests/biblio2yaml/angenendt.biblatex view
@@ -47,7 +47,7 @@ - family: Angenendt given: Arnold issued:- - year: '2002'+ - year: 2002 title: In Honore Salvatoris – Vom Sinn und Unsinn der Patrozinienkunde title-short: In Honore Salvatoris container-title: Revue d’Histoire Ecclésiastique
tests/biblio2yaml/aristotle-anima.biblatex view
@@ -46,7 +46,7 @@ - family: Hicks given: Robert Drew issued:- - year: '1907'+ - year: 1907 title: De anima publisher: Cambridge University Press publisher-place: Cambridge
tests/biblio2yaml/aristotle-physics.biblatex view
@@ -46,7 +46,7 @@ - family: Cornford given: F. M. issued:- - year: '1929'+ - year: 1929 title: Physics title-short: Physics publisher: G. P. Putnam
tests/biblio2yaml/aristotle-poetics.biblatex view
@@ -46,7 +46,7 @@ - family: Lucas given: D. W. issued:- - year: '1968'+ - year: 1968 title: Poetics title-short: Poetics collection-title: Clarendon Aristotle
tests/biblio2yaml/aristotle-rhetoric.biblatex view
@@ -60,7 +60,7 @@ - family: Cope given: Edward Meredith issued:- - year: '1877'+ - year: 1877 title: The rhetoric of Aristotle with a commentary by the late Edward Meredith Cope title-short: Rhetoric publisher: Cambridge University Press
tests/biblio2yaml/article.biblatex view
@@ -85,9 +85,9 @@ - family: Author given: Ann issued:- - year: '2013'- month: '7'- day: '29'+ - year: 2013+ month: 7+ day: 29 title: An article entry with just the required fields container-title: The Journaltitle language: en-US@@ -105,13 +105,13 @@ - family: Translator given: Ted issued:- - year: '2008'- month: '12'- day: '31'+ - year: 2008+ month: 12+ day: 31 accessed:- - year: '2013'- month: '7'- day: '29'+ - year: 2013+ month: 7+ day: 29 title: 'An article entry with the required and all optional fields: The subtitle. The titleaddon' title-short: An article entry with the required and all optional fields
tests/biblio2yaml/augustine.biblatex view
@@ -40,7 +40,7 @@ - family: Augustine given: Robert L. issued:- - year: '1995'+ - year: 1995 title: Heterogeneous catalysis for the synthetic chemist title-short: Heterogeneous catalysis publisher: Marcel Dekker
tests/biblio2yaml/averroes-bland.biblatex view
@@ -62,7 +62,7 @@ - family: Bland given: Kalman P. issued:- - year: '1982'+ - year: 1982 title: The epistle on the possibility of conjunction with the active intellect by Ibn Rushd with the commentary of Moses Narboni title-short: Possibility of conjunction
tests/biblio2yaml/averroes-hannes.biblatex view
@@ -64,7 +64,7 @@ - family: Hannes given: Ludwig issued:- - year: '1892'+ - year: 1892 title: 'Des Averroës Abhandlung: “Über die Möglichkeit der Conjunktion” oder “Über den materiellen Intellekt”' title-short: Über die Möglichkeit der Conjunktion
tests/biblio2yaml/averroes-hercz.biblatex view
@@ -64,7 +64,7 @@ - family: Hercz given: J. issued:- - year: '1869'+ - year: 1869 title: 'Drei Abhandlungen über die Conjunction des separaten Intellects mit dem Menschen: Von Averroes (Vater und Sohn), aus dem Arabischen übersetzt von Samuel Ibn Tibbon'
tests/biblio2yaml/baez-article.biblatex view
@@ -54,7 +54,7 @@ - family: Lauda given: Aaron D. issued:- - year: '2004'+ - year: 2004 title: 'Higher-dimensional algebra V: 2-groups' title-short: Higher-dimensional algebra V container-title: Theory and Applications of Categories
tests/biblio2yaml/baez-online.biblatex view
@@ -51,9 +51,9 @@ - family: Lauda given: Aaron D. issued:- - year: '2004'- month: '10'- day: '27'+ - year: 2004+ month: 10+ day: 27 title: 'Higher-dimensional algebra V: 2-groups' title-short: Higher-dimensional algebra V version: '3'
tests/biblio2yaml/basic.bibtex view
@@ -33,7 +33,7 @@ - family: Doe given: John issued:- - year: '2005'+ - year: 2005 title: First book publisher: Cambridge University Press publisher-place: Cambridge@@ -44,7 +44,7 @@ - family: Doe given: John issued:- - year: '2006'+ - year: 2006 title: Article container-title: Journal of Generic Studies page: '33-34'@@ -61,7 +61,7 @@ - family: Smith given: Sam issued:- - year: '2007'+ - year: 2007 title: Why water is wet container-title: Third book publisher: Oxford University Press
tests/biblio2yaml/bertram.biblatex view
@@ -48,7 +48,7 @@ - family: Wentworth given: Richard issued:- - year: '1996'+ - year: 1996 title: Gromov invariants for holomorphic maps on Riemann surfaces title-short: Gromov invariants container-title: J. Amer. Math. Soc.
tests/biblio2yaml/book-averroes.biblatex view
@@ -62,7 +62,7 @@ - family: Bland given: Kalman P. issued:- - year: '1982'+ - year: 1982 title: The epistle on the possibility of conjunction with the active intellect by Ibn Rushd with the commentary of Moses Narboni title-short: Possibility of conjunction@@ -87,7 +87,7 @@ - family: Hannes given: Ludwig issued:- - year: '1892'+ - year: 1892 title: 'Des Averroës Abhandlung: “Über die Möglichkeit der Conjunktion” oder “Über den materiellen Intellekt”' title-short: Über die Möglichkeit der Conjunktion@@ -110,7 +110,7 @@ - family: Hercz given: J. issued:- - year: '1869'+ - year: 1869 title: 'Drei Abhandlungen über die Conjunction des separaten Intellects mit dem Menschen: Von Averroes (Vater und Sohn), aus dem Arabischen übersetzt von Samuel Ibn Tibbon'
tests/biblio2yaml/book-coleridge.biblatex view
@@ -36,7 +36,7 @@ - family: Bate given: W. Jackson issued:- - year: '1983'+ - year: 1983 title: The collected works of Samuel Taylor Coleridge volume-title: Biographia literaria, or Biographical sketches of my literary life and opinions
tests/biblio2yaml/book-title-maintitle-series.biblatex view
@@ -22,7 +22,7 @@ - family: Author given: Al issued:- - year: '2013'+ - year: 2013 title: 'Maintitle: Mainsubtitle. Maintitleaddon' volume-title: 'Title of the Book: Subtitle. Titleaddon' collection-title: Series
tests/biblio2yaml/book-vazques-de-parga.biblatex view
@@ -29,7 +29,7 @@ - family: Uría Ríu given: Juan issued:- - year: '1993'+ - year: 1993 title: Las Peregrinaciones a Santiago de Compostela title-short: Peregrinaciones publisher: Iberdrola
tests/biblio2yaml/brandt.biblatex view
@@ -64,7 +64,7 @@ - family: Seibt given: Ferdinand issued:- - year: '1987'+ - year: 1987 title: Die nordischen Länder von der Mitte des 11. Jahrhunderts bis 1448 title-short: Die nordischen Länder container-title: Europa im Hoch- und Spätmittelalter
tests/biblio2yaml/britannica.biblatex view
@@ -62,7 +62,7 @@ - family: Preece given: Warren E. issued:- - year: '2003'+ - year: 2003 title: The new encyclopædia Britannica title-short: Encyclopædia Britannica publisher: Encyclopædia Britannica
tests/biblio2yaml/chiu.biblatex view
@@ -57,7 +57,7 @@ - family: Chow given: We Min issued:- - year: '1978'+ - year: 1978 title: A hybrid hierarchical model of a multiple virtual storage (MVS) operating system publisher: IBM
tests/biblio2yaml/cicero.biblatex view
@@ -63,7 +63,7 @@ - family: Blank-Sangmeister given: Ursula issued:- - year: '1995'+ - year: 1995 title: De natura deorum. Über das Wesen der Götter title-short: De natura deorum publisher: Reclam
tests/biblio2yaml/cms.biblatex view
@@ -57,7 +57,7 @@ - id: cms type: book issued:- - year: '2003'+ - year: 2003 title: 'The Chicago manual of style: The essential guide for writers, editors, and publishers' title-short: Chicago manual of style
tests/biblio2yaml/coleridge.biblatex view
@@ -63,7 +63,7 @@ - family: Bate given: W. Jackson issued:- - year: '1983'+ - year: 1983 title: The collected works of Samuel Taylor Coleridge volume-title: Biographia literaria, or Biographical sketches of my literary life and opinions
tests/biblio2yaml/companion.biblatex view
@@ -50,7 +50,7 @@ - family: Samarin given: Alexander issued:- - year: '1994'+ - year: 1994 title: The LaTeX companion title-short: LaTeX companion publisher: Addison-Wesley
tests/biblio2yaml/cotton.biblatex view
@@ -51,7 +51,7 @@ - family: Bochmann given: Manfred issued:- - year: '1999'+ - year: 1999 title: Advanced inorganic chemistry publisher: Wiley publisher-place: Chichester
tests/biblio2yaml/crossref-inbook-mvbook.biblatex view
@@ -31,7 +31,7 @@ container-author: - family: Shakespeare issued:- - year: '1975'+ - year: 1975 title: Macbeth \[title field of inbook-1\] container-title: Collected works \[title field of mvbook-1\] publisher: Publisher@@ -46,8 +46,8 @@ author: - family: Shakespeare issued:- - year: '1970'- - year: '1980'+ - year: 1970+ - year: 1980 title: Collected works \[title field of mvbook-1\] publisher: Publisher publisher-place: Location
tests/biblio2yaml/crossref-nested.biblatex view
@@ -43,7 +43,7 @@ container-author: - family: Shakespeare issued:- - year: '1975'+ - year: 1975 title: Macbeth \[title field of bookinbook-1\] container-title: Collected works \[title field of mvbook-1\] volume-title: Tragedies \[title field of book-1\]@@ -61,7 +61,7 @@ container-author: - family: Shakespeare issued:- - year: '1975'+ - year: 1975 title: Macbeth \[title field of inbook-1\] container-title: Collected works \[title field of mvbook-1\] volume-title: Tragedies \[title field of book-1\]@@ -79,7 +79,7 @@ container-author: - family: Shakespeare issued:- - year: '1975'+ - year: 1975 title: Collected works \[title field of mvbook-1\] volume-title: Tragedies \[title field of book-1\] publisher: Publisher@@ -92,8 +92,8 @@ author: - family: Shakespeare issued:- - year: '1970'- - year: '1980'+ - year: 1970+ - year: 1980 title: Collected works \[title field of mvbook-1\] publisher: Publisher publisher-place: Location
tests/biblio2yaml/ctan.biblatex view
@@ -52,11 +52,11 @@ - id: ctan type: webpage issued:- - year: '2006'+ - year: 2006 accessed:- - year: '2006'- month: '10'- day: '1'+ - year: 2006+ month: 10+ day: 1 title: 'CTAN: The Comprehensive TeX Archive Network' title-short: CTAN annote: This is an online entry. The <span style="font-variant:small-caps;">url</span>,
tests/biblio2yaml/dates.biblatex view
@@ -84,8 +84,8 @@ - family: Author given: Al issued:- - year: '1999'- month: '8'+ - year: 1999+ month: 8 title: Year and month, bibtex style, supported by biblatex for backwards compatibility container-title: Journal @@ -95,8 +95,8 @@ - family: Author given: Al issued:- - year: '1999'- month: '08'+ - year: 1999+ month: 8 title: Year and month, biblatex style; note that biblatex does not have a “day” field container-title: Journal@@ -107,21 +107,21 @@ - family: Author given: Al issued:- - year: '2012'- month: '12'- day: '13'+ - year: 2012+ month: 12+ day: 13 event-date:- - year: '2011'- month: '10'- day: '3'+ - year: 2011+ month: 10+ day: 3 accessed:- - year: '1999'- month: '5'- day: '23'+ - year: 1999+ month: 5+ day: 23 original-date:- - year: '1888'- month: '10'- day: '1'+ - year: 1888+ month: 10+ day: 1 title: Dates, default biblatex style; year, month to be ignored if date exists container-title: Journal @@ -131,31 +131,31 @@ - family: Author given: Al issued:- - year: '1999'- month: '10'- day: '14'- - year: '2010'- month: '1'- day: '23'+ - year: 1999+ month: 10+ day: 14+ - year: 2010+ month: 1+ day: 23 event-date:- - year: '1999'- month: '12'- - year: '2000'- month: '1'+ - year: 1999+ month: 12+ - year: 2000+ month: 1 accessed:- - year: '2012'- month: '10'- day: '12'- - year: '2013'- month: '1'- day: '31'+ - year: 2012+ month: 10+ day: 12+ - year: 2013+ month: 1+ day: 31 original-date:- - year: '1888'- month: '1'- day: '2'- - year: '1913'- month: '12'- day: '13'+ - year: 1888+ month: 1+ day: 2+ - year: 1913+ month: 12+ day: 13 title: Date ranges; different years container-title: Journal @@ -165,31 +165,31 @@ - family: Author given: Al issued:- - year: '1999'- month: '10'- day: '14'- - year: '1999'- month: '10'- day: '15'+ - year: 1999+ month: 10+ day: 14+ - year: 1999+ month: 10+ day: 15 event-date:- - year: '1999'- month: '10'- - year: '1999'- month: '11'+ - year: 1999+ month: 10+ - year: 1999+ month: 11 accessed:- - year: '2012'- month: '10'- day: '31'- - year: '2012'- month: '11'- day: '1'+ - year: 2012+ month: 10+ day: 31+ - year: 2012+ month: 11+ day: 1 original-date:- - year: '1888'- month: '1'- day: '2'- - year: '1888'- month: '12'- day: '13'+ - year: 1888+ month: 1+ day: 2+ - year: 1888+ month: 12+ day: 13 title: Date ranges; same year container-title: Journal @@ -199,23 +199,23 @@ - family: Author given: Al issued:- - year: '1999'- month: '10'- day: '14'+ - year: 1999+ month: 10+ day: 14 - {} event-date:- - year: '1999'- month: '10'+ - year: 1999+ month: 10 - {} accessed:- - year: '2012'- month: '10'- day: '31'+ - year: 2012+ month: 10+ day: 31 - {} original-date:- - year: '1888'- month: '1'- day: '2'+ - year: 1888+ month: 1+ day: 2 - {} title: Date ranges, open-ended container-title: Journal@@ -226,21 +226,21 @@ - family: Author given: Al issued:- - year: '712'- month: '12'- day: '13'+ - year: 712+ month: 12+ day: 13 event-date:- - year: '311'- month: '10'- day: '3'+ - year: 311+ month: 10+ day: 3 accessed:- - year: '999'- month: '12'- day: '14'+ - year: 999+ month: 12+ day: 14 original-date:- - year: '88'- month: '10'- day: '1'+ - year: 88+ month: 10+ day: 1 title: Dates, year less than 1000 container-title: Journal ...
tests/biblio2yaml/doody.biblatex view
@@ -69,7 +69,7 @@ - family: Doody given: Terrence issued:- - year: '1974'+ - year: 1974 title: Hemingway’s style and Jake’s narration container-title: The Journal of Narrative Technique page: '212-225'@@ -85,7 +85,7 @@ - family: Matuz given: Roger issued:- - year: '1990'+ - year: 1990 title: Contemporary literary criticism publisher: Gale publisher-place: Detroit
tests/biblio2yaml/edtf-date.biblatex view
@@ -18,81 +18,81 @@ - id: item3-3 type: article-journal issued:- - year: '1998'+ - year: 1998 - {} - id: item3-4 type: article-journal issued:- - year: '1999'+ - year: 1999 - {} - id: item3-10 type: article-journal issued:- - year: '2004'- month: '4'- day: '5'+ - year: 2004+ month: 4+ day: 5 - id: item5-1 type: article-journal issued:- - year: '-1'+ - year: -1 - id: item5-2 type: article-journal issued:- - year: '-877'+ - year: -877 - id: item5-3 type: article-journal issued:- - year: '-878'- - year: '-867'+ - year: -878+ - year: -867 - id: item5-5 type: article-journal issued:- - year: '-344'- month: '2'+ - year: -344+ month: 2 - id: item5-8 type: article-journal issued:- - year: '1723'- circa: '1'+ - year: 1723+ circa: true - id: item5-9 type: article-journal issued:- - year: '1723'+ - year: 1723 - id: item5-10 type: article-journal issued:- - year: '1723'- circa: '1'+ - year: 1723+ circa: true - id: item5-11 type: article-journal issued:- - year: '2004'- season: '2'+ - year: 2004+ season: 2 - id: item5-12 type: article-journal issued:- - year: '2004'- season: '4'+ - year: 2004+ season: 4 - id: item5-13 type: article-journal issued:- - year: '2000'- - year: '2099'+ - year: 2000+ - year: 2099 - id: item5-14 type: article-journal issued:- - year: '-123456790'+ - year: -123456790 ...
tests/biblio2yaml/gaonkar-in.biblatex view
@@ -46,7 +46,7 @@ - family: Gaonkar given: Dilip Parameshwar issued:- - year: '2001'+ - year: 2001 title: On alternative modernities container-title: Alternative modernities publisher: Duke University Press
tests/biblio2yaml/gaonkar.biblatex view
@@ -42,7 +42,7 @@ - family: Gaonkar given: Dilip Parameshwar issued:- - year: '2001'+ - year: 2001 title: Alternative modernities publisher: Duke University Press publisher-place: Durham; London
tests/biblio2yaml/geer.biblatex view
@@ -49,7 +49,7 @@ given: Ingrid dropping-particle: de issued:- - year: '1985'+ - year: 1985 title: 'Earl, saint, bishop, skald – and music: The Orkney earldom of the twelfth century. A musicological study' title-short: Earl, saint, bishop, skald – and music
tests/biblio2yaml/gerhardt.biblatex view
@@ -46,7 +46,7 @@ - family: Gerhardt given: Michael J. issued:- - year: '2000'+ - year: 2000 title: 'The federal appointments process: A constitutional and historical analysis' title-short: Federal appointments process publisher: Duke University Press
tests/biblio2yaml/gillies.biblatex view
@@ -51,7 +51,7 @@ - family: Gillies given: Alexander issued:- - year: '1933'+ - year: 1933 title: Herder and the preparation of Goethe’s idea of world literature container-title: Publications of the English Goethe Society collection-title: new series
tests/biblio2yaml/glashow.biblatex view
@@ -37,7 +37,7 @@ - family: Glashow given: Sheldon issued:- - year: '1961'+ - year: 1961 title: Partial symmetries of weak interactions container-title: Nucl. Phys. page: '579-588'
tests/biblio2yaml/gonzalez.biblatex view
@@ -43,7 +43,7 @@ - family: Gonzalez given: Ray issued:- - year: '2001'+ - year: 2001 title: The ghost of John Wayne and other stories title-short: Ghost of John Wayne publisher: The University of Arizona Press
tests/biblio2yaml/hammond.biblatex view
@@ -45,7 +45,7 @@ - family: Hammond given: Christopher issued:- - year: '1997'+ - year: 1997 title: The basics of crystallography and diffraction title-short: Crystallography and diffraction publisher: International Union of Crystallography; Oxford University Press
tests/biblio2yaml/herrmann.biblatex view
@@ -54,7 +54,7 @@ - family: Hoffmann given: Stephan D. issued:- - year: '2006'+ - year: 2006 title: A carbocyclic carbene as an efficient catalyst ligand for C–C coupling reactions container-title: Angew. Chem. Int. Ed. page: '3859-3862'
tests/biblio2yaml/hyman.biblatex view
@@ -57,7 +57,7 @@ - family: O’Meara given: Dominic J. issued:- - year: '1981'+ - year: 1981 title: Aristotle’s theory of the intellect and its interpretation by Averroes title-short: Aristotle’s theory of the intellect container-title: Studies in Aristotle
tests/biblio2yaml/iliad.biblatex view
@@ -49,7 +49,7 @@ - family: Schadewaldt given: Wolfgang issued:- - year: '2004'+ - year: 2004 title: Die Ilias title-short: Ilias publisher: Artemis & Winkler
tests/biblio2yaml/inbook-title-booktitle-maintitle-series-2.biblatex view
@@ -29,7 +29,7 @@ - family: Bookauthor given: Bob issued:- - year: '2011'+ - year: 2011 title: 'Title of the “inbook” Entry: Subtitle. Titleaddon' container-title: 'Maintitle: Mainsubtitle. Maintitleaddon' volume-title: 'Booktitle: Booksubtitle. Booktitleaddon'
tests/biblio2yaml/inbook-title-booktitle-maintitle-series.biblatex view
@@ -25,7 +25,7 @@ - family: Author given: Al issued:- - year: '2011'+ - year: 2011 title: 'Title of the “inbook” Entry: Subtitle. Titleaddon' container-title: 'Maintitle: Mainsubtitle. Maintitleaddon' volume-title: 'Booktitle: Booksubtitle. Booktitleaddon'
tests/biblio2yaml/inbook.biblatex view
@@ -70,7 +70,7 @@ - family: Kant given: Immanuel issued:- - year: '1968'+ - year: 1968 title: Kritik der praktischen Vernunft title-short: Kritik der praktischen Vernunft container-title: Kants Werke. Akademie Textausgabe@@ -95,7 +95,7 @@ - family: Kant given: Immanuel issued:- - year: '1968'+ - year: 1968 title: Kritik der Urtheilskraft container-title: Kants Werke. Akademie Textausgabe volume-title: Kritik der praktischen Vernunft. Kritik der Urtheilskraft@@ -122,7 +122,7 @@ - family: Nietzsche given: Friedrich issued:- - year: '1988'+ - year: 1988 title: 'Unzeitgemässe Betrachtungen. Zweites Stück: Vom Nutzen und Nachtheil der Historie für das Leben' title-short: Vom Nutzen und Nachtheil der Historie
tests/biblio2yaml/incollection-2.biblatex view
@@ -48,7 +48,7 @@ - family: Westfahl given: Gary issued:- - year: '2000'+ - year: 2000 title: 'The true frontier: Confronting and avoiding the realities of space in American science fiction films' title-short: The true frontier@@ -69,7 +69,7 @@ - family: Gaonkar given: Dilip Parameshwar issued:- - year: '2001'+ - year: 2001 title: On alternative modernities container-title: Alternative modernities publisher: Duke University Press@@ -83,7 +83,7 @@ - family: Westfahl given: Gary issued:- - year: '2000'+ - year: 2000 title: 'Space and beyond: The frontier theme in science fiction' title-short: Space and beyond publisher: Greenwood
tests/biblio2yaml/incollection.biblatex view
@@ -66,7 +66,7 @@ - family: Seibt given: Ferdinand issued:- - year: '1987'+ - year: 1987 title: Die nordischen Länder von der Mitte des 11. Jahrhunderts bis 1448 title-short: Die nordischen Länder container-title: Europa im Hoch- und Spätmittelalter@@ -89,7 +89,7 @@ - family: O’Meara given: Dominic J. issued:- - year: '1981'+ - year: 1981 title: Aristotle’s theory of the intellect and its interpretation by Averroes title-short: Aristotle’s theory of the intellect container-title: Studies in Aristotle@@ -111,7 +111,7 @@ - family: Twersky given: Isadore issued:- - year: '1979'+ - year: 1979 title: The limitations of human knowledge according to Al-Farabi, <span class="nocase">ibn Bajja</span>, and Maimonides title-short: Limitations of human knowledge
tests/biblio2yaml/inproceedings.biblatex view
@@ -47,9 +47,9 @@ - family: Owen given: G. E. L. issued:- - year: '1979'+ - year: 1979 event-date:- - year: '1975'+ - year: 1975 title: 'Le *De Anima* dans la tradition grècque: Quelques aspects de l’interpretation du traité, de Theophraste à Themistius' title-short: '*De Anima* dans la tradition grècque'@@ -72,14 +72,14 @@ - family: Svartholm given: Nils issued:- - year: '1968'+ - year: 1968 event-date:- - year: '1968'- month: '5'- day: '19'- - year: '1968'- month: '5'- day: '25'+ - year: 1968+ month: 5+ day: 19+ - year: 1968+ month: 5+ day: 25 title: Weak and electromagnetic interactions container-title: 'Elementary particle theory: Relativistic groups and analyticity. Proceedings of the eighth Nobel symposium'
tests/biblio2yaml/issue288.biblatex view
@@ -18,8 +18,8 @@ - family: Leavitt given: Alex issued:- - year: '2016'- month: '8'+ - year: 2016+ month: 8 title: 'Upvoting the news: Breaking news aggregation, crowd collaboration, and algorithm-driven attention on reddit.com' title-short: Upvoting the news
tests/biblio2yaml/itzhaki.biblatex view
@@ -59,9 +59,9 @@ - family: Itzhaki given: Nissan issued:- - year: '1996'- month: '3'- day: '11'+ - year: 1996+ month: 3+ day: 11 title: Some remarks on ’<span class="nocase">t Hooft’s</span> S-matrix for black holes version: '1'
tests/biblio2yaml/jaffe.biblatex view
@@ -63,8 +63,8 @@ - family: Jaffé given: Philipp issued:- - year: '1885'- - year: '1888'+ - year: 1885+ - year: 1888 title: Regesta Pontificum Romanorum ab condita ecclesia ad annum post Christum natum <span style="font-variant:small-caps;">mcxcviii</span> title-short: Regesta Pontificum Romanorum
tests/biblio2yaml/jcg.biblatex view
@@ -38,7 +38,7 @@ - id: jcg type: article-journal issued:- - year: '2011'+ - year: 2011 title: Semantic 3D media and content container-title: Computers and Graphics volume: '35'
tests/biblio2yaml/kant-kpv.biblatex view
@@ -64,7 +64,7 @@ - family: Kant given: Immanuel issued:- - year: '1968'+ - year: 1968 title: Kritik der praktischen Vernunft title-short: Kritik der praktischen Vernunft container-title: Kants Werke. Akademie Textausgabe
tests/biblio2yaml/kant-ku.biblatex view
@@ -60,7 +60,7 @@ - family: Kant given: Immanuel issued:- - year: '1968'+ - year: 1968 title: Kritik der Urtheilskraft container-title: Kants Werke. Akademie Textausgabe volume-title: Kritik der praktischen Vernunft. Kritik der Urtheilskraft
tests/biblio2yaml/kastenholz.biblatex view
@@ -85,7 +85,7 @@ - family: Hünenberger given: Philippe H. issued:- - year: '2006'+ - year: 2006 title: 'Computation of methodology-independent ionic solvation free energies from molecular simulations: I. The electrostatic potential in molecular liquids' title-short: Computation of methodology-independent ionic solvation free energies
tests/biblio2yaml/knuth-ct-a.biblatex view
@@ -56,7 +56,7 @@ - family: Knuth given: Donald E. issued:- - year: '1984'+ - year: 1984 title: Computers & typesetting volume-title: The TeX book publisher: Addison-Wesley
tests/biblio2yaml/knuth-ct-b.biblatex view
@@ -51,7 +51,7 @@ - family: Knuth given: Donald E. issued:- - year: '1986'+ - year: 1986 title: Computers & typesetting title-short: TeX volume-title: 'TeX: The program'
tests/biblio2yaml/knuth-ct-c.biblatex view
@@ -51,7 +51,7 @@ - family: Knuth given: Donald E. issued:- - year: '1986'+ - year: 1986 title: Computers & typesetting volume-title: The METAFONTbook publisher: Addison-Wesley
tests/biblio2yaml/knuth-ct-d.biblatex view
@@ -52,7 +52,7 @@ - family: Knuth given: Donald E. issued:- - year: '1986'+ - year: 1986 title: Computers & typesetting title-short: METAFONT volume-title: 'METAFONT: The program'
tests/biblio2yaml/knuth-ct-e.biblatex view
@@ -48,7 +48,7 @@ - family: Knuth given: Donald E. issued:- - year: '1986'+ - year: 1986 title: Computers & typesetting volume-title: Computer modern typefaces publisher: Addison-Wesley
@@ -55,8 +55,8 @@ - family: Knuth given: Donald E. issued:- - year: '1984'- - year: '1986'+ - year: 1984+ - year: 1986 title: Computers & typesetting publisher: Addison-Wesley publisher-place: Reading, Mass.
tests/biblio2yaml/knuth-ct.biblatex view
@@ -49,8 +49,8 @@ - family: Knuth given: Donald E. issued:- - year: '1984'- - year: '1986'+ - year: 1984+ - year: 1986 title: Computers & typesetting publisher: Addison-Wesley publisher-place: Reading, Mass.
tests/biblio2yaml/kowalik.biblatex view
@@ -49,9 +49,9 @@ - family: Isard given: M. issued:- - year: '1995'- month: '1'- day: '11'+ - year: 1995+ month: 1+ day: 11 title: Estimateur d’un défaut de fonctionnement d’un modulateur en quadrature et étage de modulation l’utilisant genre: French patent request
@@ -46,7 +46,7 @@ - family: Kullback given: Solomon issued:- - year: '1997'+ - year: 1997 title: Information theory and statistics publisher: Dover Publications publisher-place: New York
tests/biblio2yaml/kullback-reprint.biblatex view
@@ -52,9 +52,9 @@ - family: Kullback given: Solomon issued:- - year: '1997'+ - year: 1997 original-date:- - year: '1959'+ - year: 1959 title: Information theory and statistics publisher: Dover Publications original-publisher: John Wiley & Sons
tests/biblio2yaml/kullback.biblatex view
@@ -38,7 +38,7 @@ - family: Kullback given: Solomon issued:- - year: '1959'+ - year: 1959 title: Information theory and statistics publisher: John Wiley & Sons publisher-place: New York
tests/biblio2yaml/laufenberg.biblatex view
@@ -85,9 +85,9 @@ - family: Ebner given: Norbert issued:- - year: '2006'- month: '9'- day: '13'+ - year: 2006+ month: 9+ day: 13 title: Elektrische Einrichtung und Betriebsverfahren genre: European patent annote: This is a patent entry with a holder field. Note the format of the type
tests/biblio2yaml/loh.biblatex view
@@ -48,7 +48,7 @@ - family: Loh given: Nin C. issued:- - year: '1992'+ - year: 1992 title: High-resolution micromachined interferometric accelerometer publisher: Massachusetts Institute of Technology publisher-place: Cambridge, Mass.
tests/biblio2yaml/malinowski.biblatex view
@@ -47,7 +47,7 @@ - family: Malinowski given: Bronisław issued:- - year: '1972'+ - year: 1972 title: 'Argonauts of the Western Pacific: An account of native enterprise and adventure in the <span class="nocase">Archipelagoes of Melanesian New Guinea</span>' title-short: Argonauts
tests/biblio2yaml/manual.biblatex view
@@ -27,7 +27,7 @@ - id: cms type: book issued:- - year: '2003'+ - year: 2003 title: 'The Chicago manual of style: The essential guide for writers, editors, and publishers' title-short: Chicago manual of style
tests/biblio2yaml/markey.biblatex view
@@ -47,13 +47,13 @@ - family: Markey given: Nicolas issued:- - year: '2005'- month: '10'- day: '16'+ - year: 2005+ month: 10+ day: 16 accessed:- - year: '2006'- month: '10'- day: '1'+ - year: 2006+ month: 10+ day: 1 title: 'Tame the BeaST: The B to X of BibTeX' title-short: Tame the BeaST version: '1.3'
tests/biblio2yaml/maron.biblatex view
@@ -52,7 +52,7 @@ - family: Goldstein given: Brigitte issued:- - year: '2000'+ - year: 2000 title: Animal triste title-short: Animal triste publisher: University of Nebraska Press
tests/biblio2yaml/massa.biblatex view
@@ -40,7 +40,7 @@ - family: Massa given: Werner issued:- - year: '2004'+ - year: 2004 title: Crystal structure determination publisher: Spinger publisher-place: Berlin
@@ -48,7 +48,7 @@ - family: Moore given: Gordon E. issued:- - year: '1998'+ - year: 1998 title: Cramming more components onto integrated circuits container-title: Proceedings of the IEEE page: '82-85'
tests/biblio2yaml/moore.biblatex view
@@ -40,7 +40,7 @@ - family: Moore given: Gordon E. issued:- - year: '1965'+ - year: 1965 title: Cramming more components onto integrated circuits container-title: Electronics page: '114-117'
tests/biblio2yaml/moraux.biblatex view
@@ -70,9 +70,9 @@ - family: Owen given: G. E. L. issued:- - year: '1979'+ - year: 1979 event-date:- - year: '1975'+ - year: 1975 title: 'Le *De Anima* dans la tradition grècque: Quelques aspects de l’interpretation du traité, de Theophraste à Themistius' title-short: '*De Anima* dans la tradition grècque'
tests/biblio2yaml/murray.biblatex view
@@ -83,7 +83,7 @@ - family: Murray given: Royce W. issued:- - year: '1998'+ - year: 1998 title: 'Alkanethiolate gold cluster molecules with core diameters from 1.5 to 5.2 <span class="nocase">nm</span>: Core and monolayer properties as a function of core size'
tests/biblio2yaml/nietzsche-historie.biblatex view
@@ -74,7 +74,7 @@ - family: Nietzsche given: Friedrich issued:- - year: '1988'+ - year: 1988 title: 'Unzeitgemässe Betrachtungen. Zweites Stück: Vom Nutzen und Nachtheil der Historie für das Leben' title-short: Vom Nutzen und Nachtheil der Historie
tests/biblio2yaml/nietzsche-ksa.biblatex view
@@ -66,7 +66,7 @@ - family: Montinari given: Mazzino issued:- - year: '1988'+ - year: 1988 title: 'Sämtliche Werke: Kritische Studienausgabe' title-short: Sämtliche Werke publisher: Deutscher Taschenbuch-Verlag; Walter de Gruyter
tests/biblio2yaml/nietzsche-ksa1.biblatex view
@@ -72,7 +72,7 @@ - family: Nietzsche given: Friedrich issued:- - year: '1988'+ - year: 1988 title: 'Sämtliche Werke: Kritische Studienausgabe' volume-title: Die Geburt der Tragödie. Unzeitgemäße Betrachtungen I–IV. Nachgelassene Schriften 1870–1973
tests/biblio2yaml/nussbaum.biblatex view
@@ -46,7 +46,7 @@ - family: Nussbaum given: Martha issued:- - year: '1978'+ - year: 1978 title: Aristotle’s “De Motu Animalium” publisher: Princeton University Press publisher-place: Princeton
tests/biblio2yaml/online.biblatex view
@@ -32,13 +32,13 @@ - family: Markey given: Nicolas issued:- - year: '2005'- month: '10'- day: '16'+ - year: 2005+ month: 10+ day: 16 accessed:- - year: '2006'- month: '10'- day: '1'+ - year: 2006+ month: 10+ day: 1 title: 'Tame the BeaST: The B to X of BibTeX' title-short: Tame the BeaST version: '1.3'@@ -50,11 +50,11 @@ - id: CTAN type: webpage issued:- - year: '2006'+ - year: 2006 accessed:- - year: '2006'- month: '10'- day: '1'+ - year: 2006+ month: 10+ day: 1 title: 'CTAN: The Comprehensive TeX Archive Network' title-short: CTAN annote: This is an online entry. The <span style="font-variant:small-caps;">url</span>,
tests/biblio2yaml/options-url-false-doi-false.biblatex view
@@ -36,7 +36,7 @@ - family: Author given: Andy issued:- - year: '2012'+ - year: 2012 title: Title, any entry type except online container-title: Journal @@ -46,7 +46,7 @@ - family: Author given: Andy issued:- - year: '2012'+ - year: 2012 title: Title, entry type online container-title: Journal URL: http://foo.bar
tests/biblio2yaml/padhye.biblatex view
@@ -77,7 +77,7 @@ - family: Towsley given: Don issued:- - year: '1999'+ - year: 1999 title: A stochastic model of TCP Reno congestion avoidance and control publisher: University of Massachusetts publisher-place: Amherst, Mass.
tests/biblio2yaml/pandoc-2/ctan.biblatex view
@@ -52,11 +52,11 @@ - id: ctan type: webpage issued:- - year: '2006'+ - year: 2006 accessed:- - year: '2006'- month: '10'- day: '1'+ - year: 2006+ month: 10+ day: 1 title: 'CTAN: The Comprehensive TeX Archive Network' title-short: CTAN annote: This is an online entry. The <span class="smallcaps">url</span>, which is
tests/biblio2yaml/pandoc-2/jaffe.biblatex view
@@ -63,8 +63,8 @@ - family: Jaffé given: Philipp issued:- - year: '1885'- - year: '1888'+ - year: 1885+ - year: 1888 title: Regesta Pontificum Romanorum ab condita ecclesia ad annum post Christum natum <span class="smallcaps">mcxcviii</span> title-short: Regesta Pontificum Romanorum
tests/biblio2yaml/pandoc-2/kastenholz.biblatex view
@@ -85,7 +85,7 @@ - family: Hünenberger given: Philippe H. issued:- - year: '2006'+ - year: 2006 title: 'Computation of methodology-independent ionic solvation free energies from molecular simulations: I. The electrostatic potential in molecular liquids' title-short: Computation of methodology-independent ionic solvation free energies
tests/biblio2yaml/pandoc-2/online.biblatex view
@@ -32,13 +32,13 @@ - family: Markey given: Nicolas issued:- - year: '2005'- month: '10'- day: '16'+ - year: 2005+ month: 10+ day: 16 accessed:- - year: '2006'- month: '10'- day: '1'+ - year: 2006+ month: 10+ day: 1 title: 'Tame the BeaST: The B to X of BibTeX' title-short: Tame the BeaST version: '1.3'@@ -50,11 +50,11 @@ - id: CTAN type: webpage issued:- - year: '2006'+ - year: 2006 accessed:- - year: '2006'- month: '10'- day: '1'+ - year: 2006+ month: 10+ day: 1 title: 'CTAN: The Comprehensive TeX Archive Network' title-short: CTAN annote: This is an online entry. The <span class="smallcaps">url</span>, which is
tests/biblio2yaml/pandoc-2/sigfridsson.biblatex view
@@ -72,7 +72,7 @@ - family: Ryde given: Ulf issued:- - year: '1998'+ - year: 1998 title: Comparison of methods for deriving atomic charges from the electrostatic potential and moments container-title: Journal of Computational Chemistry
tests/biblio2yaml/patent.biblatex view
@@ -65,7 +65,7 @@ - family: Nozal given: Fernando issued:- - year: '1998'+ - year: 1998 title: Elektromagnetisches Signalhorn jurisdiction: France; United Kingdom; Germany annote: This is a patent entry with a location field. The number is given in the@@ -82,9 +82,9 @@ - family: Isard given: M. issued:- - year: '1995'- month: '1'- day: '11'+ - year: 1995+ month: 1+ day: 11 title: Estimateur d’un défaut de fonctionnement d’un modulateur en quadrature et étage de modulation l’utilisant genre: French patent request@@ -122,9 +122,9 @@ - family: Ebner given: Norbert issued:- - year: '2006'- month: '9'- day: '13'+ - year: 2006+ month: 9+ day: 13 title: Elektrische Einrichtung und Betriebsverfahren genre: European patent annote: This is a patent entry with a holder field. Note the format of the type@@ -147,9 +147,9 @@ - family: Vaughn given: Steven A. issued:- - year: '1997'- month: '9'- day: '16'+ - year: 1997+ month: 9+ day: 16 title: High-speed digital-to-RF converter genre: U.S. patent annote: This is a patent entry with a holder field. Note the format of the type
tests/biblio2yaml/periodical.biblatex view
@@ -14,7 +14,7 @@ - id: jcg type: article-journal issued:- - year: '2011'+ - year: 2011 title: Semantic 3D media and content container-title: Computers and Graphics volume: '35'
tests/biblio2yaml/piccato.biblatex view
@@ -42,7 +42,7 @@ - family: Piccato given: Pablo issued:- - year: '2001'+ - year: 2001 title: 'City of suspects: Crime in Mexico City, 1900–1931' title-short: City of suspects publisher: Duke University Press
tests/biblio2yaml/pines.biblatex view
@@ -57,7 +57,7 @@ - family: Twersky given: Isadore issued:- - year: '1979'+ - year: 1979 title: The limitations of human knowledge according to Al-Farabi, <span class="nocase">ibn Bajja</span>, and Maimonides title-short: Limitations of human knowledge
tests/biblio2yaml/quotes.biblatex view
@@ -27,7 +27,7 @@ - family: Nussbaum given: Martha issued:- - year: '1978'+ - year: 1978 title: Aristotle’s “De Motu Animalium” publisher: Princeton University Press publisher-place: Princeton
tests/biblio2yaml/reese.biblatex view
@@ -51,7 +51,7 @@ - family: Reese given: Trevor R. issued:- - year: '1958'+ - year: 1958 title: Georgia in Anglo-Spanish diplomacy, 1736-1739 container-title: William and Mary Quarterly collection-title: 3rd ser.
tests/biblio2yaml/report.biblatex view
@@ -59,7 +59,7 @@ - family: Chow given: We Min issued:- - year: '1978'+ - year: 1978 title: A hybrid hierarchical model of a Multiple Virtual Storage (MVS) operating system publisher: IBM@@ -80,7 +80,7 @@ - family: Towsley given: Don issued:- - year: '1999'+ - year: 1999 title: A stochastic model of TCP Reno congestion avoidance and control publisher: University of Massachusetts publisher-place: Amherst, Mass.
tests/biblio2yaml/salam.biblatex view
@@ -51,14 +51,14 @@ - family: Svartholm given: Nils issued:- - year: '1968'+ - year: 1968 event-date:- - year: '1968'- month: '5'- day: '19'- - year: '1968'- month: '5'- day: '25'+ - year: 1968+ month: 5+ day: 19+ - year: 1968+ month: 5+ day: 25 title: Weak and electromagnetic interactions container-title: 'Elementary particle theory: Relativistic groups and analyticity. Proceedings of the eighth Nobel symposium'
tests/biblio2yaml/sarfraz.biblatex view
@@ -46,7 +46,7 @@ - family: Razzak given: M. F. A. issued:- - year: '2002'+ - year: 2002 title: 'Technical section: An algorithm for automatic capturing of the font outlines' title-short: Technical section container-title: Computers and Graphics
tests/biblio2yaml/shore.biblatex view
@@ -46,8 +46,8 @@ - family: Shore given: Bradd issued:- - year: '1991'- month: '3'+ - year: 1991+ month: 3 title: 'Twice-born, once conceived: Meaning construction and cultural cognition' title-short: Twice-born, once conceived container-title: American Anthropologist
tests/biblio2yaml/sigfridsson.biblatex view
@@ -72,7 +72,7 @@ - family: Ryde given: Ulf issued:- - year: '1998'+ - year: 1998 title: Comparison of methods for deriving atomic charges from the electrostatic potential and moments container-title: Journal of Computational Chemistry
tests/biblio2yaml/sorace.biblatex view
@@ -48,9 +48,9 @@ - family: Vaughn given: Steven A. issued:- - year: '1997'- month: '9'- day: '16'+ - year: 1997+ month: 9+ day: 16 title: High-speed digital-to-RF converter genre: U.S. patent annote: This is a patent entry with a holder field. Note the format of the type
tests/biblio2yaml/spiegelberg.biblatex view
@@ -55,7 +55,7 @@ - family: Spiegelberg given: Herbert issued:- - year: '1969'+ - year: 1969 title: “Intention” und “Intentionalität” in der Scholastik, bei Brentano und Husserl title-short: Intention und Intentionalität container-title: Studia Philosophica
tests/biblio2yaml/springer.biblatex view
@@ -41,7 +41,7 @@ - family: Springer given: Otto issued:- - year: '1950'+ - year: 1950 title: Mediaeval pilgrim routes from Scandinavia to Rome title-short: Mediaeval pilgrim routes container-title: Mediaeval Studies
tests/biblio2yaml/strings.biblatex view
@@ -29,7 +29,7 @@ - family: Hoffmann given: Stephan D. issued:- - year: '2006'+ - year: 2006 title: A carbocyclic carbene as an efficient catalyst ligand for C–C coupling reactions container-title: Angew. Chem. Int. Ed. page: '3859-3862'
tests/biblio2yaml/test-case-conversion.biblatex view
@@ -58,7 +58,7 @@ - family: Author given: Ann issued:- - year: '2013'+ - year: 2013 title: A title, in English, with a Proper Name and an ACRONYM and a <span class="nocase">camelCase</span> word and some units, 400 <span class="nocase">nm</span>, 3 <span class="nocase">cm</span>, and a quote, *Alea <span class="nocase">iacta est</span>*
tests/biblio2yaml/thesis.biblatex view
@@ -34,7 +34,7 @@ given: Ingrid dropping-particle: de issued:- - year: '1985'+ - year: 1985 title: 'Earl, saint, bishop, skald – and music: The Orkney earldom of the twelfth century. A musicological study' title-short: Earl, saint, bishop, skald – and music@@ -52,7 +52,7 @@ - family: Loh given: Nin C. issued:- - year: '1992'+ - year: 1992 title: High-resolution micromachined interferometric accelerometer publisher: Massachusetts Institute of Technology publisher-place: Cambridge, Mass.
@@ -52,7 +52,7 @@ given: Arnold non-dropping-particle: van issued:- - year: '1909'+ - year: 1909 title: Les rites de passage title-short: Rites de passage publisher: Nourry
tests/biblio2yaml/vangennep-trans.biblatex view
@@ -53,7 +53,7 @@ - family: Caffee given: Gabrielle L. issued:- - year: '1960'+ - year: 1960 title: The rites of passage title-short: Rites of passage publisher: University of Chicago Press
tests/biblio2yaml/vangennep.biblatex view
@@ -44,7 +44,7 @@ given: Arnold non-dropping-particle: van issued:- - year: '1909'+ - year: 1909 title: Les rites de passage title-short: Rites de passage publisher: Nourry
tests/biblio2yaml/vazques-de-parga-mvbook.biblatex view
@@ -56,7 +56,7 @@ - family: Uría Ríu given: Juan issued:- - year: '1993'+ - year: 1993 title: Las Peregrinaciones a Santiago de Compostela title-short: Peregrinaciones publisher: Iberdrola
tests/biblio2yaml/vazques-de-parga.biblatex view
@@ -55,7 +55,7 @@ - family: Uría Ríu given: Juan issued:- - year: '1993'+ - year: 1993 title: Las Peregrinaciones a Santiago de Compostela title-short: Peregrinaciones publisher: Iberdrola
@@ -52,7 +52,7 @@ - family: Caffee given: Gabrielle L. issued:- - year: '1960'+ - year: 1960 title: The rites of passage title-short: Rites of passage publisher: University of Chicago Press
tests/biblio2yaml/wassenberg.biblatex view
@@ -58,9 +58,9 @@ - family: Sanders given: Peter issued:- - year: '2010'- month: '8'- day: '17'+ - year: 2010+ month: 8+ day: 17 title: Faster radix sort via virtual memory and write-combining version: '1' annote: A recent online reference from arXiv using the new (April 2007 onward) identifier
tests/biblio2yaml/weinberg.biblatex view
@@ -38,7 +38,7 @@ - family: Weinberg given: Steven issued:- - year: '1967'+ - year: 1967 title: A model of leptons container-title: Phys. Rev. Lett. page: '1264-1266'
tests/biblio2yaml/westfahl-frontier.biblatex view
@@ -43,7 +43,7 @@ - family: Westfahl given: Gary issued:- - year: '2000'+ - year: 2000 title: 'Space and beyond: The frontier theme in science fiction' title-short: Space and beyond publisher: Greenwood
tests/biblio2yaml/westfahl-space.biblatex view
@@ -71,7 +71,7 @@ - family: Westfahl given: Gary issued:- - year: '2000'+ - year: 2000 title: 'The true frontier: Confronting and avoiding the realities of space in American science fiction films' title-short: The true frontier@@ -89,7 +89,7 @@ - family: Westfahl given: Gary issued:- - year: '2000'+ - year: 2000 title: 'Space and beyond: The frontier theme in science fiction' title-short: Space and beyond publisher: Greenwood
tests/biblio2yaml/wilde.biblatex view
@@ -48,7 +48,7 @@ - family: Wilde given: Oscar issued:- - year: '1899'+ - year: 1899 title: 'The importance of being earnest: A trivial comedy for serious people' title-short: The importance of being earnest collection-title: English and american drama of the nineteenth century
tests/biblio2yaml/worman.biblatex view
@@ -44,7 +44,7 @@ - family: Worman given: Nancy issued:- - year: '2002'+ - year: 2002 title: 'The cast of character: Style in Greek literature' title-short: Cast of character publisher: University of Texas Press
tests/biblio2yaml/yoon.biblatex view
@@ -50,7 +50,7 @@ - family: Ahn given: Kyo Han issued:- - year: '2006'+ - year: 2006 title: 'Palladium pincer complexes with reduced bond angle strain: Efficient catalysts for the Heck reaction' title-short: Palladium pincer complexes with reduced bond angle strain
+ tests/issue250.expected.native view
@@ -0,0 +1,5 @@+Pandoc (Meta {unMeta = fromList [("link-citations",MetaBool True),("references",MetaList [MetaMap (fromList [("author",MetaMap (fromList [("family",MetaInlines [Str "Doe"])])),("id",MetaInlines [Str "doe"]),("title",MetaInlines [Str "Title"])])])]})+[Para [Cite [Citation {citationId = "doe", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 1}] [Str "(Doe,",Space,Link ("",[],[]) [Str "n.d."] ("#ref-doe",""),Str ")"]]+,Div ("refs",["references"],[])+ [Div ("ref-doe",[],[])+ [Para [Str "Doe.",Space,Str "n.d.",Space,Str "\8220Title.\8221"]]]]
+ tests/issue250.in.native view
@@ -0,0 +1,2 @@+Pandoc (Meta {unMeta = fromList [("link-citations",MetaBool True),("references",MetaList [MetaMap (fromList [("author",MetaMap (fromList [("family",MetaInlines [Str "Doe"])])),("id",MetaInlines [Str "doe"]),("title",MetaInlines [Str "Title"])])])]})+[Para [Cite [Citation {citationId = "doe", citationPrefix = [], citationSuffix = [], citationMode = NormalCitation, citationNoteNum = 0, citationHash = 0}] [Str "[@doe]"]]]
− tests/jats.csl
@@ -1,208 +0,0 @@-<?xml version="1.0" encoding="utf-8"?>-<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" default-locale="en-US">- <info>- <title>Journal Article Tag Suite</title>- <title-short>JATS</title-short>- <id>http://www.zotero.org/styles/journal-article-tag-suite</id>- <link href="https://github.com/MartinPaulEve/JATS-CSL/blob/master/jats.csl" rel="self"/>- <link rel="documentation" href="http://jats.nlm.nih.gov/archiving/tag-library/1.0/index.html"/>- <author>- <name>Martin Paul Eve</name>- <email>martin@martineve.com</email>- </author>- <category citation-format="numeric"/>- <category field="medicine"/>- <category field="biology"/>- <summary>Use this style to generate bibliographic data in Journal Article Tagging Suite (JATS) 1.0 XML format</summary>- <updated>2014-06-21T17:41:26+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. Originally by Martin Fenner.</rights>- </info>- <locale xml:lang="en">- <terms>- <term name="et-al">{{jats}}<etal/>{{/jats}}</term>- </terms>- </locale>- <macro name="citation-number">- <text variable="citation-number" prefix="{{jats}}id="ref-{{/jats}}" suffix="{{jats}}">{{/jats}}"/>- </macro>- <macro name="author">- <names variable="author">- <name prefix="{{jats}}<name>{{/jats}}" suffix="{{jats}}</name>{{/jats}}" name-as-sort-order="all" sort-separator="">- <name-part name="family" text-case="capitalize-first" prefix="{{jats}}<surname>{{/jats}}" suffix="{{jats}}</surname>{{/jats}}"/>- <name-part name="given" text-case="capitalize-first" prefix="{{jats}}<given-names>{{/jats}}" suffix="{{jats}}</given-names>{{/jats}}"/>- </name>- <substitute>- <names variable="editor"/>- </substitute>- </names>- </macro>-- <macro name="editor">- <names variable="editor" prefix="{{jats}}<person-group person-group-type="editor">{{/jats}}" suffix="{{jats}}</person-group>{{/jats}}">- <name prefix="{{jats}}<name>{{/jats}}" suffix="{{jats}}</name>{{/jats}}" name-as-sort-order="all" sort-separator="">- <name-part name="family" text-case="capitalize-first" prefix="{{jats}}<surname>{{/jats}}" suffix="{{jats}}</surname>{{/jats}}"/>- <name-part name="given" text-case="capitalize-first" prefix="{{jats}}<given-names>{{/jats}}" suffix="{{jats}}</given-names>{{/jats}}"/>- </name>- <substitute>- <names variable="editor"/>- </substitute>- </names>- </macro>-- <macro name="editor">- <group delimiter=": ">- <names variable="editor">- <name prefix="{{jats}}<name>{{/jats}}" suffix="{{jats}}</name>{{/jats}}" name-as-sort-order="all" sort-separator="">- <name-part name="family" text-case="capitalize-first" prefix="{{jats}}<surname>{{/jats}}" suffix="{{jats}}</surname>{{/jats}}"/>- <name-part name="given" text-case="capitalize-first" prefix="{{jats}}<given-names>{{/jats}}" suffix="{{jats}}<given-names>{{/jats}}"/>- </name>- </names>- </group>- </macro>- <macro name="title">- <choose>- <if type="book" match="any">- <group prefix="{{jats}}<source>{{/jats}}" suffix="{{jats}}</source>{{/jats}}">- <text variable="title"/>- </group> - </if>- <else>- <group prefix="{{jats}}<article-title>{{/jats}}" suffix="{{jats}}</article-title>{{/jats}}">- <text variable="title"/>- </group>- </else>- </choose>- </macro>- <macro name="container-title">- <text variable="container-title" form="short" prefix="{{jats}}<source>{{/jats}}" suffix="{{jats}}</source>{{/jats}}"/>- </macro>- <macro name="publisher">- <text variable="publisher" prefix="{{jats}}<publisher-name>{{/jats}}" suffix="{{jats}}</publisher-name>{{/jats}}"/>- <text variable="publisher-place" prefix="{{jats}}<publisher-loc>{{/jats}}" suffix="{{jats}}</publisher-loc>{{/jats}}"/>- </macro>- <macro name="link">- <choose>- <if match="any" variable="DOI">- <group prefix="{{jats}}<pub-id pub-id-type="doi">{{/jats}}" suffix="{{jats}}</pub-id>{{/jats}}">- <text variable="DOI"/>- </group>- </if>- </choose>- <choose>- <if match="any" variable="PMID">- <group prefix="{{jats}}<ext-link ext-link-type="pmid" {{/jats}}" suffix="{{jats}}</ext-link>{{/jats}}">- <text variable="PMID" prefix="{{jats}}xlink:href="http://www.ncbi.nlm.nih.gov/pubmed/{{/jats}}" suffix="{{jats}}" xlink:type="simple">{{/jats}}"/>- <text variable="PMID"/>- </group>- </if>- </choose>- <choose>- <if variable="URL" match="any">- <group prefix="{{jats}}<ext-link ext-link-type="uri" {{/jats}}" suffix="{{jats}}</ext-link>{{/jats}}">- <text variable="URL" prefix="{{jats}}xlink:href="{{/jats}}" suffix="{{jats}}" xlink:type="simple">{{/jats}}"/>- <text variable="URL"/>- </group>- </if>- </choose>- </macro>- <macro name="date">- <choose>- <if type="article-journal article-magazine article-newspaper report patent book" match="any">- <group prefix="{{jats}}<date>{{/jats}}" suffix="{{jats}}</date>{{/jats}}">- <date variable="issued">- <date-part name="day" form="numeric-leading-zeros" prefix="{{jats}}<day>{{/jats}}" suffix="{{jats}}</day>{{/jats}}"/>- <date-part name="month" form="numeric-leading-zeros" prefix="{{jats}}<month>{{/jats}}" suffix="{{jats}}</month>{{/jats}}"/>- <date-part name="year" prefix="{{jats}}<year>{{/jats}}" suffix="{{jats}}</year>{{/jats}}"/>- </date>- </group>- </if>- <else>- <group prefix="{{jats}}<date-in-citation content-type="access-date"{{/jats}}" suffix="{{jats}}</date-in-citation>{{/jats}}">- <date variable="accessed" prefix="{{jats}} iso-8601-date="{{/jats}}" suffix="{{jats}}">{{/jats}}">- <date-part name="year"/>- <date-part name="month" form="numeric-leading-zeros" prefix="{{jats}}-{{/jats}}"/>- <date-part name="day" form="numeric-leading-zeros" prefix="{{jats}}-{{/jats}}"/>- </date>- <date variable="accessed">- <date-part name="day" prefix="{{jats}}<day>{{/jats}}" suffix="{{jats}}</day>{{/jats}}"/>- <date-part name="month" form="numeric-leading-zeros" prefix="{{jats}}<month>{{/jats}}" suffix="{{jats}}</month>{{/jats}}"/>- <date-part name="year" prefix="{{jats}}<year>{{/jats}}" suffix="{{jats}}</year>{{/jats}}"/>- </date>- </group>- </else>- </choose>- </macro>- <macro name="location">- <choose>- <if type="article-journal article-magazine" match="any">- <text variable="volume" prefix="{{jats}}<volume>{{/jats}}" suffix="{{jats}}</volume>{{/jats}}"/>- <text variable="issue" prefix="{{jats}}<issue>{{/jats}}" suffix="{{jats}}</issue>{{/jats}}"/>- </if>- </choose>- <choose>- <if type="article-journal article-magazine article-newspaper chapter" match="any">- <text variable="page-first" prefix="{{jats}}<fpage>{{/jats}}" suffix="{{jats}}</fpage>{{/jats}}"/>- </if>- </choose>- </macro>- <macro name="publication-type">- <group prefix="{{jats}} publication-type="{{/jats}}" suffix="{{jats}}">{{/jats}}">- <choose>- <if type="article-journal article-magazine article-newspaper" match="any">- <text value="journal"/>- </if>- <else-if type="book" match="any">- <text value="book"/>- </else-if>- <else-if type="chapter" match="any">- <text value="bookchapter"/>- </else-if>- <else-if type="dataset" match="any">- <text value="dataset"/>- </else-if>- <else-if type="patent" match="any">- <text value="patent"/>- </else-if>- <else-if type="report" match="any">- <text value="report"/>- </else-if>- <else-if type="review" match="any">- <text value="review"/>- </else-if>- <else>- <text value="standard"/>- </else>- </choose>- </group>- </macro>- <citation collapse="citation-number">- <sort>- <key variable="citation-number"/>- </sort>- <layout delimiter=",">- <group prefix="{{jats}}<xref ref-type="bibr" rid="{{/jats}}" suffix="{{jats}}</xref>{{/jats}}">- <text variable="citation-number" prefix="{{jats}}ref-{{/jats}}" suffix="{{jats}}">{{/jats}}"/>- <text variable="citation-number"/>- </group>- </layout>- </citation>- <bibliography sort-separator="">- <layout>- <group prefix="{{jats}}<ref {{/jats}}" suffix="{{jats}}</ref>{{/jats}}">- <text macro="citation-number"/>- <group prefix="{{jats}}<element-citation{{/jats}}" suffix="{{jats}}</element-citation>{{/jats}}">- <text macro="publication-type"/>- <text macro="author" prefix="{{jats}}<person-group person-group-type="author">{{/jats}}" suffix="{{jats}}</person-group>{{/jats}}"/>- <text macro="title" />- <text macro="container-title"/>- <text macro="editor"/>- <text macro="publisher"/>- <text macro="date"/>- <text macro="location"/>- <text macro="link"/>- </group>- </group>- </layout>- </bibliography>-</style>-
+ tests/modern-language-association-7th-edition.csl view
@@ -0,0 +1,460 @@+<?xml version="1.0" encoding="utf-8"?>+<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="never">+ <info>+ <title>Modern Language Association 7th edition</title>+ <title-short>MLA</title-short>+ <id>http://www.zotero.org/styles/modern-language-association-7th-edition</id>+ <link href="http://www.zotero.org/styles/modern-language-association-7th-edition" rel="self"/>+ <link href="http://owl.english.purdue.edu/owl/section/2/11/" rel="documentation"/>+ <author>+ <name>Ilouise S. Bradford</name>+ <email>isbradford@gmail.com</email>+ </author>+ <contributor>+ <name>Sarah Ficke</name>+ <email>sficke@email.unc.edu</email>+ </contributor>+ <contributor>+ <name>Sebastian Karcher</name>+ <email>karcher@u.northwestern.edu</email>+ </contributor>+ <contributor>+ <name>Christian Werthschulte</name>+ <email>Christian.Werthschulte@rub.de</email>+ </contributor>+ <contributor>+ <name>Simon Kornblith</name>+ <email>simon@simonster.com</email>+ </contributor>+ <contributor>+ <name>James Johnston</name>+ <email>thejamesjohnston@gmail.com</email>+ </contributor>+ <category citation-format="author"/>+ <category field="generic-base"/>+ <summary>This style adheres to the MLA 7th edition handbook and contains modifications to these types of sources: e-mail, forum posts, interviews, manuscripts, maps, presentations, TV broadcasts, and web pages.</summary>+ <updated>2017-04-27T18:03:35+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="month-01" form="short">Jan.</term>+ <term name="month-02" form="short">Feb.</term>+ <term name="month-03" form="short">Mar.</term>+ <term name="month-04" form="short">Apr.</term>+ <term name="month-05" form="short">May</term>+ <term name="month-06" form="short">June</term>+ <term name="month-07" form="short">July</term>+ <term name="month-08" form="short">Aug.</term>+ <term name="month-09" form="short">Sept.</term>+ <term name="month-10" form="short">Oct.</term>+ <term name="month-11" form="short">Nov.</term>+ <term name="month-12" form="short">Dec.</term>+ <term name="volume" form="short">+ <single>Vol.</single>+ <multiple>vols</multiple>+ </term>+ <term name="edition" form="short">ed</term>+ <term name="editor" form="verb-short">ed.</term>+ <term name="translator" form="verb-short">trans.</term>+ <term name="translator" form="short">trans.</term>+ </terms>+ </locale>+ <macro name="editor-translator">+ <names variable="editor translator" delimiter=". ">+ <label form="verb-short" text-case="capitalize-first" suffix=" "/>+ <name and="text" delimiter=", "/>+ </names>+ </macro>+ <macro name="author">+ <names variable="author">+ <name name-as-sort-order="first" and="text" sort-separator=", " delimiter=", " delimiter-precedes-last="always"/>+ <label form="short" prefix=", "/>+ <substitute>+ <names variable="editor"/>+ <names variable="translator"/>+ <text macro="title"/>+ </substitute>+ </names>+ </macro>+ <macro name="author-short">+ <names variable="author">+ <name form="short" and="text" delimiter=", " initialize-with=". "/>+ <substitute>+ <names variable="editor"/>+ <names variable="translator"/>+ <text macro="title-short"/>+ </substitute>+ </names>+ </macro>+ <macro name="access">+ <group delimiter=" ">+ <date variable="accessed">+ <date-part name="day" suffix=" "/>+ <date-part name="month" form="short" suffix=" "/>+ <date-part name="year"/>+ </date>+ </group>+ </macro>+ <macro name="issued-full-date">+ <choose>+ <if variable="issued">+ <date variable="issued">+ <date-part name="day" suffix=" "/>+ <date-part name="month" form="short" suffix=" " strip-periods="false"/>+ <date-part name="year"/>+ </date>+ </if>+ <else>+ <text term="no date" form="short"/>+ </else>+ </choose>+ </macro>+ <macro name="medium">+ <choose>+ <if type="motion_picture">+ <choose>+ <if variable="medium">+ <text variable="medium" prefix=" "/>+ </if>+ <else>+ <text value="Film" prefix=" "/>+ </else>+ </choose>+ </if>+ <else-if type="broadcast">+ <choose>+ <if variable="medium">+ <text variable="medium" prefix=" "/>+ </if>+ <else>+ <text value="Television" prefix=" "/>+ </else>+ </choose>+ </else-if>+ <else-if type="manuscript">+ <text value=""/>+ </else-if>+ <else-if type="personal_communication" match="any">+ <text value="" prefix=" "/>+ </else-if>+ <else-if type="speech" match="any">+ <text value=""/>+ </else-if>+ <else-if type="interview">+ <text variable="medium" prefix=" "/>+ </else-if>+ <else-if type="song">+ <choose>+ <if variable="medium">+ <text variable="medium" prefix=" "/>+ </if>+ <else>+ <text value="Audio Recording" prefix=" "/>+ </else>+ </choose>+ </else-if>+ <else-if type="graphic" variable="medium" match="all">+ <text variable="medium" prefix=" "/>+ </else-if>+ <else>+ <choose>+ <if variable="URL DOI" match="any">+ <text variable="source" prefix=" " suffix="." font-style="italic"/>+ <group>+ <text value="Web." prefix=" "/>+ </group>+ <text prefix=" " suffix="." macro="access"/>+ </if>+ <else>+ <text value="Print" prefix=" "/>+ </else>+ </choose>+ </else>+ </choose>+ </macro>+ <macro name="title">+ <choose>+ <if type="bill book graphic legal_case legislation manuscript motion_picture report song" match="any">+ <text variable="title" font-style="italic" text-case="title"/>+ </if>+ <else-if type="interview personal_communication" match="any">+ <text variable="title" text-case="title" quotes="false"/>+ </else-if>+ <else>+ <text variable="title" text-case="title" quotes="true"/>+ </else>+ </choose>+ </macro>+ <macro name="title-short">+ <choose>+ <if type="bill book graphic legal_case legislation manuscript motion_picture report song" match="any">+ <text variable="title" text-case="title" form="short" font-style="italic"/>+ </if>+ <else>+ <text variable="title" text-case="title" form="short" quotes="true"/>+ </else>+ </choose>+ </macro>+ <macro name="pages">+ <choose>+ <if variable="page">+ <text variable="page"/>+ </if>+ <else-if type="personal_communication interview" match="any">+ <text value=""/>+ </else-if>+ <else>+ <text value="n. pag"/>+ </else>+ </choose>+ </macro>+ <macro name="edition">+ <choose>+ <if is-numeric="edition">+ <group delimiter=" ">+ <number variable="edition" form="ordinal"/>+ <text term="edition" form="short"/>+ </group>+ </if>+ <else>+ <text variable="edition"/>+ </else>+ </choose>+ </macro>+ <macro name="volume">+ <choose>+ <if is-numeric="volume">+ <group delimiter=" ">+ <text term="volume" form="short" strip-periods="false"/>+ <number variable="volume"/>+ </group>+ </if>+ <else>+ <text variable="volume"/>+ </else>+ </choose>+ </macro>+ <macro name="number-of-volumes-only">+ <choose>+ <if variable="volume" match="none">+ <choose>+ <if is-numeric="number-of-volumes">+ <group delimiter=" ">+ <number variable="number-of-volumes"/>+ <text term="volume" form="short" plural="true" strip-periods="true"/>+ </group>+ </if>+ <else>+ <text variable="number-of-volumes"/>+ </else>+ </choose>+ </if>+ </choose>+ </macro>+ <macro name="number-of-volumes-optional">+ <choose>+ <if variable="volume">+ <choose>+ <if is-numeric="number-of-volumes">+ <group delimiter=" ">+ <number variable="number-of-volumes"/>+ <text term="volume" form="short" plural="true" strip-periods="true"/>+ </group>+ </if>+ <else>+ <text variable="number-of-volumes"/>+ </else>+ </choose>+ </if>+ </choose>+ </macro>+ <macro name="collection-title">+ <text variable="collection-title" text-case="title" prefix=" "/>+ </macro>+ <macro name="collection-number">+ <text variable="collection-number" prefix=" " suffix="."/>+ </macro>+ <macro name="publisher">+ <choose>+ <if variable="publisher">+ <text variable="publisher"/>+ </if>+ <else>+ <text value="N.p."/>+ </else>+ </choose>+ </macro>+ <macro name="publisher-year">+ <group delimiter=", ">+ <group delimiter=": ">+ <text variable="publisher-place"/>+ <text macro="publisher"/>+ </group>+ <date variable="issued">+ <date-part name="year"/>+ </date>+ </group>+ </macro>+ <citation et-al-min="2" et-al-use-first="1" disambiguate-add-names="true" disambiguate-add-givenname="true">+ <layout prefix="(" suffix=")" delimiter="; ">+ <group delimiter=" ">+ <choose>+ <if variable="author editor translator" match="any">+ <group delimiter=", ">+ <text macro="author-short"/>+ <choose>+ <if disambiguate="true">+ <text macro="title-short"/>+ </if>+ </choose>+ </group>+ </if>+ <else>+ <text macro="title-short"/>+ </else>+ </choose>+ <text variable="locator"/>+ </group>+ </layout>+ </citation>+ <bibliography hanging-indent="true" et-al-min="4" et-al-use-first="1" line-spacing="2" entry-spacing="0" subsequent-author-substitute="---">+ <sort>+ <key macro="author"/>+ <key variable="title"/>+ </sort>+ <layout suffix=".">+ <text macro="author" suffix="."/>+ <text macro="title" prefix=" " suffix="."/>+ <choose>+ <if type="bill book graphic legal_case legislation motion_picture report song" match="any">+ <text macro="editor-translator" prefix=" " suffix="."/>+ <text macro="edition" prefix=" " suffix="."/>+ <text macro="volume" prefix=" " suffix="."/>+ <text macro="number-of-volumes-only" prefix=" " suffix="."/>+ <text macro="publisher-year" prefix=" " suffix="."/>+ </if>+ <else-if type="chapter paper-conference" match="any">+ <group>+ <text variable="container-title" text-case="title" font-style="italic" prefix=" " suffix="."/>+ <text macro="editor-translator" prefix=" " suffix="."/>+ <text macro="edition" prefix=" " suffix="."/>+ <text macro="volume" prefix=" " suffix="."/>+ <text macro="number-of-volumes-only" prefix=" " suffix="."/>+ <text macro="publisher-year" prefix=" " suffix="."/>+ </group>+ <text variable="page" prefix=" " suffix="."/>+ </else-if>+ <else-if type="thesis">+ <text variable="genre" prefix=" " suffix="."/>+ <group delimiter=", ">+ <text macro="publisher" prefix=" "/>+ <date variable="issued" prefix=" " suffix=".">+ <date-part name="year"/>+ </date>+ </group>+ <text variable="archive_location" prefix=" " suffix="."/>+ </else-if>+ <else-if type="manuscript">+ <date variable="issued" prefix=" " suffix=".">+ <date-part name="year"/>+ </date>+ <text variable="genre" prefix=" " suffix="."/>+ <text variable="archive_location" prefix=" " suffix="."/>+ <text variable="publisher-place" prefix=" "/>+ </else-if>+ <else-if type="personal_communication">+ <date variable="issued" prefix=" " suffix=".">+ <date-part name="day" suffix=" "/>+ <date-part name="month" form="short" suffix=" "/>+ <date-part name="year"/>+ </date>+ <choose>+ <if variable="genre">+ <text prefix=" " suffix="." variable="genre"/>+ </if>+ <else>+ <text prefix=" " suffix="." value="E-mail"/>+ </else>+ </choose>+ </else-if>+ <else-if type="map">+ <text variable="genre" prefix=" " suffix="."/>+ <text variable="publisher-place" prefix=" " suffix=":"/>+ <text macro="publisher" prefix=" "/>+ <date variable="issued" prefix=" " suffix=",">+ <date-part name="year"/>+ </date>+ </else-if>+ <else-if type="speech">+ <text variable="event" prefix=" " suffix="."/>+ <text variable="publisher-place" prefix=" " suffix="."/>+ <date variable="issued" prefix=" " suffix=".">+ <date-part name="year"/>+ </date>+ <text variable="genre" prefix=" " suffix="."/>+ </else-if>+ <else-if type="webpage post-weblog" match="any">+ <text variable="genre" prefix=" " suffix="."/>+ <text variable="container-title" font-style="italic" prefix=" " suffix="."/>+ <group delimiter=", " prefix=" ">+ <text macro="publisher"/>+ <text macro="issued-full-date" suffix="."/>+ </group>+ </else-if>+ <else-if type="broadcast">+ <text variable="container-title" font-style="italic" prefix=" " suffix="."/>+ <text macro="publisher" prefix=" " suffix=","/>+ <date variable="issued" prefix=" " suffix=".">+ <date-part name="day" suffix=" "/>+ <date-part name="month" form="short" suffix=" " strip-periods="false"/>+ <date-part name="year"/>+ </date>+ </else-if>+ <else>+ <group prefix=" " suffix="." delimiter=": ">+ <group delimiter=" ">+ <text macro="editor-translator" suffix="."/>+ <text variable="container-title" font-style="italic"/>+ <choose>+ <if type="article-journal">+ <group delimiter=" ">+ <group delimiter=".">+ <text variable="volume"/>+ <text variable="issue"/>+ </group>+ <date variable="issued" prefix="(" suffix="):">+ <date-part name="year"/>+ </date>+ </group>+ <text macro="pages" prefix=" "/>+ </if>+ <else>+ <group>+ <date variable="issued">+ <date-part name="day" suffix=" "/>+ <date-part name="month" form="short" suffix=" " strip-periods="false"/>+ <date-part name="year"/>+ </date>+ <choose>+ <if variable="URL DOI" match="any">+ <text variable="page" prefix=": "/>+ </if>+ <else>+ <text macro="pages" prefix=": "/>+ </else>+ </choose>+ </group>+ </else>+ </choose>+ </group>+ </group>+ </else>+ </choose>+ <text macro="medium" suffix="."/>+ <text macro="number-of-volumes-optional" suffix="." prefix=" "/>+ <text macro="collection-title"/>+ <text macro="collection-number"/>+ </layout>+ </bibliography>+</style>
tests/test-citeproc.hs view
@@ -1,28 +1,31 @@-{-# LANGUAGE OverloadedStrings, TypeSynonymInstances, FlexibleInstances,- ScopedTypeVariables, CPP #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeSynonymInstances #-} -import Text.Printf-import System.Exit-import qualified Control.Exception as E-import Text.Pandoc (Block(..), Inline(..), Format(..), bottomUp,- nullMeta, Pandoc(..))-import Text.CSL.Compat.Pandoc (writeHtmlString)-import Data.Char (isSpace, toLower)-import System.Environment (getArgs)-import System.Process-import System.IO.Temp (withSystemTempDirectory)-import qualified Text.Pandoc.UTF8 as UTF8-import Data.Aeson-import Data.Aeson.Types (Parser)-import System.FilePath-import System.Directory-import Data.List (sort, isInfixOf)-import qualified Data.Map as M-import Text.CSL.Style hiding (Number)-import Text.CSL.Reference-import Text.CSL-import Control.Monad-import qualified Data.ByteString.Lazy as BL+import qualified Control.Exception as E+import Control.Monad+import Data.Aeson+import Data.Aeson.Types (Parser)+import qualified Data.ByteString.Lazy as BL+import Data.Char (isSpace, toLower)+import Data.List (isInfixOf, sort)+import qualified Data.Map as M+import System.Directory+import System.Environment (getArgs)+import System.Exit+import System.FilePath+import System.IO.Temp (withSystemTempDirectory)+import System.Process+import Text.CSL+import Text.CSL.Compat.Pandoc (writeHtmlString)+import Text.CSL.Reference+import Text.CSL.Style hiding (Number)+import Text.Pandoc (Block (..), Format (..), Inline (..),+ Pandoc (..), bottomUp, nullMeta)+import qualified Text.Pandoc.UTF8 as UTF8+import Text.Printf data TestCase = TestCase{ testMode :: Mode -- mode@@ -43,12 +46,12 @@ deriving Show instance FromJSON Mode where- parseJSON (String "citation") = return CitationMode- parseJSON (String "citation-rtf") = return CitationRTFMode- parseJSON (String "bibliography") = return BibliographyMode+ parseJSON (String "citation") = return CitationMode+ parseJSON (String "citation-rtf") = return CitationRTFMode+ parseJSON (String "bibliography") = return BibliographyMode parseJSON (String "bibliography-header") = return BibliographyHeaderMode parseJSON (String "bibliography-nosort") = return BibliographyNoSortMode- parseJSON _ = fail "Unknown mode"+ parseJSON _ = fail "Unknown mode" instance FromJSON TestCase where parseJSON (Object v) = TestCase <$>@@ -61,8 +64,8 @@ v .: "input" <*> v .: "result" where parseCitations :: Data.Aeson.Value -> Parser [CiteObject]- parseCitations x@(Array{}) = parseJSON x- parseCitations _ = return []+ parseCitations x@Array{} = parseJSON x+ parseCitations _ = return [] parseJSON _ = fail "Could not parse test case" newtype CiteObject =@@ -81,7 +84,7 @@ #else instance FromJSON [CiteObject] where parseJSON (Array v) = mapM parseJSON $ V.toList v- parseJSON _ = return []+ parseJSON _ = return [] #endif data TestResult =@@ -153,8 +156,8 @@ -- We want & instead of & etc. adjustEntities :: String -> String adjustEntities ('&':'#':'3':'8':';':xs) = "&" ++ adjustEntities xs-adjustEntities (x:xs) = x : adjustEntities xs-adjustEntities [] = []+adjustEntities (x:xs) = x : adjustEntities xs+adjustEntities [] = [] -- citeproc-js test suite expects "citations" to be formatted like -- .. [0] Smith (2007)
tests/test-pandoc-citeproc.hs view
@@ -1,30 +1,30 @@-{-# LANGUAGE CPP #-}+{-# LANGUAGE CPP #-} {-# LANGUAGE ScopedTypeVariables #-} module Main where-import System.Exit-import System.Directory-import System.FilePath-import Data.Maybe (fromMaybe)-import System.IO-import System.IO.Temp (withSystemTempDirectory)-import System.Process (rawSystem)-import qualified Data.Aeson as Aeson-import Text.Pandoc.Definition-import qualified Text.Pandoc.UTF8 as UTF8-import Text.CSL.Compat.Pandoc (writeNative, pipeProcess)-import Data.List (isSuffixOf)-import System.Environment-import Control.Monad (when)+import Control.Monad (when)+import qualified Data.Aeson as Aeson+import Data.List (isSuffixOf)+import Data.Maybe (fromMaybe)+import System.Directory+import System.Environment+import System.Exit+import System.FilePath+import System.IO+import System.IO.Temp (withSystemTempDirectory)+import System.Process (rawSystem)+import Text.CSL.Compat.Pandoc (pipeProcess, writeNative)+import Text.Pandoc.Definition+import qualified Text.Pandoc.UTF8 as UTF8 #if MIN_VERSION_pandoc(2,0,0)-import qualified Control.Exception as E+import qualified Control.Exception as E #endif main :: IO () main = do args <- getArgs let regenerate = "--accept" `elem` args- testnames <- fmap (map (dropExtension . takeBaseName) .- filter (".in.native" `isSuffixOf`)) $+ testnames <- (map (dropExtension . takeBaseName) .+ filter (".in.native" `isSuffixOf`)) <$> getDirectoryContents "tests" citeprocTests <- mapM (testCase regenerate) testnames fs <- filter (\f -> takeExtension f `elem` [".bibtex",".biblatex"])@@ -57,7 +57,7 @@ hPutStr stderr $ "[" ++ csl ++ ".in.native] " indataNative <- UTF8.readFile $ "tests/" ++ csl ++ ".in.native" expectedNative <- UTF8.readFile $ "tests/" ++ csl ++ ".expected.native"- let jsonIn = Aeson.encode $ (read indataNative :: Pandoc)+ let jsonIn = Aeson.encode (read indataNative :: Pandoc) let expectedDoc = read expectedNative testProgPath <- getExecutablePath let pandocCiteprocPath = takeDirectory testProgPath </> ".." </>@@ -68,11 +68,11 @@ [] jsonIn if ec == ExitSuccess then do- let outDoc = fromMaybe mempty $ Aeson.decode $ jsonOut+ let outDoc = fromMaybe mempty $Aeson.decode jsonOut if outDoc == expectedDoc then err "PASSED" >> return Passed else do- err $ "FAILED"+ err "FAILED" showDiff (writeNative expectedDoc) (writeNative outDoc) when regenerate $ UTF8.writeFile ("tests/" ++ csl ++ ".expected.native") $