@@ -0,0 +1,181 @@
1+{-# LANGUAGE OverloadedStrings #-}
3+Module : Text.Pandoc.Writers.Docx
4+Copyright : Copyright (C) 2012-2021 John MacFarlane
5+License : GNU GPL, version 2 or above
6+Maintainer : John MacFarlane <jgm@berkeley.edu>
8+Conversion of table blocks to docx.
10+module Text.Pandoc.Writers.Docx.Types
26+import Control.Applicative ((<|>))
27+import Control.Monad.Reader
28+import Control.Monad.State.Strict
29+import Data.Text (Text)
30+import Text.Pandoc.Class.PandocMonad (PandocMonad)
31+import Text.Pandoc.Definition
32+import Text.Pandoc.MIME (MimeType)
33+import Text.Pandoc.Writers.Docx.StyleMap
34+import Text.Pandoc.Writers.OOXML
35+import Text.Pandoc.XML.Light as XML
36+import qualified Data.ByteString as B
37+import qualified Data.Map as M
38+import qualified Data.Set as Set
39+import qualified Data.Text as T
41+data ListMarker = NoMarker
43+ | NumberMarker ListNumberStyle ListNumberDelim Int
44+ deriving (Show, Read, Eq, Ord)
46+listMarkerToId :: ListMarker -> Text
47+listMarkerToId NoMarker = "990"
48+listMarkerToId BulletMarker = "991"
49+listMarkerToId (NumberMarker sty delim n) = T.pack $
50+ '9' : '9' : styNum : delimNum : show n
51+ where styNum = case sty of
59+ delimNum = case delim of
66+data EnvProps = EnvProps{ styleElement :: Maybe Element
67+ , otherElements :: [Element]
70+instance Semigroup EnvProps where
71+ EnvProps s es <> EnvProps s' es' = EnvProps (s <|> s') (es ++ es')
73+instance Monoid EnvProps where
74+ mempty = EnvProps Nothing []
77+data WriterEnv = WriterEnv
78+ { envTextProperties :: EnvProps
79+ , envParaProperties :: EnvProps
81+ , envListLevel :: Int
82+ , envListNumId :: Int
84+ , envChangesAuthor :: Text
85+ , envChangesDate :: Text
86+ , envPrintWidth :: Integer
89+defaultWriterEnv :: WriterEnv
90+defaultWriterEnv = WriterEnv
91+ { envTextProperties = mempty
92+ , envParaProperties = mempty
97+ , envChangesAuthor = "unknown"
98+ , envChangesDate = "1969-12-31T19:00:00Z"
103+data WriterState = WriterState{
104+ stFootnotes :: [Element]
105+ , stComments :: [([(Text, Text)], [Inline])]
106+ , stSectionIds :: Set.Set Text
107+ , stExternalLinks :: M.Map Text Text
108+ , stImages :: M.Map FilePath (String, String, Maybe MimeType, B.ByteString)
109+ , stLists :: [ListMarker]
112+ , stStyleMaps :: StyleMaps
113+ , stFirstPara :: Bool
116+ , stTocTitle :: [Inline]
117+ , stDynamicParaProps :: Set.Set ParaStyleName
118+ , stDynamicTextProps :: Set.Set CharStyleName
122+defaultWriterState :: WriterState
123+defaultWriterState = WriterState{
124+ stFootnotes = defaultFootnotes
126+ , stSectionIds = Set.empty
127+ , stExternalLinks = M.empty
128+ , stImages = M.empty
129+ , stLists = [NoMarker]
132+ , stStyleMaps = StyleMaps M.empty M.empty
133+ , stFirstPara = False
136+ , stTocTitle = [Str "Table of Contents"]
137+ , stDynamicParaProps = Set.empty
138+ , stDynamicTextProps = Set.empty
142+setFirstPara :: PandocMonad m => WS m ()
143+setFirstPara = modify $ \s -> s { stFirstPara = True }
145+type WS m = ReaderT WriterEnv (StateT WriterState m)
147+-- Word will insert these footnotes into the settings.xml file
148+-- (whether or not they're visible in the document). If they're in the
149+-- file, but not in the footnotes.xml file, it will produce
150+-- problems. So we want to make sure we insert them into our document.
151+defaultFootnotes :: [Element]
152+defaultFootnotes = [ mknode "w:footnote"
153+ [("w:type", "separator"), ("w:id", "-1")]
156+ [ mknode "w:separator" [] ()]]]
157+ , mknode "w:footnote"
158+ [("w:type", "continuationSeparator"), ("w:id", "0")]
161+ [ mknode "w:continuationSeparator" [] ()]]]]
163+pStyleM :: (PandocMonad m) => ParaStyleName -> WS m XML.Element
164+pStyleM styleName = do
165+ pStyleMap <- gets (smParaStyle . stStyleMaps)
166+ let sty' = getStyleIdFromName styleName pStyleMap
167+ return $ mknode "w:pStyle" [("w:val", fromStyleId sty')] ()
169+withParaProp :: PandocMonad m => Element -> WS m a -> WS m a
171+ local (\env -> env {envParaProperties = ep <> envParaProperties env}) p
172+ where ep = if isStyle d then EnvProps (Just d) [] else EnvProps Nothing [d]
174+withParaPropM :: PandocMonad m => WS m Element -> WS m a -> WS m a
175+withParaPropM md p = do
179+isStyle :: Element -> Bool
180+isStyle e = isElem [] "w" "rStyle" e ||
181+ isElem [] "w" "pStyle" e