aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Text/Pandoc/Writers/Muse.hs50
-rw-r--r--test/Tests/Writers/Muse.hs88
2 files changed, 129 insertions, 9 deletions
diff --git a/src/Text/Pandoc/Writers/Muse.hs b/src/Text/Pandoc/Writers/Muse.hs
index 408215602..46aae113b 100644
--- a/src/Text/Pandoc/Writers/Muse.hs
+++ b/src/Text/Pandoc/Writers/Muse.hs
@@ -80,12 +80,14 @@ data WriterEnv =
data WriterState =
WriterState { stNotes :: Notes
+ , stNoteNum :: Int
, stIds :: Set.Set String
, stUseTags :: Bool -- ^ Use tags for emphasis, for example because previous character is a letter
}
instance Default WriterState
where def = WriterState { stNotes = []
+ , stNoteNum = 1
, stIds = Set.empty
, stUseTags = False
}
@@ -127,7 +129,7 @@ pandocToMuse (Pandoc meta blocks) = do
(fmap render' . inlineListToMuse)
meta
body <- blockListToMuse blocks
- notes <- fmap (reverse . stNotes) get >>= notesToMuse
+ notes <- currentNotesToMuse
let main = render colwidth $ body $+$ notes
let context = defField "body" main metadata
case writerTemplate opts of
@@ -141,7 +143,7 @@ catWithBlankLines :: PandocMonad m
-> Int -- ^ Number of blank lines
-> Muse m Doc
catWithBlankLines (b : bs) n = do
- b' <- blockToMuse b
+ b' <- blockToMuseWithNotes b
bs' <- flatBlockListToMuse bs
return $ b' <> blanklines n <> bs'
catWithBlankLines _ _ = error "Expected at least one block"
@@ -290,26 +292,61 @@ blockToMuse (Table caption aligns widths headers rows) =
blockToMuse (Div _ bs) = flatBlockListToMuse bs
blockToMuse Null = return empty
+-- | Return Muse representation of notes collected so far.
+currentNotesToMuse :: PandocMonad m
+ => Muse m Doc
+currentNotesToMuse = do
+ notes <- reverse <$> gets stNotes
+ modify $ \st -> st { stNotes = mempty }
+ notesToMuse notes
+
-- | Return Muse representation of notes.
notesToMuse :: PandocMonad m
=> Notes
-> Muse m Doc
-notesToMuse notes = vsep <$> zipWithM noteToMuse [1 ..] notes
+notesToMuse notes = do
+ n <- gets stNoteNum
+ modify $ \st -> st { stNoteNum = stNoteNum st + length notes }
+ vsep <$> zipWithM noteToMuse [n ..] notes
-- | Return Muse representation of a note.
noteToMuse :: PandocMonad m
=> Int
-> [Block]
-> Muse m Doc
-noteToMuse num note =
- hang (length marker) (text marker) <$>
+noteToMuse num note = do
+ res <- hang (length marker) (text marker) <$>
local (\env -> env { envInsideBlock = True
, envInlineStart = True
, envAfterSpace = True
}) (blockListToMuse note)
+ return $ res <> blankline
where
marker = "[" ++ show num ++ "] "
+-- | Return Muse representation of block and accumulated notes.
+blockToMuseWithNotes :: PandocMonad m
+ => Block
+ -> Muse m Doc
+blockToMuseWithNotes blk = do
+ topLevel <- asks envTopLevel
+ opts <- asks envOptions
+ let hdrToMuse hdr@(Header{}) = do
+ b <- blockToMuse hdr
+ if topLevel && writerReferenceLocation opts == EndOfSection
+ then do
+ notes <- currentNotesToMuse
+ return $ notes $+$ b
+ else
+ return b
+ hdrToMuse b = blockToMuse b
+ b <- hdrToMuse blk
+ if topLevel && writerReferenceLocation opts == EndOfBlock
+ then do
+ notes <- currentNotesToMuse
+ return $ b $+$ notes <> blankline
+ else return b
+
-- | Escape special characters for Muse.
escapeString :: String -> String
escapeString s =
@@ -659,7 +696,8 @@ inlineToMuse (Note contents) = do
modify $ \st -> st { stNotes = contents:notes
, stUseTags = False
}
- let ref = show $ length notes + 1
+ n <- gets stNoteNum
+ let ref = show $ n + length notes
return $ "[" <> text ref <> "]"
inlineToMuse (Span (anchor,names,_) inlines) = do
contents <- inlineListToMuse inlines
diff --git a/test/Tests/Writers/Muse.hs b/test/Tests/Writers/Muse.hs
index 57fbb3e57..ad4f421a3 100644
--- a/test/Tests/Writers/Muse.hs
+++ b/test/Tests/Writers/Muse.hs
@@ -9,10 +9,13 @@ import Text.Pandoc
import Text.Pandoc.Arbitrary ()
import Text.Pandoc.Builder
+defopts :: WriterOptions
+defopts = def{ writerWrapText = WrapPreserve,
+ writerExtensions = extensionsFromList [Ext_amuse,
+ Ext_auto_identifiers] }
+
muse :: (ToPandoc a) => a -> String
-muse = museWithOpts def{ writerWrapText = WrapPreserve,
- writerExtensions = extensionsFromList [Ext_amuse,
- Ext_auto_identifiers] }
+muse = museWithOpts defopts
museWithOpts :: (ToPandoc a) => WriterOptions -> a -> String
museWithOpts opts = unpack . purely (writeMuse opts) . toPandoc
@@ -22,6 +25,84 @@ infix 4 =:
=> String -> (a, String) -> TestTree
(=:) = test muse
+noteLocationTestDoc :: Blocks
+noteLocationTestDoc =
+ header 1 (text "First Header") <>
+ para (text "This is a footnote." <>
+ note (para (text "First note."))) <>
+ blockQuote (para (text "A note inside a block quote." <>
+ note (para (text "The second note."))) <>
+ para (text "A second paragraph.")) <>
+ header 1 (text "Second Header") <>
+ para (text "Some more text.")
+
+noteLocationTests :: TestTree
+noteLocationTests = testGroup "note location"
+ [ test (museWithOpts defopts {writerReferenceLocation=EndOfDocument})
+ "footnotes at the end of document" $
+ noteLocationTestDoc =?>
+ (unlines [ "* First Header"
+ , ""
+ , "This is a footnote.[1]"
+ , ""
+ , "<quote>"
+ , "A note inside a block quote.[2]"
+ , ""
+ , "A second paragraph."
+ , "</quote>"
+ , ""
+ , "* Second Header"
+ , ""
+ , "Some more text."
+ , ""
+ , "[1] First note."
+ , ""
+ , "[2] The second note."
+ ])
+ , test (museWithOpts defopts {writerReferenceLocation=EndOfBlock})
+ "footnotes at the end of block" $
+ noteLocationTestDoc =?>
+ (unlines [ "* First Header"
+ , ""
+ , "This is a footnote.[1]"
+ , ""
+ , "[1] First note."
+ , ""
+ , "<quote>"
+ , "A note inside a block quote.[2]"
+ , ""
+ , "[2] The second note."
+ , ""
+ , "A second paragraph."
+ , "</quote>"
+ , ""
+ , "* Second Header"
+ , ""
+ , "Some more text."
+ ])
+ , test (museWithOpts defopts {writerReferenceLocation=EndOfSection})
+ "footnotes at the end of section" $
+ noteLocationTestDoc =?>
+ (unlines [ "* First Header"
+ , ""
+ , "This is a footnote.[1]"
+ , ""
+ , "<quote>"
+ , "A note inside a block quote.[2]"
+ , ""
+ , "A second paragraph."
+ , "</quote>"
+ , ""
+ , "[1] First note."
+ , ""
+ , "[2] The second note."
+ , ""
+ , "* Second Header"
+ , ""
+ , "Some more text."
+ ])
+ ]
+
tests :: [TestTree]
tests = [ testGroup "block elements"
[ "plain" =: plain (text "Foo bar.") =?> "Foo bar."
@@ -501,6 +582,7 @@ tests = [ testGroup "block elements"
, ""
, "[1] Foo"
]
+ , noteLocationTests
, "span with class" =: spanWith ("",["foobar"],[]) (text "Some text")
=?> "<class name=\"foobar\">Some text</class>"
, "span without class" =: spanWith ("",[],[]) (text "Some text")