citeproc 0.1 → 0.1.0.1
raw patch · 8 files changed
+251/−37 lines, 8 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- CHANGELOG.md +17/−0
- README.md +1/−6
- app/Main.hs +2/−1
- citeproc.cabal +2/−1
- man/citeproc.1 +199/−0
- src/Citeproc.hs +0/−1
- src/Citeproc/Eval.hs +29/−27
- test/Spec.hs +1/−1
CHANGELOG.md view
@@ -4,3 +4,20 @@ * Initial release. +## 0.1.0.1++ * Fix sorting when no `<sorting>` element given. The spec says:+ "In the absence of cs:sort, cites and bibliographic entries appear in+ the order in which they are cited." This affects IEEE in particular. See+ jgm/pandoc#6741.++ * Improve `sameNames` and citation grouping. Preivously if a citation+ item had a prefix, it would not be grouped with following citations.+ See jgm/pandoc#6722 for discussion.++ * Remove unneeded `hasNoSuffix` check in `sameNames`.++ * Remove unneeded import++ * `citeproc` executable: strip BOM before parsing style (#18).+
README.md view
@@ -3,12 +3,7 @@ [](LICENSE) [](https://github.com/jgm/citeproc/actions)--<!-- [](https://hackage.haskell.org/package/citeproc)-[](http://stackage.org/lts/package/citeproc)-[](http://stackage.org/nightly/package/citeproc)---> This library generates citations and bibliography formatted according to a [CSL] style. Currently version 1.0.2 of the CSL@@ -94,7 +89,7 @@ Although this library is much more accurate in implementing the CSL spec than pandoc-citeproc was, it still fails some of the-tests from the CSL test suite (59/845). However, most of the+tests from the CSL test suite (58/845). However, most of the failures are on minor corner cases, and in many cases the expected behavior goes beyond what is required by the CSL spec.
app/Main.hs view
@@ -45,7 +45,8 @@ Left e -> err e Right (inp :: Inputs (CslJson Text)) -> do stylesheet <- case optStyle opt of- Just fp -> TIO.readFile fp+ Just fp -> T.dropWhile (=='\xFEFF') <$> -- drop BOM+ TIO.readFile fp Nothing -> case inputsStyle inp of Just s -> return s
citeproc.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.2 name: citeproc-version: 0.1+version: 0.1.0.1 synopsis: Generates citations and bibliography from CSL styles. description: citeproc parses CSL style files and uses them to generate a list of formatted citations and bibliography@@ -20,6 +20,7 @@ locales/*.xml locales/locales.json man/citeproc.1.md+ man/citeproc.1 test/NOTES.md test/csl/*.txt test/extra/*.txt
+ man/citeproc.1 view
@@ -0,0 +1,199 @@+.\" Automatically generated by Pandoc 2.11+.\"+.TH "citeproc" "1" "" "citeproc 0.1.0.1" ""+.hy+.SH NAME+.PP+citeproc - process citations using a CSL stylesheet.+.SH SYNOPSIS+.PP+\f[C]citeproc [options] [file]\f[R]+.SH DESCRIPTION+.PP+\f[C]citeproc\f[R] reads a JSON-encoded \f[C]Inputs\f[R] object from+\f[C]stdin\f[R] (or from a file if a filename is provided) and writes a+JSON-encoded \f[C]Result\f[R] object to \f[C]stdout\f[R].+This executable can be used to add citation processing to non-Haskell+projects.+.SH OPTIONS+.TP+\f[B]\f[CB]-s\f[B]\f[R] \f[I]FILE\f[R], \f[B]\f[CB]--style=\f[B]\f[R]\f[I]FILE\f[R]+Specify a CSL style to be used.+.TP+\f[B]\f[CB]-r\f[B]\f[R] \f[I]FILE\f[R], \f[B]\f[CB]--references=\f[B]\f[R]\f[I]FILE\f[R]+Specify a CSL JSON bibliography to be used as a source for references.+.TP+\f[B]\f[CB]a\f[B]\f[R] \f[I]FILE\f[R], \f[B]\f[CB]--abbreviations=\f[B]\f[R]\f[I]FILE\f[R]+Specify a CSL abbreviations file.+.TP+\f[B]\f[CB]l\f[B]\f[R] \f[I]LANG\f[R], \f[B]\f[CB]--lang=\f[B]\f[R]\f[I]LANG\f[R]+Specify a locale to override the style\[cq]s default (IETF language+code).+.TP+\f[B]\f[CB]f\f[B]\f[R] \f[I]html|json\f[R], \f[B]\f[CB]--format=\f[B]\f[R]\f[I]html|json\f[R]+Specify the format to be used for the entries.+\f[C]html\f[R] (the default) uses HTML tags and entities for formatting.+\f[C]json\f[R] creates a structured JSON representation of a formatted+document.+.TP+\f[B]\f[CB]-h, --help\f[B]\f[R]+Print usage information.+.TP+\f[B]\f[CB]-V, --version\f[B]\f[R]+Print version.+.SH NOTES+.PP+The input JSON should have the structure:+.IP+.nf+\f[C]+{ \[dq]citations\[dq]: [ ...list of citations... ],+ \[dq]references\[dq]: [ ...list of references... ],+ \[dq]style\[dq]: \[dq]<style>...</style>\[dq],+ \[dq]abbreviations\[dq]: { ...abbreviations... },+ \[dq]lang\[dq]: \[dq]fr-FR\[dq] }+\f[R]+.fi+.PP+None of these fields is mandatory.+Instead of providing \f[C]references\f[R] in the input JSON, one can+specify a file containing a CSL JSON bibliography, using the+\f[C]--references\f[R] option on the command line.+Instead of providing a CSL stylesheet in the JSON, one can specify a+file using the \f[C]--style\f[R] option.+\f[C]--abbreviations\f[R] and \f[C]--lang\f[R] may also be used on the+command line to specify an abbreviations file or a locale.+(Command-line options always override any values given in the JSON+file.)+.PP+A citation is structured like this:+.IP+.nf+\f[C]+{ \[dq]citationID\[dq]: \[dq]foo\[dq],+ \[dq]citationItems\[dq]: [ ...list of citationItems... ],+ \[dq]citationNoteNumber\[dq]: 3 }+\f[R]+.fi+.PP+Only \f[C]citationItems\f[R] is necessary.+Alternatively, instead of+.IP+.nf+\f[C]+{ \[dq]citationItems\[dq]: [ ... ] }+\f[R]+.fi+.PP+one can just specify an array of items directly:+.IP+.nf+\f[C]+[ ... ]+\f[R]+.fi+.PP+A citation item is structured like this:+.IP+.nf+\f[C]+{ \[dq]id\[dq]: \[dq]foo\[dq],+ \[dq]type\[dq]: \[dq]suppress-author\[dq],+ \[dq]label\[dq]: \[dq]page\[dq],+ \[dq]locator\[dq]: \[dq]45\[dq],+ \[dq]prefix\[dq]: \[dq]see \[dq],+ \[dq]suffix\[dq]: \[dq] and others\[dq] }+\f[R]+.fi+.PP+Only \f[C]id\f[R] is mandatory.+If \f[C]type\f[R] is omitted, it will be assumed to be+\f[C]normal-cite\f[R] (other values are \f[C]suppress-author\f[R] and+\f[C]author-only\f[R]).+.PP+A reference is structured like this:+.IP+.nf+\f[C]+{+ \[dq]author\[dq]: [+ {+ \[dq]family\[dq]: \[dq]Aristotle\[dq]+ }+ ],+ \[dq]id\[dq]: \[dq]aristotle:prior\[dq],+ \[dq]issued\[dq]: {+ \[dq]date-parts\[dq]: [+ [+ 1989+ ]+ ]+ },+ \[dq]publisher\[dq]: \[dq]Hackett\[dq],+ \[dq]publisher-place\[dq]: \[dq]Indianapolis\[dq],+ \[dq]title\[dq]: \[dq]Prior analytics\[dq],+ \[dq]translator\[dq]: [+ {+ \[dq]family\[dq]: \[dq]Smith\[dq],+ \[dq]given\[dq]: \[dq]Robin\[dq]+ }+ ],+ \[dq]type\[dq]: \[dq]book\[dq]+}+\f[R]+.fi+.PP+An abbreviations object has this form:+.IP+.nf+\f[C]+{ \[dq]default\[dq]: {+ \[dq]container-title\[dq]: {+ \[dq]Lloyd\[aq]s Law Reports\[dq]: \[dq]Lloyd\[aq]s Rep\[dq],+ \[dq]Estates Gazette\[dq]: \[dq]EG\[dq],+ \[dq]Scots Law Times\[dq]: \[dq]SLT\[dq]+ }+ }+}+\f[R]+.fi+.PP+The abbreviations will be substituted in the output only when the+\f[C]form\f[R] attribute for the style element that renders the variable+is set to \f[C]short\f[R].+.PP+The output JSON will have the structure:+.IP+.nf+\f[C]+{ \[dq]citations\[dq]: [ ...list of strings... ],+ \[dq]bibliography\[dq]: [ ...list of arrays: item id and a string... ],+ \[dq]warnings\[dq]: [ ...list of warnings... ]+}+\f[R]+.fi+.PP+The contents of the entries will be HTML by default, but if+\f[C]--format=json\f[R] is specified, it will be a structured+representation of formatted text.+.IP+.nf+\f[C]+[+ \[dq]\[em]\[em]\[em]. 1983b. \[lq]The Concept of Truth in Formalized Languages.\[rq] In \[dq],+ {+ \[dq]format\[dq]: \[dq]italics\[dq],+ \[dq]contents\[dq]: [+ \[dq]Logic, Semantics, Metamathematics\[dq]+ ]+ },+ \[dq], edited by John Corcoran, 152\[en]278. Indianapolis: Hackett.\[dq]+]+\f[R]+.fi+.PP+This representation can be used if you want to convert the result to a+format other than HTML.+.SH AUTHORS+.PP+John MacFarlane
src/Citeproc.hs view
@@ -10,7 +10,6 @@ , citeproc , Result(..) ) where-import Data.Text (Text) import Data.Semigroup import qualified Data.Text as T import qualified Data.Set as Set
src/Citeproc/Eval.hs view
@@ -28,7 +28,7 @@ import Control.Applicative import Data.Generics.Uniplate.Operations (universe, transform) --- import Debug.Trace (trace)+-- import Debug.Trace (traceShowId) -- import Text.Show.Pretty (ppShow) -- ppTrace :: Show a => a -> a -- ppTrace x = trace (ppShow x) x@@ -127,7 +127,14 @@ addIfMissing _ (Just x) = Just x go = do- assignCitationNumbers (map referenceId refs)+ -- list of citationItemIds that are actually cited+ let citationOrder = M.fromList $ reverse $ zip+ (concatMap (map citationItemId . citationItems) citations)+ [(1 :: Int)..]+ let citeIds = M.keysSet citationOrder+ let sortedCiteIds = sortOn (`M.lookup` citationOrder)+ (map referenceId refs)+ assignCitationNumbers sortedCiteIds -- sorting of bibliography, insertion of citation-number (bibCitations, bibSortKeyMap) <- case styleBibliography style of@@ -141,9 +148,9 @@ refs let sortedIds = if null (layoutSortKeys biblayout)- then map referenceId refs+ then sortedCiteIds else sortOn (`M.lookup` bibSortKeyMap)- (map referenceId refs)+ (map referenceId refs) assignCitationNumbers $ case layoutSortKeys biblayout of (SortKeyVariable Descending "citation-number":_)@@ -160,9 +167,6 @@ [CitationItem ident Nothing Nothing NormalCite Nothing Nothing]) sortedIds return (bibCitations, bibSortKeyMap)- -- list of citationItemIds that are actually cited- let citeIds = foldr (Set.insert . citationItemId) mempty- (concatMap citationItems citations) -- styling of citations sortKeyMap <- foldM (\m citeId -> do@@ -777,29 +781,27 @@ (Tagged (TagItem _ _) (Tagged (TagCitationNumber n2) _xs2)) = n2 == n1 + 1 isAdjacentCitationNumber _ _ = False- sameNames (Tagged (TagItem ty1 _id1) x1)- (Tagged (TagItem ty2 _id2) x2)- | hasNoSuffix x1- , hasNoSuffix x2- , ty1 /= AuthorOnly- , ty2 /= AuthorOnly- = case (unFormat x1, unFormat x2) of- (Tagged (TagNames t1 _nf1 ns1) ws1,- Tagged (TagNames t2 _nf2 ns2) ws2)- -> t1 == t2 && (if ns1 == ns2- then not (null ns1) || ws1 == ws2- else ws1 == ws2)- -- case where it's just a date with no name or anything;- -- we treat this as same name e.g. (1955a,b)- (Tagged TagDate{} _, Tagged TagDate{} _)+ sameNames x y =+ case (extractTags x, extractTags y) of+ (Just (Tagged (TagNames t1 _nf1 ns1) ws1),+ Just (Tagged (TagNames t2 _nf2 ns2) ws2))+ -> t1 == t2 && (if ns1 == ns2+ then not (null ns1) || ws1 == ws2+ else ws1 == ws2)+ -- case where it's just a date with no name or anything;+ -- we treat this as same name e.g. (1955a,b)+ (Just (Tagged TagDate{} _), Just (Tagged TagDate{} _)) -> True -- case where title is substituted _ -> False- sameNames _ _ = False- hasNoSuffix (Formatted f' _) = isNothing (formatSuffix f')- hasNoSuffix _ = True- unFormat (Formatted _ (z:_)) = unFormat z- unFormat x = x+ extractTags x =+ let items = [y | y@(Tagged (TagItem ty _) _) <- universe x+ , ty /= AuthorOnly]+ names = [y | y@(Tagged TagNames{} _) <- concatMap universe items]+ dates = [y | y@(Tagged TagDate{} _) <- concatMap universe items]+ in if null items+ then Nothing+ else listToMaybe names <|> listToMaybe dates groupAndCollapseCitations _ _ _ _ x = x takeSeq :: Show a => (a -> a -> Bool) -> [a] -> ([a], [a])
test/Spec.hs view
@@ -319,7 +319,7 @@ (length (skipped counts)) case length (failed counts) + length (errored counts) of 0 -> exitWith ExitSuccess- n | n <= 59 -> do+ n | n <= 58 -> do putStrLn "We have passed all the CSL tests we expect to..." exitWith ExitSuccess | otherwise -> exitWith $ ExitFailure n