{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ViewPatterns #-}
{-
Copyright (C) 2012 John MacFarlane <jgm@berkeley.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
-}

{- | Functions for writing a parsed formula as OMML.
-}

module Text.TeXMath.Writers.OMML (writeOMML)
where

import Text.XML.Light
import Text.TeXMath.Types
import Data.Generics (everywhere, mkT)
import Data.Char (isSymbol, isPunctuation)
import qualified Data.Text as T

-- | Transforms an expression tree to an OMML XML Tree
writeOMML :: DisplayType -> [Exp] -> Element
writeOMML :: DisplayType -> [Exp] -> Element
writeOMML dt :: DisplayType
dt = [Element] -> Element
container ([Element] -> Element) -> ([Exp] -> [Element]) -> [Exp] -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Exp -> [Element]) -> [Exp] -> [Element]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([Element] -> Exp -> [Element]
showExp [])
            ([Exp] -> [Element]) -> ([Exp] -> [Exp]) -> [Exp] -> [Element]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Data a => a -> a) -> forall a. Data a => a -> a
everywhere (([Exp] -> [Exp]) -> a -> a
forall a b. (Typeable a, Typeable b) => (b -> b) -> a -> a
mkT (([Exp] -> [Exp]) -> a -> a) -> ([Exp] -> [Exp]) -> a -> a
forall a b. (a -> b) -> a -> b
$ DisplayType -> [Exp] -> [Exp]
handleDownup DisplayType
dt)
            ([Exp] -> [Exp]) -> ([Exp] -> [Exp]) -> [Exp] -> [Exp]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Data a => a -> a) -> forall a. Data a => a -> a
everywhere (([InEDelimited] -> [InEDelimited]) -> a -> a
forall a b. (Typeable a, Typeable b) => (b -> b) -> a -> a
mkT (([InEDelimited] -> [InEDelimited]) -> a -> a)
-> ([InEDelimited] -> [InEDelimited]) -> a -> a
forall a b. (a -> b) -> a -> b
$ DisplayType -> [InEDelimited] -> [InEDelimited]
handleDownup' DisplayType
dt)
    where container :: [Element] -> Element
container = case DisplayType
dt of
                  DisplayBlock  -> \x :: [Element]
x -> String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "oMathPara"
                                    [ String -> Element -> Element
forall t. Node t => String -> t -> Element
mnode "oMathParaPr"
                                      (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$ String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "jc" "center" ()
                                    , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "oMath" [Element]
x ]
                  DisplayInline -> String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "oMath"

-- Kept as String for Text.XML.Light
mnode :: Node t => String -> t -> Element
mnode :: String -> t -> Element
mnode s :: String
s = QName -> t -> Element
forall t. Node t => QName -> t -> Element
node (String -> Maybe String -> Maybe String -> QName
QName String
s Maybe String
forall a. Maybe a
Nothing (String -> Maybe String
forall a. a -> Maybe a
Just "m"))

-- Kept as String for Text.XML.Light
mnodeA :: Node t => String -> String -> t -> Element
mnodeA :: String -> String -> t -> Element
mnodeA s :: String
s v :: String
v = Attr -> Element -> Element
add_attr (QName -> String -> Attr
Attr (String -> Maybe String -> Maybe String -> QName
QName "val" Maybe String
forall a. Maybe a
Nothing (String -> Maybe String
forall a. a -> Maybe a
Just "m")) String
v) (Element -> Element) -> (t -> Element) -> t -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> t -> Element
forall t. Node t => String -> t -> Element
mnode String
s

str :: [Element] -> T.Text -> Element
str :: [Element] -> Text -> Element
str []    s :: Text
s = String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "r" [ String -> String -> Element
forall t. Node t => String -> t -> Element
mnode "t" (String -> Element) -> String -> Element
forall a b. (a -> b) -> a -> b
$ Text -> String
T.unpack Text
s ]
str props :: [Element]
props s :: Text
s = String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "r" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "rPr" [Element]
props
                        , String -> String -> Element
forall t. Node t => String -> t -> Element
mnode "t" (String -> Element) -> String -> Element
forall a b. (a -> b) -> a -> b
$ Text -> String
T.unpack Text
s ]

showFraction :: [Element] -> FractionType -> Exp -> Exp -> Element
showFraction :: [Element] -> FractionType -> Exp -> Exp -> Element
showFraction props :: [Element]
props ft :: FractionType
ft x :: Exp
x y :: Exp
y =
  case FractionType
