@@ -25,10 +25,10 @@ FictionBook is an XML-based e-book format. For more information see:
25<http://www.fictionbook.org/index.php/Eng:XML_Schema_Fictionbook_2.1>
25<http://www.fictionbook.org/index.php/Eng:XML_Schema_Fictionbook_2.1>
28−module Text.Pandoc.Writers.FB2 (writeFB2) where
28+module Text.Pandoc.Writers.FB2 (writeFB2, writeFB2Pure) where
30−import Control.Monad.State (StateT, evalStateT, get, modify)
30+import Control.Monad.State (StateT, evalStateT, get, modify, lift)
31−import Control.Monad.State (liftM, liftIO)
31+import Control.Monad.State (liftM)
32import Data.ByteString.Base64 (encode)
32import Data.ByteString.Base64 (encode)
33import Data.Char (toLower, isSpace, isAscii, isControl)
33import Data.Char (toLower, isSpace, isAscii, isControl)
34import Data.List (intersperse, intercalate, isPrefixOf, stripPrefix)
34import Data.List (intersperse, intercalate, isPrefixOf, stripPrefix)
@@ -44,7 +44,9 @@ import qualified Data.ByteString.Char8 as B8
44import Text.Pandoc.Definition
44import Text.Pandoc.Definition
45import Text.Pandoc.Options (WriterOptions(..), HTMLMathMethod(..), def)
45import Text.Pandoc.Options (WriterOptions(..), HTMLMathMethod(..), def)
46import Text.Pandoc.Shared (orderedListMarkers, isHeaderBlock, capitalize,
46import Text.Pandoc.Shared (orderedListMarkers, isHeaderBlock, capitalize,
47− linesToPara, fetchItem)
47+ linesToPara)
48+import Text.Pandoc.Free (PandocAction, runIO)
49+import qualified Text.Pandoc.Free as P
49-- | Data to be written at the end of the document:
51-- | Data to be written at the end of the document:
50-- (foot)notes, URLs, references, images.
52-- (foot)notes, URLs, references, images.
@@ -57,7 +59,7 @@ data FbRenderState = FbRenderState
57 } deriving (Show)
59 } deriving (Show)
59-- | FictionBook building monad.
61-- | FictionBook building monad.
60−type FBM = StateT FbRenderState IO
62+type FBM = StateT FbRenderState PandocAction
62newFB :: FbRenderState
64newFB :: FbRenderState
63newFB = FbRenderState { footnotes = [], imagesToFetch = []
65newFB = FbRenderState { footnotes = [], imagesToFetch = []
@@ -73,7 +75,12 @@ instance Show ImageMode where
73writeFB2 :: WriterOptions -- ^ conversion options
75writeFB2 :: WriterOptions -- ^ conversion options
74 -> Pandoc -- ^ document to convert
76 -> Pandoc -- ^ document to convert
75 -> IO String -- ^ FictionBook2 document (not encoded yet)
77 -> IO String -- ^ FictionBook2 document (not encoded yet)
78+writeFB2 opts doc = runIO $ writeFB2Pure opts doc
80+writeFB2Pure :: WriterOptions
82+ -> PandocAction String
76−writeFB2 opts doc = flip evalStateT newFB $ pandocToFB2 opts doc
83+writeFB2Pure opts doc = flip evalStateT newFB $ pandocToFB2 opts doc
78pandocToFB2 :: WriterOptions
85pandocToFB2 :: WriterOptions
@@ -85,7 +92,7 @@ pandocToFB2 opts (Pandoc meta blocks) = do
85 secs <- renderSections 1 blocks
92 secs <- renderSections 1 blocks
86 let body = el "body" $ fp ++ secs
93 let body = el "body" $ fp ++ secs
87 notes <- renderFootnotes
94 notes <- renderFootnotes
88− (imgs,missing) <- liftM imagesToFetch get >>= \s -> liftIO (fetchImages s)
95+ (imgs,missing) <- liftM imagesToFetch get >>= \s -> lift (fetchImages s)
89 let body' = replaceImagesWithAlt missing body
96 let body' = replaceImagesWithAlt missing body
90 let fb2_xml = el "FictionBook" (fb2_attrs, [desc, body'] ++ notes ++ imgs)
97 let fb2_xml = el "FictionBook" (fb2_attrs, [desc, body'] ++ notes ++ imgs)
91 return $ xml_head ++ (showContent fb2_xml) ++ "\n"
98 return $ xml_head ++ (showContent fb2_xml) ++ "\n"
@@ -217,14 +224,14 @@ renderFootnotes = do
218-- | Fetch images and encode them for the FictionBook XML.
225-- | Fetch images and encode them for the FictionBook XML.
219-- Return image data and a list of hrefs of the missing images.
226-- Return image data and a list of hrefs of the missing images.
220−fetchImages :: [(String,String)] -> IO ([Content],[String])
227+fetchImages :: [(String,String)] -> PandocAction ([Content],[String])
221fetchImages links = do
228fetchImages links = do
222 imgs <- mapM (uncurry fetchImage) links
229 imgs <- mapM (uncurry fetchImage) links
223 return $ (rights imgs, lefts imgs)
230 return $ (rights imgs, lefts imgs)
225-- | Fetch image data from disk or from network and make a <binary> XML section.
232-- | Fetch image data from disk or from network and make a <binary> XML section.
226-- Return either (Left hrefOfMissingImage) or (Right xmlContent).
233-- Return either (Left hrefOfMissingImage) or (Right xmlContent).
227−fetchImage :: String -> String -> IO (Either String Content)
234+fetchImage :: String -> String -> PandocAction (Either String Content)
228fetchImage href link = do
235fetchImage href link = do
230 case (isURI link, readDataURI link) of
237 case (isURI link, readDataURI link) of
@@ -235,7 +242,7 @@ fetchImage href link = do
235 else return Nothing
242 else return Nothing
236 (True, Just _) -> return Nothing -- not base64-encoded
243 (True, Just _) -> return Nothing -- not base64-encoded
238− response <- fetchItem Nothing link
245+ response <- P.fetchItem Nothing link
239 case response of
246 case response of
240 Right (bs, Just mime) -> return $ Just (mime, B8.unpack $ encode bs)
247 Right (bs, Just mime) -> return $ Just (mime, B8.unpack $ encode bs)
241 _ -> return $ Nothing
248 _ -> return $ Nothing