@@ -27,7 +27,7 @@ import Text.Pandoc.Error (PandocError(..))
27import Text.Pandoc.Extensions (pandocExtensions)
27import Text.Pandoc.Extensions (pandocExtensions)
28import Text.Pandoc.Logging (LogMessage(..))
28import Text.Pandoc.Logging (LogMessage(..))
29import Text.Pandoc.Options (ReaderOptions(..))
29import Text.Pandoc.Options (ReaderOptions(..))
30−import Text.Pandoc.Shared (stringify, ordNub, blocksToInlines, tshow)
30+import Text.Pandoc.Shared (stringify, ordNub, tshow)
31import qualified Text.Pandoc.UTF8 as UTF8
31import qualified Text.Pandoc.UTF8 as UTF8
32import Text.Pandoc.Walk (query, walk, walkM)
32import Text.Pandoc.Walk (query, walk, walkM)
33import Control.Applicative ((<|>))
33import Control.Applicative ((<|>))
@@ -49,6 +49,7 @@ import qualified Data.Text as T
49import System.FilePath (takeExtension)
49import System.FilePath (takeExtension)
50import Safe (lastMay, initSafe)
50import Safe (lastMay, initSafe)
52processCitations :: PandocMonad m => Pandoc -> m Pandoc
53processCitations :: PandocMonad m => Pandoc -> m Pandoc
53processCitations (Pandoc meta bs) = do
54processCitations (Pandoc meta bs) = do
54 style <- getStyle (Pandoc meta bs)
55 style <- getStyle (Pandoc meta bs)
@@ -90,22 +91,18 @@ processCitations (Pandoc meta bs) = do
90 walk (convertQuotes locale) .
91 walk (convertQuotes locale) .
91 insertSpace $ out)
92 insertSpace $ out)
92 (resultBibliography result)
93 (resultBibliography result)
93− let moveNotes = maybe True truish $
94+ let moveNotes = styleIsNoteStyle sopts &&
94− lookupMeta "notes-after-punctuation" meta
95+ maybe True truish (lookupMeta "notes-after-punctuation" meta)
95 let cits = map (walk (convertQuotes locale)) $
96 let cits = map (walk (convertQuotes locale)) $
96 resultCitations result
97 resultCitations result
98− let fixQuotes = case localePunctuationInQuote locale of
100− B.toList . movePunctuationInsideQuotes . B.fromList
103 let metanocites = lookupMeta "nocite" meta
99 let metanocites = lookupMeta "nocite" meta
104 let Pandoc meta'' bs' =
100 let Pandoc meta'' bs' =
105 maybe id (setMeta "nocite") metanocites .
101 maybe id (setMeta "nocite") metanocites .
106− walk (map capitalizeNoteCitation .
107− fixQuotes . mvPunct moveNotes locale) .
102+ walk (mvPunct moveNotes locale) .
103+ (if styleIsNoteStyle sopts
108− walk deNote .
104+ then walk addNote . walk deNote
109 evalState (walkM insertResolvedCitations $ Pandoc meta' bs)
106 evalState (walkM insertResolvedCitations $ Pandoc meta' bs)
111 return $ Pandoc meta''
108 return $ Pandoc meta''
@@ -375,7 +372,6 @@ formatFromExtension fp = case dropWhile (== '.') $ takeExtension fp of
377isNote :: Inline -> Bool
374isNote :: Inline -> Bool
378−isNote (Note _) = True
379isNote (Cite _ [Note _]) = True
375isNote (Cite _ [Note _]) = True
380 -- the following allows citation styles that are "in-text" but use superscript
376 -- the following allows citation styles that are "in-text" but use superscript
381 -- references to be treated as if they are "notes" for the purposes of moving
377 -- references to be treated as if they are "notes" for the purposes of moving
@@ -388,6 +384,12 @@ isSpacy Space = True
388isSpacy SoftBreak = True
384isSpacy SoftBreak = True
389isSpacy _ = False
385isSpacy _ = False
387+movePunctInsideQuotes :: Locale -> [Inline] -> [Inline]
388+movePunctInsideQuotes locale
389+ | localePunctuationInQuote locale == Just True
390+ = B.toList . movePunctuationInsideQuotes . B.fromList
392mvPunct :: Bool -> Locale -> [Inline] -> [Inline]
394mvPunct :: Bool -> Locale -> [Inline] -> [Inline]
393mvPunct moveNotes locale (x : xs)
395mvPunct moveNotes locale (x : xs)
@@ -400,7 +402,8 @@ mvPunct moveNotes locale (q : s : x : ys)
400 in if moveNotes
402 in if moveNotes
401 then if T.null spunct
403 then if T.null spunct
402 then q : x : mvPunct moveNotes locale ys
404 then q : x : mvPunct moveNotes locale ys
405+ else movePunctInsideQuotes locale
403− else q : Str spunct : x : mvPunct moveNotes locale
406+ [q , Str spunct , x] ++ mvPunct moveNotes locale
404 (B.toList
407 (B.toList
405 (dropTextWhile isPunctuation (B.fromList ys)))
408 (dropTextWhile isPunctuation (B.fromList ys)))
406 else q : x : mvPunct moveNotes locale ys
409 else q : x : mvPunct moveNotes locale ys
@@ -412,9 +415,10 @@ mvPunct moveNotes locale (Cite cs ils : ys)
412 , moveNotes
415 , moveNotes
413 = let s = stringify ys
416 = let s = stringify ys
414 spunct = T.takeWhile isPunctuation s
417 spunct = T.takeWhile isPunctuation s
418+ in Cite cs (movePunctInsideQuotes locale $
415− in Cite cs (init ils
419+ init ils
416− ++ [Str spunct | not (endWithPunct False (init ils))]
420+ ++ [Str spunct | not (endWithPunct False (init ils))]
417− ++ [last ils]) :
421+ ++ [last ils]) :
418 mvPunct moveNotes locale
422 mvPunct moveNotes locale
419 (B.toList (dropTextWhile isPunctuation (B.fromList ys)))
423 (B.toList (dropTextWhile isPunctuation (B.fromList ys)))
420mvPunct moveNotes locale (s : x : ys) | isSpacy s, isNote x =
424mvPunct moveNotes locale (s : x : ys) | isSpacy s, isNote x =
@@ -560,42 +564,62 @@ extractText (FancyVal x) = toText x
560extractText (NumVal n) = T.pack (show n)
564extractText (NumVal n) = T.pack (show n)
561extractText _ = mempty
565extractText _ = mempty
567+-- Here we take the Spans with class csl-note that are left
568+-- after deNote has removed nested ones, and convert them
563−capitalizeNoteCitation :: Inline -> Inline
570+addNote :: Inline -> Inline
564−capitalizeNoteCitation (Cite cs [Note [Para ils]]) =
571+addNote (Span ("",["csl-note"],[]) ils) =
565− Cite cs
572+ Note [Para $
566− [Note [Para $ B.toList $ addTextCase Nothing CapitalizeFirst
573+ B.toList . addTextCase Nothing CapitalizeFirst . B.fromList $ ils]
567− $ B.fromList ils]]
574+addNote x = x
568−capitalizeNoteCitation x = x
575+
569−
576+-- Here we handle citation notes that occur inside footnotes
577+-- or other citation notes, in a note style. We don't want
578+-- notes inside notes, so we convert these to parenthesized
579+-- or comma-separated citations.
570−deNote :: [Inline] -> [Inline]
580+deNote :: Inline -> Inline
571−deNote [] = []
581+deNote (Note bs) =
572−deNote (Note bs:rest) =
582+ case bs of
573− Note (walk go bs) : deNote rest
583+ [Para (cit@(Cite (c:_) _) : ils)]
584+ | citationMode c /= AuthorInText ->
585+ -- if citation is first in note, no need to parenthesize.
586+ Note [Para (walk removeNotes $ cit : walk addParens ils)]
587+ _ -> Note (walk removeNotes . walk addParens $ bs)
575− go [] = []
590+ addParens [] = []
576− go (Cite (c:cs) ils : zs)
591+ addParens (Cite (c:cs) ils : zs)
577 | citationMode c == AuthorInText
592 | citationMode c == AuthorInText
578− = Cite (c:cs) (concatMap (noteAfterComma (needsPeriod zs)) ils) : go zs
593+ = Cite (c:cs) (concatMap (noteAfterComma (needsPeriod zs)) ils) :
579 | otherwise
595 | otherwise
580− = Cite (c:cs) (concatMap noteInParens ils) : go zs
596+ = Cite (c:cs) (concatMap noteInParens ils) : addParens zs
581− go (x:xs) = x : go xs
597+ addParens (x:xs) = x : addParens xs
599+ removeNotes (Span ("",["csl-note"],[]) ils) = Span ("",[],[]) ils
582 needsPeriod [] = True
602 needsPeriod [] = True
583 needsPeriod (Str t:_) = case T.uncons t of
603 needsPeriod (Str t:_) = case T.uncons t of
584 Nothing -> False
604 Nothing -> False
585 Just (c,_) -> isUpper c
605 Just (c,_) -> isUpper c
586 needsPeriod (Space:zs) = needsPeriod zs
606 needsPeriod (Space:zs) = needsPeriod zs
587 needsPeriod _ = False
607 needsPeriod _ = False
588− noteInParens (Note bs')
609+ noteInParens (Span ("",["csl-note"],[]) ils)
589 = Space : Str "(" :
610 = Space : Str "(" :
590− removeFinalPeriod (blocksToInlines bs') ++ [Str ")"]
611+ removeFinalPeriod ils ++ [Str ")"]
591 noteInParens x = [x]
612 noteInParens x = [x]
592− noteAfterComma needsPer (Note bs')
614+ noteAfterComma needsPer (Span ("",["csl-note"],[]) ils)
593 = Str "," : Space :
616 = Str "," : Space :
594− (if needsPer
617+ if needsPer
595− then id
618+ then ils
596− else removeFinalPeriod) (blocksToInlines bs')
619+ else removeFinalPeriod ils
597 noteAfterComma _ x = [x]
620 noteAfterComma _ x = [x]
598−deNote (x:xs) = x : deNote xs
622+deNote x = x
600-- Note: we can't use dropTextWhileEnd indiscriminately,
624-- Note: we can't use dropTextWhileEnd indiscriminately,
601-- because this would remove the final period on abbreviations like Ibid.
625-- because this would remove the final period on abbreviations like Ibid.