ft of
       NormalFrac -> String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "f" [ String -> Element -> Element
forall t. Node t => String -> t -> Element
mnode "fPr" (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$
                                String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "type" "bar" ()
                             , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "num" [Element]
x'
                             , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "den" [Element]
y']
       DisplayFrac -> [Element] -> FractionType -> Exp -> Exp -> Element
showFraction [Element]
props FractionType
NormalFrac Exp
x Exp
y
       InlineFrac -> String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "f" [ String -> Element -> Element
forall t. Node t => String -> t -> Element
mnode "fPr" (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$
                                 String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "type" "lin" ()
                              , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "num" [Element]
x'
                              , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "den" [Element]
y']
       NoLineFrac -> String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "f" [ String -> Element -> Element
forall t. Node t => String -> t -> Element
mnode "fPr" (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$
                                              String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "type" "noBar" ()
                                             , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "num" [Element]
x'
                                             , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "den" [Element]
y'
                                             ]
    where x' :: [Element]
x' = [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x
          y' :: [Element]
y' = [Element] -> Exp -> [Element]
showExp [Element]
props Exp
y

maximum' :: [Int] -> Int
maximum' :: [Int] -> Int
maximum' [] = 0
maximum' xs :: [Int]
xs = [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [Int]
xs

makeArray :: [Element] -> [Alignment] -> [ArrayLine] -> Element
makeArray :: [Element] -> [Alignment] -> [ArrayLine] -> Element
makeArray props :: [Element]
props as :: [Alignment]
as rs :: [ArrayLine]
rs = String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "m" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ Element
mProps Element -> [Element] -> [Element]
forall a. a -> [a] -> [a]
: (ArrayLine -> Element) -> [ArrayLine] -> [Element]
forall a b. (a -> b) -> [a] -> [b]
map ArrayLine -> Element
forall (t :: * -> *). Foldable t => [t Exp] -> Element
toMr [ArrayLine]
rs
  where mProps :: Element
mProps = String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "mPr"
                  [ String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "baseJc" "center" ()
                  , String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "plcHide" "1" ()
                  , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "mcs" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ (Alignment -> Element) -> [Alignment] -> [Element]
forall a b. (a -> b) -> [a] -> [b]
map Alignment -> Element
toMc [Alignment]
as' ]
        as' :: [Alignment]
as'    = Int -> [Alignment] -> [Alignment]
forall a. Int -> [a] -> [a]
take ([Int] -> Int
maximum' ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ (ArrayLine -> Int) -> [ArrayLine] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map ArrayLine -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ArrayLine]
rs) ([Alignment] -> [Alignment]) -> [Alignment] -> [Alignment]
forall a b. (a -> b) -> a -> b
$ [Alignment]
as [Alignment] -> [Alignment] -> [Alignment]
forall a. [a] -> [a] -> [a]
++ [Alignment] -> [Alignment]
forall a. [a] -> [a]
cycle [Alignment
AlignCenter]
        toMr :: [t Exp] -> Element
toMr r :: [t Exp]
r = String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "mr" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ (t Exp -> Element) -> [t Exp] -> [Element]
forall a b. (a -> b) -> [a] -> [b]
map (String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "e" ([Element] -> Element) -> (t Exp -> [Element]) -> t Exp -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Exp -> [Element]) -> t Exp -> [Element]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([Element] -> Exp -> [Element]
showExp [Element]
props)) [t Exp]
r
        toMc :: Alignment -> Element
toMc a :: Alignment
a = String -> Element -> Element
forall t. Node t => String -> t -> Element
mnode "mc" (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "mcPr"
                            [ String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "mcJc" (Alignment -> String
forall p. IsString p => Alignment -> p
toAlign Alignment
a) ()
                            , String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "count" "1" ()
                            ]
        toAlign :: Alignment -> p
toAlign AlignLeft    = "left"
        toAlign AlignRight   = "right"
        toAlign AlignCenter  = "center"

makeText :: TextType -> T.Text -> Element
makeText :: TextType -> Text -> Element
makeText a :: TextType
a s :: Text
s = [Element] -> Text -> Element
str (String -> () -> Element
forall t. Node t => String -> t -> Element
mnode "nor" () Element -> [Element] -> [Element]
forall a. a -> [a] -> [a]
: TextType -> [Element]
setProps TextType
a) Text
s

setProps :: TextType -> [Element]
setProps :: TextType -> [Element]
setProps tt :: TextType
tt =
  case TextType
tt of
       TextNormal       -> [String -> Element
sty "p"]
       TextBold         -> [String -> Element
sty "b"]
       TextItalic       -> [String -> Element
sty "i"]
       TextMonospace    -> [String -> Element
sty "p", String -> Element
scr "monospace"]
       TextSansSerif    -> [String -> Element
sty "p", String -> Element
scr "sans-serif"]
       TextDoubleStruck -> [String -> Element
sty "p", String -> Element
scr "double-struck"]
       TextScript       -> [String -> Element
sty "p", String -> Element
scr "script"]
       TextFraktur      -> [String -> Element
sty "p", String -> Element
scr "fraktur"]
       TextBoldItalic    -> [String -> Element
sty "bi"]
       TextSansSerifBold -> [String -> Element
sty "b", String -> Element
scr "sans-serif"]
       TextBoldScript    -> [String -> Element
sty "b", String -> Element
scr "script"]
       TextBoldFraktur   -> [String -> Element
sty "b", String -> Element
scr "fraktur"]
       TextSansSerifItalic -> [String -> Element
sty "i", String -> Element
scr "sans-serif"]
       TextSansSerifBoldItalic -> [String -> Element
sty "bi", String -> Element
scr "sans-serif"]
   where sty :: String -> Element
sty x :: String
x = String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "sty" String
x ()
         scr :: String -> Element
scr x :: String
x = String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "scr" String
x ()

handleDownup :: DisplayType -> [Exp] -> [Exp]
handleDownup :: DisplayType -> [Exp] -> [Exp]
handleDownup dt :: DisplayType
dt (exp' :: Exp
exp' : xs :: [Exp]
xs) =
  case Exp
exp' of
       EOver convertible :: Bool
convertible x :: Exp
x y :: Exp
y
         | Exp -> Bool
isNary Exp
x  ->
             [Exp] -> Exp
EGrouped [Bool -> Exp -> Exp -> Exp -> Exp
EUnderover Bool
convertible Exp
x Exp
emptyGroup Exp
y, Exp
next] Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
rest
         | Bool
convertible Bool -> Bool -> Bool
&& DisplayType
dt DisplayType -> DisplayType -> Bool
forall a. Eq a => a -> a -> Bool
== DisplayType
DisplayInline -> Exp -> Exp -> Exp
ESuper Exp
x Exp
y Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
xs
       EUnder convertible :: Bool
convertible x :: Exp
x y :: Exp
y
         | Exp -> Bool
isNary Exp
x  ->
             [Exp] -> Exp
EGrouped [Bool -> Exp -> Exp -> Exp -> Exp
EUnderover Bool
convertible Exp
x Exp
y Exp
emptyGroup, Exp
next] Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
rest
         | Bool
convertible Bool -> Bool -> Bool
&& DisplayType
dt DisplayType -> DisplayType -> Bool
forall a. Eq a => a -> a -> Bool
== DisplayType
DisplayInline -> Exp -> Exp -> Exp
ESub Exp
x Exp
y Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
xs
       EUnderover convertible :: Bool
convertible x :: Exp
x y :: Exp
y z :: Exp
z
         | Exp -> Bool
isNary Exp
x  ->
             [Exp] -> Exp
EGrouped [Bool -> Exp -> Exp -> Exp -> Exp
EUnderover Bool
convertible Exp
x Exp
y Exp
z, Exp
next] Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
rest
         | Bool
convertible Bool -> Bool -> Bool
&& DisplayType
dt DisplayType -> DisplayType -> Bool
forall a. Eq a => a -> a -> Bool
== DisplayType
DisplayInline -> Exp -> Exp -> Exp -> Exp
ESubsup Exp
x Exp
y Exp
z Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
xs
       ESub x :: Exp
x y :: Exp
y
         | Exp -> Bool
isNary Exp
x  -> [Exp] -> Exp
EGrouped [Exp -> Exp -> Exp -> Exp
ESubsup Exp
x Exp
y Exp
emptyGroup, Exp
next] Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
rest
       ESuper x :: Exp
x y :: Exp
y
         | Exp -> Bool
isNary Exp
x  -> [Exp] -> Exp
EGrouped [Exp -> Exp -> Exp -> Exp
ESubsup Exp
x Exp
emptyGroup Exp
y, Exp
next] Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
rest
       ESubsup x :: Exp
x y :: Exp
y z :: Exp
z
         | Exp -> Bool
isNary Exp
x  -> [Exp] -> Exp
EGrouped [Exp -> Exp -> Exp -> Exp
ESubsup Exp
x Exp
y Exp
z, Exp
next] Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
rest
       _             -> Exp
exp' Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
xs
    where (next :: Exp
next, rest :: [Exp]
rest) = case [Exp]
xs of
                              (t :: Exp
t:ts :: [Exp]
ts) -> (Exp
t,[Exp]
ts)
                              []     -> (Exp
emptyGroup, [])
          emptyGroup :: Exp
emptyGroup = [Exp] -> Exp
EGrouped []
handleDownup _ []            = []

-- TODO This duplication is ugly and inefficient.  See #92.
handleDownup' :: DisplayType -> [InEDelimited] -> [InEDelimited]
handleDownup' :: DisplayType -> [InEDelimited] -> [InEDelimited]
handleDownup' dt :: DisplayType
dt ((Right exp' :: Exp
exp') : xs :: [InEDelimited]
xs) =
  case Exp
exp' of
       EOver convertible :: Bool
convertible x :: Exp
x y :: Exp
y
         | Exp -> Bool
isNary Exp
x  ->
             Exp -> InEDelimited
forall a b. b -> Either a b
Right ([Exp] -> Exp
EGrouped [Bool -> Exp -> Exp -> Exp -> Exp
EUnderover Bool
convertible Exp
x Exp
emptyGroup Exp
y, Exp
next]) InEDelimited -> [InEDelimited] -> [InEDelimited]
forall a. a -> [a] -> [a]
:
             [InEDelimited]
rest
         | Bool
convertible Bool -> Bool -> Bool
&& DisplayType
dt DisplayType -> DisplayType -> Bool
forall a. Eq a => a -> a -> Bool
== DisplayType
DisplayInline -> Exp -> InEDelimited
forall a b. b -> Either a b
Right (Exp -> Exp -> Exp
ESuper Exp
x Exp
y) InEDelimited -> [InEDelimited] -> [InEDelimited]
forall a. a -> [a] -> [a]
: [InEDelimited]
xs
       EUnder convertible :: Bool
convertible x :: Exp
x y :: Exp
y
         | Exp -> Bool
isNary Exp
x  ->
             Exp -> InEDelimited
forall a b. b -> Either a b
Right ([Exp] -> Exp
EGrouped [Bool -> Exp -> Exp -> Exp -> Exp
EUnderover Bool
convertible Exp
x Exp
y Exp
emptyGroup, Exp
next]) InEDelimited -> [InEDelimited] -> [InEDelimited]
forall a. a -> [a] -> [a]
:
             [InEDelimited]
rest
         | Bool
convertible Bool -> Bool -> Bool
&& DisplayType
dt DisplayType -> DisplayType -> Bool
forall a. Eq a => a -> a -> Bool
== DisplayType
DisplayInline -> Exp -> InEDelimited
forall a b. b -> Either a b
Right (Exp -> Exp -> Exp
ESub Exp
x Exp
y) InEDelimited -> [InEDelimited] -> [InEDelimited]
forall a. a -> [a] -> [a]
: [InEDelimited]
xs
       EUnderover convertible :: Bool
convertible x :: Exp
x y :: Exp
y z :: Exp
z
         | Exp -> Bool
isNary Exp
x  ->
             Exp -> InEDelimited
forall a b. b -> Either a b
Right ([Exp] -> Exp
EGrouped [Bool -> Exp -> Exp -> Exp -> Exp
EUnderover Bool
convertible Exp
x Exp
y Exp
z, Exp
next]) InEDelimited -> [InEDelimited] -> [InEDelimited]
forall a. a -> [a] -> [a]
: [InEDelimited]
rest
         | Bool
convertible Bool -> Bool -> Bool
&& DisplayType
dt DisplayType -> DisplayType -> Bool
forall a. Eq a => a -> a -> Bool
== DisplayType
DisplayInline -> Exp -> InEDelimited
forall a b. b -> Either a b
Right (Exp -> Exp -> Exp -> Exp
ESubsup Exp
x Exp
y Exp
z) InEDelimited -> [InEDelimited] -> [InEDelimited]
forall a. a -> [a] -> [a]
: [InEDelimited]
xs
       ESub x :: Exp
x y :: Exp
y
         | Exp -> Bool
isNary Exp
x  -> Exp -> InEDelimited
forall a b. b -> Either a b
Right ([Exp] -> Exp
EGrouped [Exp -> Exp -> Exp -> Exp
ESubsup Exp
x Exp
y Exp
emptyGroup, Exp
next]) InEDelimited -> [InEDelimited] -> [InEDelimited]
forall a. a -> [a] -> [a]
: [InEDelimited]
rest
       ESuper x :: Exp
x y :: Exp
y
         | Exp -> Bool
isNary Exp
x  -> Exp -> InEDelimited
forall a b. b -> Either a b
Right ([Exp] -> Exp
EGrouped [Exp -> Exp -> Exp -> Exp
ESubsup Exp
x Exp
emptyGroup Exp
y, Exp
next]) InEDelimited -> [InEDelimited] -> [InEDelimited]
forall a. a -> [a] -> [a]
: [InEDelimited]
rest
       ESubsup x :: Exp
x y :: Exp
y z :: Exp
z
         | Exp -> Bool
isNary Exp
x  -> Exp -> InEDelimited
forall a b. b -> Either a b
Right ([Exp] -> Exp
EGrouped [Exp -> Exp -> Exp -> Exp
ESubsup Exp
x Exp
y Exp
z, Exp
next]) InEDelimited -> [InEDelimited] -> [InEDelimited]
forall a. a -> [a] -> [a]
: [InEDelimited]
rest
       _             -> Exp -> InEDelimited
forall a b. b -> Either a b
Right Exp
exp' InEDelimited -> [InEDelimited] -> [InEDelimited]
forall a. a -> [a] -> [a]
: [InEDelimited]
xs
    where (next :: Exp
next, rest :: [InEDelimited]
rest) = case [InEDelimited]
xs of
                              (Right t :: Exp
t:ts :: [InEDelimited]
ts) -> (Exp
t,[InEDelimited]
ts)
                              _            -> (Exp
emptyGroup, [InEDelimited]
xs)
          emptyGroup :: Exp
emptyGroup = [Exp] -> Exp
EGrouped []
handleDownup' _ xs :: [InEDelimited]
xs = [InEDelimited]
xs

showExp :: [Element] -> Exp -> [Element]
showExp :: [Element] -> Exp -> [Element]
showExp props :: [Element]
props e :: Exp
e =
 case Exp
e of
   ENumber x :: Text
x        -> [[Element] -> Text -> Element
str [Element]
props Text
x]
   EGrouped [EUnderover _ (ESymbol Op s :: Text
s) y :: Exp
y z :: Exp
z, w :: Exp
w] ->
     [[Element] -> String -> Text -> Exp -> Exp -> Exp -> Element
makeNary [Element]
props "undOvr" Text
s Exp
y Exp
z Exp
w]
   EGrouped [ESubsup (ESymbol Op s :: Text
s) y :: Exp
y z :: Exp
z, w :: Exp
w] ->
     [[Element] -> String -> Text -> Exp -> Exp -> Exp -> Element
makeNary [Element]
props "subSup" Text
s Exp
y Exp
z Exp
w]
   EGrouped []      -> [[Element] -> Text -> Element
str [Element]
props "\x200B"] -- avoid dashed box, see #118
   EGrouped xs :: [Exp]
xs      -> (Exp -> [Element]) -> [Exp] -> [Element]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([Element] -> Exp -> [Element]
showExp [Element]
props) [Exp]
xs
   EDelimited start :: Text
start end :: Text
end xs :: [InEDelimited]
xs ->
                       [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "d" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "dPr"
                                    [ String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "begChr" (Text -> String
T.unpack Text
start) ()
                                    , String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "endChr" (Text -> String
T.unpack Text
end) ()
                                    , String -> () -> Element
forall t. Node t => String -> t -> Element
mnode "grow" () ]
                                  , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ (InEDelimited -> [Element]) -> [InEDelimited] -> [Element]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap
                                    ((Text -> [Element])
-> (Exp -> [Element]) -> InEDelimited -> [Element]
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either ((Element -> [Element] -> [Element]
forall a. a -> [a] -> [a]
:[]) (Element -> [Element]) -> (Text -> Element) -> Text -> [Element]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Element] -> Text -> Element
str [Element]
props) ([Element] -> Exp -> [Element]
showExp [Element]
props)) [InEDelimited]
xs
                                  ] ]
   EIdentifier ""   -> [[Element] -> Text -> Element
str [Element]
props "\x200B"]  -- 0-width space
                       -- to avoid the dashed box we get otherwise; see #118
   EIdentifier x :: Text
x    -> [[Element] -> Text -> Element
str [Element]
props Text
x]
   EMathOperator x :: Text
x  -> [TextType -> Text -> Element
makeText TextType
TextNormal Text
x]  -- TODO revisit, use props?
   ESymbol ty :: TeXSymbolType
ty xs :: Text
xs
    | Just (c :: Char
c, xs' :: Text
xs') <- Text -> Maybe (Char, Text)
T.uncons Text
xs
    , Text -> Bool
T.null Text
xs'
    , Char -> Bool
isSymbol Char
c Bool -> Bool -> Bool
|| Char -> Bool
isPunctuation Char
c
                    -> [[Element] -> Text -> Element
str [Element]
props Text
xs]
    | TeXSymbolType
ty TeXSymbolType -> [TeXSymbolType] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [TeXSymbolType
Op, TeXSymbolType
Bin, TeXSymbolType
Rel]
                    -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "box"
                        [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "boxPr"
                          [ String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "opEmu" "1" () ]
                        , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "e"
                          [[Element] -> Text -> Element
str [Element]
props Text
xs]
                        ]]
    | Bool
otherwise     -> [[Element] -> Text -> Element
str [Element]
props Text
xs]
   ESpace n :: Rational
n
     | Rational
n Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
> 0 Bool -> Bool -> Bool
&& Rational
n Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
<= 0.17    -> [[Element] -> Text -> Element
str [Element]
props "\x2009"]
     | Rational
n Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
> 0.17 Bool -> Bool -> Bool
&& Rational
n Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
<= 0.23 -> [[Element] -> Text -> Element
str [Element]
props "\x2005"]
     | Rational
n Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
> 0.23 Bool -> Bool -> Bool
&& Rational
n Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
<= 0.28 -> [[Element] -> Text -> Element
str [Element]
props "\x2004"]
     | Rational
n Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
> 0.28 Bool -> Bool -> Bool
&& Rational
n Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
<= 0.5  -> [[Element] -> Text -> Element
str [Element]
props "\x2004"]
     | Rational
n Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
> 0.5 Bool -> Bool -> Bool
&& Rational
n Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
<= 1.8   -> [[Element] -> Text -> Element
str [Element]
props "\x2001"]
     | Rational
n Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
> 1.8               -> [[Element] -> Text -> Element
str [Element]
props "\x2001\x2001"]
     | Bool
otherwise             -> [[Element] -> Text -> Element
str [Element]
props "\x200B"]
       -- this is how the xslt sheet handles all spaces
   EUnder _ x :: Exp
x (ESymbol TUnder t :: Text
t) | (Char -> Bool) -> Text -> Bool
T.all Char -> Bool
isBarChar Text
t ->
                       [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "bar" [ String -> Element -> Element
forall t. Node t => String -> t -> Element
mnode "barPr" (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$
                                        String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "pos" "bot" ()
                                    , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x ]]
   EOver _ x :: Exp
x (ESymbol TOver t :: Text
t) | (Char -> Bool) -> Text -> Bool
T.all Char -> Bool
isBarChar Text
t ->
                       [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "bar" [ String -> Element -> Element
forall t. Node t => String -> t -> Element
mnode "barPr" (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$
                                        String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "pos" "top" ()
                                    , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x ]]
   EOver _ x :: Exp
x (ESymbol st :: TeXSymbolType
st (Text -> String
T.unpack -> String
y))
    | TeXSymbolType
st TeXSymbolType -> TeXSymbolType -> Bool
forall a. Eq a => a -> a -> Bool
== TeXSymbolType
Accent  -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "acc" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "accPr" [ String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "chr" String
y () ]
                                    , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x ]]
    | TeXSymbolType
st TeXSymbolType -> TeXSymbolType -> Bool
forall a. Eq a => a -> a -> Bool
== TeXSymbolType
TUnder  -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "groupChr" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "groupChrPr"
                                           [ String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "chr" String
y ()
                                           , String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "pos" "bot" ()
                                           , String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "vertJc" "top" () ]
                                    , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x ]]
    | TeXSymbolType
st TeXSymbolType -> TeXSymbolType -> Bool
forall a. Eq a => a -> a -> Bool
== TeXSymbolType
TOver   -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "groupChr" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "groupChrPr"
                                           [ String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "chr" String
y ()
                                           , String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "pos" "top" ()
                                           , String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "vertJc" "bot" () ]
                                    , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x ]]
   ESub x :: Exp
x y :: Exp
y         -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "sSub" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x
                                     , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "sub" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
y]]
   ESuper x :: Exp
