git.iko.soy/typeable/pandoc
on master help sign in
Docx reader: Use TeXMath to write math
3bc2ea4Jesse Rosenthal
src/Text/Pandoc/Readers/Docx.hs+190−155
@@ -82,17 +82,17 @@ import Text.Pandoc.Walk
82import Text.Pandoc.Readers.Docx.Parse
82import Text.Pandoc.Readers.Docx.Parse
83import Text.Pandoc.Readers.Docx.Lists
83import Text.Pandoc.Readers.Docx.Lists
84import Text.Pandoc.Readers.Docx.Reducible
84import Text.Pandoc.Readers.Docx.Reducible
85−import Text.Pandoc.Readers.Docx.TexChar
86import Text.Pandoc.Shared
85import Text.Pandoc.Shared
87import Text.Pandoc.MediaBag (insertMedia, MediaBag)
86import Text.Pandoc.MediaBag (insertMedia, MediaBag)
88import Data.Maybe (mapMaybe, fromMaybe)
87import Data.Maybe (mapMaybe, fromMaybe)
89−import Data.List (delete, stripPrefix, (\\), intercalate, intersect)
88+import Data.List (delete, stripPrefix, (\\), intersperse, intersect)
90import Data.Monoid
89import Data.Monoid
90+import Text.TeXMath (writeTeX)
91+import qualified Text.TeXMath.Types as TM
91import qualified Data.ByteString.Lazy as B
92import qualified Data.ByteString.Lazy as B
92import qualified Data.Map as M
93import qualified Data.Map as M
93import Control.Monad.Reader
94import Control.Monad.Reader
94import Control.Monad.State
95import Control.Monad.State
95−import Text.Printf (printf)
96
96
97readDocx :: ReaderOptions
97readDocx :: ReaderOptions
98 -> B.ByteString
98 -> B.ByteString
@@ -381,158 +381,192 @@ parPartToInlines (ExternalHyperLink target runs) = do
381 ils <- concatMapM runToInlines runs
381 ils <- concatMapM runToInlines runs
382 return [Link ils (target, "")]
382 return [Link ils (target, "")]
383parPartToInlines (PlainOMath omath) = do
383parPartToInlines (PlainOMath omath) = do
384− s <- oMathToTexString omath
384+ e <- oMathToExps omath
385− return [Math InlineMath s]
385+ return [Math InlineMath (writeTeX e)]
386−
386+
387−oMathToTexString :: OMath -> DocxContext String
387+oMathToExps :: OMath -> DocxContext [TM.Exp]
388−oMathToTexString (OMath omathElems) = do
388+oMathToExps (OMath oMathElems) = concatMapM oMathElemToExps oMathElems
389− ss <- mapM oMathElemToTexString omathElems
389+
390− return $ intercalate " " ss
391−oMathElemToTexString :: OMathElem -> DocxContext String
390+oMathElemToExps :: OMathElem -> DocxContext [TM.Exp]
392−oMathElemToTexString (Accent style base) | Just c <- accentChar style = do
391+oMathElemToExps (Accent style base) = do
393− baseString <- baseToTexString base
392+ baseExp <- baseToExp base
394− return $ case lookupTexChar c of
393+ let chr = case accentChar style of
395− s@('\\' : _) -> printf "%s{%s}" s baseString
394+ Just c -> c
396− _ -> printf "\\acute{%s}" baseString -- we default.
395+ Nothing -> '\180' -- default to acute.
397−oMathElemToTexString (Accent _ base) =
396+ return [TM.EOver False baseExp (TM.ESymbol TM.Accent [chr])]
398− baseToTexString base >>= (\s -> return $ printf "\\acute{%s}" s)
399−oMathElemToTexString (Bar style base) = do
397+oMathElemToExps(Bar style base) = do
400− baseString <- baseToTexString base
398+ baseExp <- baseToExp base
401 return $ case barPos style of
399 return $ case barPos style of
402− Top -> printf "\\overline{%s}" baseString
400+ Top -> [TM.EOver False baseExp (TM.ESymbol TM.Accent "\175")]
403− Bottom -> printf "\\underline{%s}" baseString
401+ Bottom -> [TM.EUnder False baseExp (TM.ESymbol TM.Accent "\818")]
404−oMathElemToTexString (Box base) = baseToTexString base
402+oMathElemToExps (Box base) =
403+ (\e -> return [e]) =<< baseToExp base
405−oMathElemToTexString (BorderBox base) =
404+oMathElemToExps (BorderBox base) =
406− baseToTexString base >>= (\s -> return $ printf "\\boxed{%s}" s)
405+ -- TODO: This should be "\\boxed" somehow
406+ (\e -> return [e]) =<< baseToExp base
407−oMathElemToTexString (Delimiter dPr bases) = do
407+oMathElemToExps (Delimiter dPr bases) = do
408+ baseExps <- mapM baseToExp bases
409+ let inDelimExps = map Right baseExps
408− let beg = fromMaybe '(' (delimBegChar dPr)
410+ beg = fromMaybe '(' (delimBegChar dPr)
409 end = fromMaybe ')' (delimEndChar dPr)
411 end = fromMaybe ')' (delimEndChar dPr)
410 sep = fromMaybe '|' (delimSepChar dPr)
412 sep = fromMaybe '|' (delimSepChar dPr)
411− left = "\\left" ++ lookupTexChar beg
413+ exps = intersperse (Left [sep]) inDelimExps
412− right = "\\right" ++ lookupTexChar end
414+ return [TM.EDelimited [beg] [end] exps]
413− mid = "\\middle" ++ lookupTexChar sep
414− baseStrings <- mapM baseToTexString bases
415− return $ printf "%s %s %s"
416− left
417− (intercalate (" " ++ mid ++ " ") baseStrings)
418− right
419−oMathElemToTexString (EquationArray bases) = do
415+oMathElemToExps (EquationArray bases) = do
420− baseStrings <- mapM baseToTexString bases
416+ let f b = do bs <- baseToExp' b
421− inSub <- gets docxInTexSubscript
422− return $
417+ return [bs]
423− if inSub
418+ baseExps <- mapM f bases
424− then
419+ return [TM.EArray [] baseExps]
425− printf "\\substack{%s}" (intercalate "\\\\ " baseStrings)
426− else
427− printf
428− "\\begin{aligned}\n%s\n\\end{aligned}"
429− (intercalate "\\\\\n" baseStrings)
430−oMathElemToTexString (Fraction num denom) = do
420+oMathElemToExps (Fraction num denom) = do
431− numString <- concatMapM oMathElemToTexString num
421+ numExp <- concatMapM oMathElemToExps num >>= (return . TM.EGrouped)
432− denString <- concatMapM oMathElemToTexString denom
422+ denExp <- concatMapM oMathElemToExps denom >>= (return . TM.EGrouped)
433− return $ printf "\\frac{%s}{%s}" numString denString
423+ return [TM.EFraction TM.NormalFrac numExp denExp]
434−oMathElemToTexString (Function fname base) = do
424+oMathElemToExps (Function fname base) = do
435− fnameString <- concatMapM oMathElemToTexString fname
425+ -- We need a string for the fname, but omml gives it to us as a
436− baseString <- baseToTexString base
426+ -- series of oMath elems. We're going to filter out the oMathRuns,
437− return $ printf "%s %s" fnameString baseString
427+ -- which should work for us most of the time.
438−oMathElemToTexString (Group style base)
428+ let f :: OMathElem -> String
439− | Just c <- groupChr style
429+ f (OMathRun _ run) = runToString run
440− , grouper <- lookupTexChar c
430+ f _ = ""
441− , notElem grouper ["\\overbrace", "\\underbrace"]
431+ fnameString = concatMap f fname
442− = do
432+ baseExp <- baseToExp base
443− baseString <- baseToTexString base
433+ return [TM.EMathOperator fnameString, baseExp]
434+oMathElemToExps (Group style base)
435+ | Just Top <- groupPos style = do
436+ baseExp <- baseToExp base
444− return $ case groupPos style of
437+ let chr = case groupChr style of
445− Just Top -> printf "\\overset{%s}{%s}" grouper baseString
438+ Just c -> c
446− _ -> printf "\\underset{%s}{%s}" grouper baseString
439+ Nothing -> '\65079' -- default to overbrace
447−oMathElemToTexString (Group style base) = do
440+ return [TM.EOver False baseExp (TM.ESymbol TM.Accent [chr])]
448− baseString <- baseToTexString base
441+ | otherwise = do
442+ baseExp <- baseToExp base
449− return $ case groupPos style of
443+ let chr = case groupChr style of
450− Just Top -> printf "\\overbrace{%s}" baseString
444+ Just c -> c
451− _ -> printf "\\underbrace{%s}" baseString
445+ Nothing -> '\65080' -- default to underbrace
446+ return [TM.EUnder False baseExp (TM.ESymbol TM.Accent [chr])]
452−oMathElemToTexString (LowerLimit base limElems) = do
447+oMathElemToExps (LowerLimit base limElems) = do
453− baseString <- baseToTexString base
448+ baseExp <- baseToExp base
454− lim <- concatMapM oMathElemToTexString limElems
449+ lim <- concatMapM oMathElemToExps limElems >>= (return . TM.EGrouped)
455− -- we want to make sure to replace the `\rightarrow` with `\to`
450+ return [TM.EUnder True lim baseExp]
456− let arrowToTo :: String -> String
457− arrowToTo "" = ""
458− arrowToTo s | Just s' <- stripPrefix "\\rightarrow" s =
459− "\\to" ++ arrowToTo s'
460− arrowToTo (c:cs) = c : arrowToTo cs
461− lim' = arrowToTo lim
462− return $ case baseString of
463− "lim" -> printf "\\lim_{%s}" lim'
464− "max" -> printf "\\max_{%s}" lim'
465− "min" -> printf "\\min_{%s}" lim'
466− _ -> printf "\\operatorname*{%s}_{%s}" baseString lim'
467−oMathElemToTexString (UpperLimit base limElems) = do
451+oMathElemToExps (UpperLimit base limElems) = do
468− baseString <- baseToTexString base
452+ baseExp <- baseToExp base
469− lim <- concatMapM oMathElemToTexString limElems
453+ lim <- concatMapM oMathElemToExps limElems >>= (return . TM.EGrouped)
470− -- we want to make sure to replace the `\rightarrow` with `\to`
454+ return [TM.EOver True lim baseExp]
471− let arrowToTo :: String -> String
472− arrowToTo "" = ""
473− arrowToTo s | Just s' <- stripPrefix "\\rightarrow" s =
474− "\\to" ++ arrowToTo s'
475− arrowToTo (c:cs) = c : arrowToTo cs
476− lim' = arrowToTo lim
477− return $ case baseString of
478− "lim" -> printf "\\lim^{%s}" lim'
479− "max" -> printf "\\max^{%s}" lim'
480− "min" -> printf "\\min^{%s}" lim'
481− _ -> printf "\\operatorname*{%s}^{%s}" baseString lim'
482−oMathElemToTexString (Matrix bases) = do
455+oMathElemToExps (Matrix bases) = do
483− let rowString :: [Base] -> DocxContext String
456+ rows <- mapM (mapM (\b -> baseToExp' b)) bases
484− rowString bs = liftM (intercalate " & ") (mapM baseToTexString bs)
457+ return [TM.EArray [TM.AlignCenter] rows]
485−
458+oMathElemToExps (NAry style sub sup base) = do
486− s <- liftM (intercalate " \\\\\n")(mapM rowString bases)
459+ subExps <- concatMapM oMathElemToExps sub
487− return $ printf "\\begin{matrix}\n%s\n\\end{matrix}" s
460+ supExps <- concatMapM oMathElemToExps sup
488−oMathElemToTexString (NAry style sub sup base) | Just c <- nAryChar style = do
461+ baseExp <- baseToExp base
489− subString <- withDState (\s -> s{docxInTexSubscript = True}) $
462+ let opChar = case nAryChar style of
490− concatMapM oMathElemToTexString sub
463+ Just c -> c
491− supString <- concatMapM oMathElemToTexString sup
464+ -- default to integral
492− baseString <- baseToTexString base
465+ Nothing -> '\8747'
493− return $ case M.lookup c uniconvMap of
466+ return [ TM.ESubsup
494− Just s@('\\':_) -> printf "%s_{%s}^{%s}{%s}"
467+ (TM.ESymbol TM.Op [opChar])
495− s subString supString baseString
468+ (TM.EGrouped subExps)
496− _ -> printf "\\operatorname*{%s}_{%s}^{%s}{%s}"
469+ (TM.EGrouped supExps)
497− [c] subString supString baseString
470+ , baseExp]
498−oMathElemToTexString (NAry _ sub sup base) = do
471+oMathElemToExps (Phantom base) =
499− subString <- concatMapM oMathElemToTexString sub
472+ (\e -> return [TM.EPhantom e]) =<< baseToExp base
500− supString <- concatMapM oMathElemToTexString sup
501− baseString <- baseToTexString base
502− return $ printf "\\int_{%s}^{%s}{%s}"
503− subString supString baseString
504−oMathElemToTexString (Phantom base) = do
505− baseString <- baseToTexString base
506− return $ printf "\\phantom{%s}" baseString
507−oMathElemToTexString (Radical degree base) = do
473+oMathElemToExps (Radical degree base) = do
508− degString <- concatMapM oMathElemToTexString degree
474+ degExps <- concatMapM oMathElemToExps degree
509− baseString <- baseToTexString base
475+ baseExp <- baseToExp base
510− return $ case trim degString of
476+ return $ case degExps of
511− "" -> printf "\\sqrt{%s}" baseString
477+ [] -> [TM.ESqrt baseExp]
512− _ -> printf "\\sqrt[%s]{%s}" degString baseString
478+ ds -> [TM.ERoot (TM.EGrouped ds) baseExp]
513−oMathElemToTexString (PreSubSuper sub sup base) = do
479+oMathElemToExps (PreSubSuper sub sup base) = do
514− subString <- concatMapM oMathElemToTexString sub
480+ subExps <- concatMapM oMathElemToExps sub
515− supString <- concatMapM oMathElemToTexString sup
481+ supExps <- concatMapM oMathElemToExps sup
516− baseString <- baseToTexString base
482+ baseExp <- baseToExp base
517− return $ printf "_{%s}^{%s}%s" subString supString baseString
483+ return [ TM.ESubsup
484+ (TM.EIdentifier "") (TM.EGrouped subExps) (TM.EGrouped supExps)
485+ , baseExp]
518−oMathElemToTexString (Sub base sub) = do
486+oMathElemToExps (Sub base sub) = do
519− baseString <- baseToTexString base
487+ baseExp <- baseToExp base
520− subString <- concatMapM oMathElemToTexString sub
488+ subExps <- concatMapM oMathElemToExps sub
521− return $ printf "%s_{%s}" baseString subString
489+ return [TM.ESub baseExp (TM.EGrouped subExps)]
522−oMathElemToTexString (SubSuper base sub sup) = do
490+oMathElemToExps (SubSuper base sub sup) = do
523− baseString <- baseToTexString base
491+ baseExp <- baseToExp base
524− subString <- concatMapM oMathElemToTexString sub
492+ subExps <- concatMapM oMathElemToExps sub
525− supString <- concatMapM oMathElemToTexString sup
493+ supExps <- concatMapM oMathElemToExps sup
526− return $ printf "%s_{%s}^{%s}" baseString subString supString
494+ return [TM.ESubsup baseExp (TM.EGrouped subExps) (TM.EGrouped supExps)]
527−oMathElemToTexString (Super base sup) = do
495+oMathElemToExps (Super base sup) = do
528− baseString <- baseToTexString base
496+ baseExp <- baseToExp base
529− supString <- concatMapM oMathElemToTexString sup
497+ supExps <- concatMapM oMathElemToExps sup
530− return $ printf "%s^{%s}" baseString supString
498+ return [TM.ESuper baseExp (TM.EGrouped supExps)]
531−oMathElemToTexString (OMathRun _ run) = return $ stringToTex $ runToString run
499+oMathElemToExps (OMathRun sty run@(Run _ _))
532−
500+ | NoStyle <- oMathRunTextStyle sty =
533−baseToTexString :: Base -> DocxContext String
501+ return $ [TM.EIdentifier $ runToString run]
534−baseToTexString (Base mathElems) =
502+ | Nothing <- oMathRunStyleToTextType sty =
535− concatMapM oMathElemToTexString mathElems
503+ return $ [TM.EIdentifier $ runToString run]
504+ | Just textType <- oMathRunStyleToTextType sty =
505+ return $ if oMathLit sty
506+ then [TM.EText textType (runToString run)]
507+ else [TM.EStyled textType [TM.EIdentifier $ runToString run]]
508+oMathElemToExps (OMathRun _ _) = return []
509+
510+oMathRunStyleToTextType :: OMathRunStyle -> Maybe TM.TextType
511+oMathRunStyleToTextType mrPr
512+ | Normal <- oMathRunTextStyle mrPr =
513+ Just $ TM.TextNormal
514+ | Styled scr sty <- oMathRunTextStyle mrPr
515+ ,Just OBold <- sty
516+ , Just OSansSerif <- scr =
517+ Just $ TM.TextSansSerifBold
518+ | Styled scr sty <- oMathRunTextStyle mrPr
519+ , Just OBoldItalic <- sty
520+ , Just OSansSerif <- scr =
521+ Just $ TM.TextSansSerifBoldItalic
522+ | Styled scr sty <- oMathRunTextStyle mrPr
523+ , Just OBold <- sty
524+ , Just OScript <- scr =
525+ Just $ TM.TextBoldScript
526+ | Styled scr sty <- oMathRunTextStyle mrPr
527+ , Just OBold <- sty
528+ , Just OFraktur <- scr =
529+ Just $ TM.TextBoldFraktur
530+ | Styled scr sty <- oMathRunTextStyle mrPr
531+ , Just OItalic <- sty
532+ , Just OSansSerif <- scr =
533+ Just $ TM.TextSansSerifItalic
534+ | Styled _ sty <- oMathRunTextStyle mrPr
535+ , Just OBold <- sty =
536+ Just $ TM.TextBold
537+ | Styled _ sty <- oMathRunTextStyle mrPr
538+ , Just OItalic <- sty =
539+ Just $ TM.TextItalic
540+ | Styled scr _ <- oMathRunTextStyle mrPr
541+ , Just OMonospace <- scr =
542+ Just $ TM.TextMonospace
543+ | Styled scr _ <- oMathRunTextStyle mrPr
544+ , Just OSansSerif <- scr =
545+ Just $ TM.TextSansSerif
546+ | Styled scr _ <- oMathRunTextStyle mrPr
547+ , Just ODoubleStruck <- scr =
548+ Just $ TM.TextDoubleStruck
549+ | Styled scr _ <- oMathRunTextStyle mrPr
550+ , Just OScript <- scr =
551+ Just $ TM.TextDoubleStruck
552+ | Styled scr _ <- oMathRunTextStyle mrPr
553+ , Just OFraktur <- scr =
554+ Just $ TM.TextFraktur
555+ | Styled _ sty <- oMathRunTextStyle mrPr
556+ , Just OBoldItalic <- sty =
557+ Just $ TM.TextBoldItalic
558+ | otherwise = Nothing
559+
560+
561+
562+baseToExp :: Base -> DocxContext TM.Exp
563+baseToExp (Base mathElems) =
564+ concatMapM oMathElemToExps mathElems >>= (return . TM.EGrouped)
565+
566+-- an ungrouped version of baseToExp
567+baseToExp' :: Base -> DocxContext [TM.Exp]
568+baseToExp' (Base mathElems) =
569+ concatMapM oMathElemToExps mathElems
536
570
537
571
538isAnchorSpan :: Inline -> Bool
572isAnchorSpan :: Inline -> Bool
@@ -659,9 +693,10 @@ bodyPartToBlocks (Tbl cap _ look (r:rs)) = do
659
693
660 return [Table caption alignments widths hdrCells cells]
694 return [Table caption alignments widths hdrCells cells]
661bodyPartToBlocks (OMathPara _ maths) = do
695bodyPartToBlocks (OMathPara _ maths) = do
662− omaths <- mapM oMathToTexString maths
696+ omaths <- mapM oMathToExps maths
697+ return [Para $
663− return [Para $ map (\s -> Math DisplayMath s) omaths]
698+ map (\m -> Math DisplayMath (writeTeX m))
664−
699+ omaths]
665
700
666-- replace targets with generated anchors.
701-- replace targets with generated anchors.
667rewriteLink :: Inline -> DocxContext Inline
702rewriteLink :: Inline -> DocxContext Inline
src/Text/Pandoc/Readers/Docx/Parse.hs+125−22
@@ -45,6 +45,10 @@ module Text.Pandoc.Readers.Docx.Parse ( Docx(..)
45 , NAryStyle(..)
45 , NAryStyle(..)
46 , DelimStyle(..)
46 , DelimStyle(..)
47 , GroupStyle(..)
47 , GroupStyle(..)
48+ , OMathRunStyle(..)
49+ , OMathRunTextStyle(..)
50+ , OMathTextScript(..)
51+ , OMathTextStyle(..)
48 , Run(..)
52 , Run(..)
49 , RunElem(..)
53 , RunElem(..)
50 , Notes
54 , Notes
@@ -93,13 +97,14 @@ maybeToD :: Maybe a -> D a
93maybeToD (Just a) = return a
97maybeToD (Just a) = return a
94maybeToD Nothing = throwError DocxError
98maybeToD Nothing = throwError DocxError
95
99
96−mapD :: (a -> D b) -> [a] -> D [b]
100+concatMapM :: (Monad m) => (a -> m [b]) -> [a] -> m [b]
97−mapD _ [] = return []
101+concatMapM f xs = liftM concat (mapM f xs)
98−mapD f (x:xs) = do
99− y <- (f x >>= (\z -> return [z])) `catchError` (\_ -> return [])
100− ys <- mapD f xs
101− return $ y ++ ys
102
102
103+mapD :: (a -> D b) -> [a] -> D [b]
104+mapD f xs =
105+ let handler x = (f x >>= (\y-> return [y])) `catchError` (\_ -> return [])
106+ in
107+ concatMapM handler xs
103
108
104type NameSpaces = [(String, String)]
109type NameSpaces = [(String, String)]
105
110
@@ -128,6 +133,7 @@ type Level = (String, String, String, Maybe Integer)
128
133
129data Relationship = Relationship (RelId, Target)
134data Relationship = Relationship (RelId, Target)
130 deriving Show
135 deriving Show
136+
131data Notes = Notes NameSpaces
137data Notes = Notes NameSpaces
132 (Maybe (M.Map String Element))
138 (Maybe (M.Map String Element))
133 (Maybe (M.Map String Element))
139 (Maybe (M.Map String Element))
@@ -223,6 +229,30 @@ data NAryStyle = NAryStyle { nAryChar :: Maybe Char
223 , nAryLimLoc :: LimLoc}
229 , nAryLimLoc :: LimLoc}
224 deriving Show
230 deriving Show
225
231
232+data OMathRunStyle = OMathRunStyle { oMathLit :: Bool
233+ , oMathRunTextStyle :: OMathRunTextStyle }
234+ deriving Show
235+
236+data OMathRunTextStyle = NoStyle
237+ | Normal
238+ | Styled { oMathScript :: Maybe OMathTextScript
239+ , oMathStyle :: Maybe OMathTextStyle }
240+ deriving Show
241+
242+data OMathTextScript = ORoman
243+ | OScript
244+ | OFraktur
245+ | ODoubleStruck
246+ | OSansSerif
247+ | OMonospace
248+ deriving (Show, Eq)
249+
250+data OMathTextStyle = OPlain
251+ | OBold
252+ | OItalic
253+ | OBoldItalic
254+ deriving (Show, Eq)
255+
226defaultNAryStyle :: NAryStyle
256defaultNAryStyle :: NAryStyle
227defaultNAryStyle = NAryStyle { nAryChar = Nothing -- integral, in practice
257defaultNAryStyle = NAryStyle { nAryChar = Nothing -- integral, in practice
228 , nAryLimLoc = SubSup }
258 , nAryLimLoc = SubSup }
@@ -246,9 +276,6 @@ data GroupStyle = GroupStyle { groupChr :: Maybe Char
246defaultGroupStyle :: GroupStyle
276defaultGroupStyle :: GroupStyle
247defaultGroupStyle = GroupStyle {groupChr = Nothing, groupPos = Nothing}
277defaultGroupStyle = GroupStyle {groupChr = Nothing, groupPos = Nothing}
248
278
249−type OMathRunStyle = [String]
250−
251−
252data Run = Run RunStyle [RunElem]
279data Run = Run RunStyle [RunElem]
253 | Footnote [BodyPart]
280 | Footnote [BodyPart]
254 | Endnote [BodyPart]
281 | Endnote [BodyPart]
@@ -596,6 +623,75 @@ elemToBase ns element | isElem ns "m" "e" element =
596 (\es -> return $ Base es)
623 (\es -> return $ Base es)
597elemToBase _ _ = throwError WrongElem
624elemToBase _ _ = throwError WrongElem
598
625
626+-- TODO: The right way to do this is to use the ampersand to break the
627+-- text lines into multiple columns. That's tricky, though, and this
628+-- will get us most of the way for the time being.
629+filterAmpersand :: OMathElem -> OMathElem
630+filterAmpersand (OMathRun mrPr (Run wrPr elems)) =
631+ let f (TextRun s) = TextRun $ filter ('&' /=) s
632+ f re = re
633+ in
634+ OMathRun mrPr $ Run wrPr (map f elems)
635+filterAmpersand e = e
636+
637+elemToBaseNoAmpersand :: NameSpaces -> Element -> D Base
638+elemToBaseNoAmpersand ns element | isElem ns "m" "e" element =
639+ mapD
640+ (\e -> (elemToMathElem ns e >>= (return . filterAmpersand)))
641+ (elChildren element) >>=
642+ (\es -> return $ Base es)
643+elemToBaseNoAmpersand _ _ = throwError WrongElem
644+
645+
646+elemToOMathRunStyle :: NameSpaces -> Element -> OMathRunStyle
647+elemToOMathRunStyle ns element =
648+ let lit =
649+ case
650+ findChild (elemName ns "m" "lit") element >>=
651+ findAttr (elemName ns "m" "val")
652+ of
653+ Just "on" -> True
654+ _ -> False
655+ in
656+ OMathRunStyle { oMathLit = lit
657+ , oMathRunTextStyle = (elemToOMathRunTextStyle ns element)
658+ }
659+
660+elemToOMathRunTextStyle :: NameSpaces -> Element -> OMathRunTextStyle
661+elemToOMathRunTextStyle ns element
662+ | Just mrPr <- findChild (elemName ns "m" "rPr") element
663+ , Just _ <- findChild (elemName ns "m" "nor") mrPr =
664+ Normal
665+ | Just mrPr <- findChild (elemName ns "m" "rPr") element =
666+ let scr =
667+ case
668+ findChild (elemName ns "m" "scr") mrPr >>=
669+ findAttr (elemName ns "m" "val")
670+ of
671+ Just "roman" -> Just ORoman
672+ Just "script" -> Just OScript
673+ Just "fraktur" -> Just OFraktur
674+ Just "double-struck" -> Just ODoubleStruck
675+ Just "sans-serif" -> Just OSansSerif
676+ Just "monospace" -> Just OMonospace
677+ _ -> Nothing
678+
679+ sty =
680+ case
681+ findChild (elemName ns "m" "sty") mrPr >>=
682+ findAttr (elemName ns "m" "val")
683+ of
684+ Just "p" -> Just OPlain
685+ Just "b" -> Just OBold
686+ Just "i" -> Just OItalic
687+ Just "bi" -> Just OBoldItalic
688+ _ -> Nothing
689+ in
690+ Styled { oMathScript = scr, oMathStyle = sty }
691+ | otherwise = NoStyle
692+
693+
694+
599elemToNAryStyle :: NameSpaces -> Element -> NAryStyle
695elemToNAryStyle :: NameSpaces -> Element -> NAryStyle
600elemToNAryStyle ns element
696elemToNAryStyle ns element
601 | Just narypr <- findChild (QName "naryPr" (lookup "m" ns) (Just "m")) element =
697 | Just narypr <- findChild (QName "naryPr" (lookup "m" ns) (Just "m")) element =
@@ -618,13 +714,13 @@ elemToDelimStyle ns element
618 | Just dPr <- findChild (QName "dPr" (lookup "m" ns) (Just "m")) element =
714 | Just dPr <- findChild (QName "dPr" (lookup "m" ns) (Just "m")) element =
619 let begChr = findChild (QName "begChr" (lookup "m" ns) (Just "m")) dPr >>=
715 let begChr = findChild (QName "begChr" (lookup "m" ns) (Just "m")) dPr >>=
620 findAttr (QName "val" (lookup "m" ns) (Just "m")) >>=
716 findAttr (QName "val" (lookup "m" ns) (Just "m")) >>=
621− (\c -> if null c then Nothing else (Just $ head c))
717+ (\c -> if null c then (Just ' ') else (Just $ head c))
622 sepChr = findChild (QName "sepChr" (lookup "m" ns) (Just "m")) dPr >>=
718 sepChr = findChild (QName "sepChr" (lookup "m" ns) (Just "m")) dPr >>=
623 findAttr (QName "val" (lookup "m" ns) (Just "m")) >>=
719 findAttr (QName "val" (lookup "m" ns) (Just "m")) >>=
624− (\c -> if null c then Nothing else (Just $ head c))
720+ (\c -> if null c then (Just ' ') else (Just $ head c))
625 endChr = findChild (QName "endChr" (lookup "m" ns) (Just "m")) dPr >>=
721 endChr = findChild (QName "endChr" (lookup "m" ns) (Just "m")) dPr >>=
626 findAttr (QName "val" (lookup "m" ns) (Just "m")) >>=
722 findAttr (QName "val" (lookup "m" ns) (Just "m")) >>=
627− (\c -> if null c then Nothing else (Just $ head c))
723+ (\c -> if null c then (Just ' ') else (Just $ head c))
628 in
724 in
629 DelimStyle { delimBegChar = begChr
725 DelimStyle { delimBegChar = begChr
630 , delimSepChar = sepChr
726 , delimSepChar = sepChr
@@ -647,9 +743,9 @@ elemToGroupStyle _ _ = defaultGroupStyle
647elemToMathElem :: NameSpaces -> Element -> D OMathElem
743elemToMathElem :: NameSpaces -> Element -> D OMathElem
648elemToMathElem ns element | isElem ns "m" "acc" element = do
744elemToMathElem ns element | isElem ns "m" "acc" element = do
649 let accChar =
745 let accChar =
650− findChild (QName "accPr" (lookup "m" ns) (Just "m")) element >>=
746+ findChild (elemName ns "m" "accPr") element >>=
651− findChild (QName "chr" (lookup "m" ns) (Just "m")) >>=
747+ findChild (elemName ns "m" "chr") >>=
652− findAttr (QName "val" (lookup "m" ns) (Just "m")) >>=
748+ findAttr (elemName ns "m" "val") >>=
653 Just . head
749 Just . head
654 accPr = AccentStyle { accentChar = accChar}
750 accPr = AccentStyle { accentChar = accChar}
655 base <-(maybeToD $ findChild (elemName ns "m" "e") element) >>=
751 base <-(maybeToD $ findChild (elemName ns "m" "e") element) >>=
@@ -681,7 +777,7 @@ elemToMathElem ns element | isElem ns "m" "d" element =
681 mapD (elemToBase ns) (elChildren element) >>=
777 mapD (elemToBase ns) (elChildren element) >>=
682 (\es -> return $ Delimiter style es)
778 (\es -> return $ Delimiter style es)
683elemToMathElem ns element | isElem ns "m" "eqArr" element =
779elemToMathElem ns element | isElem ns "m" "eqArr" element =
684− mapD (elemToBase ns) (elChildren element) >>=
780+ mapD (elemToBaseNoAmpersand ns) (elChildren element) >>=
685 (\es -> return $ EquationArray es)
781 (\es -> return $ EquationArray es)
686elemToMathElem ns element | isElem ns "m" "f" element = do
782elemToMathElem ns element | isElem ns "m" "f" element = do
687 num <- maybeToD $ findChild (elemName ns "m" "num") element
783 num <- maybeToD $ findChild (elemName ns "m" "num") element
@@ -763,12 +859,12 @@ elemToMathElem ns element | isElem ns "m" "sSup" element = do
763 elemToBase ns
859 elemToBase ns
764 sup <- maybeToD (findChild (elemName ns "m" "sup") element) >>=
860 sup <- maybeToD (findChild (elemName ns "m" "sup") element) >>=
765 (\e -> mapD (elemToMathElem ns) (elChildren e))
861 (\e -> mapD (elemToMathElem ns) (elChildren e))
766− return $ Sub base sup
862+ return $ Super base sup
767elemToMathElem ns element | isElem ns "m" "r" element = do
863elemToMathElem ns element | isElem ns "m" "r" element = do
768− let style = [] -- placeholder
864+ let mrPr = elemToOMathRunStyle ns element
769− rstyle = elemToRunStyle ns element
865+ wrPr = elemToRunStyle ns element
770 relems <- elemToRunElems ns element
866 relems <- elemToRunElems ns element
771− return $ OMathRun style $ Run rstyle relems
867+ return $ OMathRun mrPr $ Run wrPr relems
772elemToMathElem _ _ = throwError WrongElem
868elemToMathElem _ _ = throwError WrongElem
773
869
774lookupRelationship :: RelId -> [Relationship] -> Maybe Target
870lookupRelationship :: RelId -> [Relationship] -> Maybe Target
@@ -832,6 +928,9 @@ elemToParPart ns element
832 return $ case lookupRelationship relId rels of
928 return $ case lookupRelationship relId rels of
833 Just target -> ExternalHyperLink target runs
929 Just target -> ExternalHyperLink target runs
834 Nothing -> ExternalHyperLink "" runs
930 Nothing -> ExternalHyperLink "" runs
931+elemToParPart ns element
932+ | isElem ns "m" "oMath" element =
933+ elemToMath ns element >>= (return . PlainOMath)
835elemToParPart _ _ = throwError WrongElem
934elemToParPart _ _ = throwError WrongElem
836
935
837lookupFootnote :: String -> Notes -> Maybe Element
936lookupFootnote :: String -> Notes -> Maybe Element
@@ -908,7 +1007,9 @@ elemToRunStyle _ _ = defaultRunStyle
908
1007
909elemToRunElem :: NameSpaces -> Element -> D RunElem
1008elemToRunElem :: NameSpaces -> Element -> D RunElem
910elemToRunElem ns element
1009elemToRunElem ns element
1010+ | isElem ns "w" "t" element
911− | isElem ns "w" "t" element || isElem ns "w" "delText" element =
1011+ || isElem ns "w" "delText" element
1012+ || isElem ns "m" "t" element =
912 return $ TextRun $ strContent element
1013 return $ TextRun $ strContent element
913 | isElem ns "w" "br" element = return LnBrk
1014 | isElem ns "w" "br" element = return LnBrk
914 | isElem ns "w" "tab" element = return Tab
1015 | isElem ns "w" "tab" element = return Tab
@@ -916,7 +1017,9 @@ elemToRunElem ns element
916
1017
917elemToRunElems :: NameSpaces -> Element -> D [RunElem]
1018elemToRunElems :: NameSpaces -> Element -> D [RunElem]
918elemToRunElems ns element
1019elemToRunElems ns element
1020+ | isElem ns "w" "r" element
1021+ || isElem ns "m" "r" element =
919− | isElem ns "w" "r" element = mapD (elemToRunElem ns) (elChildren element)
1022+ mapD (elemToRunElem ns) (elChildren element)
920elemToRunElems _ _ = throwError WrongElem
1023elemToRunElems _ _ = throwError WrongElem
921
1024
922
1025