Merge pull request #1494 from jkr/math-module

Math module
This commit is contained in:
John MacFarlane 2014-08-07 13:44:19 -07:00
commit 17e48ba81e
4 changed files with 657 additions and 585 deletions

View file

@ -324,6 +324,7 @@ Library
Other-Modules: Text.Pandoc.Readers.Docx.Lists,
Text.Pandoc.Readers.Docx.Reducible,
Text.Pandoc.Readers.Docx.Parse,
Text.Pandoc.Readers.Docx.OMath,
Text.Pandoc.Writers.Shared,
Text.Pandoc.Asciify,
Text.Pandoc.MIME,

View file

@ -84,15 +84,16 @@ import Text.Pandoc.Readers.Docx.Lists
import Text.Pandoc.Readers.Docx.Reducible
import Text.Pandoc.Shared
import Text.Pandoc.MediaBag (insertMedia, MediaBag)
import Data.Maybe (mapMaybe, fromMaybe)
import Data.List (delete, stripPrefix, (\\), intersperse, intersect)
import Data.Maybe (mapMaybe)
import Data.List (delete, stripPrefix, (\\), intersect)
import Data.Monoid
import Text.TeXMath (writeTeX)
import qualified Text.TeXMath.Types as TM
import Data.Default (Default)
import qualified Data.ByteString.Lazy as B
import qualified Data.Map as M
import Control.Monad.Reader
import Control.Monad.State
import Control.Applicative ((<$>))
readDocx :: ReaderOptions
-> B.ByteString
@ -104,26 +105,20 @@ readDocx opts bytes =
Left _ -> error $ "couldn't parse docx file"
data DState = DState { docxAnchorMap :: M.Map String String
, docxMediaBag :: MediaBag
, docxInHeaderBlock :: Bool}
, docxMediaBag :: MediaBag }
defaultDState :: DState
defaultDState = DState { docxAnchorMap = M.empty
, docxMediaBag = mempty
, docxInHeaderBlock = False}
instance Default DState where
def = DState { docxAnchorMap = M.empty
, docxMediaBag = mempty }
data DEnv = DEnv { docxOptions :: ReaderOptions}
data DEnv = DEnv { docxOptions :: ReaderOptions
, docxInHeaderBlock :: Bool }
instance Default DEnv where
def = DEnv def False
type DocxContext = ReaderT DEnv (State DState)
withDState :: (DState -> DState) -> DocxContext a -> DocxContext a
withDState f dctx = do
ds <- get
modify f
ctx' <- dctx
put ds
return ctx'
evalDocxContext :: DocxContext a -> DEnv -> DState -> a
evalDocxContext ctx env st = evalState (runReaderT ctx env) st
@ -161,7 +156,7 @@ isEmptyPar (Paragraph _ parParts) =
isEmptyElem (TextRun s) = trim s == ""
isEmptyElem _ = True
isEmptyPar _ = False
bodyPartsToMeta' :: [BodyPart] -> DocxContext (M.Map String MetaValue)
bodyPartsToMeta' [] = return M.empty
bodyPartsToMeta' (bp : bps)
@ -170,7 +165,7 @@ bodyPartsToMeta' (bp : bps)
, (Just metaField) <- M.lookup c metaStyles = do
inlines <- parPartsToInlines parParts
remaining <- bodyPartsToMeta' bps
let
let
f (MetaInlines ils) (MetaInlines ils') = MetaBlocks [Para ils, Para ils']
f (MetaInlines ils) (MetaBlocks blks) = MetaBlocks ((Para ils) : blks)
f m (MetaList mv) = MetaList (m : mv)
@ -357,7 +352,7 @@ parPartToInlines (BookMark _ anchor) =
-- user-defined anchor links with header auto ids.
do
-- get whether we're in a header.
inHdrBool <- gets docxInHeaderBlock
inHdrBool <- asks docxInHeaderBlock
-- Get the anchor map.
anchorMap <- gets docxAnchorMap
-- We don't want to rewrite if we're in a header, since we'll take
@ -372,7 +367,8 @@ parPartToInlines (BookMark _ anchor) =
if not inHdrBool && anchor `elem` (M.elems anchorMap)
then uniqueIdent [Str anchor] (M.elems anchorMap)
else anchor
modify $ \s -> s { docxAnchorMap = M.insert anchor newAnchor anchorMap}
unless inHdrBool
(modify $ \s -> s { docxAnchorMap = M.insert anchor newAnchor anchorMap})
return [Span (newAnchor, ["anchor"], []) []]
parPartToInlines (Drawing fp bs) = do
mediaBag <- gets docxMediaBag
@ -384,193 +380,8 @@ parPartToInlines (InternalHyperLink anchor runs) = do
parPartToInlines (ExternalHyperLink target runs) = do
ils <- concatMapM runToInlines runs
return [Link ils (target, "")]
parPartToInlines (PlainOMath omath) = do
e <- oMathToExps omath
return [Math InlineMath (writeTeX e)]
oMathToExps :: OMath -> DocxContext [TM.Exp]
oMathToExps (OMath oMathElems) = concatMapM oMathElemToExps oMathElems
oMathElemToExps :: OMathElem -> DocxContext [TM.Exp]
oMathElemToExps (Accent style base) = do
baseExp <- baseToExp base
let chr = case accentChar style of
Just c -> c
Nothing -> '\180' -- default to acute.
return [TM.EOver False baseExp (TM.ESymbol TM.Accent [chr])]
oMathElemToExps(Bar style base) = do
baseExp <- baseToExp base
return $ case barPos style of
Top -> [TM.EOver False baseExp (TM.ESymbol TM.Accent "\175")]
Bottom -> [TM.EUnder False baseExp (TM.ESymbol TM.Accent "\818")]
oMathElemToExps (Box base) =
(\e -> return [e]) =<< baseToExp base
oMathElemToExps (BorderBox base) =
-- TODO: This should be "\\boxed" somehow
(\e -> return [e]) =<< baseToExp base
oMathElemToExps (Delimiter dPr bases) = do
baseExps <- mapM baseToExp bases
let inDelimExps = map Right baseExps
beg = fromMaybe '(' (delimBegChar dPr)
end = fromMaybe ')' (delimEndChar dPr)
sep = fromMaybe '|' (delimSepChar dPr)
exps = intersperse (Left [sep]) inDelimExps
return [TM.EDelimited [beg] [end] exps]
oMathElemToExps (EquationArray bases) = do
let f b = do bs <- baseToExp' b
return [bs]
baseExps <- mapM f bases
return [TM.EArray [] baseExps]
oMathElemToExps (Fraction num denom) = do
numExp <- concatMapM oMathElemToExps num >>= (return . TM.EGrouped)
denExp <- concatMapM oMathElemToExps denom >>= (return . TM.EGrouped)
return [TM.EFraction TM.NormalFrac numExp denExp]
oMathElemToExps (Function fname base) = do
-- We need a string for the fname, but omml gives it to us as a
-- series of oMath elems. We're going to filter out the oMathRuns,
-- which should work for us most of the time.
let f :: OMathElem -> String
f (OMathRun _ run) = runToString run
f _ = ""
fnameString = concatMap f fname
baseExp <- baseToExp base
return [TM.EMathOperator fnameString, baseExp]
oMathElemToExps (Group style base)
| Just Top <- groupPos style = do
baseExp <- baseToExp base
let chr = case groupChr style of
Just c -> c
Nothing -> '\65079' -- default to overbrace
return [TM.EOver False baseExp (TM.ESymbol TM.Accent [chr])]
| otherwise = do
baseExp <- baseToExp base
let chr = case groupChr style of
Just c -> c
Nothing -> '\65080' -- default to underbrace
return [TM.EUnder False baseExp (TM.ESymbol TM.Accent [chr])]
oMathElemToExps (LowerLimit base limElems) = do
baseExp <- baseToExp base
lim <- concatMapM oMathElemToExps limElems >>= (return . TM.EGrouped)
return [TM.EUnder True lim baseExp]
oMathElemToExps (UpperLimit base limElems) = do
baseExp <- baseToExp base
lim <- concatMapM oMathElemToExps limElems >>= (return . TM.EGrouped)
return [TM.EOver True lim baseExp]
oMathElemToExps (Matrix bases) = do
rows <- mapM (mapM (\b -> baseToExp' b)) bases
return [TM.EArray [TM.AlignCenter] rows]
oMathElemToExps (NAry style sub sup base) = do
subExps <- concatMapM oMathElemToExps sub
supExps <- concatMapM oMathElemToExps sup
baseExp <- baseToExp base
let opChar = case nAryChar style of
Just c -> c
-- default to integral
Nothing -> '\8747'
return [ TM.ESubsup
(TM.ESymbol TM.Op [opChar])
(TM.EGrouped subExps)
(TM.EGrouped supExps)
, baseExp]
oMathElemToExps (Phantom base) =
(\e -> return [TM.EPhantom e]) =<< baseToExp base
oMathElemToExps (Radical degree base) = do
degExps <- concatMapM oMathElemToExps degree
baseExp <- baseToExp base
return $ case degExps of
[] -> [TM.ESqrt baseExp]
ds -> [TM.ERoot (TM.EGrouped ds) baseExp]
oMathElemToExps (PreSubSuper sub sup base) = do
subExps <- concatMapM oMathElemToExps sub
supExps <- concatMapM oMathElemToExps sup
baseExp <- baseToExp base
return [ TM.ESubsup
(TM.EIdentifier "") (TM.EGrouped subExps) (TM.EGrouped supExps)
, baseExp]
oMathElemToExps (Sub base sub) = do
baseExp <- baseToExp base
subExps <- concatMapM oMathElemToExps sub
return [TM.ESub baseExp (TM.EGrouped subExps)]
oMathElemToExps (SubSuper base sub sup) = do
baseExp <- baseToExp base
subExps <- concatMapM oMathElemToExps sub
supExps <- concatMapM oMathElemToExps sup
return [TM.ESubsup baseExp (TM.EGrouped subExps) (TM.EGrouped supExps)]
oMathElemToExps (Super base sup) = do
baseExp <- baseToExp base
supExps <- concatMapM oMathElemToExps sup
return [TM.ESuper baseExp (TM.EGrouped supExps)]
oMathElemToExps (OMathRun sty run@(Run _ _))
| NoStyle <- oMathRunTextStyle sty =
return $ [TM.EIdentifier $ runToString run]
| Nothing <- oMathRunStyleToTextType sty =
return $ [TM.EIdentifier $ runToString run]
| Just textType <- oMathRunStyleToTextType sty =
return $ if oMathLit sty
then [TM.EText textType (runToString run)]
else [TM.EStyled textType [TM.EIdentifier $ runToString run]]
oMathElemToExps (OMathRun _ _) = return []
oMathRunStyleToTextType :: OMathRunStyle -> Maybe TM.TextType
oMathRunStyleToTextType mrPr
| Normal <- oMathRunTextStyle mrPr =
Just $ TM.TextNormal
| Styled scr sty <- oMathRunTextStyle mrPr
,Just OBold <- sty
, Just OSansSerif <- scr =
Just $ TM.TextSansSerifBold
| Styled scr sty <- oMathRunTextStyle mrPr
, Just OBoldItalic <- sty
, Just OSansSerif <- scr =
Just $ TM.TextSansSerifBoldItalic
| Styled scr sty <- oMathRunTextStyle mrPr
, Just OBold <- sty
, Just OScript <- scr =
Just $ TM.TextBoldScript
| Styled scr sty <- oMathRunTextStyle mrPr
, Just OBold <- sty
, Just OFraktur <- scr =
Just $ TM.TextBoldFraktur
| Styled scr sty <- oMathRunTextStyle mrPr
, Just OItalic <- sty
, Just OSansSerif <- scr =
Just $ TM.TextSansSerifItalic
| Styled _ sty <- oMathRunTextStyle mrPr
, Just OBold <- sty =
Just $ TM.TextBold
| Styled _ sty <- oMathRunTextStyle mrPr
, Just OItalic <- sty =
Just $ TM.TextItalic
| Styled scr _ <- oMathRunTextStyle mrPr
, Just OMonospace <- scr =
Just $ TM.TextMonospace
| Styled scr _ <- oMathRunTextStyle mrPr
, Just OSansSerif <- scr =
Just $ TM.TextSansSerif
| Styled scr _ <- oMathRunTextStyle mrPr
, Just ODoubleStruck <- scr =
Just $ TM.TextDoubleStruck
| Styled scr _ <- oMathRunTextStyle mrPr
, Just OScript <- scr =
Just $ TM.TextDoubleStruck
| Styled scr _ <- oMathRunTextStyle mrPr
, Just OFraktur <- scr =
Just $ TM.TextFraktur
| Styled _ sty <- oMathRunTextStyle mrPr
, Just OBoldItalic <- sty =
Just $ TM.TextBoldItalic
| otherwise = Nothing
baseToExp :: Base -> DocxContext TM.Exp
baseToExp (Base mathElems) =
concatMapM oMathElemToExps mathElems >>= (return . TM.EGrouped)
-- an ungrouped version of baseToExp
baseToExp' :: Base -> DocxContext [TM.Exp]
baseToExp' (Base mathElems) =
concatMapM oMathElemToExps mathElems
parPartToInlines (PlainOMath exps) = do
return [Math InlineMath (writeTeX exps)]
isAnchorSpan :: Inline -> Bool
@ -638,8 +449,8 @@ bodyPartToBlocks (Paragraph pPr parparts)
[CodeBlock ("", [], []) (concatMap parPartToString parparts)]
bodyPartToBlocks (Paragraph pPr parparts)
| any isHeaderContainer (parStyleToContainers pPr) = do
ils <-withDState (\s -> s{docxInHeaderBlock = True}) $
parPartsToInlines parparts >>= (return . normalizeSpaces)
ils <- normalizeSpaces <$> local (\s -> s{docxInHeaderBlock = True})
(parPartsToInlines parparts)
let (Container hdrFun) = head $ filter isHeaderContainer (parStyleToContainers pPr)
Header n attr _ = hdrFun []
hdr <- makeHeaderAnchor $ Header n attr ils
@ -696,11 +507,10 @@ bodyPartToBlocks (Tbl cap _ look (r:rs)) = do
widths = replicate size 0 :: [Double]
return [Table caption alignments widths hdrCells cells]
bodyPartToBlocks (OMathPara _ maths) = do
omaths <- mapM oMathToExps maths
bodyPartToBlocks (OMathPara exps) = do
return [Para $
map (\m -> Math DisplayMath (writeTeX m))
omaths]
map (\e -> Math DisplayMath (writeTeX e))
exps]
-- replace targets with generated anchors.
rewriteLink :: Inline -> DocxContext Inline
@ -724,10 +534,8 @@ bodyToOutput (Body bps) = do
docxToOutput :: ReaderOptions -> Docx -> (Meta, [Block], MediaBag)
docxToOutput opts (Docx (Document _ body)) =
let dState = defaultDState
dEnv = DEnv { docxOptions = opts }
in
evalDocxContext (bodyToOutput body) dEnv dState
let dEnv = def { docxOptions = opts} in
evalDocxContext (bodyToOutput body) dEnv def
ilToCode :: Inline -> String

View file

@ -0,0 +1,622 @@
{-# LANGUAGE PatternGuards #-}
{-
Copyright (C) 2014 Jesse Rosenthal <jrosenthal@jhu.edu>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-}
{- |
Module : Text.Pandoc.Readers.Docx.Math
Copyright : Copyright (C) 2014 Jesse Rosenthal
License : GNU GPL, version 2 or above
Maintainer : Jesse Rosenthal <jrosenthal@jhu.edu>
Stability : alpha
Portability : portable
Types and functions for conversion of OMML into TeXMath.
-}
module Text.Pandoc.Readers.Docx.OMath ( elemToExps
) where
import Text.XML.Light
import Data.Maybe (mapMaybe, fromMaybe)
import Data.List (intersperse)
import qualified Text.TeXMath.Types as TM
import Control.Applicative ((<$>))
type NameSpaces = [(String, String)]
elemName :: NameSpaces -> String -> String -> QName
elemName ns prefix name = (QName name (lookup prefix ns) (Just prefix))
isElem :: NameSpaces -> String -> String -> Element -> Bool
isElem ns prefix name element =
qName (elName element) == name &&
qURI (elName element) == (lookup prefix ns)
data OMath = OMath [OMathElem]
deriving Show
data OMathElem = Accent AccentStyle Base
| Bar BarStyle Base
| Box Base
| BorderBox Base
| Delimiter DelimStyle [Base]
| EquationArray [Base]
| Fraction [OMathElem] [OMathElem]
| Function [OMathElem] Base
| Group GroupStyle Base
| LowerLimit Base [OMathElem]
| UpperLimit Base [OMathElem]
| Matrix [[Base]]
| NAry NAryStyle [OMathElem] [OMathElem] Base
| Phantom Base
| Radical [OMathElem] Base
| PreSubSuper [OMathElem] [OMathElem] Base
| Sub Base [OMathElem]
| SubSuper Base [OMathElem] [OMathElem]
| Super Base [OMathElem]
| OMathRun OMathRunStyle [OMathRunElem]
deriving Show
data OMathRunElem = TextRun String
| LnBrk
| Tab
deriving Show
data Base = Base [OMathElem]
deriving Show
data TopBottom = Top | Bottom
deriving Show
data AccentStyle = AccentStyle { accentChar :: Maybe Char }
deriving Show
data BarStyle = BarStyle { barPos :: TopBottom}
deriving Show
data NAryStyle = NAryStyle { nAryChar :: Maybe Char
, nAryLimLoc :: LimLoc}
deriving Show
data OMathRunStyle = OMathRunStyle { oMathLit :: Bool
, oMathRunTextStyle :: OMathRunTextStyle }
deriving Show
data OMathRunTextStyle = NoStyle
| Normal
| Styled { oMathScript :: Maybe OMathTextScript
, oMathStyle :: Maybe OMathTextStyle }
deriving Show
data OMathTextScript = ORoman
| OScript
| OFraktur
| ODoubleStruck
| OSansSerif
| OMonospace
deriving (Show, Eq)
data OMathTextStyle = OPlain
| OBold
| OItalic
| OBoldItalic
deriving (Show, Eq)
defaultNAryStyle :: NAryStyle
defaultNAryStyle = NAryStyle { nAryChar = Nothing -- integral, in practice
, nAryLimLoc = SubSup }
data LimLoc = SubSup | UnderOver deriving Show
data DelimStyle = DelimStyle { delimBegChar :: Maybe Char
, delimSepChar :: Maybe Char
, delimEndChar :: Maybe Char}
deriving Show
defaultDelimStyle :: DelimStyle
defaultDelimStyle = DelimStyle { delimBegChar = Nothing
, delimSepChar = Nothing
, delimEndChar = Nothing }
data GroupStyle = GroupStyle { groupChr :: Maybe Char
, groupPos :: Maybe TopBottom }
deriving Show
defaultGroupStyle :: GroupStyle
defaultGroupStyle = GroupStyle {groupChr = Nothing, groupPos = Nothing}
elemToMath :: NameSpaces -> Element -> Maybe OMath
elemToMath ns element | isElem ns "m" "oMath" element =
Just $ OMath $ mapMaybe (elemToMathElem ns) (elChildren element)
elemToMath _ _ = Nothing
elemToBase :: NameSpaces -> Element -> Maybe Base
elemToBase ns element | isElem ns "m" "e" element =
Just $ Base $ mapMaybe (elemToMathElem ns) (elChildren element)
elemToBase _ _ = Nothing
-- TODO: The right way to do this is to use the ampersand to break the
-- text lines into multiple columns. That's tricky, though, and this
-- will get us most of the way for the time being.
filterAmpersand :: OMathElem -> OMathElem
filterAmpersand (OMathRun mrPr elems) =
let f (TextRun s) = TextRun $ filter ('&' /=) s
f re = re
in
OMathRun mrPr (map f elems)
filterAmpersand e = e
elemToBaseNoAmpersand :: NameSpaces -> Element -> Maybe Base
elemToBaseNoAmpersand ns element | isElem ns "m" "e" element =
return $ Base $
mapMaybe
(\e -> (elemToMathElem ns e >>= (return . filterAmpersand)))
(elChildren element)
elemToBaseNoAmpersand _ _ = Nothing
elemToOMathRunStyle :: NameSpaces -> Element -> OMathRunStyle
elemToOMathRunStyle ns element =
let lit =
case
findChild (elemName ns "m" "lit") element >>=
findAttr (elemName ns "m" "val")
of
Just "on" -> True
_ -> False
in
OMathRunStyle { oMathLit = lit
, oMathRunTextStyle = (elemToOMathRunTextStyle ns element)
}
elemToOMathRunTextStyle :: NameSpaces -> Element -> OMathRunTextStyle
elemToOMathRunTextStyle ns element
| Just mrPr <- findChild (elemName ns "m" "rPr") element
, Just _ <- findChild (elemName ns "m" "nor") mrPr =
Normal
| Just mrPr <- findChild (elemName ns "m" "rPr") element =
let scr =
case
findChild (elemName ns "m" "scr") mrPr >>=
findAttr (elemName ns "m" "val")
of
Just "roman" -> Just ORoman
Just "script" -> Just OScript
Just "fraktur" -> Just OFraktur
Just "double-struck" -> Just ODoubleStruck
Just "sans-serif" -> Just OSansSerif
Just "monospace" -> Just OMonospace
_ -> Nothing
sty =
case
findChild (elemName ns "m" "sty") mrPr >>=
findAttr (elemName ns "m" "val")
of
Just "p" -> Just OPlain
Just "b" -> Just OBold
Just "i" -> Just OItalic
Just "bi" -> Just OBoldItalic
_ -> Nothing
in
Styled { oMathScript = scr, oMathStyle = sty }
| otherwise = NoStyle
elemToNAryStyle :: NameSpaces -> Element -> NAryStyle
elemToNAryStyle ns element
| Just narypr <- findChild (QName "naryPr" (lookup "m" ns) (Just "m")) element =
let
chr = findChild (QName "chr" (lookup "m" ns) (Just "m")) narypr >>=
findAttr (QName "val" (lookup "m" ns) (Just "m")) >>=
Just . head
limLoc = findChild (QName "limLoc" (lookup "m" ns) (Just "m")) narypr >>=
findAttr (QName "val" (lookup "m" ns) (Just "m"))
limLoc' = case limLoc of
Just "undOver" -> UnderOver
Just "subSup" -> SubSup
_ -> SubSup
in
NAryStyle { nAryChar = chr, nAryLimLoc = limLoc'}
elemToNAryStyle _ _ = defaultNAryStyle
elemToDelimStyle :: NameSpaces -> Element -> DelimStyle
elemToDelimStyle ns element
| Just dPr <- findChild (QName "dPr" (lookup "m" ns) (Just "m")) element =
let begChr = findChild (QName "begChr" (lookup "m" ns) (Just "m")) dPr >>=
findAttr (QName "val" (lookup "m" ns) (Just "m")) >>=
(\c -> if null c then (Just ' ') else (Just $ head c))
sepChr = findChild (QName "sepChr" (lookup "m" ns) (Just "m")) dPr >>=
findAttr (QName "val" (lookup "m" ns) (Just "m")) >>=
(\c -> if null c then (Just ' ') else (Just $ head c))
endChr = findChild (QName "endChr" (lookup "m" ns) (Just "m")) dPr >>=
findAttr (QName "val" (lookup "m" ns) (Just "m")) >>=
(\c -> if null c then (Just ' ') else (Just $ head c))
in
DelimStyle { delimBegChar = begChr
, delimSepChar = sepChr
, delimEndChar = endChr}
elemToDelimStyle _ _ = defaultDelimStyle
elemToGroupStyle :: NameSpaces -> Element -> GroupStyle
elemToGroupStyle ns element
| Just gPr <- findChild (QName "groupChrPr" (lookup "m" ns) (Just "m")) element =
let chr = findChild (QName "chr" (lookup "m" ns) (Just "m")) gPr >>=
findAttr (QName "val" (lookup "m" ns) (Just "m")) >>=
Just . head
pos = findChild (QName "pos" (lookup "m" ns) (Just "m")) gPr >>=
findAttr (QName "val" (lookup "m" ns) (Just "m")) >>=
(\s -> Just $ if s == "top" then Top else Bottom)
in
GroupStyle { groupChr = chr, groupPos = pos }
elemToGroupStyle _ _ = defaultGroupStyle
elemToMathElem :: NameSpaces -> Element -> Maybe OMathElem
elemToMathElem ns element | isElem ns "m" "acc" element = do
let accChar =
findChild (elemName ns "m" "accPr") element >>=
findChild (elemName ns "m" "chr") >>=
findAttr (elemName ns "m" "val") >>=
Just . head
accPr = AccentStyle { accentChar = accChar}
base <- findChild (elemName ns "m" "e") element >>=
elemToBase ns
return $ Accent accPr base
elemToMathElem ns element | isElem ns "m" "bar" element = do
barPr <- findChild (QName "barPr" (lookup "m" ns) (Just "m")) element >>=
findChild (QName "pos" (lookup "m" ns) (Just "m")) >>=
findAttr (QName "val" (lookup "m" ns) (Just "m")) >>=
(\s ->
Just $ BarStyle {
barPos = (if s == "bot" then Bottom else Top)
})
base <- findChild (QName "e" (lookup "m" ns) (Just "m")) element >>=
elemToBase ns
return $ Bar barPr base
elemToMathElem ns element | isElem ns "m" "box" element =
findChild (elemName ns "m" "e") element >>=
elemToBase ns >>=
(\b -> return $ Box b)
elemToMathElem ns element | isElem ns "m" "borderBox" element =
findChild (elemName ns "m" "e") element >>=
elemToBase ns >>=
(\b -> return $ BorderBox b)
elemToMathElem ns element | isElem ns "m" "d" element =
let style = elemToDelimStyle ns element
in
return $ Delimiter style $ mapMaybe (elemToBase ns) (elChildren element)
elemToMathElem ns element | isElem ns "m" "eqArr" element =
return $ EquationArray $ mapMaybe (elemToBaseNoAmpersand ns) (elChildren element)
elemToMathElem ns element | isElem ns "m" "f" element = do
num <- findChild (elemName ns "m" "num") element
den <- findChild (elemName ns "m" "den") element
let numElems = mapMaybe (elemToMathElem ns) (elChildren num)
denElems = mapMaybe (elemToMathElem ns) (elChildren den)
return $ Fraction numElems denElems
elemToMathElem ns element | isElem ns "m" "func" element = do
fName <- findChild (elemName ns "m" "fName") element
base <- findChild (elemName ns "m" "e") element >>=
elemToBase ns
let fnElems = mapMaybe (elemToMathElem ns) (elChildren fName)
return $ Function fnElems base
elemToMathElem ns element | isElem ns "m" "groupChr" element =
let style = elemToGroupStyle ns element
in
findChild (elemName ns "m" "e") element >>=
elemToBase ns >>=
(\b -> return $ Group style b)
elemToMathElem ns element | isElem ns "m" "limLow" element = do
base <- findChild (elemName ns "m" "e") element
>>= elemToBase ns
lim <- findChild (elemName ns "m" "lim") element
let limElems = mapMaybe (elemToMathElem ns) (elChildren lim)
return $ LowerLimit base limElems
elemToMathElem ns element | isElem ns "m" "limUpp" element = do
base <- findChild (elemName ns "m" "e") element
>>= elemToBase ns
lim <- findChild (elemName ns "m" "lim") element
let limElems = mapMaybe (elemToMathElem ns) (elChildren lim)
return $ UpperLimit base limElems
elemToMathElem ns element | isElem ns "m" "m" element = do
let rows = findChildren (elemName ns "m" "mr") element
let bases = mapMaybe (\mr -> mapM (elemToBase ns) (elChildren mr)) rows
return $ Matrix bases
elemToMathElem ns element | isElem ns "m" "nary" element = do
let style = elemToNAryStyle ns element
sub <- findChild (elemName ns "m" "sub") element >>=
(\e -> return $ mapMaybe (elemToMathElem ns) (elChildren e))
sup <- findChild (elemName ns "m" "sup") element >>=
(\e -> return $ mapMaybe (elemToMathElem ns) (elChildren e))
base <- findChild (elemName ns "m" "e") element >>=
elemToBase ns
return $ NAry style sub sup base
elemToMathElem ns element | isElem ns "m" "rad" element = do
deg <- findChild (elemName ns "m" "deg") element >>=
(\e -> return $ mapMaybe (elemToMathElem ns) (elChildren e))
base <- findChild (elemName ns "m" "e") element >>=
elemToBase ns
return $ Radical deg base
elemToMathElem ns element | isElem ns "m" "phant" element = do
base <- findChild (elemName ns "m" "e") element >>=
elemToBase ns
return $ Phantom base
elemToMathElem ns element | isElem ns "m" "sPre" element = do
sub <- findChild (elemName ns "m" "sub") element >>=
(\e -> return $ mapMaybe (elemToMathElem ns) (elChildren e))
sup <- findChild (elemName ns "m" "sup") element >>=
(\e -> return $ mapMaybe (elemToMathElem ns) (elChildren e))
base <- findChild (elemName ns "m" "e") element >>=
elemToBase ns
return $ PreSubSuper sub sup base
elemToMathElem ns element | isElem ns "m" "sSub" element = do
base <- findChild (elemName ns "m" "e") element >>=
elemToBase ns
sub <- findChild (elemName ns "m" "sub") element >>=
(\e -> return $ mapMaybe (elemToMathElem ns) (elChildren e))
return $ Sub base sub
elemToMathElem ns element | isElem ns "m" "sSubSup" element = do
base <- findChild (elemName ns "m" "e") element >>=
elemToBase ns
sub <- findChild (elemName ns "m" "sub") element >>=
(\e -> return $ mapMaybe (elemToMathElem ns) (elChildren e))
sup <- findChild (elemName ns "m" "sup") element >>=
(\e -> return $ mapMaybe (elemToMathElem ns) (elChildren e))
return $ SubSuper base sub sup
elemToMathElem ns element | isElem ns "m" "sSup" element = do
base <- findChild (elemName ns "m" "e") element >>=
elemToBase ns
sup <- findChild (elemName ns "m" "sup") element >>=
(\e -> return $ mapMaybe (elemToMathElem ns) (elChildren e))
return $ Super base sup
elemToMathElem ns element | isElem ns "m" "r" element = do
let mrPr = elemToOMathRunStyle ns element
mrElems <- elemToOMathRunElems ns element
return $ OMathRun mrPr mrElems
elemToMathElem _ _ = Nothing
elemToOMathRunElem :: NameSpaces -> Element -> Maybe OMathRunElem
elemToOMathRunElem ns element
| isElem ns "w" "t" element
|| isElem ns "m" "t" element
|| isElem ns "w" "delText" element = Just $ TextRun $ strContent element
| isElem ns "w" "br" element = Just LnBrk
| isElem ns "w" "tab" element = Just Tab
| otherwise = Nothing
elemToOMathRunElems :: NameSpaces -> Element -> Maybe [OMathRunElem]
elemToOMathRunElems ns element
| isElem ns "w" "r" element
|| isElem ns "m" "r" element =
Just $ mapMaybe (elemToOMathRunElem ns) (elChildren element)
elemToOMathRunElems _ _ = Nothing
----- And now the TeXMath Creation
oMathRunElemToString :: OMathRunElem -> String
oMathRunElemToString (TextRun s) = s
oMathRunElemToString (LnBrk) = ['\n']
oMathRunElemToString (Tab) = ['\t']
oMathRunElemsToString :: [OMathRunElem] -> String
oMathRunElemsToString = concatMap oMathRunElemToString
oMathElemToString :: OMathElem -> String
oMathElemToString (OMathRun _ oMathRunElems) =
oMathRunElemsToString oMathRunElems
oMathElemToString _ = ""
oMathToExps :: OMath -> [TM.Exp]
oMathToExps (OMath oMathElems) = concatMap oMathElemToExps oMathElems
oMathElemToExps :: OMathElem -> [TM.Exp]
oMathElemToExps (Accent style base) =
let baseExp = baseToExp base
chr = case accentChar style of
Just c -> c
Nothing -> '\180' -- default to acute.
in
[TM.EOver False baseExp (TM.ESymbol TM.Accent [chr])]
oMathElemToExps(Bar style base) =
let baseExp = baseToExp base
in
case barPos style of
Top -> [TM.EOver False baseExp (TM.ESymbol TM.Accent "\175")]
Bottom -> [TM.EUnder False baseExp (TM.ESymbol TM.Accent "\818")]
oMathElemToExps (Box base) = [baseToExp base]
oMathElemToExps (BorderBox base) =
-- TODO: This should be "\\boxed" somehow
[baseToExp base]
oMathElemToExps (Delimiter dPr bases) =
let baseExps = map baseToExp bases
inDelimExps = map Right baseExps
beg = fromMaybe '(' (delimBegChar dPr)
end = fromMaybe ')' (delimEndChar dPr)
sep = fromMaybe '|' (delimSepChar dPr)
exps = intersperse (Left [sep]) inDelimExps
in
[TM.EDelimited [beg] [end] exps]
oMathElemToExps (EquationArray bases) =
let baseExps = map (\b -> [baseToExp' b]) bases
in
[TM.EArray [] baseExps]
oMathElemToExps (Fraction num denom) =
let numExp = TM.EGrouped $ concatMap oMathElemToExps num
denExp = TM.EGrouped $ concatMap oMathElemToExps denom
in
[TM.EFraction TM.NormalFrac numExp denExp]
oMathElemToExps (Function fname base) =
-- We need a string for the fname, but omml gives it to us as a
-- series of oMath elems. We're going to filter out the oMathRuns,
-- which should work for us most of the time.
let fnameString = concatMap oMathElemToString fname
baseExp = baseToExp base
in
[TM.EMathOperator fnameString, baseExp]
oMathElemToExps (Group style base)
| Just Top <- groupPos style =
let baseExp = baseToExp base
chr = case groupChr style of
Just c -> c
Nothing -> '\65079' -- default to overbrace
in
[TM.EOver False baseExp (TM.ESymbol TM.Accent [chr])]
| otherwise =
let baseExp = baseToExp base
chr = case groupChr style of
Just c -> c
Nothing -> '\65080' -- default to underbrace
in
[TM.EUnder False baseExp (TM.ESymbol TM.Accent [chr])]
oMathElemToExps (LowerLimit base limElems) = do
let baseExp = baseToExp base
lim = TM.EGrouped $ concatMap oMathElemToExps limElems
in
[TM.EUnder True lim baseExp]
oMathElemToExps (UpperLimit base limElems) =
let baseExp = baseToExp base
lim = TM.EGrouped $ concatMap oMathElemToExps limElems
in
[TM.EOver True lim baseExp]
oMathElemToExps (Matrix bases) =
let rows = map (map baseToExp') bases
in
[TM.EArray [TM.AlignCenter] rows]
oMathElemToExps (NAry style sub sup base) =
let
subExps = concatMap oMathElemToExps sub
supExps = concatMap oMathElemToExps sup
baseExp = baseToExp base
opChar = case nAryChar style of
Just c -> c
-- default to integral
Nothing -> '\8747'
in [ TM.ESubsup
(TM.ESymbol TM.Op [opChar])
(TM.EGrouped subExps)
(TM.EGrouped supExps)
, baseExp]
oMathElemToExps (Phantom base) =
[TM.EPhantom $ baseToExp base]
oMathElemToExps (Radical degree base) =
let degExps = concatMap oMathElemToExps degree
baseExp = baseToExp base
in
case degExps of
[] -> [TM.ESqrt baseExp]
ds -> [TM.ERoot (TM.EGrouped ds) baseExp]
oMathElemToExps (PreSubSuper sub sup base) =
let subExps = concatMap oMathElemToExps sub
supExps = concatMap oMathElemToExps sup
baseExp = baseToExp base
in [ TM.ESubsup
(TM.EIdentifier "") (TM.EGrouped subExps) (TM.EGrouped supExps)
, baseExp]
oMathElemToExps (Sub base sub) =
let baseExp = baseToExp base
subExps = concatMap oMathElemToExps sub
in
[TM.ESub baseExp (TM.EGrouped subExps)]
oMathElemToExps (SubSuper base sub sup) =
let baseExp = baseToExp base
subExps = concatMap oMathElemToExps sub
supExps = concatMap oMathElemToExps sup
in
[TM.ESubsup baseExp (TM.EGrouped subExps) (TM.EGrouped supExps)]
oMathElemToExps (Super base sup) =
let baseExp = baseToExp base
supExps = concatMap oMathElemToExps sup
in
[TM.ESuper baseExp (TM.EGrouped supExps)]
oMathElemToExps (OMathRun sty elems)
| NoStyle <- oMathRunTextStyle sty =
[TM.EIdentifier $ oMathRunElemsToString elems]
| Nothing <- oMathRunStyleToTextType sty =
[TM.EIdentifier $ oMathRunElemsToString elems]
| Just textType <- oMathRunStyleToTextType sty =
if oMathLit sty
then [TM.EText textType (oMathRunElemsToString elems)]
else [TM.EStyled textType [TM.EIdentifier $ oMathRunElemsToString elems]]
oMathElemToExps (OMathRun _ _) = []
oMathRunStyleToTextType :: OMathRunStyle -> Maybe TM.TextType
oMathRunStyleToTextType mrPr
| Normal <- oMathRunTextStyle mrPr =
Just $ TM.TextNormal
| Styled scr sty <- oMathRunTextStyle mrPr
,Just OBold <- sty
, Just OSansSerif <- scr =
Just $ TM.TextSansSerifBold
| Styled scr sty <- oMathRunTextStyle mrPr
, Just OBoldItalic <- sty
, Just OSansSerif <- scr =
Just $ TM.TextSansSerifBoldItalic
| Styled scr sty <- oMathRunTextStyle mrPr
, Just OBold <- sty
, Just OScript <- scr =
Just $ TM.TextBoldScript
| Styled scr sty <- oMathRunTextStyle mrPr
, Just OBold <- sty
, Just OFraktur <- scr =
Just $ TM.TextBoldFraktur
| Styled scr sty <- oMathRunTextStyle mrPr
, Just OItalic <- sty
, Just OSansSerif <- scr =
Just $ TM.TextSansSerifItalic
| Styled _ sty <- oMathRunTextStyle mrPr
, Just OBold <- sty =
Just $ TM.TextBold
| Styled _ sty <- oMathRunTextStyle mrPr
, Just OItalic <- sty =
Just $ TM.TextItalic
| Styled scr _ <- oMathRunTextStyle mrPr
, Just OMonospace <- scr =
Just $ TM.TextMonospace
| Styled scr _ <- oMathRunTextStyle mrPr
, Just OSansSerif <- scr =
Just $ TM.TextSansSerif
| Styled scr _ <- oMathRunTextStyle mrPr
, Just ODoubleStruck <- scr =
Just $ TM.TextDoubleStruck
| Styled scr _ <- oMathRunTextStyle mrPr
, Just OScript <- scr =
Just $ TM.TextDoubleStruck
| Styled scr _ <- oMathRunTextStyle mrPr
, Just OFraktur <- scr =
Just $ TM.TextFraktur
| Styled _ sty <- oMathRunTextStyle mrPr
, Just OBoldItalic <- sty =
Just $ TM.TextBoldItalic
| otherwise = Nothing
baseToExp :: Base -> TM.Exp
baseToExp b = TM.EGrouped $ baseToExp' b
-- an ungrouped version of baseToExp
baseToExp' :: Base -> [TM.Exp]
baseToExp' (Base mathElems) =
concatMap oMathElemToExps mathElems
elemToExps :: NameSpaces -> Element -> Maybe [TM.Exp]
elemToExps ns element = oMathToExps <$> (elemToMath ns element)

View file

@ -36,19 +36,6 @@ module Text.Pandoc.Readers.Docx.Parse ( Docx(..)
, BodyPart(..)
, TblLook(..)
, ParPart(..)
, OMath(..)
, OMathElem(..)
, Base(..)
, TopBottom(..)
, AccentStyle(..)
, BarStyle(..)
, NAryStyle(..)
, DelimStyle(..)
, GroupStyle(..)
, OMathRunStyle(..)
, OMathRunTextStyle(..)
, OMathTextScript(..)
, OMathTextStyle(..)
, Run(..)
, RunElem(..)
, Notes
@ -74,6 +61,8 @@ import qualified Text.Pandoc.UTF8 as UTF8
import Control.Monad.Reader
import qualified Data.Map as M
import Text.Pandoc.Compat.Except
import Text.Pandoc.Readers.Docx.OMath (elemToExps)
import Text.TeXMath (Exp)
data ReaderEnv = ReaderEnv { envNotes :: Notes
, envNumbering :: Numbering
@ -161,7 +150,7 @@ defaultParagraphStyle = ParagraphStyle { pStyle = []
data BodyPart = Paragraph ParagraphStyle [ParPart]
| ListItem ParagraphStyle String String Level [ParPart]
| Tbl String TblGrid TblLook [Row]
| OMathPara OMathParaStyle [OMath]
| OMathPara [[Exp]]
deriving Show
type TblGrid = [Integer]
@ -185,100 +174,9 @@ data ParPart = PlainRun Run
| InternalHyperLink Anchor [Run]
| ExternalHyperLink URL [Run]
| Drawing FilePath B.ByteString
| PlainOMath OMath
| PlainOMath [Exp]
deriving Show
data OMath = OMath [OMathElem]
deriving Show
data OMathElem = Accent AccentStyle Base
| Bar BarStyle Base
| Box Base
| BorderBox Base
| Delimiter DelimStyle [Base]
| EquationArray [Base]
| Fraction [OMathElem] [OMathElem]
| Function [OMathElem] Base
| Group GroupStyle Base
| LowerLimit Base [OMathElem]
| UpperLimit Base [OMathElem]
| Matrix [[Base]]
| NAry NAryStyle [OMathElem] [OMathElem] Base
| Phantom Base
| Radical [OMathElem] Base
| PreSubSuper [OMathElem] [OMathElem] Base
| Sub Base [OMathElem]
| SubSuper Base [OMathElem] [OMathElem]
| Super Base [OMathElem]
| OMathRun OMathRunStyle Run
deriving Show
data Base = Base [OMathElem]
deriving Show
-- placeholders
type OMathParaStyle = [String]
data TopBottom = Top | Bottom
deriving Show
data AccentStyle = AccentStyle { accentChar :: Maybe Char }
deriving Show
data BarStyle = BarStyle { barPos :: TopBottom}
deriving Show
data NAryStyle = NAryStyle { nAryChar :: Maybe Char
, nAryLimLoc :: LimLoc}
deriving Show
data OMathRunStyle = OMathRunStyle { oMathLit :: Bool
, oMathRunTextStyle :: OMathRunTextStyle }
deriving Show
data OMathRunTextStyle = NoStyle
| Normal
| Styled { oMathScript :: Maybe OMathTextScript
, oMathStyle :: Maybe OMathTextStyle }
deriving Show
data OMathTextScript = ORoman
| OScript
| OFraktur
| ODoubleStruck
| OSansSerif
| OMonospace
deriving (Show, Eq)
data OMathTextStyle = OPlain
| OBold
| OItalic
| OBoldItalic
deriving (Show, Eq)
defaultNAryStyle :: NAryStyle
defaultNAryStyle = NAryStyle { nAryChar = Nothing -- integral, in practice
, nAryLimLoc = SubSup }
data LimLoc = SubSup | UnderOver deriving Show
data DelimStyle = DelimStyle { delimBegChar :: Maybe Char
, delimSepChar :: Maybe Char
, delimEndChar :: Maybe Char}
deriving Show
defaultDelimStyle :: DelimStyle
defaultDelimStyle = DelimStyle { delimBegChar = Nothing
, delimSepChar = Nothing
, delimEndChar = Nothing }
data GroupStyle = GroupStyle { groupChr :: Maybe Char
, groupPos :: Maybe TopBottom }
deriving Show
defaultGroupStyle :: GroupStyle
defaultGroupStyle = GroupStyle {groupChr = Nothing, groupPos = Nothing}
data Run = Run RunStyle [RunElem]
| Footnote [BodyPart]
| Endnote [BodyPart]
@ -577,9 +475,8 @@ elemToBodyPart ns element
| isElem ns "w" "p" element
, (c:_) <- findChildren (elemName ns "m" "oMathPara") element =
do
let style = [] -- placeholder
maths <- mapD (elemToMath ns) (elChildren c)
return $ OMathPara style maths
expsLst <- mapD (\e -> (maybeToD $ elemToExps ns e)) (elChildren c)
return $ OMathPara expsLst
elemToBodyPart ns element
| isElem ns "w" "p" element
, Just (numId, lvl) <- elemToNumInfo ns element = do
@ -615,262 +512,6 @@ elemToBodyPart ns element
return $ Tbl caption grid tblLook rows
elemToBodyPart _ _ = throwError WrongElem
elemToMath :: NameSpaces -> Element -> D OMath
elemToMath ns element | isElem ns "m" "oMath" element =
mapD (elemToMathElem ns) (elChildren element) >>=
(\es -> return $ OMath es)
elemToMath _ _ = throwError WrongElem
elemToBase :: NameSpaces -> Element -> D Base
elemToBase ns element | isElem ns "m" "e" element =
mapD (elemToMathElem ns) (elChildren element) >>=
(\es -> return $ Base es)
elemToBase _ _ = throwError WrongElem
-- TODO: The right way to do this is to use the ampersand to break the
-- text lines into multiple columns. That's tricky, though, and this
-- will get us most of the way for the time being.
filterAmpersand :: OMathElem -> OMathElem
filterAmpersand (OMathRun mrPr (Run wrPr elems)) =
let f (TextRun s) = TextRun $ filter ('&' /=) s
f re = re
in
OMathRun mrPr $ Run wrPr (map f elems)
filterAmpersand e = e
elemToBaseNoAmpersand :: NameSpaces -> Element -> D Base
elemToBaseNoAmpersand ns element | isElem ns "m" "e" element =
mapD
(\e -> (elemToMathElem ns e >>= (return . filterAmpersand)))
(elChildren element) >>=
(\es -> return $ Base es)
elemToBaseNoAmpersand _ _ = throwError WrongElem
elemToOMathRunStyle :: NameSpaces -> Element -> OMathRunStyle
elemToOMathRunStyle ns element =
let lit =
case
findChild (elemName ns "m" "lit") element >>=
findAttr (elemName ns "m" "val")
of
Just "on" -> True
_ -> False
in
OMathRunStyle { oMathLit = lit
, oMathRunTextStyle = (elemToOMathRunTextStyle ns element)
}
elemToOMathRunTextStyle :: NameSpaces -> Element -> OMathRunTextStyle
elemToOMathRunTextStyle ns element
| Just mrPr <- findChild (elemName ns "m" "rPr") element
, Just _ <- findChild (elemName ns "m" "nor") mrPr =
Normal
| Just mrPr <- findChild (elemName ns "m" "rPr") element =
let scr =
case
findChild (elemName ns "m" "scr") mrPr >>=
findAttr (elemName ns "m" "val")
of
Just "roman" -> Just ORoman
Just "script" -> Just OScript
Just "fraktur" -> Just OFraktur
Just "double-struck" -> Just ODoubleStruck
Just "sans-serif" -> Just OSansSerif
Just "monospace" -> Just OMonospace
_ -> Nothing
sty =
case
findChild (elemName ns "m" "sty") mrPr >>=
findAttr (elemName ns "m" "val")
of
Just "p" -> Just OPlain
Just "b" -> Just OBold
Just "i" -> Just OItalic
Just "bi" -> Just OBoldItalic
_ -> Nothing
in
Styled { oMathScript = scr, oMathStyle = sty }
| otherwise = NoStyle
elemToNAryStyle :: NameSpaces -> Element -> NAryStyle
elemToNAryStyle ns element
| Just narypr <- findChild (QName "naryPr" (lookup "m" ns) (Just "m")) element =
let
chr = findChild (QName "chr" (lookup "m" ns) (Just "m")) narypr >>=
findAttr (QName "val" (lookup "m" ns) (Just "m")) >>=
Just . head
limLoc = findChild (QName "limLoc" (lookup "m" ns) (Just "m")) narypr >>=
findAttr (QName "val" (lookup "m" ns) (Just "m"))
limLoc' = case limLoc of
Just "undOver" -> UnderOver
Just "subSup" -> SubSup
_ -> SubSup
in
NAryStyle { nAryChar = chr, nAryLimLoc = limLoc'}
elemToNAryStyle _ _ = defaultNAryStyle
elemToDelimStyle :: NameSpaces -> Element -> DelimStyle
elemToDelimStyle ns element
| Just dPr <- findChild (QName "dPr" (lookup "m" ns) (Just "m")) element =
let begChr = findChild (QName "begChr" (lookup "m" ns) (Just "m")) dPr >>=
findAttr (QName "val" (lookup "m" ns) (Just "m")) >>=
(\c -> if null c then (Just ' ') else (Just $ head c))
sepChr = findChild (QName "sepChr" (lookup "m" ns) (Just "m")) dPr >>=
findAttr (QName "val" (lookup "m" ns) (Just "m")) >>=
(\c -> if null c then (Just ' ') else (Just $ head c))
endChr = findChild (QName "endChr" (lookup "m" ns) (Just "m")) dPr >>=
findAttr (QName "val" (lookup "m" ns) (Just "m")) >>=
(\c -> if null c then (Just ' ') else (Just $ head c))
in
DelimStyle { delimBegChar = begChr
, delimSepChar = sepChr
, delimEndChar = endChr}
elemToDelimStyle _ _ = defaultDelimStyle
elemToGroupStyle :: NameSpaces -> Element -> GroupStyle
elemToGroupStyle ns element
| Just gPr <- findChild (QName "groupChrPr" (lookup "m" ns) (Just "m")) element =
let chr = findChild (QName "chr" (lookup "m" ns) (Just "m")) gPr >>=
findAttr (QName "val" (lookup "m" ns) (Just "m")) >>=
Just . head
pos = findChild (QName "pos" (lookup "m" ns) (Just "m")) gPr >>=
findAttr (QName "val" (lookup "m" ns) (Just "m")) >>=
(\s -> Just $ if s == "top" then Top else Bottom)
in
GroupStyle { groupChr = chr, groupPos = pos }
elemToGroupStyle _ _ = defaultGroupStyle
elemToMathElem :: NameSpaces -> Element -> D OMathElem
elemToMathElem ns element | isElem ns "m" "acc" element = do
let accChar =
findChild (elemName ns "m" "accPr") element >>=
findChild (elemName ns "m" "chr") >>=
findAttr (elemName ns "m" "val") >>=
Just . head
accPr = AccentStyle { accentChar = accChar}
base <-(maybeToD $ findChild (elemName ns "m" "e") element) >>=
elemToBase ns
return $ Accent accPr base
elemToMathElem ns element | isElem ns "m" "bar" element = do
barPr <- maybeToD $
findChild (QName "barPr" (lookup "m" ns) (Just "m")) element >>=
findChild (QName "pos" (lookup "m" ns) (Just "m")) >>=
findAttr (QName "val" (lookup "m" ns) (Just "m")) >>=
(\s ->
Just $ BarStyle {
barPos = (if s == "bot" then Bottom else Top)
})
base <-maybeToD (findChild (QName "e" (lookup "m" ns) (Just "m")) element) >>=
elemToBase ns
return $ Bar barPr base
elemToMathElem ns element | isElem ns "m" "box" element =
maybeToD (findChild (elemName ns "m" "e") element) >>=
elemToBase ns >>=
(\b -> return $ Box b)
elemToMathElem ns element | isElem ns "m" "borderBox" element =
maybeToD (findChild (elemName ns "m" "e") element) >>=
elemToBase ns >>=
(\b -> return $ BorderBox b)
elemToMathElem ns element | isElem ns "m" "d" element =
let style = elemToDelimStyle ns element
in
mapD (elemToBase ns) (elChildren element) >>=
(\es -> return $ Delimiter style es)
elemToMathElem ns element | isElem ns "m" "eqArr" element =
mapD (elemToBaseNoAmpersand ns) (elChildren element) >>=
(\es -> return $ EquationArray es)
elemToMathElem ns element | isElem ns "m" "f" element = do
num <- maybeToD $ findChild (elemName ns "m" "num") element
den <- maybeToD $ findChild (elemName ns "m" "den") element
numElems <- mapD (elemToMathElem ns) (elChildren num)
denElems <- mapD (elemToMathElem ns) (elChildren den)
return $ Fraction numElems denElems
elemToMathElem ns element | isElem ns "m" "func" element = do
fName <- maybeToD $ findChild (elemName ns "m" "fName") element
base <- maybeToD (findChild (elemName ns "m" "e") element) >>=
elemToBase ns
fnElems <- mapD (elemToMathElem ns) (elChildren fName)
return $ Function fnElems base
elemToMathElem ns element | isElem ns "m" "groupChr" element =
let style = elemToGroupStyle ns element
in
maybeToD (findChild (elemName ns "m" "e") element) >>=
elemToBase ns >>=
(\b -> return $ Group style b)
elemToMathElem ns element | isElem ns "m" "limLow" element = do
base <- maybeToD (findChild (elemName ns "m" "e") element)
>>= elemToBase ns
lim <- maybeToD $ findChild (elemName ns "m" "lim") element
limElems <- mapD (elemToMathElem ns) (elChildren lim)
return $ LowerLimit base limElems
elemToMathElem ns element | isElem ns "m" "limUpp" element = do
base <- maybeToD (findChild (elemName ns "m" "e") element)
>>= elemToBase ns
lim <- maybeToD $ findChild (elemName ns "m" "lim") element
limElems <- mapD (elemToMathElem ns) (elChildren lim)
return $ UpperLimit base limElems
elemToMathElem ns element | isElem ns "m" "m" element = do
let rows = findChildren (elemName ns "m" "mr") element
bases <- mapD (\mr -> mapD (elemToBase ns) (elChildren mr)) rows
return $ Matrix bases
elemToMathElem ns element | isElem ns "m" "nary" element = do
let style = elemToNAryStyle ns element
sub <- maybeToD (findChild (elemName ns "m" "sub") element) >>=
(\e -> mapD (elemToMathElem ns) (elChildren e))
sup <- maybeToD (findChild (elemName ns "m" "sup") element) >>=
(\e -> mapD (elemToMathElem ns) (elChildren e))
base <- maybeToD (findChild (elemName ns "m" "e") element) >>=
elemToBase ns
return $ NAry style sub sup base
elemToMathElem ns element | isElem ns "m" "rad" element = do
deg <- maybeToD (findChild (elemName ns "m" "deg") element) >>=
(\e -> mapD (elemToMathElem ns) (elChildren e))
base <- maybeToD (findChild (elemName ns "m" "e") element) >>=
elemToBase ns
return $ Radical deg base
elemToMathElem ns element | isElem ns "m" "phant" element = do
base <- maybeToD (findChild (elemName ns "m" "e") element) >>=
elemToBase ns
return $ Phantom base
elemToMathElem ns element | isElem ns "m" "sPre" element = do
sub <- maybeToD (findChild (elemName ns "m" "sub") element) >>=
(\e -> mapD (elemToMathElem ns) (elChildren e))
sup <- maybeToD (findChild (elemName ns "m" "sup") element) >>=
(\e -> mapD (elemToMathElem ns) (elChildren e))
base <- maybeToD (findChild (elemName ns "m" "e") element) >>=
elemToBase ns
return $ PreSubSuper sub sup base
elemToMathElem ns element | isElem ns "m" "sSub" element = do
base <- maybeToD (findChild (elemName ns "m" "e") element) >>=
elemToBase ns
sub <- maybeToD (findChild (elemName ns "m" "sub") element) >>=
(\e -> mapD (elemToMathElem ns) (elChildren e))
return $ Sub base sub
elemToMathElem ns element | isElem ns "m" "sSubSup" element = do
base <- maybeToD (findChild (elemName ns "m" "e") element) >>=
elemToBase ns
sub <- maybeToD (findChild (elemName ns "m" "sub") element) >>=
(\e -> mapD (elemToMathElem ns) (elChildren e))
sup <- maybeToD (findChild (elemName ns "m" "sup") element) >>=
(\e -> mapD (elemToMathElem ns) (elChildren e))
return $ SubSuper base sub sup
elemToMathElem ns element | isElem ns "m" "sSup" element = do
base <- maybeToD (findChild (elemName ns "m" "e") element) >>=
elemToBase ns
sup <- maybeToD (findChild (elemName ns "m" "sup") element) >>=
(\e -> mapD (elemToMathElem ns) (elChildren e))
return $ Super base sup
elemToMathElem ns element | isElem ns "m" "r" element = do
let mrPr = elemToOMathRunStyle ns element
wrPr = elemToRunStyle ns element
relems <- elemToRunElems ns element
return $ OMathRun mrPr $ Run wrPr relems
elemToMathElem _ _ = throwError WrongElem
lookupRelationship :: RelId -> [Relationship] -> Maybe Target
lookupRelationship relid rels =
lookup relid (map (\(Relationship pair) -> pair) rels)
@ -934,7 +575,7 @@ elemToParPart ns element
Nothing -> ExternalHyperLink "" runs
elemToParPart ns element
| isElem ns "m" "oMath" element =
elemToMath ns element >>= (return . PlainOMath)
(maybeToD $ elemToExps ns element) >>= (return . PlainOMath)
elemToParPart _ _ = throwError WrongElem
lookupFootnote :: String -> Notes -> Maybe Element