git.iko.soy/typeable/pandoc
on master help sign in
Changes to use citeproc 0.3.
ac06ca2John MacFarlane
src/Text/Pandoc/Biblio.hs+65−10
@@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 Copyright : Copyright (C) 2008 Andrea Rossato
22 Copyright : Copyright (C) 2008 Andrea Rossato
23 License : GNU GPL, version 2 or above
23 License : GNU GPL, version 2 or above
24
24
25− Maintainer : Andrea Rossato <andrea.rossato@ing.unitn.it>
25+ Maintainer : Andrea Rossato <andrea.rossato@unitn.it>
26 Stability : alpha
26 Stability : alpha
27 Portability : portable
27 Portability : portable
28-}
28-}
@@ -31,7 +31,9 @@ module Text.Pandoc.Biblio ( processBiblio ) where
31
31
32import Control.Monad ( when )
32import Control.Monad ( when )
33import Data.List
33import Data.List
34−import Text.CSL
34+import Data.Unique
35+import Text.CSL hiding ( Cite(..), Citation(..) )
36+import qualified Text.CSL as CSL ( Cite(..) )
35import Text.Pandoc.Definition
37import Text.Pandoc.Definition
36
38
37-- | Process a 'Pandoc' document by adding citations formatted
39-- | Process a 'Pandoc' document by adding citations formatted
@@ -42,25 +44,78 @@ processBiblio cf r p
42 else do
44 else do
43 when (null cf) $ error "Missing the needed citation style file"
45 when (null cf) $ error "Missing the needed citation style file"
44 csl <- readCSLFile cf
46 csl <- readCSLFile cf
45− let groups = queryWith getCite p
47+ p' <- if styleClass csl == "note"
48+ then processNote p
49+ else processWithM setHash p
50+ let groups = if styleClass csl /= "note"
51+ then queryWith getCitation p'
52+ else getNoteCitations p'
46− result = citeproc csl r groups
53+ result = citeproc' csl r (setNearNote csl $ map (map toCslCite) groups)
47 cits_map = zip groups (citations result)
54 cits_map = zip groups (citations result)
48 biblioList = map (read . renderPandoc' csl) (bibliography result)
55 biblioList = map (read . renderPandoc' csl) (bibliography result)
49− Pandoc m b = processWith (processCite csl cits_map) p
56+ Pandoc m b = processWith (processCite csl cits_map) p'
50 return $ Pandoc m $ b ++ biblioList
57 return $ Pandoc m $ b ++ biblioList
51
58
52-- | Substitute 'Cite' elements with formatted citations.
59-- | Substitute 'Cite' elements with formatted citations.
53−processCite :: Style -> [([Target],[FormattedOutput])] -> Inline -> Inline
60+processCite :: Style -> [([Citation],[FormattedOutput])] -> Inline -> Inline
54processCite s cs il
61processCite s cs il
55 | Cite t _ <- il = Cite t (process t)
62 | Cite t _ <- il = Cite t (process t)
56 | otherwise = il
63 | otherwise = il
57 where
64 where
58− process t = case elemIndex t (map fst cs) of
65+ process t = case lookup t cs of
59− Just i -> read . renderPandoc s $ snd (cs !! i)
66+ Just i -> read $ renderPandoc s i
60 Nothing -> [Str ("Error processing " ++ show t)]
67 Nothing -> [Str ("Error processing " ++ show t)]
61
68
62-- | Retrieve all citations from a 'Pandoc' docuument. To be used with
69-- | Retrieve all citations from a 'Pandoc' docuument. To be used with
63-- 'queryWith'.
70-- 'queryWith'.
64−getCite :: Inline -> [[(String,String)]]
71+getCitation :: Inline -> [[Citation]]
65−getCite i | Cite t _ <- i = [t]
72+getCitation i | Cite t _ <- i = [t]
73+ | otherwise = []
74+
75+getNote :: Inline -> [Inline]
76+getNote i | Note _ <- i = [i]
77+ | otherwise = []
78+
79+getCite :: Inline -> [Inline]
80+getCite i | Cite _ _ <- i = [i]
66 | otherwise = []
81 | otherwise = []
82+
83+getNoteCitations :: Pandoc -> [[Citation]]
84+getNoteCitations
85+ = let cits = concat . flip (zipWith $ setCiteNoteNum) [1..] .
86+ map (queryWith getCite) . queryWith getNote
87+ in queryWith getCitation . cits
88+
89+setHash :: Citation -> IO Citation
90+setHash (Citation i p l nn ao na _)
91+ = hashUnique `fmap` newUnique >>= return . Citation i p l nn ao na
92+
93+processNote :: Pandoc -> IO Pandoc
94+processNote p = do
95+ p' <- processWithM setHash p
96+ let cits = queryWith getCite p'
97+ ncits = map (queryWith getCite) $ queryWith getNote p'
98+ needNote = cits \\ concat ncits
99+ return $ processWith (mvCiteInNote needNote) p'
100+
101+mvCiteInNote :: [Inline] -> Inline -> Inline
102+mvCiteInNote is i = if i `elem` is then Note [Para [i]] else i
103+
104+setCiteNoteNum :: [Inline] -> Int -> [Inline]
105+setCiteNoteNum ((Cite cs o):xs) n = Cite (setCitationNoteNum n cs) o : setCiteNoteNum xs n
106+setCiteNoteNum _ _ = []
107+
108+setCitationNoteNum :: Int -> [Citation] -> [Citation]
109+setCitationNoteNum i = map $ \c -> c { citationNoteNum = i}
110+
111+toCslCite :: Citation -> CSL.Cite
112+toCslCite (Citation i p l nn ao na _)
113+ = let (la,lo) = parseLocator l
114+ in emptyCite { CSL.citeId = i
115+ , CSL.citePrefix = p
116+ , CSL.citeLabel = la
117+ , CSL.citeLocator = lo
118+ , CSL.citeNoteNumber = show nn
119+ , CSL.authorOnly = ao
120+ , CSL.suppressAuthor = na
121+ }
src/Text/Pandoc/Definition.hs+15−1
@@ -112,7 +112,7 @@ data Inline
112 | Subscript [Inline] -- ^ Subscripted text (list of inlines)
112 | Subscript [Inline] -- ^ Subscripted text (list of inlines)
113 | SmallCaps [Inline] -- ^ Small caps text (list of inlines)
113 | SmallCaps [Inline] -- ^ Small caps text (list of inlines)
114 | Quoted QuoteType [Inline] -- ^ Quoted text (list of inlines)
114 | Quoted QuoteType [Inline] -- ^ Quoted text (list of inlines)
115− | Cite [Target] [Inline] -- ^ Citation (list of inlines)
115+ | Cite [Citation] [Inline] -- ^ Citation (list of inlines)
116 | Code String -- ^ Inline code (literal)
116 | Code String -- ^ Inline code (literal)
117 | Space -- ^ Inter-word space
117 | Space -- ^ Inter-word space
118 | EmDash -- ^ Em dash
118 | EmDash -- ^ Em dash
@@ -129,6 +129,20 @@ data Inline
129 | Note [Block] -- ^ Footnote or endnote
129 | Note [Block] -- ^ Footnote or endnote
130 deriving (Show, Eq, Ord, Read, Typeable, Data)
130 deriving (Show, Eq, Ord, Read, Typeable, Data)
131
131
132+data Citation = Citation { citationId :: String
133+ , citationPrefix :: String
134+ , citationLocator :: String
135+ , citationNoteNum :: Int
136+ , citationAutOnly :: Bool
137+ , citationNoAut :: Bool
138+ , citationHash :: Int
139+ }
140+ deriving (Show, Ord, Read, Typeable, Data)
141+
142+instance Eq Citation where
143+ (==) (Citation _ _ _ _ _ _ ha)
144+ (Citation _ _ _ _ _ _ hb) = ha == hb
145+
132-- | Applies a transformation on @a@s to matching elements in a @b@.
146-- | Applies a transformation on @a@s to matching elements in a @b@.
133processWith :: (Data a, Data b) => (a -> a) -> b -> b
147processWith :: (Data a, Data b) => (a -> a) -> b -> b
134processWith f = everywhere (mkT f)
148processWith f = everywhere (mkT f)
src/Text/Pandoc/Readers/Markdown.hs+20−12
@@ -1316,27 +1316,35 @@ inlineCitation = try $ do
1316 then return $ Cite citations []
1316 then return $ Cite citations []
1317 else fail "no citation found"
1317 else fail "no citation found"
1318
1318
1319−chkCit :: Target -> GenParser Char ParserState (Maybe Target)
1319+chkCit :: Citation -> GenParser Char ParserState (Maybe Citation)
1320chkCit t = do
1320chkCit t = do
1321 st <- getState
1321 st <- getState
1322− case lookupKeySrc (stateKeys st) (Key [Str $ fst t]) of
1322+ case lookupKeySrc (stateKeys st) (Key [Str $ citationId t]) of
1323 Just _ -> fail "This is a link"
1323 Just _ -> fail "This is a link"
1324− Nothing -> if elem (fst t) $ stateCitations st
1324+ Nothing -> if elem (citationId t) $ stateCitations st
1325 then return $ Just t
1325 then return $ Just t
1326 else return $ Nothing
1326 else return $ Nothing
1327
1327
1328citeMarker :: GenParser Char ParserState String
1328citeMarker :: GenParser Char ParserState String
1329citeMarker = char '[' >> manyTill ( noneOf "\n" <|> (newline >>~ notFollowedBy blankline) ) (char ']')
1329citeMarker = char '[' >> manyTill ( noneOf "\n" <|> (newline >>~ notFollowedBy blankline) ) (char ']')
1330
1330
1331−parseCitation :: GenParser Char ParserState [(String,String)]
1331+parseCitation :: GenParser Char ParserState [Citation]
1332−parseCitation = try $ sepBy (parseLabel) (oneOf ";")
1332+parseCitation = try $ sepBy (parseLabel) (skipMany1 $ char ';')
1333
1333
1334−parseLabel :: GenParser Char ParserState (String,String)
1334+parseLabel :: GenParser Char ParserState Citation
1335parseLabel = try $ do
1335parseLabel = try $ do
1336− res <- sepBy (skipSpaces >> optional newline >> skipSpaces >> many1 (noneOf "@;")) (oneOf "@")
1336+ r <- many (noneOf ";")
1337− case res of
1337+ let t' s = if s /= [] then tail s else []
1338− [lab,loc] -> return (lab, loc)
1338+ trim = unwords . words
1339− [lab] -> return (lab, "" )
1339+ pref = takeWhile (/= '@') r
1340− _ -> return ("" , "" )
1340+ rest = t' $ dropWhile (/= '@') r
1341−
1341+ cit = takeWhile (/= ',') rest
1342+ loc = t' $ dropWhile (/= ',') rest
1343+ (p,na) = if pref /= [] && last pref == '-'
1344+ then (init pref, True )
1345+ else (pref , False)
1346+ (p',o) = if p /= [] && last p == '+'
1347+ then (init p , True )
1348+ else (p , False)
1349+ return $ Citation cit (trim p') (trim loc) 0 o na 0
1342#endif
1350#endif
src/pandoc.hs+1−1
@@ -789,7 +789,7 @@ main = do
789 lhsExtension sources,
789 lhsExtension sources,
790 stateStandalone = standalone',
790 stateStandalone = standalone',
791#ifdef _CITEPROC
791#ifdef _CITEPROC
792− stateCitations = map citeKey refs,
792+ stateCitations = map refId refs,
793#endif
793#endif
794 stateSmart = smart || writerName' `elem`
794 stateSmart = smart || writerName' `elem`
795 ["latex", "context", "latex+lhs", "man"],
795 ["latex", "context", "latex+lhs", "man"],