ideas-1.9.1: src/Ideas/Text/MathML.hs
{-# LANGUAGE OverloadedStrings #-}
-----------------------------------------------------------------------------
-- Copyright 2019, Ideas project team. This file is distributed under the
-- terms of the Apache License 2.0. For more information, see the files
-- "LICENSE.txt" and "NOTICE.txt", which are included in the distribution.
-----------------------------------------------------------------------------
-- |
-- Maintainer : bastiaan.heeren@ou.nl
-- Stability : provisional
-- Portability : portable (depends on ghc)
--
-----------------------------------------------------------------------------
module Ideas.Text.MathML
( MathML(..), xml2mathml, mathml2xml
) where
import Ideas.Text.XML
import Ideas.Utils.Uniplate hiding (children)
import Ideas.Utils.Decoding
data MathML = MRow [MathML]
| MId String
| MNumber String
| MOperator String
| MString String
| MText String
| MSqrt MathML
| MRoot MathML MathML
| MSup MathML MathML -- base, superscript
| MSub MathML MathML -- base, subscript
| MSubSup MathML MathML MathML -- base, subscript, superscript
| MFrac MathML MathML -- numerator, denominator
| MFenced String String MathML -- left, right, content
| MSpace
| MStyle
| MPadded
| MPhantom
| MError
| MEnclose
| MUnder
| MOver
| MUnderOver
| MTable
| MTableRow
| MLabeledTableRow
| MTableData
deriving (Show, Eq)
{-
from: https://www.w3.org/TR/MathML2/chapter3.html#presm.mn @ 3.2.1
Conversely, since mn is a presentation element, there are a few situations where it may desirable to include arbitrary text in the content of an mn that should merely render as a numeric literal
-}
instance ToXML MathML where
toXML = mathml2xml
instance InXML MathML where
xmlDecoder = rec
where
rec = xmlTag "mrow" (MRow <$> many rec)
<|> xmlTag "msqrt" (MSqrt <$> impliedRow)
<|> xmlTag "math" impliedRow
<|> xmlTag "mi" (MId <$> xmlString)
<|> xmlTag "mn" (MNumber <$> xmlString)
<|> xmlTag "mo" (MOperator <$> xmlString)
<|> xmlTag "ms" (MString <$> xmlString)
<|> xmlTag "mtext" (MText <$> xmlString)
<|> xmlTag "mroot" (MRoot <$> rec <*> rec)
<|> xmlTag "msup" (MSup <$> rec <*> rec)
<|> xmlTag "msub" (MSub <$> rec <*> rec)
<|> xmlTag "msubsup" (MSubSup <$> rec <*> rec <*> rec)
<|> xmlTag "mfrac" (MFrac <$> rec <*> rec)
<|> xmlTag "mfenced" (MFenced <$> xmlAttr "open" <*> xmlAttr "close" <*> rec)
<|> xmlTag "mspace" (return MSpace)
<|> xmlTag "mstyle" (return MStyle)
<|> xmlTag "mpadded" (return MPadded)
<|> xmlTag "mphantom" (return MPhantom)
<|> xmlTag "merror" (return MError)
<|> xmlTag "menclose" (return MEnclose)
<|> xmlTag "munder" (return MUnder)
<|> xmlTag "mover" (return MOver)
<|> xmlTag "munderover" (return MUnderOver)
<|> xmlTag "mtable" (return MTable)
<|> xmlTag "mtr" (return MTableRow)
<|> xmlTag "mlabeledtr" (return MLabeledTableRow)
<|> xmlTag "mtd" (return MTableData)
impliedRow = f <$> many rec
f [x] = x
f xs = MRow xs
instance Uniplate MathML where
uniplate math =
case math of
MRow xs -> plate MRow ||* xs
_ -> plate math
----------------------------------------------------------
-- conversion functions: XML <-> MathML
xml2mathml :: XML -> Either String MathML
xml2mathml = either (Left . show) (Right . fst) . runDecoder xmlDecoder () . builder
mathml2xml :: MathML -> XML
mathml2xml = makeXML "math" . rec
where
rec :: MathML -> XMLBuilder
rec math =
case math of
MRow ms -> element "mrow" (map rec ms)
MId s -> element "mi" [string s]
MNumber s -> element "mn" [string s]
MOperator s -> element "mo" [string s]
MString s -> element "ms" [string s]
MText s -> element "mtext" [string s]
MSqrt m -> element "msqrt" [rec m]
MRoot m1 m2 -> element "mroot" [rec m1, rec m2]
MSup m1 m2 -> element "msup" [rec m1, rec m2]
MSub m1 m2 -> element "msub" [rec m1, rec m2]
MSubSup m1 m2 m3 -> element "msubsup" [rec m1, rec m2, rec m3]
MFrac m1 m2 -> element "mfrac" [rec m1, rec m2]
MFenced s1 s2 m -> element "mfenced" ["open" .=. s1, "close" .=. s2, rec m]
MSpace -> element "mspace" []
MStyle -> element "mstyle" []
MPadded -> element "mpadded" []
MPhantom -> element "mphantom" []
MError -> element "merror" []
MEnclose -> element "menclose" []
MUnder -> element "munder" []
MOver -> element "mover" []
MUnderOver -> element "munderover" []
MTable -> element "mtable" []
MTableRow -> element "mtr" []
MLabeledTableRow -> element "mlabeledtr" []
MTableData -> element "mtd" []