@@ -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)
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)]
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"
417− (intercalate (" " ++ mid ++ " ") baseStrings)
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)
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
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
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)
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 []
510+oMathRunStyleToTextType :: OMathRunStyle -> Maybe TM.TextType
511+oMathRunStyleToTextType mrPr
512+ | Normal <- oMathRunTextStyle mrPr =
513+ Just $ TM.TextNormal
514+ | Styled scr sty <- oMathRunTextStyle mrPr
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
524+ , Just OScript <- scr =
525+ Just $ TM.TextBoldScript
526+ | Styled scr sty <- oMathRunTextStyle mrPr
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 =
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
562+baseToExp :: Base -> DocxContext TM.Exp
563+baseToExp (Base mathElems) =
564+ concatMapM oMathElemToExps mathElems >>= (return . TM.EGrouped)
566+-- an ungrouped version of baseToExp
567+baseToExp' :: Base -> DocxContext [TM.Exp]
568+baseToExp' (Base mathElems) =
569+ concatMapM oMathElemToExps mathElems
538isAnchorSpan :: Inline -> Bool
572isAnchorSpan :: Inline -> Bool
@@ -659,9 +693,10 @@ bodyPartToBlocks (Tbl cap _ look (r:rs)) = do
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
663− return [Para $ map (\s -> Math DisplayMath s) omaths]
698+ map (\m -> Math DisplayMath (writeTeX m))
666-- replace targets with generated anchors.
701-- replace targets with generated anchors.
667rewriteLink :: Inline -> DocxContext Inline
702rewriteLink :: Inline -> DocxContext Inline