@@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29Conversion of 'Pandoc' documents to docx.
29Conversion of 'Pandoc' documents to docx.
31module Text.Pandoc.Writers.Docx ( writeDocx ) where
31module Text.Pandoc.Writers.Docx ( writeDocx ) where
32−import Data.List ( intercalate, isPrefixOf, isSuffixOf, stripPrefix )
32+import Data.List ( intercalate, isPrefixOf, isSuffixOf )
33import qualified Data.ByteString as B
33import qualified Data.ByteString as B
34import qualified Data.ByteString.Lazy as BL
34import qualified Data.ByteString.Lazy as BL
35import qualified Data.ByteString.Lazy.Char8 as BL8
35import qualified Data.ByteString.Lazy.Char8 as BL8
@@ -54,6 +54,8 @@ import Text.Pandoc.Walk
54import Text.Highlighting.Kate.Types ()
54import Text.Highlighting.Kate.Types ()
55import Text.XML.Light as XML
55import Text.XML.Light as XML
56import Text.TeXMath
56import Text.TeXMath
57+import Text.Pandoc.Readers.Docx.StyleMap
58+import Text.Pandoc.Readers.Docx.Util (elemName)
57import Control.Monad.State
59import Control.Monad.State
58import Text.Highlighting.Kate
60import Text.Highlighting.Kate
59import Data.Unique (hashUnique, newUnique)
61import Data.Unique (hashUnique, newUnique)
@@ -63,8 +65,7 @@ import qualified Control.Exception as E
63import Text.Pandoc.MIME (MimeType, getMimeType, getMimeTypeDef,
65import Text.Pandoc.MIME (MimeType, getMimeType, getMimeTypeDef,
64 extensionFromMimeType)
66 extensionFromMimeType)
65import Control.Applicative ((<$>), (<|>), (<*>))
67import Control.Applicative ((<$>), (<|>), (<*>))
66−import Data.Maybe (fromMaybe, mapMaybe)
68+import Data.Maybe (fromMaybe, mapMaybe, maybeToList)
67−import Data.Char (isDigit)
69data ListMarker = NoMarker
70data ListMarker = NoMarker
70 | BulletMarker
71 | BulletMarker
@@ -106,7 +107,7 @@ data WriterState = WriterState{
106 , stChangesAuthor :: String
107 , stChangesAuthor :: String
107 , stChangesDate :: String
108 , stChangesDate :: String
108 , stPrintWidth :: Integer
109 , stPrintWidth :: Integer
109− , stHeadingStyles :: [(Int,String)]
110+ , stStyleMaps :: StyleMaps
110 , stFirstPara :: Bool
111 , stFirstPara :: Bool
@@ -127,7 +128,7 @@ defaultWriterState = WriterState{
127 , stChangesAuthor = "unknown"
128 , stChangesAuthor = "unknown"
128 , stChangesDate = "1969-12-31T19:00:00Z"
129 , stChangesDate = "1969-12-31T19:00:00Z"
129 , stPrintWidth = 1
130 , stPrintWidth = 1
130− , stHeadingStyles = []
131+ , stStyleMaps = defaultStyleMaps
131 , stFirstPara = False
132 , stFirstPara = False
@@ -215,32 +216,14 @@ writeDocx opts doc@(Pandoc meta _) = do
215 styledoc <- parseXml refArchive distArchive stylepath
216 styledoc <- parseXml refArchive distArchive stylepath
217 -- parse styledoc for heading styles
218 -- parse styledoc for heading styles
218− let styleNamespaces = map ((,) <$> qName . attrKey <*> attrVal) .
219+ let styleMaps = getStyleMaps styledoc
219− filter ((==Just "xmlns") . qPrefix . attrKey) .
220− elAttribs $ styledoc
223− mywURI = lookup "w" styleNamespaces
224− myName name = QName name mywURI (Just "w")
225− getAttrStyleId = findAttr (myName "styleId")
226− getNameVal = findChild (myName "name") >=> findAttr (myName "val")
227− getNum s | not $ null s, all isDigit s = Just (read s :: Int)
228− | otherwise = Nothing
229− getEngHeader = getAttrStyleId >=> stripPrefix "Heading" >=> getNum
230− getIntHeader = getNameVal >=> stripPrefix "heading " >=> getNum
231− toTuple getF = liftM2 (,) <$> getF <*> getAttrStyleId
232− toMap getF = mapMaybe (toTuple getF) $
233− findChildren (myName "style") styledoc
234− select a b | not $ null a = a
237− select (toMap getEngHeader) (toMap getIntHeader)
239 ((contents, footnotes), st) <- runStateT (writeOpenXML opts{writerWrapText = False} doc')
221 ((contents, footnotes), st) <- runStateT (writeOpenXML opts{writerWrapText = False} doc')
240 defaultWriterState{ stChangesAuthor = fromMaybe "unknown" username
222 defaultWriterState{ stChangesAuthor = fromMaybe "unknown" username
241 , stChangesDate = formatTime defaultTimeLocale "%FT%XZ" utctime
223 , stChangesDate = formatTime defaultTimeLocale "%FT%XZ" utctime
242 , stPrintWidth = (maybe 420 (\x -> quot x 20) pgContentWidth)
224 , stPrintWidth = (maybe 420 (\x -> quot x 20) pgContentWidth)
243− , stHeadingStyles = headingStyles}
225+ , stStyleMaps = styleMaps
244 let epochtime = floor $ utcTimeToPOSIXSeconds utctime
227 let epochtime = floor $ utcTimeToPOSIXSeconds utctime
245 let imgs = M.elems $ stImages st
228 let imgs = M.elems $ stImages st
@@ -393,9 +376,18 @@ writeDocx opts doc@(Pandoc meta _) = do
395 -- styles
378 -- styles
396− let newstyles = styleToOpenXml $ writerHighlightStyle opts
379+ let newstyles = styleToOpenXml styleMaps $ writerHighlightStyle opts
397− let styledoc' = styledoc{ elContent = elContent styledoc ++
380+ let styledoc' = styledoc{ elContent = modifyContent (elContent styledoc) }
398− [Elem x | x <- newstyles, writerHighlight opts] }
383+ | writerHighlight opts = (++ map Elem newstyles)
384+ | otherwise = filter notTokStyle
385+ notTokStyle (Elem el) = notStyle el || notTokId el
386+ notTokStyle _ = True
387+ notStyle = (/= elemName' "style") . elName
388+ notTokId = maybe True (`notElem` tokStys) . findAttr (elemName' "styleId")
389+ tokStys = "SourceCode" : map show (enumFromTo KeywordTok NormalTok)
390+ elemName' = elemName (sNameSpaces styleMaps) "w"
399 let styleEntry = toEntry stylepath epochtime $ renderXml styledoc'
391 let styleEntry = toEntry stylepath epochtime $ renderXml styledoc'
401 -- construct word/numbering.xml
393 -- construct word/numbering.xml
@@ -472,10 +464,13 @@ writeDocx opts doc@(Pandoc meta _) = do
472 miscRelEntries ++ otherMediaEntries
464 miscRelEntries ++ otherMediaEntries
473 return $ fromArchive archive
465 return $ fromArchive archive
475−styleToOpenXml :: Style -> [Element]
467+styleToOpenXml :: StyleMaps -> Style -> [Element]
476−styleToOpenXml style = parStyle : map toStyle alltoktypes
468+styleToOpenXml sm style =
469+ maybeToList parStyle ++ mapMaybe toStyle alltoktypes
477 where alltoktypes = enumFromTo KeywordTok NormalTok
470 where alltoktypes = enumFromTo KeywordTok NormalTok
471+ toStyle toktype | hasStyleName (show toktype) (sCharStyleMap sm) = Nothing
472+ | otherwise = Just $
478− toStyle toktype = mknode "w:style" [("w:type","character"),
473+ mknode "w:style" [("w:type","character"),
479 ("w:customStyle","1"),("w:styleId",show toktype)]
474 ("w:customStyle","1"),("w:styleId",show toktype)]
480 [ mknode "w:name" [("w:val",show toktype)] ()
475 [ mknode "w:name" [("w:val",show toktype)] ()
481 , mknode "w:basedOn" [("w:val","VerbatimChar")] ()
476 , mknode "w:basedOn" [("w:val","VerbatimChar")] ()
@@ -496,7 +491,9 @@ styleToOpenXml style = parStyle : map toStyle alltoktypes
496 tokBg toktype = maybe "auto" (drop 1 . fromColor)
491 tokBg toktype = maybe "auto" (drop 1 . fromColor)
497 $ (tokenBackground =<< lookup toktype tokStyles)
492 $ (tokenBackground =<< lookup toktype tokStyles)
498 `mplus` backgroundColor style
493 `mplus` backgroundColor style
494+ parStyle | hasStyleName "Source Code" (sParaStyleMap sm) = Nothing
495+ | otherwise = Just $
499− parStyle = mknode "w:style" [("w:type","paragraph"),
496+ mknode "w:style" [("w:type","paragraph"),
500 ("w:customStyle","1"),("w:styleId","SourceCode")]
497 ("w:customStyle","1"),("w:styleId","SourceCode")]
501 [ mknode "w:name" [("w:val","Source Code")] ()
498 [ mknode "w:name" [("w:val","Source Code")] ()
502 , mknode "w:basedOn" [("w:val","Normal")] ()
499 , mknode "w:basedOn" [("w:val","Normal")] ()
@@ -602,14 +599,14 @@ writeOpenXML opts (Pandoc meta blocks) = do
602 Just (MetaBlocks [Para xs]) -> xs
599 Just (MetaBlocks [Para xs]) -> xs
603 Just (MetaInlines xs) -> xs
600 Just (MetaInlines xs) -> xs
605− title <- withParaProp (pStyle "Title") $ blocksToOpenXML opts [Para tit | not (null tit)]
602+ title <- withParaPropM (pStyleM "Title") $ blocksToOpenXML opts [Para tit | not (null tit)]
606− subtitle <- withParaProp (pStyle "Subtitle") $ blocksToOpenXML opts [Para subtitle' | not (null subtitle')]
603+ subtitle <- withParaPropM (pStyleM "Subtitle") $ blocksToOpenXML opts [Para subtitle' | not (null subtitle')]
607− authors <- withParaProp (pStyle "Author") $ blocksToOpenXML opts $
604+ authors <- withParaProp (pCustomStyle "Author") $ blocksToOpenXML opts $
608 map Para auths
605 map Para auths
609− date <- withParaProp (pStyle "Date") $ blocksToOpenXML opts [Para dat | not (null dat)]
606+ date <- withParaPropM (pStyleM "Date") $ blocksToOpenXML opts [Para dat | not (null dat)]
610 abstract <- if null abstract'
607 abstract <- if null abstract'
611 then return []
608 then return []
612− else withParaProp (pStyle "Abstract") $ blocksToOpenXML opts abstract'
609+ else withParaProp (pCustomStyle "Abstract") $ blocksToOpenXML opts abstract'
613 let convertSpace (Str x : Space : Str y : xs) = Str (x ++ " " ++ y) : xs
610 let convertSpace (Str x : Space : Str y : xs) = Str (x ++ " " ++ y) : xs
614 convertSpace (Str x : Str y : xs) = Str (x ++ y) : xs
611 convertSpace (Str x : Str y : xs) = Str (x ++ y) : xs
615 convertSpace xs = xs
612 convertSpace xs = xs
@@ -623,11 +620,23 @@ writeOpenXML opts (Pandoc meta blocks) = do
623blocksToOpenXML :: WriterOptions -> [Block] -> WS [Element]
620blocksToOpenXML :: WriterOptions -> [Block] -> WS [Element]
624blocksToOpenXML opts bls = concat `fmap` mapM (blockToOpenXML opts) bls
621blocksToOpenXML opts bls = concat `fmap` mapM (blockToOpenXML opts) bls
626−pStyle :: String -> Element
623+pCustomStyle :: String -> Element
627−pStyle sty = mknode "w:pStyle" [("w:val",sty)] ()
624+pCustomStyle sty = mknode "w:pStyle" [("w:val",sty)] ()
626+pStyleM :: String -> WS XML.Element
627+pStyleM styleName = do
628+ styleMaps <- gets stStyleMaps
629+ let sty' = getStyleId styleName $ sParaStyleMap styleMaps
630+ return $ mknode "w:pStyle" [("w:val",sty')] ()
632+rCustomStyle :: String -> Element
633+rCustomStyle sty = mknode "w:rStyle" [("w:val",sty)] ()
629−rStyle :: String -> Element
635+rStyleM :: String -> WS XML.Element
636+rStyleM styleName = do
637+ styleMaps <- gets stStyleMaps
638+ let sty' = getStyleId styleName $ sCharStyleMap styleMaps
630−rStyle sty = mknode "w:rStyle" [("w:val",sty)] ()
639+ return $ mknode "w:rStyle" [("w:val",sty')] ()
632getUniqueId :: MonadIO m => m String
641getUniqueId :: MonadIO m => m String
633-- the + 20 is to ensure that there are no clashes with the rIds
642-- the + 20 is to ensure that there are no clashes with the rIds
@@ -641,13 +650,12 @@ blockToOpenXML opts (Div (_,["references"],_) bs) = do
641 let (hs, bs') = span isHeaderBlock bs
650 let (hs, bs') = span isHeaderBlock bs
642 header <- blocksToOpenXML opts hs
651 header <- blocksToOpenXML opts hs
643 -- We put the Bibliography style on paragraphs after the header
652 -- We put the Bibliography style on paragraphs after the header
644− rest <- withParaProp (pStyle "Bibliography") $ blocksToOpenXML opts bs'
653+ rest <- withParaPropM (pStyleM "Bibliography") $ blocksToOpenXML opts bs'
645 return (header ++ rest)
654 return (header ++ rest)
646blockToOpenXML opts (Div _ bs) = blocksToOpenXML opts bs
655blockToOpenXML opts (Div _ bs) = blocksToOpenXML opts bs
647blockToOpenXML opts (Header lev (ident,_,_) lst) = do
656blockToOpenXML opts (Header lev (ident,_,_) lst) = do
648 setFirstPara
657 setFirstPara
649− headingStyles <- gets stHeadingStyles
658+ paraProps <- withParaPropM (pStyleM ("Heading "++show lev)) $
650− paraProps <- maybe id (withParaProp . pStyle) (lookup lev headingStyles) $
651 getParaProps False
659 getParaProps False
652 contents <- inlinesToOpenXML opts lst
660 contents <- inlinesToOpenXML opts lst
653 usedIdents <- gets stSectionIds
661 usedIdents <- gets stSectionIds
@@ -660,26 +668,27 @@ blockToOpenXML opts (Header lev (ident,_,_) lst) = do
660 ,("w:name",bookmarkName)] ()
668 ,("w:name",bookmarkName)] ()
661 let bookmarkEnd = mknode "w:bookmarkEnd" [("w:id", id')] ()
669 let bookmarkEnd = mknode "w:bookmarkEnd" [("w:id", id')] ()
662 return [mknode "w:p" [] (paraProps ++ [bookmarkStart, bookmarkEnd] ++ contents)]
670 return [mknode "w:p" [] (paraProps ++ [bookmarkStart, bookmarkEnd] ++ contents)]
663−blockToOpenXML opts (Plain lst) = withParaProp (pStyle "Compact")
671+blockToOpenXML opts (Plain lst) = withParaProp (pCustomStyle "Compact")
664 $ blockToOpenXML opts (Para lst)
672 $ blockToOpenXML opts (Para lst)
665-- title beginning with fig: indicates that the image is a figure
673-- title beginning with fig: indicates that the image is a figure
666blockToOpenXML opts (Para [Image alt (src,'f':'i':'g':':':tit)]) = do
674blockToOpenXML opts (Para [Image alt (src,'f':'i':'g':':':tit)]) = do
667 setFirstPara
675 setFirstPara
668 paraProps <- getParaProps False
676 paraProps <- getParaProps False
669 contents <- inlinesToOpenXML opts [Image alt (src,tit)]
677 contents <- inlinesToOpenXML opts [Image alt (src,tit)]
670− captionNode <- withParaProp (pStyle "ImageCaption")
678+ captionNode <- withParaProp (pCustomStyle "ImageCaption")
671 $ blockToOpenXML opts (Para alt)
679 $ blockToOpenXML opts (Para alt)
672 return $ mknode "w:p" [] (paraProps ++ contents) : captionNode
680 return $ mknode "w:p" [] (paraProps ++ contents) : captionNode
673-- fixDisplayMath sometimes produces a Para [] as artifact
681-- fixDisplayMath sometimes produces a Para [] as artifact
674blockToOpenXML _ (Para []) = return []
682blockToOpenXML _ (Para []) = return []
675blockToOpenXML opts (Para lst) = do
683blockToOpenXML opts (Para lst) = do
676− isFirstPara <- gets stFirstPara
684+ isFirstPara <- gets stFirstPara
677 paraProps <- getParaProps $ case lst of
685 paraProps <- getParaProps $ case lst of
678 [Math DisplayMath _] -> True
686 [Math DisplayMath _] -> True
679 _ -> False
687 _ -> False
688+ bodyTextStyle <- pStyleM "Body Text"
680 let paraProps' = case paraProps of
689 let paraProps' = case paraProps of
681− [] | isFirstPara -> [mknode "w:pPr" [] [(pStyle "FirstParagraph")]]
690+ [] | isFirstPara -> [mknode "w:pPr" [] [pCustomStyle "FirstParagraph"]]
682− [] -> [mknode "w:pPr" [] [(pStyle "BodyText")]]
691+ [] -> [mknode "w:pPr" [] [bodyTextStyle]]
684 modify $ \s -> s { stFirstPara = False }
693 modify $ \s -> s { stFirstPara = False }
685 contents <- inlinesToOpenXML opts lst
694 contents <- inlinesToOpenXML opts lst
@@ -688,11 +697,11 @@ blockToOpenXML _ (RawBlock format str)
688 | format == Format "openxml" = return [ x | Elem x <- parseXML str ]
697 | format == Format "openxml" = return [ x | Elem x <- parseXML str ]
689 | otherwise = return []
698 | otherwise = return []
690blockToOpenXML opts (BlockQuote blocks) = do
699blockToOpenXML opts (BlockQuote blocks) = do
691− p <- withParaProp (pStyle "BlockQuote") $ blocksToOpenXML opts blocks
700+ p <- withParaPropM (pStyleM "Block Text") $ blocksToOpenXML opts blocks
692 setFirstPara
701 setFirstPara
694blockToOpenXML opts (CodeBlock attrs str) = do
703blockToOpenXML opts (CodeBlock attrs str) = do
695− p <- withParaProp (pStyle "SourceCode") $ (blockToOpenXML opts $ Para [Code attrs str])
704+ p <- withParaProp (pCustomStyle "SourceCode") (blockToOpenXML opts $ Para [Code attrs str])
696 setFirstPara
705 setFirstPara
698blockToOpenXML _ HorizontalRule = do
707blockToOpenXML _ HorizontalRule = do
@@ -707,7 +716,7 @@ blockToOpenXML opts (Table caption aligns widths headers rows) = do
707 let captionStr = stringify caption
716 let captionStr = stringify caption
708 caption' <- if null caption
717 caption' <- if null caption
709 then return []
718 then return []
710− else withParaProp (pStyle "TableCaption")
719+ else withParaProp (pCustomStyle "TableCaption")
711 $ blockToOpenXML opts (Para caption)
720 $ blockToOpenXML opts (Para caption)
712 let alignmentFor al = mknode "w:jc" [("w:val",alignmentToString al)] ()
721 let alignmentFor al = mknode "w:jc" [("w:val",alignmentToString al)] ()
713 let cellToOpenXML (al, cell) = withParaProp (alignmentFor al)
722 let cellToOpenXML (al, cell) = withParaProp (alignmentFor al)
@@ -718,32 +727,36 @@ blockToOpenXML opts (Table caption aligns widths headers rows) = do
718 [ mknode "w:tcBorders" []
727 [ mknode "w:tcBorders" []
719 $ mknode "w:bottom" [("w:val","single")] ()
728 $ mknode "w:bottom" [("w:val","single")] ()
720 , mknode "w:vAlign" [("w:val","bottom")] () ]
729 , mknode "w:vAlign" [("w:val","bottom")] () ]
721− let emptyCell = [mknode "w:p" [] [mknode "w:pPr" []
730+ let emptyCell = [mknode "w:p" [] [pCustomStyle "Compact"]]
722− [mknode "w:pStyle" [("w:val","Compact")] ()]]]
723 let mkcell border contents = mknode "w:tc" []
731 let mkcell border contents = mknode "w:tc" []
724 $ [ borderProps | border ] ++
732 $ [ borderProps | border ] ++
725 if null contents
733 if null contents
726 then emptyCell
734 then emptyCell
727 else contents
735 else contents
728− let mkrow border cells = mknode "w:tr" [] $ map (mkcell border) cells
736+ let mkrow border cells = mknode "w:tr" [] $
737+ [mknode "w:trPr" [] [
738+ mknode "w:cnfStyle" [("w:firstRow","1")] ()] | border]
739+ ++ map (mkcell border) cells
729 let textwidth = 7920 -- 5.5 in in twips, 1/20 pt
740 let textwidth = 7920 -- 5.5 in in twips, 1/20 pt
730 let fullrow = 5000 -- 100% specified in pct
741 let fullrow = 5000 -- 100% specified in pct
731 let rowwidth = fullrow * sum widths
742 let rowwidth = fullrow * sum widths
732 let mkgridcol w = mknode "w:gridCol"
743 let mkgridcol w = mknode "w:gridCol"
733 [("w:w", show (floor (textwidth * w) :: Integer))] ()
744 [("w:w", show (floor (textwidth * w) :: Integer))] ()
745+ let hasHeader = not (all null headers)
735 caption' ++
747 caption' ++
736 [mknode "w:tbl" []
748 [mknode "w:tbl" []
737 ( mknode "w:tblPr" []
749 ( mknode "w:tblPr" []
738 ( mknode "w:tblStyle" [("w:val","TableNormal")] () :
750 ( mknode "w:tblStyle" [("w:val","TableNormal")] () :
739 mknode "w:tblW" [("w:type", "pct"), ("w:w", show rowwidth)] () :
751 mknode "w:tblW" [("w:type", "pct"), ("w:w", show rowwidth)] () :
752+ mknode "w:tblLook" [("w:firstRow","1") | hasHeader ] () :
740 [ mknode "w:tblCaption" [("w:val", captionStr)] ()
753 [ mknode "w:tblCaption" [("w:val", captionStr)] ()
741 | not (null caption) ] )
754 | not (null caption) ] )
742 : mknode "w:tblGrid" []
755 : mknode "w:tblGrid" []
743 (if all (==0) widths
756 (if all (==0) widths
745 else map mkgridcol widths)
758 else map mkgridcol widths)
746− : [ mkrow True headers' | not (all null headers) ] ++
759+ : [ mkrow True headers' | hasHeader ] ++
747 map (mkrow False) rows'
760 map (mkrow False) rows'
749blockToOpenXML opts (BulletList lst) = do
762blockToOpenXML opts (BulletList lst) = do
@@ -767,9 +780,9 @@ blockToOpenXML opts (DefinitionList items) = do
768definitionListItemToOpenXML :: WriterOptions -> ([Inline],[[Block]]) -> WS [Element]
781definitionListItemToOpenXML :: WriterOptions -> ([Inline],[[Block]]) -> WS [Element]
769definitionListItemToOpenXML opts (term,defs) = do
782definitionListItemToOpenXML opts (term,defs) = do
770− term' <- withParaProp (pStyle "DefinitionTerm")
783+ term' <- withParaProp (pCustomStyle "DefinitionTerm")
771 $ blockToOpenXML opts (Para term)
784 $ blockToOpenXML opts (Para term)
772− defs' <- withParaProp (pStyle "Definition")
785+ defs' <- withParaProp (pCustomStyle "Definition")
773 $ concat `fmap` mapM (blocksToOpenXML opts) defs
786 $ concat `fmap` mapM (blocksToOpenXML opts) defs
774 return $ term' ++ defs'
787 return $ term' ++ defs'
@@ -833,6 +846,9 @@ withTextProp d p = do
833 popTextProp
846 popTextProp
834 return res
847 return res
849+withTextPropM :: WS Element -> WS a -> WS a
850+withTextPropM = (. flip withTextProp) . (>>=)
836getParaProps :: Bool -> WS [Element]
852getParaProps :: Bool -> WS [Element]
837getParaProps displayMathPara = do
853getParaProps displayMathPara = do
838 props <- gets stParaProperties
854 props <- gets stParaProperties
@@ -861,6 +877,9 @@ withParaProp d p = do
861 popParaProp
877 popParaProp
862 return res
878 return res
880+withParaPropM :: WS Element -> WS a -> WS a
881+withParaPropM = (. flip withParaProp) . (>>=)
864formattedString :: String -> WS [Element]
883formattedString :: String -> WS [Element]
865formattedString str = do
884formattedString str = do
866 props <- getTextProps
885 props <- getTextProps
@@ -943,25 +962,26 @@ inlineToOpenXML opts (Math mathType str) = do
943 Right r -> return [r]
962 Right r -> return [r]
944 Left _ -> inlinesToOpenXML opts (texMathToInlines mathType str)
963 Left _ -> inlinesToOpenXML opts (texMathToInlines mathType str)
945inlineToOpenXML opts (Cite _ lst) = inlinesToOpenXML opts lst
964inlineToOpenXML opts (Cite _ lst) = inlinesToOpenXML opts lst
946−inlineToOpenXML opts (Code attrs str) =
965+inlineToOpenXML opts (Code attrs str) = do
947− withTextProp (rStyle "VerbatimChar")
948− $ if writerHighlight opts
949− then case highlight formatOpenXML attrs str of
950− Nothing -> unhighlighted
953− where unhighlighted = intercalate [br] `fmap`
966+ let unhighlighted = intercalate [br] `fmap`
954− (mapM formattedString $ lines str)
967+ (mapM formattedString $ lines str)
955− formatOpenXML _fmtOpts = intercalate [br] . map (map toHlTok)
968+ formatOpenXML _fmtOpts = intercalate [br] . map (map toHlTok)
956− toHlTok (toktype,tok) = mknode "w:r" []
969+ toHlTok (toktype,tok) = mknode "w:r" []
957− [ mknode "w:rPr" []
970+ [ mknode "w:rPr" []
958− [ rStyle $ show toktype ]
971+ [ rCustomStyle (show toktype) ]
959− , mknode "w:t" [("xml:space","preserve")] tok ]
972+ , mknode "w:t" [("xml:space","preserve")] tok ]
973+ withTextProp (rCustomStyle "VerbatimChar")
974+ $ if writerHighlight opts
975+ then case highlight formatOpenXML attrs str of
976+ Nothing -> unhighlighted
960inlineToOpenXML opts (Note bs) = do
979inlineToOpenXML opts (Note bs) = do
961 notes <- gets stFootnotes
980 notes <- gets stFootnotes
962 notenum <- getUniqueId
981 notenum <- getUniqueId
982+ footnoteStyle <- rStyleM "Footnote Reference"
963 let notemarker = mknode "w:r" []
983 let notemarker = mknode "w:r" []
964− [ mknode "w:rPr" [] (rStyle "FootnoteRef")
984+ [ mknode "w:rPr" [] footnoteStyle
965 , mknode "w:footnoteRef" [] () ]
985 , mknode "w:footnoteRef" [] () ]
966 let notemarkerXml = RawInline (Format "openxml") $ ppElement notemarker
986 let notemarkerXml = RawInline (Format "openxml") $ ppElement notemarker
967 let insertNoteRef (Plain ils : xs) = Plain (notemarkerXml : ils) : xs
987 let insertNoteRef (Plain ils : xs) = Plain (notemarkerXml : ils) : xs
@@ -971,22 +991,22 @@ inlineToOpenXML opts (Note bs) = do
971 oldParaProperties <- gets stParaProperties
991 oldParaProperties <- gets stParaProperties
972 oldTextProperties <- gets stTextProperties
992 oldTextProperties <- gets stTextProperties
973 modify $ \st -> st{ stListLevel = -1, stParaProperties = [], stTextProperties = [] }
993 modify $ \st -> st{ stListLevel = -1, stParaProperties = [], stTextProperties = [] }
974− contents <- withParaProp (pStyle "FootnoteText") $ blocksToOpenXML opts
994+ contents <- withParaPropM (pStyleM "Footnote Text") $ blocksToOpenXML opts
975 $ insertNoteRef bs
995 $ insertNoteRef bs
976 modify $ \st -> st{ stListLevel = oldListLevel, stParaProperties = oldParaProperties,
996 modify $ \st -> st{ stListLevel = oldListLevel, stParaProperties = oldParaProperties,
977 stTextProperties = oldTextProperties }
997 stTextProperties = oldTextProperties }
978 let newnote = mknode "w:footnote" [("w:id", notenum)] $ contents
998 let newnote = mknode "w:footnote" [("w:id", notenum)] $ contents
979 modify $ \s -> s{ stFootnotes = newnote : notes }
999 modify $ \s -> s{ stFootnotes = newnote : notes }
980 return [ mknode "w:r" []
1000 return [ mknode "w:r" []
981− [ mknode "w:rPr" [] (rStyle "FootnoteRef")
1001+ [ mknode "w:rPr" [] footnoteStyle
982 , mknode "w:footnoteReference" [("w:id", notenum)] () ] ]
1002 , mknode "w:footnoteReference" [("w:id", notenum)] () ] ]
983-- internal link:
1003-- internal link:
984inlineToOpenXML opts (Link txt ('#':xs,_)) = do
1004inlineToOpenXML opts (Link txt ('#':xs,_)) = do
985− contents <- withTextProp (rStyle "Link") $ inlinesToOpenXML opts txt
1005+ contents <- withTextPropM (rStyleM "Hyperlink") $ inlinesToOpenXML opts txt
986 return [ mknode "w:hyperlink" [("w:anchor",xs)] contents ]
1006 return [ mknode "w:hyperlink" [("w:anchor",xs)] contents ]
987-- external link:
1007-- external link:
988inlineToOpenXML opts (Link txt (src,_)) = do
1008inlineToOpenXML opts (Link txt (src,_)) = do
989− contents <- withTextProp (rStyle "Link") $ inlinesToOpenXML opts txt
1009+ contents <- withTextPropM (rStyleM "Hyperlink") $ inlinesToOpenXML opts txt
990 extlinks <- gets stExternalLinks
1010 extlinks <- gets stExternalLinks
991 id' <- case M.lookup src extlinks of
1011 id' <- case M.lookup src extlinks of
992 Just i -> return i
1012 Just i -> return i
@@ -1088,7 +1108,7 @@ defaultFootnotes = [ mknode "w:footnote"
1088 [ mknode "w:p" [] $
1108 [ mknode "w:p" [] $
1089 [ mknode "w:r" [] $
1109 [ mknode "w:r" [] $
1090 [ mknode "w:continuationSeparator" [] ()]]]]
1110 [ mknode "w:continuationSeparator" [] ()]]]]
1092parseXml :: Archive -> Archive -> String -> IO Element
1112parseXml :: Archive -> Archive -> String -> IO Element
1093parseXml refArchive distArchive relpath =
1113parseXml refArchive distArchive relpath =
1094 case ((findEntryByPath relpath refArchive `mplus`
1114 case ((findEntryByPath relpath refArchive `mplus`