@@ -28,7 +28,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
2828
2929Conversion of 'Pandoc' documents to docx.
3030-}
31−module Text.Pandoc.Writers.Docx ( writeDocx, writeDocxPure ) where
31+module Text.Pandoc.Writers.Docx ( writeDocx ) where
3232import Data.List ( intercalate, isPrefixOf, isSuffixOf )
3333import qualified Data.ByteString as B
3434import qualified Data.ByteString.Lazy as BL
@@ -65,8 +65,8 @@ import Text.Pandoc.MIME (MimeType, getMimeType, getMimeTypeDef,
6565import Control.Applicative ((<|>))
6666import Data.Maybe (fromMaybe, mapMaybe, maybeToList, isNothing)
6767import Data.Char (ord, isSpace, toLower)
68−import Text.Pandoc.Free (PandocAction, runIO)
69−import qualified Text.Pandoc.Free as P
68+import Text.Pandoc.Class (PandocMonad)
69+import qualified Text.Pandoc.Class as P
7070
7171data ListMarker = NoMarker
7272 | BulletMarker
@@ -146,7 +146,7 @@ defaultWriterState = WriterState{
146146 , stDynamicTextProps = []
147147 }
148148
149−type WS = ReaderT WriterEnv (StateT WriterState (PandocAction))
149+type WS m = ReaderT WriterEnv (StateT WriterState m)
150150
151151mknode :: Node t => String -> [(String,String)] -> t -> Element
152152mknode s attrs =
@@ -215,17 +215,11 @@ metaValueToInlines _ = []
215215
216216
217217
218−writeDocx :: WriterOptions -- ^ Writer options
218+writeDocx :: (PandocMonad m)
219+ => WriterOptions -- ^ Writer options
219220 -> Pandoc -- ^ Document to convert
220− -> IO BL.ByteString
221−writeDocx opts doc = runIO $ writeDocxPure opts doc
222−
223−
224−-- | Produce an Docx file from a Pandoc document.
225−writeDocxPure :: WriterOptions -- ^ Writer options
226− -> Pandoc -- ^ Document to convert
227− -> PandocAction BL.ByteString
228−writeDocxPure opts doc@(Pandoc meta _) = do
221+ -> m BL.ByteString
222+writeDocx opts doc@(Pandoc meta _) = do
229223 let datadir = writerUserDataDir opts
230224 let doc' = walk fixDisplayMath $ doc
231225 username <- P.lookupEnv "USERNAME"
@@ -611,7 +605,7 @@ styleToOpenXml sm style =
611605 $ backgroundColor style )
612606 ]
613607
614−copyChildren :: Archive -> Archive -> String -> Integer -> [String] -> PandocAction Entry
608+copyChildren :: (PandocMonad m) => Archive -> Archive -> String -> Integer -> [String] -> m Entry
615609copyChildren refArchive distArchive path timestamp elNames = do
616610 ref <- parseXml refArchive distArchive path
617611 dist <- parseXml distArchive distArchive path
@@ -630,7 +624,7 @@ copyChildren refArchive distArchive path timestamp elNames = do
630624baseListId :: Int
631625baseListId = 1000
632626
633−mkNumbering :: [ListMarker] -> PandocAction [Element]
627+mkNumbering :: (PandocMonad m) => [ListMarker] -> m [Element]
634628mkNumbering lists = do
635629 elts <- mapM mkAbstractNum (ordNub lists)
636630 return $ elts ++ zipWith mkNum lists [baseListId..(baseListId + length lists - 1)]
@@ -646,7 +640,7 @@ mkNum marker numid =
646640 map (\lvl -> mknode "w:lvlOverride" [("w:ilvl",show (lvl :: Int))]
647641 $ mknode "w:startOverride" [("w:val",show start)] ()) [0..6]
648642
649−mkAbstractNum :: ListMarker -> PandocAction Element
643+mkAbstractNum :: (PandocMonad m) => ListMarker -> m Element
650644mkAbstractNum marker = do
651645 gen <- P.newStdGen
652646 let (nsid, _) = randomR (0x10000000 :: Integer, 0xFFFFFFFF :: Integer) gen
@@ -701,11 +695,11 @@ mkLvl marker lvl =
701695 patternFor TwoParens s = "(" ++ s ++ ")"
702696 patternFor _ s = s ++ "."
703697
704−getNumId :: WS Int
698+getNumId :: (PandocMonad m) => WS m Int
705699getNumId = (((baseListId - 1) +) . length) `fmap` gets stLists
706700
707701
708−makeTOC :: WriterOptions -> WS [Element]
702+makeTOC :: (PandocMonad m) => WriterOptions -> WS m [Element]
709703makeTOC opts | writerTableOfContents opts = do
710704 let depth = "1-"++(show (writerTOCDepth opts))
711705 let tocCmd = "TOC \\o \""++depth++"\" \\h \\z \\u"
@@ -735,7 +729,7 @@ makeTOC _ = return []
735729
736730-- | Convert Pandoc document to two lists of
737731-- OpenXML elements (the main document and footnotes).
738−writeOpenXML :: WriterOptions -> Pandoc -> WS ([Element], [Element])
732+writeOpenXML :: (PandocMonad m) => WriterOptions -> Pandoc -> WS m ([Element], [Element])
739733writeOpenXML opts (Pandoc meta blocks) = do
740734 let tit = docTitle meta ++ case lookupMeta "subtitle" meta of
741735 Just (MetaBlocks [Plain xs]) -> LineBreak : xs
@@ -770,13 +764,13 @@ writeOpenXML opts (Pandoc meta blocks) = do
770764 return (meta' ++ doc', notes')
771765
772766-- | Convert a list of Pandoc blocks to OpenXML.
773−blocksToOpenXML :: WriterOptions -> [Block] -> WS [Element]
767+blocksToOpenXML :: (PandocMonad m) => WriterOptions -> [Block] -> WS m [Element]
774768blocksToOpenXML opts bls = concat `fmap` mapM (blockToOpenXML opts) bls
775769
776770pCustomStyle :: String -> Element
777771pCustomStyle sty = mknode "w:pStyle" [("w:val",sty)] ()
778772
779−pStyleM :: String -> WS XML.Element
773+pStyleM :: (PandocMonad m) => String -> WS m XML.Element
780774pStyleM styleName = do
781775 styleMaps <- gets stStyleMaps
782776 let sty' = getStyleId styleName $ sParaStyleMap styleMaps
@@ -785,13 +779,13 @@ pStyleM styleName = do
785779rCustomStyle :: String -> Element
786780rCustomStyle sty = mknode "w:rStyle" [("w:val",sty)] ()
787781
788−rStyleM :: String -> WS XML.Element
782+rStyleM :: (PandocMonad m) => String -> WS m XML.Element
789783rStyleM styleName = do
790784 styleMaps <- gets stStyleMaps
791785 let sty' = getStyleId styleName $ sCharStyleMap styleMaps
792786 return $ mknode "w:rStyle" [("w:val",sty')] ()
793787
794−getUniqueId :: PandocAction String
788+getUniqueId :: (PandocMonad m) => m String
795789-- the + 20 is to ensure that there are no clashes with the rIds
796790-- already in word/document.xml.rel
797791getUniqueId = (show . (+ 20)) <$> P.newUniqueHash
@@ -801,10 +795,10 @@ dynamicStyleKey :: String
801795dynamicStyleKey = "custom-style"
802796
803797-- | Convert a Pandoc block element to OpenXML.
804−blockToOpenXML :: WriterOptions -> Block -> WS [Element]
798+blockToOpenXML :: (PandocMonad m) => WriterOptions -> Block -> WS m [Element]
805799blockToOpenXML opts blk = withDirection $ blockToOpenXML' opts blk
806800
807−blockToOpenXML' :: WriterOptions -> Block -> WS [Element]
801+blockToOpenXML' :: (PandocMonad m) => WriterOptions -> Block -> WS m [Element]
808802blockToOpenXML' _ Null = return []
809803blockToOpenXML' opts (Div (ident,classes,kvs) bs)
810804 | Just sty <- lookup dynamicStyleKey kvs = do
@@ -955,7 +949,7 @@ blockToOpenXML' opts (DefinitionList items) = do
955949 setFirstPara
956950 return l
957951
958−definitionListItemToOpenXML :: WriterOptions -> ([Inline],[[Block]]) -> WS [Element]
952+definitionListItemToOpenXML :: (PandocMonad m) => WriterOptions -> ([Inline],[[Block]]) -> WS m [Element]
959953definitionListItemToOpenXML opts (term,defs) = do
960954 term' <- withParaProp (pCustomStyle "DefinitionTerm")
961955 $ blockToOpenXML opts (Para term)
@@ -963,12 +957,12 @@ definitionListItemToOpenXML opts (term,defs) = do
963957 $ concat `fmap` mapM (blocksToOpenXML opts) defs
964958 return $ term' ++ defs'
965959
966−addList :: ListMarker -> WS ()
960+addList :: (PandocMonad m) => ListMarker -> WS m ()
967961addList marker = do
968962 lists <- gets stLists
969963 modify $ \st -> st{ stLists = lists ++ [marker] }
970964
971−listItemToOpenXML :: WriterOptions -> Int -> [Block] -> WS [Element]
965+listItemToOpenXML :: (PandocMonad m) => WriterOptions -> Int -> [Block] -> WS m [Element]
972966listItemToOpenXML _ _ [] = return []
973967listItemToOpenXML opts numid (first:rest) = do
974968 first' <- withNumId numid $ blockToOpenXML opts first
@@ -984,30 +978,30 @@ alignmentToString alignment = case alignment of
984978 AlignDefault -> "left"
985979
986980-- | Convert a list of inline elements to OpenXML.
987−inlinesToOpenXML :: WriterOptions -> [Inline] -> WS [Element]
981+inlinesToOpenXML :: (PandocMonad m) => WriterOptions -> [Inline] -> WS m [Element]
988982inlinesToOpenXML opts lst = concat `fmap` mapM (inlineToOpenXML opts) lst
989983
990−withNumId :: Int -> WS a -> WS a
984+withNumId :: (PandocMonad m) => Int -> WS m a -> WS m a
991985withNumId numid = local $ \env -> env{ envListNumId = numid }
992986
993−asList :: WS a -> WS a
987+asList :: (PandocMonad m) => WS m a -> WS m a
994988asList = local $ \env -> env{ envListLevel = envListLevel env + 1 }
995989
996−getTextProps :: WS [Element]
990+getTextProps :: (PandocMonad m) => WS m [Element]
997991getTextProps = do
998992 props <- asks envTextProperties
999993 return $ if null props
1000994 then []
1001995 else [mknode "w:rPr" [] props]
1002996
1003−withTextProp :: Element -> WS a -> WS a
997+withTextProp :: PandocMonad m => Element -> WS m a -> WS m a
1004998withTextProp d p =
1005999 local (\env -> env {envTextProperties = d : envTextProperties env}) p
10061000
1007−withTextPropM :: WS Element -> WS a -> WS a
1001+withTextPropM :: PandocMonad m => WS m Element -> WS m a -> WS m a
10081002withTextPropM = (. flip withTextProp) . (>>=)
10091003
1010−getParaProps :: Bool -> WS [Element]
1004+getParaProps :: PandocMonad m => Bool -> WS m [Element]
10111005getParaProps displayMathPara = do
10121006 props <- asks envParaProperties
10131007 listLevel <- asks envListLevel
@@ -1022,14 +1016,14 @@ getParaProps displayMathPara = do
10221016 [] -> []
10231017 ps -> [mknode "w:pPr" [] ps]
10241018
1025−withParaProp :: Element -> WS a -> WS a
1019+withParaProp :: PandocMonad m => Element -> WS m a -> WS m a
10261020withParaProp d p =
10271021 local (\env -> env {envParaProperties = d : envParaProperties env}) p
10281022
1029−withParaPropM :: WS Element -> WS a -> WS a
1023+withParaPropM :: PandocMonad m => WS m Element -> WS m a -> WS m a
10301024withParaPropM = (. flip withParaProp) . (>>=)
10311025
1032−formattedString :: String -> WS [Element]
1026+formattedString :: PandocMonad m => String -> WS m [Element]
10331027formattedString str = do
10341028 props <- getTextProps
10351029 inDel <- asks envInDel
@@ -1038,14 +1032,14 @@ formattedString str = do
10381032 [ mknode (if inDel then "w:delText" else "w:t")
10391033 [("xml:space","preserve")] (stripInvalidChars str) ] ]
10401034
1041−setFirstPara :: WS ()
1035+setFirstPara :: PandocMonad m => WS m ()
10421036setFirstPara = modify $ \s -> s { stFirstPara = True }
10431037
10441038-- | Convert an inline element to OpenXML.
1045−inlineToOpenXML :: WriterOptions -> Inline -> WS [Element]
1039+inlineToOpenXML :: PandocMonad m => WriterOptions -> Inline -> WS m [Element]
10461040inlineToOpenXML opts il = withDirection $ inlineToOpenXML' opts il
10471041
1048−inlineToOpenXML' :: WriterOptions -> Inline -> WS [Element]
1042+inlineToOpenXML' :: PandocMonad m => WriterOptions -> Inline -> WS m [Element]
10491043inlineToOpenXML' _ (Str str) = formattedString str
10501044inlineToOpenXML' opts Space = inlineToOpenXML opts (Str " ")
10511045inlineToOpenXML' opts SoftBreak = inlineToOpenXML opts (Str " ")
@@ -1281,7 +1275,7 @@ defaultFootnotes = [ mknode "w:footnote"
12811275 [ mknode "w:r" [] $
12821276 [ mknode "w:continuationSeparator" [] ()]]]]
12831277
1284−parseXml :: Archive -> Archive -> String -> PandocAction Element
1278+parseXml :: (PandocMonad m) => Archive -> Archive -> String -> m Element
12851279parseXml refArchive distArchive relpath =
12861280 case findEntryByPath relpath refArchive `mplus`
12871281 findEntryByPath relpath distArchive of
@@ -1299,7 +1293,7 @@ fitToPage (x, y) pageWidth
12991293 (pageWidth, floor $ ((fromIntegral pageWidth) / x) * y)
13001294 | otherwise = (floor x, floor y)
13011295
1302−withDirection :: WS a -> WS a
1296+withDirection :: PandocMonad m => WS m a -> WS m a
13031297withDirection x = do
13041298 isRTL <- asks envRTL
13051299 paraProps <- asks envParaProperties