x y :: Exp
y       -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "sSup" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x
                                     , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "sup" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
y]]
   ESubsup x :: Exp
x y :: Exp
y z :: Exp
z    -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "sSubSup" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x
                                        , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "sub" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
y
                                        , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "sup" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
z]]
   EUnder _ x :: Exp
x y :: Exp
y  -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "limLow" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x
                                       , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "lim" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
y]]
   EOver _ x :: Exp
x y :: Exp
y   -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "limUpp" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x
                                       , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "lim" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
y]]
   EUnderover c :: Bool
c x :: Exp
x y :: Exp
y z :: Exp
z -> [Element] -> Exp -> [Element]
showExp [Element]
props (Bool -> Exp -> Exp -> Exp
EUnder Bool
c (Bool -> Exp -> Exp -> Exp
EOver Bool
c Exp
x Exp
z) Exp
y)
   ESqrt x :: Exp
x       -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "rad" [ String -> Element -> Element
forall t. Node t => String -> t -> Element
mnode "radPr" (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$ String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "degHide" "1" ()
                                      , String -> () -> Element
forall t. Node t => String -> t -> Element
mnode "deg" ()
                                      , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x]]
   ERoot i :: Exp
i x :: Exp
x     -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "rad" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "deg" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
i
                                 , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x]]
   EFraction ft :: FractionType
