From 912bfa5e2e3f5c74eb125dfc19404f67c61ca58b Mon Sep 17 00:00:00 2001 From: John MacFarlane Date: Tue, 9 Jun 2026 13:06:17 +0200 Subject: [PATCH] Use starmath for math in ODT. This improves appearance and editability of math in ODT. Depends on dev version of texmath. The main code changes are due to @jdpipe (#11470). --- cabal.project | 5 ++++ src/Text/Pandoc/Writers/ODT.hs | 51 ++++++++++++++++++++++++++++++++-- stack.yaml | 3 +- 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/cabal.project b/cabal.project index a0152146d..c995aed34 100644 --- a/cabal.project +++ b/cabal.project @@ -8,6 +8,11 @@ constraints: skylighting-format-blaze-html >= 0.1.2, crypton >= 1.1.1, doclayout >= 0.5.0.3 +source-repository-package + type: git + location: https://github.com/jgm/texmath.git + tag: 170899673ee31de9096e178605e8da31a36e4185 + package pandoc flags: +embed_data_files +http diff --git a/src/Text/Pandoc/Writers/ODT.hs b/src/Text/Pandoc/Writers/ODT.hs index 38d89535f..b25471678 100644 --- a/src/Text/Pandoc/Writers/ODT.hs +++ b/src/Text/Pandoc/Writers/ODT.hs @@ -350,11 +350,15 @@ transformPicMath opts (Image attr@(id', cls, _) lab (src,t)) = catchError transformPicMath _ (Math t math) = do entries <- gets stEntries let dt = if t == InlineMath then DisplayInline else DisplayBlock - case writeMathML dt <$> readTeX math of + case readTeX math of Left _ -> return $ Math t math - Right r -> do + Right exps -> do let conf = XL.useShortEmptyTags (const False) XL.defaultConfigPP - let mathml = XL.ppcTopElement conf r + let starMath = + writeStarMath dt exps <> "\n" <> starMathCommentFromTeX math + let mathmlElement = + addStarMathAnnotation starMath (writeMathML dt exps) + let mathml = XL.ppcTopElement conf mathmlElement epochtime <- floor `fmap` lift P.getPOSIXTime let dirname = "Formula-" ++ show (length entries) ++ "/" let fname = dirname ++ "content.xml" @@ -379,6 +383,47 @@ transformPicMath _ (Math t math) = do transformPicMath _ x = return x +starMathCommentFromTeX :: T.Text -> T.Text +starMathCommentFromTeX tex = + case T.lines normalized of + [] -> "%% TeX:" + (l : ls) -> + T.intercalate "\n" (("%% TeX: " <> l) : map ("%% " <>) ls) + where + normalized = T.replace "\r\n" "\n" (T.replace "\r" "\n" tex) + +addStarMathAnnotation :: T.Text -> XL.Element -> XL.Element +addStarMathAnnotation starMath e = + case XL.elContent e of + [XL.Elem sem] | XL.qName (XL.elName sem) == "semantics" -> + e { XL.elContent = [XL.Elem (withAnnotation sem)] } + _ -> + e { XL.elContent = [XL.Elem (mkSemantics (XL.elContent e))] } + where + mkSemantics cs = + XL.Element (mkMathQName "semantics") [] (cs ++ [XL.Elem annotation]) Nothing + + withAnnotation sem = + sem { XL.elContent = + filter (not . isStarMathAnnotation) (XL.elContent sem) + ++ [XL.Elem annotation] } + + annotation = + XL.Element (mkMathQName "annotation") + [XL.Attr (XL.QName "encoding" Nothing Nothing) "StarMath 5.0"] + [XL.Text (XL.CData XL.CDataText (T.unpack starMath) Nothing)] + Nothing + + isStarMathAnnotation (XL.Elem el) = + XL.qName (XL.elName el) == "annotation" && + any (\a -> XL.qName (XL.attrKey a) == "encoding" + && XL.attrVal a == "StarMath 5.0") + (XL.elAttribs el) + isStarMathAnnotation _ = False + + mkMathQName n = + XL.QName n (XL.qURI $ XL.elName e) (XL.qPrefix $ XL.elName e) + documentSettings :: Bool -> B.ByteString documentSettings isTextMode = fromStringLazy $ render Nothing $ text "" diff --git a/stack.yaml b/stack.yaml index bb40e3ffd..e488f40b9 100644 --- a/stack.yaml +++ b/stack.yaml @@ -32,8 +32,9 @@ extra-deps: - pandoc-types-1.23.1.2 - typst-symbols-0.2 - typst-0.10 -- texmath-0.13.1.2 - emojis-0.1.5 +- git: https://github.com/jgm/texmath.git + commit: 170899673ee31de9096e178605e8da31a36e4185 ghc-options: "$locals": -fhide-source-paths -Wno-missing-home-modules