模仿默认 MathML 转换的 Pandoc 过滤器

Pandoc filter mimicking default MathML conversion

我正在内部写一个Pandoc JSON filter in Haskell that should transform display LaTeX math to SVG with an external application, whereas inline LaTeX math should be transformed to MathML by pandoc

第一个 SVG 位工作正常;应该模仿标准 pandoc 行为的 MathML 位给我带来了问题。

Browsing Hackage,我发现 the texMathToMathML code example(见下文)。这个函数returnsEither String Element.

然而,我需要的是一个返回 IO String 的函数 tex2mml(见下文)。 需要在 tex2mml 的定义中添加什么才能实现此目的?

tex2mml latex = texMathToMathML DisplayInline latex

我在 (X)Ubuntu LTS 16.04 上执行此操作,安装了以下 pandoc 1.16.0.2 软件包:

$ sudo apt install pandoc libghc-pandoc-prof

以下是我目前得到的摘录:

#!/usr/bin/env runhaskell

import Text.Pandoc.JSON
import Control.Applicative ((<$>))
import Text.TeXMath (writeMathML, readTeX, DisplayType( DisplayInline ) )
import Text.XML.Light (Element)


texMathToMathML :: DisplayType -> String -> Either String Element
texMathToMathML dt s = writeMathML dt <$> readTeX s


tex2mml :: String -> IO String
tex2mml latex = texMathToMathML DisplayInline latex


main :: IO ()
main = toJSONFilter tex2math
  where tex2math (Math (DisplayMath) latex) = do
          svg <- tex2svg latex
          return (Math (DisplayMath) (svg))

        tex2math (Math (InlineMath) latex) = do
          mml <- tex2mml latex
          return (Math (InlineMath) (mml))

        tex2math other = return other

请耐心等待,因为我绝对是 Haskell 初学者。 任何关于代码改进的建议都非常受欢迎!

诚然,我不熟悉 Pandoc 和问题域,但如果正确理解 tex2mml 函数的目的,那么我相信这应该可以实现您想要的:

import Control.Applicative ((<$>))
import Text.Pandoc.JSON
import Text.TeXMath
       (writeMathML, readTeX, DisplayType(DisplayInline))
import Text.XML.Light (Element,showElement)

texMathToMathML :: DisplayType -> String -> Either String Element
texMathToMathML dt s = writeMathML dt <$> readTeX s

tex2mml :: String -> String
tex2mml latex = either id showElement (texMathToMathML DisplayInline latex)

-- actual definition of tex2svg goes here
tex2svg = undefined

main :: IO ()
main = toJSONFilter tex2math
  where
    tex2math :: Inline -> IO Inline
    tex2math (Math DisplayMath latex) = do
      svg <- tex2svg latex
      return (Math DisplayMath svg)
    tex2math (Math InlineMath latex) = return (Math InlineMath (tex2mml latex))
    tex2math other = return other

我正在使用 either 函数来检查转换函数的结果 texMathToMathML - 如果失败,错误将按原样返回 (id),如果成功 showElement 函数用于将 Element 转换为它的 XML 字符串表示形式。

如果您觉得更清楚,也可以使用模式匹配重写:

tex2mml :: String -> String
tex2mml latex = case texMathToMathML DisplayInline latex of
  Left err -> err
  Right xml -> showElement xml

由于计算是纯粹的,因此不需要嵌入到 IO monad 中,结果可以直接传递到 Math 构造函数中。

如果您希望漂亮地打印 XML 字符串或希望在输出中包含 XML 文档 header,Text.XML.Light.Output 模块中还有其他函数。