git.iko.soy/typeable/pandoc
on master help sign in
Changes to use citeproc 0.3.

Patch from Andrea Rossato. Note: the markdown syntax is preliminary and will probably change.

commitac06ca2b00f1c0b25b02b1e25aca8dd28961240d authorJohn MacFarlane <jgm@berkeley.edu> dateWed 27 Oct 2010, 18:22 (16 years ago) parent9cf27c9
4 files changed+101−24
src/Text/Pandoc/Biblio.hs+65−10 src/Text/Pandoc/Definition.hs+15−1 src/Text/Pandoc/Readers/Markdown.hs+20−12 src/pandoc.hs+1−1
src/Text/Pandoc/Biblio.hs+65−10
@@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2222 Copyright : Copyright (C) 2008 Andrea Rossato
2323 License : GNU GPL, version 2 or above
2424
25− Maintainer : Andrea Rossato <andrea.rossato@ing.unitn.it>
25+ Maintainer : Andrea Rossato <andrea.rossato@unitn.it>
2626 Stability : alpha
2727 Portability : portable
2828-}
@@ -31,7 +31,9 @@ module Text.Pandoc.Biblio ( processBiblio ) where
3131
3232import Control.Monad ( when )
3333import 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(..) )
3537import Text.Pandoc.Definition
3638
3739-- | Process a 'Pandoc' document by adding citations formatted
@@ -42,25 +44,78 @@ processBiblio cf r p
4244 else do
4345 when (null cf) $ error "Missing the needed citation style file"
4446 csl <- readCSLFile cf
45− let groups = queryWith getCite p
46− result = citeproc csl r groups
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'
53+ result = citeproc' csl r (setNearNote csl $ map (map toCslCite) groups)
4754 cits_map = zip groups (citations result)
4855 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'
5057 return $ Pandoc m $ b ++ biblioList
5158
5259-- | Substitute 'Cite' elements with formatted citations.
53−processCite :: Style -> [([Target],[FormattedOutput])] -> Inline -> Inline
60+processCite :: Style -> [([Citation],[FormattedOutput])] -> Inline -> Inline
5461processCite s cs il
5562 | Cite t _ <- il = Cite t (process t)
5663 | otherwise = il
5764 where
58− process t = case elemIndex t (map fst cs) of
59− Just i -> read . renderPandoc s $ snd (cs !! i)
65+ process t = case lookup t cs of
66+ Just i -> read $ renderPandoc s i
6067 Nothing -> [Str ("Error processing " ++ show t)]
6168
6269-- | Retrieve all citations from a 'Pandoc' docuument. To be used with
6370-- 'queryWith'.
64−getCite :: Inline -> [[(String,String)]]
65−getCite i | Cite t _ <- i = [t]
71+getCitation :: Inline -> [[Citation]]
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]
6681 | 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
112112 | Subscript [Inline] -- ^ Subscripted text (list of inlines)
113113 | SmallCaps [Inline] -- ^ Small caps text (list of inlines)
114114 | Quoted QuoteType [Inline] -- ^ Quoted text (list of inlines)
115− | Cite [Target] [Inline] -- ^ Citation (list of inlines)
115+ | Cite [Citation] [Inline] -- ^ Citation (list of inlines)
116116 | Code String -- ^ Inline code (literal)
117117 | Space -- ^ Inter-word space
118118 | EmDash -- ^ Em dash
@@ -129,6 +129,20 @@ data Inline
129129 | Note [Block] -- ^ Footnote or endnote
130130 deriving (Show, Eq, Ord, Read, Typeable, Data)
131131
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+
132146-- | Applies a transformation on @a@s to matching elements in a @b@.
133147processWith :: (Data a, Data b) => (a -> a) -> b -> b
134148processWith f = everywhere (mkT f)
src/Text/Pandoc/Readers/Markdown.hs+20−12
@@ -1316,27 +1316,35 @@ inlineCitation = try $ do
13161316 then return $ Cite citations []
13171317 else fail "no citation found"
13181318
1319−chkCit :: Target -> GenParser Char ParserState (Maybe Target)
1319+chkCit :: Citation -> GenParser Char ParserState (Maybe Citation)
13201320chkCit t = do
13211321 st <- getState
1322− case lookupKeySrc (stateKeys st) (Key [Str $ fst t]) of
1322+ case lookupKeySrc (stateKeys st) (Key [Str $ citationId t]) of
13231323 Just _ -> fail "This is a link"
1324− Nothing -> if elem (fst t) $ stateCitations st
1324+ Nothing -> if elem (citationId t) $ stateCitations st
13251325 then return $ Just t
13261326 else return $ Nothing
13271327
13281328citeMarker :: GenParser Char ParserState String
13291329citeMarker = char '[' >> manyTill ( noneOf "\n" <|> (newline >>~ notFollowedBy blankline) ) (char ']')
13301330
1331−parseCitation :: GenParser Char ParserState [(String,String)]
1332−parseCitation = try $ sepBy (parseLabel) (oneOf ";")
1331+parseCitation :: GenParser Char ParserState [Citation]
1332+parseCitation = try $ sepBy (parseLabel) (skipMany1 $ char ';')
13331333
1334−parseLabel :: GenParser Char ParserState (String,String)
1334+parseLabel :: GenParser Char ParserState Citation
13351335parseLabel = try $ do
1336− res <- sepBy (skipSpaces >> optional newline >> skipSpaces >> many1 (noneOf "@;")) (oneOf "@")
1337− case res of
1338− [lab,loc] -> return (lab, loc)
1339− [lab] -> return (lab, "" )
1340− _ -> return ("" , "" )
1341−
1336+ r <- many (noneOf ";")
1337+ let t' s = if s /= [] then tail s else []
1338+ trim = unwords . words
1339+ pref = takeWhile (/= '@') r
1340+ rest = t' $ dropWhile (/= '@') r
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
13421350#endif
src/pandoc.hs+1−1
@@ -789,7 +789,7 @@ main = do
789789 lhsExtension sources,
790790 stateStandalone = standalone',
791791#ifdef _CITEPROC
792− stateCitations = map citeKey refs,
792+ stateCitations = map refId refs,
793793#endif
794794 stateSmart = smart || writerName' `elem`
795795 ["latex", "context", "latex+lhs", "man"],