@@ -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+ }