From a3d745e48560a55d9a9ea9fa43ffdd5a8b84987f Mon Sep 17 00:00:00 2001 From: John MacFarlane Date: Tue, 29 Jun 2021 09:44:37 -0700 Subject: [PATCH] Docx writer: support figure numbers. These are set up in such a way that they will work with Word's automatic table of figures. Closes #7392. --- src/Text/Pandoc/Writers/Docx.hs | 22 +++++++++++++++++++--- src/Text/Pandoc/Writers/Docx/Types.hs | 2 ++ test/docx/golden/image.docx | Bin 26647 -> 26774 bytes 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/Text/Pandoc/Writers/Docx.hs b/src/Text/Pandoc/Writers/Docx.hs index d1065eb7d..b3e008b8a 100644 --- a/src/Text/Pandoc/Writers/Docx.hs +++ b/src/Text/Pandoc/Writers/Docx.hs @@ -36,7 +36,8 @@ import Data.Time.Clock.POSIX import Data.Digest.Pure.SHA (sha1, showDigest) import Skylighting import Text.Collate.Lang (renderLang) -import Text.Pandoc.Class.PandocMonad (PandocMonad, report, toLang) +import Text.Pandoc.Class.PandocMonad (PandocMonad, report, toLang, translateTerm) +import qualified Text.Pandoc.Translations as Term import qualified Text.Pandoc.Class.PandocMonad as P import Data.Time import Text.Pandoc.UTF8 (fromTextLazy) @@ -854,14 +855,29 @@ blockToOpenXML' opts (Plain lst) = do -- title beginning with fig: indicates that the image is a figure blockToOpenXML' opts (Para [Image attr alt (src,T.stripPrefix "fig:" -> Just tit)]) = do setFirstPara + fignum <- gets stNextFigureNum + modify $ \st -> st{ stNextFigureNum = fignum + 1 } + let figid = "fig" <> tshow fignum + figname <- translateTerm Term.Figure prop <- pStyleM $ if null alt then "Figure" else "Captioned Figure" paraProps <- local (\env -> env { envParaProperties = EnvProps (Just prop) [] <> envParaProperties env }) (getParaProps False) contents <- inlinesToOpenXML opts [Image attr alt (src,tit)] - captionNode <- withParaPropM (pStyleM "Image Caption") - $ blockToOpenXML opts (Para alt) + captionNode <- if null alt + then return [] + else withParaPropM (pStyleM "Image Caption") + $ blockToOpenXML opts + (Para $ Span (figid,[],[]) + [Str "Figure\160", + RawInline (Format "openxml") + (" figname + <> " \\* ARABIC \">" + <> tshow fignum + <> ""), + Str ":", Space] : alt) return $ Elem (mknode "w:p" [] (map Elem paraProps ++ contents)) : captionNode diff --git a/src/Text/Pandoc/Writers/Docx/Types.hs b/src/Text/Pandoc/Writers/Docx/Types.hs index 006584c30..36ac45ad2 100644 --- a/src/Text/Pandoc/Writers/Docx/Types.hs +++ b/src/Text/Pandoc/Writers/Docx/Types.hs @@ -117,6 +117,7 @@ data WriterState = WriterState{ , stDynamicParaProps :: Set.Set ParaStyleName , stDynamicTextProps :: Set.Set CharStyleName , stCurId :: Int + , stNextFigureNum :: Int } defaultWriterState :: WriterState @@ -137,6 +138,7 @@ defaultWriterState = WriterState{ , stDynamicParaProps = Set.empty , stDynamicTextProps = Set.empty , stCurId = 20 + , stNextFigureNum = 1 } setFirstPara :: PandocMonad m => WS m () diff --git a/test/docx/golden/image.docx b/test/docx/golden/image.docx index 48b72e28313ec1cf70742cb22e1a35a9274918a1..9fe65326f6feba24d58407a3d0a6e2977daaeb31 100644 GIT binary patch delta 1768 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