ft x :: Exp
x y :: Exp
y -> [[Element] -> FractionType -> Exp -> Exp -> Element
showFraction [Element]
props FractionType
ft Exp
x Exp
y]
   EPhantom x :: Exp
x       -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "phant" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "phantPr"
                                            [ String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "show" "0" () ]
                                          , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x]]
   EBoxed   x :: Exp
x       -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "borderBox" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x]]
   EScaled _ x :: Exp
x      -> [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x -- no support for scaler?
   EArray as :: [Alignment]
as ls :: [ArrayLine]
ls     -> [[Element] -> [Alignment] -> [ArrayLine] -> Element
makeArray [Element]
props [Alignment]
as [ArrayLine]
ls]
   EText a :: TextType
a s :: Text
s        -> [TextType -> Text -> Element
makeText TextType
a Text
s]
   EStyled a :: TextType
a es :: [Exp]
es     -> (Exp -> [Element]) -> [Exp] -> [Element]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([Element] -> Exp -> [Element]
showExp (TextType -> [Element]
setProps TextType
a)) [Exp]
es

isBarChar :: Char -> Bool
isBarChar :: Char -> Bool
isBarChar c :: Char
c = Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== '\x203E' Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== '\x00AF' Bool -> Bool -> Bool
||
              Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== '\x0304' Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== '\x0333'

isNary :: Exp -> Bool
isNary :: Exp -> Bool
isNary (ESymbol Op _) = Bool
True
isNary _ = Bool
False

-- Kept as String for Text.XML.Light
makeNary :: [Element] -> String -> T.Text -> Exp -> Exp -> Exp -> Element
makeNary :: [Element] -> String -> Text -> Exp -> Exp -> Exp -> Element
makeNary props :: [Element]
props t :: String
t s :: Text
s y :: Exp
y z :: Exp
z w :: Exp
w =
  String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "nary" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "naryPr"
                 [ String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "chr" (Text -> String
T.unpack Text
s) ()
                 , String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "limLoc" String
t ()
                 , String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "subHide"
                    (if Exp
y Exp -> Exp -> Bool
forall a. Eq a => a -> a -> Bool
== [Exp] -> Exp
EGrouped [] then "1" else "0") ()
                 , String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA "supHide"
                    (if Exp
z Exp -> Exp -> Bool
forall a. Eq a => a -> a -> Bool
== [Exp] -> Exp
EGrouped [] then "1" else "0") ()
                 ]
               , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "sub" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
y
               , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "sup" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
z
               , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode "e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
w ]