texmath 0.13.2.2 → 0.13.3
raw patch · 44 files changed
+537/−177 lines, 44 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Text.TeXMath.Shared: everywhereExp :: (Exp -> Exp) -> Exp -> Exp
+ Text.TeXMath.Shared: everywhereExpList :: ([Exp] -> [Exp]) -> [Exp] -> [Exp]
+ Text.TeXMath.Shared: mapExpChildren :: (Exp -> Exp) -> ([Exp] -> [Exp]) -> Exp -> Exp
Files
- changelog.md +64/−0
- src/Text/TeXMath/Readers/MathML.hs +3/−1
- src/Text/TeXMath/Readers/OMML.hs +12/−10
- src/Text/TeXMath/Readers/TeX.hs +69/−26
- src/Text/TeXMath/Readers/TeX/Macros.hs +55/−42
- src/Text/TeXMath/Shared.hs +82/−23
- src/Text/TeXMath/TeX.hs +28/−18
- src/Text/TeXMath/Writers/Eqn.hs +14/−5
- src/Text/TeXMath/Writers/MathML.hs +2/−3
- src/Text/TeXMath/Writers/OMML.hs +21/−7
- src/Text/TeXMath/Writers/StarMath.hs +1/−2
- src/Text/TeXMath/Writers/TeX.hs +39/−4
- src/Text/TeXMath/Writers/Typst.hs +1/−2
- test/reader/mml/complex3.test +2/−2
- test/reader/mml/mspace1.test +2/−2
- test/reader/mml/mspacestruts2.test +2/−1
- test/reader/omml/sym.test +9/−0
- test/reader/tex/array_column_specs.test +20/−0
- test/reader/tex/macros_escaped_braces.test +13/−0
- test/reader/tex/macros_nested_env.test +20/−0
- test/regression/296.test +16/−0
- test/regression/297.test +4/−0
- test/writer/eqn/complex3.test +1/−1
- test/writer/eqn/ms-15.test +1/−1
- test/writer/eqn/ms-16.test +1/−1
- test/writer/eqn/sans-serif-bold-italic.test +1/−1
- test/writer/eqn/sans-serif-bold.test +1/−1
- test/writer/eqn/sans-serif-italic.test +1/−1
- test/writer/eqn/sans-serif.test +1/−1
- test/writer/eqn/serif-bold-italic.test +1/−1
- test/writer/eqn/serif-bold.test +1/−1
- test/writer/eqn/serif-italic.test +1/−1
- test/writer/eqn/serif.test +1/−1
- test/writer/omml/scaled_delims.test +27/−0
- test/writer/tex/accents1.test +2/−2
- test/writer/tex/accents2.test +2/−2
- test/writer/tex/accents5.test +2/−2
- test/writer/tex/accents6.test +2/−2
- test/writer/tex/complex3.test +1/−1
- test/writer/tex/divergence.test +1/−1
- test/writer/tex/mover3.test +1/−1
- test/writer/tex/mover5.test +1/−1
- test/writer/tex/tokens.test +1/−1
- texmath.cabal +7/−5
changelog.md view
@@ -1,3 +1,67 @@+texmath (0.13.3)++ * Replace SYB traversals with hand-written ones. Text.TeXMath.Shared+ now provides `mapExpChildren`, `everywhereExp` and+ `everywhereExpList` [API change]. These replicate the SYB+ semantics but are much faster. These are now used instead of SYB+ functions throughout the code base. This speeds up many functions+ (in particular, `writeOMML` is 6x faster on our benchmark).++ * TeX reader: Fix handling of ` and " in math mode (#296).++ * TeX reader: gate hot-path command checks behind a one-char `lookAhead`.++ * TeX reader: use a prefix trie in `oneOfStrings`.++ * TeX reader: don't fail on `p{...}` and `>{...}` array column specs.+ Column specs like `p{2cm}`, `m{0.4\textwidth}`, `b{1in}`, `>{\bf}`,+ and `<{x}` caused the whole array environment to fail to parse. The AST+ cannot represent column widths or inserted material, so parse and+ ignore them.++ * TeX writer: use `\vec`, `\tilde`, `\hat` for single-character bases.+ The diacriticals table in Shared contained dead duplicate entries+ (`\vec` shadowed by `\overrightarrow`, `\tilde` by `\widetilde`),+ so the TeX writer always emitted the wide accent commands, even for+ single characters where `\vec{v}`, `\tilde{x}`, `\hat{H}` are canonical.++ * `renderTeX`: use a lazy Text accumulator to avoid quadratic rendering.+ This yields large performance gains on large outputs.++ * eqn writer: escape `"` and `\` in quoted text. (#297, Dylan Pulver).+ The writer wraps text in the double quotes eqn uses for literal text but+ emitted the content unescaped, so a `"` ended the string early and a `\`+ began a troff escape sequence.++ * Shared: fix unit conversion in `readLength`/`unitToMultiplier`.++ * Shared: hoist per-call table constructions to top-level CAFs.++ * MathML/OMML readers: don't crash on malformed input.++ * Macros: fix parsing of escaped braces in macro bodies.++ * Macros: don't silently drop input in `applyMacros`.++ * Macros: fix nested same-name environments in `newenvironment`.++ * Macros: speed up `applyMacros`.++ * OMML reader: fix `w:sym` private-use codepoints and empty-run junk.+ `lowerFromPrivate` only matched uppercase 'F' prefixes, so lowercase+ codepoints like `w:char="f062"` were not mapped down from the private+ use area and silently produced no symbol. Match 'f' as well.+ Also make `getSymChar` return Maybe instead of an empty string, so an+ unresolvable `w:sym` (unknown font, missing attributes, out-of-range+ codepoint) is dropped instead of becoming an empty text run, and fix+ `interpretText` to return `[]` for empty input.++ * OMML writer: don't require equal scales on delimiter pairs.+ `handleScaledDelims` only converted a scaled open/close pair to an+ m:d element when both delimiters had exactly the same scale factor,+ so pairs like \bigl( x \Bigr) degraded to flat character runs with+ no delimiter structure.+ texmath (0.13.2.2) * Typst writer: fix spacing commands (#295).
src/Text/TeXMath/Readers/MathML.hs view
@@ -53,6 +53,7 @@ import Control.Applicative ((<|>)) import qualified Data.Text as T import Control.Monad (filterM, mzero)+import Text.Read (readMaybe) import Control.Monad.Reader (ReaderT, runReaderT, asks, local) import Data.Either (rights) @@ -399,7 +400,8 @@ action :: Element -> MML Exp action e = do- selection <- maybe 1 (read . T.unpack) <$> (findAttrQ "selection" e) -- 1-indexing+ selection <- maybe 1 (fromMaybe 1 . readMaybe . T.unpack)+ <$> (findAttrQ "selection" e) -- 1-indexing, defaults to 1 safeExpr =<< maybeToEither ("Selection out of range") (listToMaybe $ drop (selection - 1) (elChildren e))
src/Text/TeXMath/Readers/OMML.hs view
@@ -165,7 +165,7 @@ || isElem "w" "delText" element = Just $ TextRun $ T.pack $ strContent element | isElem "w" "br" element = Just LnBrk | isElem "w" "tab" element = Just Tab- | isElem "w" "sym" element = Just $ TextRun $ getSymChar element+ | isElem "w" "sym" element = TextRun <$> getSymChar element | isElem "w" "ins" element = Just $ Inserted $ mapMaybe elemToOMathRunElem (elChildren element) | otherwise = Nothing @@ -319,7 +319,7 @@ elemToExps' element | isElem "m" "eqArr" element = let expLst = mapMaybe elemToBases (elChildren element) expLst' = map breakOnAmpersand expLst- cols = maximum (map length expLst')+ cols = foldr max 0 (map length expLst') colspecs = take cols $ cycle [AlignRight , AlignLeft] in return [EArray colspecs expLst']@@ -500,6 +500,7 @@ interpretText :: T.Text -> [Exp] interpretText s+ | T.null s = [] | Just (c, xs) <- T.uncons s , T.null xs = [interpretChar c] | T.all isDigit s = [ENumber s]@@ -508,16 +509,17 @@ | otherwise = map interpretChar (T.unpack s) -- The char attribute is a hex string-getSymChar :: Element -> T.Text-getSymChar element- | Just s <- lowerFromPrivate <$> getCodepoint- , Just font <- getFont =+getSymChar :: Element -> Maybe T.Text+getSymChar element = do+ s <- lowerFromPrivate <$> getCodepoint+ font <- getFont case readLitChar ("\\x" ++ s) of- [(char, _)] -> maybe "" T.singleton $ getUnicode font char- _ -> ""+ [(char, _)] -> T.singleton <$> getUnicode font char+ _ -> Nothing where getCodepoint = findAttrBy (hasElemName "w" "char") element getFont = (textToFont . T.pack) =<< findAttrBy (hasElemName "w" "font") element- lowerFromPrivate ('F':xs) = '0':xs+ -- Symbol fonts store codepoints in the private use area+ -- (F000-F0FF); subtract 0xF000 to get the character code.+ lowerFromPrivate (c:xs) | c == 'F' || c == 'f' = '0':xs lowerFromPrivate xs = xs-getSymChar _ = ""
src/Text/TeXMath/Readers/TeX.hs view
@@ -25,14 +25,14 @@ module Text.TeXMath.Readers.TeX (readTeX) where -import Data.List (intercalate, intersperse, find, foldl')+import Data.List (intercalate, intersperse, foldl') import Control.Monad import Data.Char (isDigit, isAscii, isLetter) import qualified Data.Map as M import qualified Data.Text as T import Data.Text (Text) import Data.Ratio ((%))-import Data.Maybe (catMaybes, fromJust, mapMaybe)+import Data.Maybe (catMaybes, fromJust, fromMaybe, mapMaybe) import Text.Parsec hiding (label) import Text.Parsec.Error import Text.Parsec.Text@@ -43,7 +43,6 @@ import Text.TeXMath.Unicode.ToTeX (getSymbolType) import Text.TeXMath.Unicode.ToUnicode (toUnicode) import Text.TeXMath.Shared (getSpaceChars)-import Data.Generics (everywhere, mkT) import Text.TeXMath.Readers.TeX.Commands ( styleOps, textOps, enclosures, operators, symbols, siUnitMap ) import Data.Text.Read (decimal)@@ -71,12 +70,13 @@ [ inbraces , variable , number- , unicode , operator , bareSubSup , enclosure , hyperref , command+ , unicode+ , special ] <* ignorable -- | Parse a formula, returning a list of 'Exp'.@@ -89,7 +89,7 @@ -- | Convert Bin symbol type in certain contexts (#176, #234). fixBinList :: [Exp] -> [Exp] fixBinList =- reverse . foldl' goExp [] . everywhere (mkT fixBins)+ reverse . foldl' goExp [] . map (S.everywhereExp fixBins) -- TeXBook: -- 5. If the current item is a Bin atom, and if this was the first@@ -195,8 +195,11 @@ expr :: TP Exp expr = do- optional (ctrlseq "displaystyle" <|> ctrlseq "textstyle" <|>- ctrlseq "scriptstyle" <|> ctrlseq "scriptscriptstyle")+ -- the lookAhead is just an optimization: it lets us skip the four+ -- ctrlseq attempts with a one-character test on most input+ optional (lookAhead (char '\\') *>+ (ctrlseq "displaystyle" <|> ctrlseq "textstyle" <|>+ ctrlseq "scriptstyle" <|> ctrlseq "scriptscriptstyle")) (a, convertible) <- try (braces operatorname) -- needed because macros add {} <|> operatorname <|> ((,False) <$> expr1)@@ -289,7 +292,10 @@ <|> return Nothing binomCmd :: TP Text-binomCmd = oneOfCommands (M.keys binomCmds)+binomCmd = lookAhead (char '\\') *> oneOfCommands (M.keys binomCmds)+ -- the lookAhead is just an optimization: this parser is run (via+ -- notFollowedBy) before every token in manyExp', and the quick+ -- one-character test lets it fail cheaply on most input. binomCmds :: M.Map Text (Exp -> Exp -> Exp) binomCmds = M.fromList@@ -466,10 +472,12 @@ arrayAlignments :: TP [Alignment] arrayAlignments = mconcat <$> braces (many (- ((:[]) . letterToAlignment <$> letter)+ ((:[]) <$> try (AlignLeft <$ oneOf "pmb" <* skipBraces))+ <|> ((:[]) . letterToAlignment <$> letter) <|> ([] <$ char '|') <|> ([] <$ oneOf " \t") <|> ([] <$ ((char '@' <|> char '!') <* inbraces))+ <|> ([] <$ ((char '>' <|> char '<') <* skipBraces)) <|> (do char '*' num <- T.pack <$> braces (many1 digit) cols <- arrayAlignments@@ -483,10 +491,15 @@ letterToAlignment 'c' = AlignCenter letterToAlignment 'r' = AlignRight letterToAlignment _ = AlignCenter+ -- Column widths (p{...}, m{...}, b{...}) and inserted material+ -- (>{...}, <{...}) can't be represented in the AST, so we parse+ -- and ignore the contents of the brace group.+ skipBraces = () <$ (char '{' *> manyTill (skipBraces <|> () <$ noneOf "}")+ (char '}')) environment :: Text -> TP Exp environment "\\begin" = do- name <- braces (oneOfStrings (M.keys environments) <* optional (char '*'))+ name <- environmentName spaces case M.lookup name environments of Just env -> do@@ -499,6 +512,11 @@ Nothing -> mzero -- should not happen environment _ = mzero +-- A top-level binding, so that the underlying trie is built only once.+environmentName :: TP Text+environmentName =+ braces (oneOfStrings (M.keys environments) <* optional (char '*'))+ environments :: M.Map Text (TP Exp) environments = M.fromList [ ("array", stdarray)@@ -642,6 +660,11 @@ c <- satisfy (not . isAscii) return (ESymbol (getSymbolType c) $ T.singleton c) +-- special is to catch some things that otherwise cause parse errors,+-- e.g. $\"y$ or $`x$ -- see #296+special :: TP Exp+special = EText TextNormal <$> (quote <|> textCommand)+ ensuremath :: Text -> TP Exp ensuremath "\\ensuremath" = inbraces ensuremath _ = mzero@@ -875,25 +898,41 @@ spaces return cmd -oneOfStrings' :: (Char -> Char -> Bool) -> [(String, Text)] -> TP Text-oneOfStrings' _ [] = mzero-oneOfStrings' matches strs = try $ do- c <- anyChar- let strs' = [(xs, t) | ((x:xs), t) <- strs, x `matches` c]- case strs' of- [] -> mzero- _ -> oneOfStrings' matches strs'- <|> case find (null . fst) strs' of- Just (_, t) -> return t- Nothing -> mzero+-- A prefix trie over the characters of a fixed set of strings; the+-- value at a node is the string spelled out by the path to it, if+-- that string is in the set.+data Trie = Trie (Maybe Text) (M.Map Char Trie) +buildTrie :: [Text] -> Trie+buildTrie = foldr insertStr (Trie Nothing M.empty) . filter (not . T.null)+ where+ insertStr t = go (T.unpack t)+ where+ go [] (Trie _ cs) = Trie (Just t) cs+ go (c:rest) (Trie v cs) = Trie v $+ M.alter (Just . go rest . fromMaybe (Trie Nothing M.empty)) c cs++-- Longest match: try to descend on the next character, and fall+-- back to the match ending at the current node.+trieParser :: Trie -> TP Text+trieParser (Trie val children) =+ (if M.null children+ then mzero+ else try $ do+ c <- anyChar+ case M.lookup c children of+ Just subtrie -> trieParser subtrie+ Nothing -> mzero)+ <|> maybe mzero return val+ -- | Parses one of a list of strings. If the list contains -- two strings one of which is a prefix of the other, the longer--- string will be matched if possible.+-- string will be matched if possible. The trie is built only once+-- when the resulting parser is shared, so prefer binding the result+-- to a name over calling this repeatedly with the same list. oneOfStrings :: [Text] -> TP Text-oneOfStrings strs = oneOfStrings' (==) strs' <??> (intercalate ", " $ map show strs)- where- strs' = map (\x -> (T.unpack x, x)) strs+oneOfStrings strs =+ trieParser (buildTrie strs) <??> (intercalate ", " $ map show strs) -- | Like '(<?>)', but moves position back to the beginning of the parse -- before reporting the error.@@ -974,7 +1013,10 @@ ligature = try ("\x2014" <$ string "---") <|> try ("\x2013" <$ string "--") <|> try (textStr "-")- <|> try ("\x201C" <$ string "``")+ <|> quote++quote :: TP Text+quote = try ("\x201C" <$ string "``") <|> try ("\x201D" <$ string "''") <|> try ("\x2019" <$ string "'") <|> try ("\x2018" <$ string "`")@@ -1127,6 +1169,7 @@ umlaut 'i' = "ï" umlaut 'o' = "ö" umlaut 'u' = "ü"+umlaut 'y' = "ÿ" umlaut c = T.singleton c dot :: Char -> Text
src/Text/TeXMath/Readers/TeX/Macros.hs view
@@ -78,32 +78,40 @@ -- same name, earlier ones will shadow later ones. applyMacros :: [Macro] -> T.Text -> T.Text applyMacros [] s = s-applyMacros ms s =- maybe s id $ iterateToFixedPoint ((2 * length ms) + 1)- (applyMacrosOnce ms) s+applyMacros ms s = maybe s id $ go ((2 * length ms) + 1) s+ where+ -- The limit caps the number of rewriting passes, in case of a+ -- loop in the macros.+ go :: Int -> T.Text -> Maybe T.Text+ go 0 _ = Nothing+ go limit x =+ case applyMacrosOnce ms x of+ Nothing -> Nothing+ Just (y, expanded)+ | expanded -> go (limit - 1) y+ | otherwise -> Just y -- no macro fired: y is a fixed point ------------------------------------------------------------------------------ -iterateToFixedPoint :: Eq a => Int -> (a -> Maybe a) -> a -> Maybe a-iterateToFixedPoint 0 _ _ = Nothing- -- Macro application did not terminate in a reasonable time, possibly- -- because of a loop in the macro.-iterateToFixedPoint limit f x =- case f x of- Nothing -> Nothing- Just y- | y == x -> Just y- | otherwise -> iterateToFixedPoint (limit - 1) f y--applyMacrosOnce :: [Macro] -> T.Text -> Maybe T.Text+-- Returns the rewritten text and whether any macro was expanded.+applyMacrosOnce :: [Macro] -> T.Text -> Maybe (T.Text, Bool) applyMacrosOnce ms s =- case parse (many tok) "input" s of- Right r -> Just $ T.concat r+ -- The unconsumed rest of the input (in case a token fails to parse,+ -- e.g. on a trailing comment or backslash) is passed through+ -- unchanged rather than dropped.+ case runParser ((,,) <$> many tok <*> getInput <*> getState)+ False "input" s of+ Right (r, rest, expanded) -> Just (T.concat r <> rest, expanded) Left _ -> Nothing where tok = try $ do skipComment choice [ choice (map (\m -> macroParser m) ms)+ <* putState True , T.pack <$> ctrlseq+ -- Macros only match at '\\' and comments+ -- only at '%', so anything else can be+ -- consumed as a single chunk.+ , T.pack <$> many1 (noneOf "\\%") , T.pack <$> count 1 anyChar ] ctrlseq :: (Monad m, Stream s m Char)@@ -181,30 +189,35 @@ (if numargs > 0 then ("[" ++ show numargs ++ "]") else "") ++ case optarg of { Nothing -> ""; Just x -> "[" ++ x ++ "]"} ++ "%\n{" ++ opener ++ "}%\n" ++ "{" ++ closer ++ "}"- return $ Macro (T.pack defn) $ fmap T.pack $ try $ do- string "\\begin"- pSkipSpaceComments- char '{'- string name- pSkipSpaceComments- char '}'- opt <- case optarg of- Nothing -> return Nothing- Just _ -> liftM (`mplus` optarg) optArg- args <- count numargs' (pSkipSpaceComments >>- (inbraces <|> ctrlseq <|> count 1 anyChar))- let args' = case opt of- Just x -> x : args- Nothing -> args- let ender = try $ do- string "\\end"- pSkipSpaceComments- char '{'- string name- char '}'- body <- manyTill anyChar ender- return $ apply args'- $ opener ++ body ++ closer+ return $ Macro (T.pack defn) $ fmap T.pack $+ let pEnv = try $ do+ string "\\begin"+ pSkipSpaceComments+ char '{'+ string name+ pSkipSpaceComments+ char '}'+ opt <- case optarg of+ Nothing -> return Nothing+ Just _ -> liftM (`mplus` optarg) optArg+ args <- count numargs' (pSkipSpaceComments >>+ (inbraces <|> ctrlseq <|> count 1 anyChar))+ let args' = case opt of+ Just x -> x : args+ Nothing -> args+ body <- pBody+ return $ apply args'+ $ opener ++ body ++ closer+ ender = try $ do+ string "\\end"+ pSkipSpaceComments+ char '{'+ string name+ char '}'+ -- Expand nested environments with the same name recursively,+ -- so that the body isn't ended at a nested \end.+ pBody = concat <$> manyTill (pEnv <|> count 1 anyChar) ender+ in pEnv -- | Parser for \DeclareMathOperator(*) command. declareMathOperator :: (Monad m, Stream s m Char)@@ -285,7 +298,7 @@ inbraces = try $ do char '{' res <- manyTill (skipComment >>- (inbraces' <|> count 1 anyChar <|> escaped "{}"))+ (inbraces' <|> escaped "{}" <|> count 1 anyChar)) (try $ skipComment >> char '}') return $ concat res
@@ -30,6 +30,9 @@ , getOperator , readLength , fixTree+ , everywhereExp+ , everywhereExpList+ , mapExpChildren , isEmpty , empty , handleDownup@@ -47,9 +50,7 @@ import Data.Maybe (fromMaybe) import Data.Ratio ((%)) import Data.List (sort)-import Control.Monad (guard) import Text.Parsec (Parsec, parse, getInput, digit, char, many1, option)-import Data.Generics (everywhere, mkT) -- As we constuct from the bottom up, this situation can occur. removeNesting :: Exp -> Exp@@ -74,8 +75,61 @@ -- fixing delimited expressions with no delimiters and unnecessarily -- grouped expressions. fixTree :: Exp -> Exp-fixTree = everywhere (mkT removeNesting) . everywhere (mkT removeEmpty)+fixTree = everywhereExp removeNesting . goE+ where+ -- Remove empty expressions from every expression list, bottom up.+ -- (Filtering each list once is equivalent to the per-tail+ -- application 'everywhereExpList' would do, since removeEmpty is+ -- an element-wise filter.)+ goE = mapExpChildren goE (removeEmpty . map goE) +-- | Apply a transformation to every subexpression, bottom up+-- (equivalent to SYB's @everywhere (mkT f)@, but faster, since it+-- involves no run-time type checks).+everywhereExp :: (Exp -> Exp) -> Exp -> Exp+everywhereExp f = go+ where go = f . mapExpChildren go (map go)++-- | Apply a transformation to every expression list in an expression+-- list, bottom up. Like SYB's @everywhere (mkT f)@, this applies the+-- function to every /tail/ of every list (right to left), since each+-- tail is itself a @[Exp]@ node; a rewrite can thus consume+-- already-rewritten material to its right.+everywhereExpList :: ([Exp] -> [Exp]) -> [Exp] -> [Exp]+everywhereExpList f = goL+ where goL = foldr (\x acc -> f (goE x : acc)) (f [])+ goE = mapExpChildren goE goL++-- | Apply @goE@ to each immediate subexpression of a node and @goL@+-- to each immediate subexpression list. A building block for+-- expression traversals.+mapExpChildren :: (Exp -> Exp) -> ([Exp] -> [Exp]) -> Exp -> Exp+mapExpChildren goE goL e =+ case e of+ ENumber{} -> e+ EGrouped es -> EGrouped (goL es)+ EDelimited o c ds -> EDelimited o c (map (fmap goE) ds)+ EIdentifier{} -> e+ EMathOperator{} -> e+ ESymbol{} -> e+ ESpace{} -> e+ ESub a b -> ESub (goE a) (goE b)+ ESuper a b -> ESuper (goE a) (goE b)+ ESubsup a b c -> ESubsup (goE a) (goE b) (goE c)+ EOver conv a b -> EOver conv (goE a) (goE b)+ EUnder conv a b -> EUnder conv (goE a) (goE b)+ EUnderover conv a b c -> EUnderover conv (goE a) (goE b) (goE c)+ EPhantom a -> EPhantom (goE a)+ EBoxed a -> EBoxed (goE a)+ ECancel st a -> ECancel st (goE a)+ EFraction ft a b -> EFraction ft (goE a) (goE b)+ ERoot a b -> ERoot (goE a) (goE b)+ ESqrt a -> ESqrt (goE a)+ EScaled r a -> EScaled r (goE a)+ EArray as rows -> EArray as (map (map goL) rows)+ EText{} -> e+ EStyled tt es -> EStyled tt (goL es)+ -- | Maps TextType to the corresponding MathML mathvariant getMMLType :: TextType -> T.Text getMMLType t = fromMaybe "normal" (fst <$> M.lookup t textTypesMap)@@ -96,12 +150,16 @@ -- | Maps a LaTeX scaling command to the percentage scaling getScalerCommand :: Rational -> Maybe T.Text getScalerCommand width =- case sort [ (w, cmd) | (cmd, w) <- scalers, w >= width ] of- ((_,cmd):_) -> Just cmd- _ -> Nothing- -- note, we don't use a Map here because we need the first- -- match: \Big, not \Bigr+ case [ cmd | (w, cmd) <- sortedScalers, w >= width ] of+ (cmd:_) -> Just cmd+ _ -> Nothing +-- Scalers sorted by increasing width (then command name), so the+-- first command with sufficient width is the preferred one:+-- \Big, not \Bigr. (We don't use a Map because of this tie-break.)+sortedScalers :: [(Rational, T.Text)]+sortedScalers = sort [ (w, cmd) | (cmd, w) <- scalers ]+ -- | Gets percentage scaling from LaTeX scaling command getScalerValue :: T.Text -> Maybe Rational getScalerValue command = lookup command scalers@@ -114,9 +172,10 @@ case pos of Under -> if below then Just command else Nothing Over -> if not below then Just command else Nothing- where- diaMap = M.fromList diacriticals +diaMap :: M.Map T.Text T.Text+diaMap = M.fromList diacriticals+ -- Operator Table getOperator :: Exp -> Maybe TeX@@ -305,14 +364,12 @@ , ("\x20DC", "\\ddddot") , ("\x00B0", "\\mathring") , ("\x030A", "\\mathring")- , ("\x20D7", "\\vec") , ("\x20D7", "\\overrightarrow") , ("\x20D6", "\\overleftarrow") , ("\x005E", "\\hat") , ("\x02C6", "\\widehat") , ("\x0302", "\\widehat") , ("\x02DC", "\\widetilde")- , ("\x0303", "\\tilde") , ("\x0303", "\\widetilde") , ("\x0304", "\\bar") , ("\x203E", "\\bar")@@ -331,19 +388,21 @@ -- Converts unit to multiplier to reach em+-- (em length per unit, assuming 1em = 10pt) unitToMultiplier :: T.Text -> Maybe Rational unitToMultiplier s = M.lookup s units- where- units = M.fromList [ ( "pt" , 10)- , ( "mm" , (351/10))- , ( "cm" , (35/100))- , ( "in" , (14/100))- , ( "ex" , (232/100))- , ( "em" , 1)- , ( "mu" , 18)- , ( "dd" , (93/100))- , ( "bp" , (996/1000))- , ( "pc" , (83/100)) ]++units :: M.Map T.Text Rational+units = M.fromList [ ( "pt" , (1/10))+ , ( "mm" , (2845/10000)) -- 1mm = 72.27/25.4 pt+ , ( "cm" , (2845/1000))+ , ( "in" , (7227/1000)) -- 1in = 72.27pt+ , ( "ex" , (43/100)) -- 1ex ~ 4.3pt (cmr10)+ , ( "em" , 1)+ , ( "mu" , (1/18)) -- 18mu = 1em+ , ( "dd" , (107/1000)) -- 1dd = 1238/1157 pt+ , ( "bp" , (1004/10000)) -- 1bp = 72.27/72 pt+ , ( "pc" , (12/10)) ] -- 1pc = 12pt handleDownup :: DisplayType -> Exp -> Exp handleDownup DisplayInline (EUnder True x y) = ESub x y
src/Text/TeXMath/TeX.hs view
@@ -7,6 +7,7 @@ where import Data.Char (isLetter, isAlphaNum, isAscii) import qualified Data.Text as T+import qualified Data.Text.Lazy as TL -- | An intermediate representation of TeX math, to be used in rendering. data TeX = ControlSeq T.Text@@ -18,23 +19,32 @@ -- | Render a 'TeX' to a string, appending to the front of the given string. renderTeX :: TeX -> T.Text -> T.Text-renderTeX (Token c) cs = T.cons c cs-renderTeX (Literal s) cs- | endsWith (not . isLetter) s = s <> cs- | startsWith isLetter cs = s <> T.cons ' ' cs- | otherwise = s <> cs-renderTeX (ControlSeq s) cs- | s == "\\ " = s <> cs+renderTeX t cs = TL.toStrict $ renderTeX' t (TL.fromStrict cs)++-- Rendering builds the output back to front, and looks ahead at the+-- rendered rest to decide on spacing. The accumulator is a lazy+-- Text, so that prepending is O(1) rather than a copy of the whole+-- rest (which would make rendering quadratic).+renderTeX' :: TeX -> TL.Text -> TL.Text+renderTeX' (Token c) cs = TL.cons c cs+renderTeX' (Literal s) cs+ | endsWith (not . isLetter) s = s' <> cs+ | startsWith isLetter cs = s' <> TL.cons ' ' cs+ | otherwise = s' <> cs+ where s' = TL.fromStrict s+renderTeX' (ControlSeq s) cs+ | s == "\\ " = s' <> cs | startsWith (\c -> isAlphaNum c || not (isAscii c)) cs- = s <> T.cons ' ' cs- | otherwise = s <> cs-renderTeX (Grouped [Grouped xs]) cs = renderTeX (Grouped xs) cs-renderTeX (Grouped xs) cs =- "{" <> foldr renderTeX "" (trimSpaces xs) <> "}" <> cs-renderTeX Space cs- | cs == "" = ""- | any (`T.isPrefixOf` cs) ps = cs- | otherwise = T.cons ' ' cs+ = s' <> TL.cons ' ' cs+ | otherwise = s' <> cs+ where s' = TL.fromStrict s+renderTeX' (Grouped [Grouped xs]) cs = renderTeX' (Grouped xs) cs+renderTeX' (Grouped xs) cs =+ "{" <> foldr renderTeX' "" (trimSpaces xs) <> "}" <> cs+renderTeX' Space cs+ | TL.null cs = ""+ | any (`TL.isPrefixOf` cs) ps = cs+ | otherwise = TL.cons ' ' cs where -- No space before ^, _, or \limits, and no doubled up spaces ps = [ "^", "_", " ", "\\limits" ]@@ -43,8 +53,8 @@ trimSpaces = reverse . go . reverse . go where go = dropWhile (== Space) -startsWith :: (Char -> Bool) -> T.Text -> Bool-startsWith p t = case T.uncons t of+startsWith :: (Char -> Bool) -> TL.Text -> Bool+startsWith p t = case TL.uncons t of Just (c, _) -> p c Nothing -> False
src/Text/TeXMath/Writers/Eqn.hs view
@@ -27,7 +27,6 @@ import Text.Printf (printf) import Text.TeXMath.Types import qualified Text.TeXMath.Shared as S-import Data.Generics (everywhere, mkT) import Data.Ratio ((%)) import Data.Text (Text) @@ -37,7 +36,7 @@ -- | Transforms an expression tree to equivalent Eqn writeEqn :: DisplayType -> [Exp] -> T.Text writeEqn dt exprs =- T.unwords $ map writeExp $ everywhere (mkT $ S.handleDownup dt) exprs+ T.unwords $ map (writeExp . S.everywhereExp (S.handleDownup dt)) exprs -- like writeExp but inserts {} if contents contain a space writeExp' :: Exp -> T.Text@@ -54,13 +53,23 @@ asgroup "" = "{\"\"}" -- see #198 asgroup t = "{" <> t <> "}" +-- Put text in the double quotes eqn uses to delimit literal text,+-- escaping the two characters that are special inside them: an+-- unescaped @"@ ends the string, and a backslash begins a troff+-- escape sequence.+quoteText :: Text -> Text+quoteText t = "\"" <> T.concatMap escapeChar t <> "\""+ where escapeChar '"' = "\\\""+ escapeChar '\\' = "\\[rs]"+ escapeChar c = T.singleton c+ writeExp :: Exp -> T.Text writeExp (ENumber s) = s writeExp (EGrouped es) = asgroup $ writeExps es writeExp (EDelimited open close es) = "left " <> mbQuote open <> " " <> T.intercalate " " (map fromDelimited es) <> " right " <> mbQuote close- where fromDelimited (Left e) = "\"" <> e <> "\""+ where fromDelimited (Left e) = quoteText e fromDelimited (Right e) = writeExp e mbQuote "" = "\"\"" mbQuote s = s@@ -69,7 +78,7 @@ "tanh", "arc", "max", "min", "lim", "log", "ln", "exp"] then s- else "\"" <> s <> "\""+ else quoteText s writeExp (ESymbol Ord (T.unpack -> [c])) -- do not render "invisible operators" | c `elem` ['\x2061'..'\x2064'] = "" -- see 3.2.5.5 of mathml spec writeExp (EIdentifier s) = writeExp (ESymbol Ord s)@@ -190,7 +199,7 @@ writeExp (ECancel _ e) = writeExp e -- TODO writeExp (EScaled _size e) = writeExp e -- TODO: any way? writeExp (EText ttype s) =- let quoted = "\"" <> s <> "\""+ let quoted = quoteText s in case ttype of TextNormal -> "roman " <> quoted TextItalic -> quoted
src/Text/TeXMath/Writers/MathML.hs view
@@ -26,9 +26,8 @@ import Text.XML.Light import Text.TeXMath.Types-import Data.Generics (everywhere, mkT) import Text.TeXMath.Unicode.ToUnicode (toUnicode)-import Text.TeXMath.Shared (getMMLType, handleDownup,+import Text.TeXMath.Shared (getMMLType, handleDownup, everywhereExp, isUppercaseGreek, isRLSequence) import Text.TeXMath.Readers.MathML.MMLDict (getMathMLOperator) import qualified Data.Text as T@@ -38,7 +37,7 @@ writeMathML :: DisplayType -> [Exp] -> Element writeMathML dt exprs = add_attr dtattr $ math $ showExp Nothing $ EGrouped- $ everywhere (mkT $ handleDownup dt) exprs+ $ map (everywhereExp (handleDownup dt)) exprs where dtattr = Attr (unqual "display") dt' dt' = case dt of DisplayBlock -> "block"
src/Text/TeXMath/Writers/OMML.hs view
@@ -26,8 +26,8 @@ import Text.XML.Light import Text.TeXMath.Types-import Text.TeXMath.Shared (isUppercaseGreek, isRLSequence)-import Data.Generics (everywhere, mkT)+import Text.TeXMath.Shared (isUppercaseGreek, isRLSequence,+ everywhereExpList, mapExpChildren) import Data.Char (isSymbol, isPunctuation) import Data.Either (lefts, isLeft, rights) import qualified Data.Text as T@@ -37,9 +37,9 @@ -- | Transforms an expression tree to an OMML XML Tree writeOMML :: DisplayType -> [Exp] -> Element writeOMML dt = container . concatMap (showExp [])- . everywhere (mkT $ handleDownup dt)- . everywhere (mkT $ handleDownup' dt)- . everywhere (mkT $ handleScaledDelims)+ . everywhereExpList (handleDownup dt)+ . handleDownupDelims dt+ . everywhereExpList handleScaledDelims where container = case dt of DisplayBlock -> \x -> mnode "oMathPara" [ mnode "oMathParaPr"@@ -132,10 +132,13 @@ where sty x = mnodeA "sty" x () scr x = mnodeA "scr" x () +-- OMML cannot represent a numeric scale factor for delimiters, so+-- render a pair of scaled delimiters as an m:d, which grows the+-- delimiters to fit their content. handleScaledDelims :: [Exp] -> [Exp]-handleScaledDelims (x@(EScaled scale (ESymbol Open op)) : xs) =+handleScaledDelims (x@(EScaled _ (ESymbol Open op)) : xs) = case break isCloser xs of- (ys, EScaled scale' (ESymbol Close cl) : zs) | scale' == scale ->+ (ys, EScaled _ (ESymbol Close cl) : zs) -> EDelimited op cl (map Right ys) : zs _ -> x:xs where@@ -171,6 +174,17 @@ [] -> (emptyGroup, []) emptyGroup = EGrouped [] handleDownup _ [] = []++-- | Apply @handleDownup' dt@ to every delimited-expression list,+-- bottom up, including every tail of every list (the same traversal+-- the SYB @everywhere@ it replaces performed).+handleDownupDelims :: DisplayType -> [Exp] -> [Exp]+handleDownupDelims dt = map goE+ where+ goE (EDelimited o c ds) = EDelimited o c (goDs ds)+ goE e = mapExpChildren goE (map goE) e+ goDs = foldr (\d acc -> f (fmap goE d : acc)) (f [])+ f = handleDownup' dt -- TODO This duplication is ugly and inefficient. See #92. handleDownup' :: DisplayType -> [InEDelimited] -> [InEDelimited]
src/Text/TeXMath/Writers/StarMath.hs view
@@ -4,7 +4,6 @@ ) where import Data.Char (isLetter)-import Data.Generics (everywhere, mkT) import qualified Data.List as List import qualified Data.Text as T import qualified Text.TeXMath.Shared as S@@ -23,7 +22,7 @@ -- Falls back to TeX output for expressions that are not yet supported. writeStarMath :: DisplayType -> [Exp] -> T.Text writeStarMath dt exps =- case renderExps dt (normalizeExps (everywhere (mkT $ S.handleDownup dt) exps)) of+ case renderExps dt (normalizeExps (map (S.everywhereExp (S.handleDownup dt)) exps)) of Just rendered -> T.strip rendered Nothing -> writeTeX exps
src/Text/TeXMath/Writers/TeX.hs view
@@ -25,7 +25,6 @@ import Text.TeXMath.Unicode.ToUnicode (fromUnicode) import qualified Text.TeXMath.Shared as S import qualified Data.Text as T-import Data.Generics (everywhere, mkT) import Control.Monad (when, unless, foldM_) import Control.Monad.Reader (MonadReader, runReader, Reader, asks, local) import Control.Monad.Writer( MonadWriter, WriterT,@@ -101,6 +100,22 @@ tell [ControlSeq cmd] writeExp y +-- | Replace styled unicode characters with their unstyled+-- equivalents in every text field of an expression.+fromUnicodeExp :: TextType -> Exp -> Exp+fromUnicodeExp ttype = S.everywhereExp go+ where+ f = fromUnicode ttype+ go e = case e of+ ENumber t -> ENumber (f t)+ EIdentifier t -> EIdentifier (f t)+ EMathOperator t -> EMathOperator (f t)+ ESymbol ty t -> ESymbol ty (f t)+ EText tt t -> EText tt (f t)+ EDelimited o c ds -> EDelimited (f o) (f c)+ (map (either (Left . f) Right) ds)+ _ -> e+ writeExp :: Exp -> Math () writeExp (ENumber s) = tell =<< getTeXMathM s writeExp (EGrouped es) = tellGroup (mapM_ writeExp es)@@ -287,11 +302,11 @@ xs -> tell $ txtcmd (Grouped xs) writeExp (EStyled TextNormal [EStyled TextBold es]) = do tell [ControlSeq "\\mathbf"]- tellGroup $ mapM_ writeExp $ everywhere (mkT (fromUnicode TextBold)) es+ tellGroup $ mapM_ (writeExp . fromUnicodeExp TextBold) es writeExp (EStyled ttype es) = do txtcmd <- (flip S.getLaTeXTextCommand ttype) <$> asks mathEnv tell [ControlSeq txtcmd]- tellGroup (mapM_ writeExp $ everywhere (mkT (fromUnicode ttype)) es)+ tellGroup (mapM_ (writeExp . fromUnicodeExp ttype) es) writeExp (EArray as rows) | S.isRLSequence as = do env <- asks mathEnv@@ -350,7 +365,8 @@ let diacmd = case e1 of ESymbol stype a | stype `elem` [Accent, TOver, TUnder]- -> S.getDiacriticalCommand pos a+ -> (if isNarrow b then narrowDiacritical else id)+ <$> S.getDiacriticalCommand pos a _ -> Nothing case diacmd of Just cmd -> do@@ -458,6 +474,25 @@ isOperator (EMathOperator _) = True isOperator (ESymbol Op _) = True isOperator _ = False++-- | True if the expression is a single character wide, so that+-- narrow accent commands like \vec are preferable to wide ones+-- like \overrightarrow.+isNarrow :: Exp -> Bool+isNarrow (EIdentifier t) = T.length t == 1+isNarrow (ENumber t) = T.length t == 1+isNarrow (ESymbol _ t) = T.length t == 1+isNarrow (EGrouped [x]) = isNarrow x+isNarrow (EStyled _ [x]) = isNarrow x+isNarrow _ = False++-- | Preferred variants of wide accent commands for single-character+-- bases.+narrowDiacritical :: T.Text -> T.Text+narrowDiacritical "\\overrightarrow" = "\\vec"+narrowDiacritical "\\widetilde" = "\\tilde"+narrowDiacritical "\\widehat" = "\\hat"+narrowDiacritical cmd = cmd removeOuterGroup :: [Exp] -> [Exp] removeOuterGroup [EGrouped es] = es
src/Text/TeXMath/Writers/Typst.hs view
@@ -26,7 +26,6 @@ import Text.TeXMath.Types import qualified Text.TeXMath.Shared as S import qualified Typst.Symbols as TS-import Data.Generics (everywhere, mkT) import Data.Text (Text) import Data.Char (isDigit, isAlpha, isAscii) import Data.Maybe (fromMaybe)@@ -38,7 +37,7 @@ -- | Transforms an expression tree to equivalent Typst writeTypst :: DisplayType -> [Exp] -> Text writeTypst dt exprs =- writeExps $ everywhere (mkT $ S.handleDownup dt) exprs+ writeExps $ map (S.everywhereExp (S.handleDownup dt)) exprs writeExps :: [Exp] -> Text writeExps = go . map writeExp
test/reader/mml/complex3.test view
@@ -19392,9 +19392,9 @@ ] , [ [ EGrouped [ ENumber "5"- , ESpace (7 % 100)+ , ESpace (7227 % 2000) , EGrouped [ ENumber "24" , ESymbol Pun "!" ]- , ESpace (7 % 100)+ , ESpace (7227 % 2000) , ESuper (EIdentifier "x") (ENumber "6") ] ]
test/reader/mml/mspace1.test view
@@ -18,9 +18,9 @@ </mrow> </math> >>> native [ EIdentifier "x"-, ESpace (58 % 25)+, ESpace (43 % 100) , EIdentifier "M"-, ESpace (58 % 25)+, ESpace (43 % 100) , EIdentifier "x" , ESpace (0 % 1) ]
test/reader/mml/mspacestruts2.test view
@@ -31,7 +31,8 @@ >>> native [ EFraction NormalFrac- (EGrouped [ EIdentifier "x" , ESpace (7 % 20) , EIdentifier "y" ])+ (EGrouped+ [ EIdentifier "x" , ESpace (569 % 200) , EIdentifier "y" ]) (ENumber "2") , ESymbol Bin "+" , EFraction
+ test/reader/omml/sym.test view
@@ -0,0 +1,9 @@+<<< omml+<m:oMath xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">+ <m:r><w:sym w:font="Symbol" w:char="F062"/></m:r>+ <m:r><w:sym w:font="Symbol" w:char="f062"/></m:r>+ <m:r><w:sym w:font="Symbol" w:char="FFFFFFFF"/></m:r>+ <m:r><w:sym w:char="F062"/></m:r>+</m:oMath>+>>> native+[ EIdentifier "\946" , EIdentifier "\946" ]
+ test/reader/tex/array_column_specs.test view
@@ -0,0 +1,20 @@+<<< tex+\begin{array}{p{2cm}|>{\bf}c<{x}m{0.4\textwidth}r}+a & b & c & d \\+e & f & g & h+\end{array}+>>> native+[ EArray+ [ AlignLeft , AlignCenter , AlignLeft , AlignRight ]+ [ [ [ EIdentifier "a" ]+ , [ EIdentifier "b" ]+ , [ EIdentifier "c" ]+ , [ EIdentifier "d" ]+ ]+ , [ [ EIdentifier "e" ]+ , [ EIdentifier "f" ]+ , [ EIdentifier "g" ]+ , [ EIdentifier "h" ]+ ]+ ]+]
+ test/reader/tex/macros_escaped_braces.test view
@@ -0,0 +1,13 @@+<<< tex+\newcommand{\set}[1]{\{#1\}}+\newcommand{\lbr}{\{}+\newcommand{\abc}{5}++\set{a} + \lbr \abc+>>> native+[ EGrouped+ [ ESymbol Open "{" , EIdentifier "a" , ESymbol Close "}" ]+, ESymbol Bin "+"+, ESymbol Open "{"+, ENumber "5"+]
+ test/reader/tex/macros_nested_env.test view
@@ -0,0 +1,20 @@+<<< tex+\newenvironment{brak}[1]{\langle #1:}{:#1\rangle}+\begin{brak}{a} x \begin{brak}{b} y \end{brak} z \end{brak}+>>> native+[ ESymbol Open "\10216"+, EIdentifier "a"+, ESymbol Rel ":"+, EIdentifier "x"+, ESymbol Open "\10216"+, EIdentifier "b"+, ESymbol Rel ":"+, EIdentifier "y"+, ESymbol Rel ":"+, EIdentifier "b"+, ESymbol Close "\10217"+, EIdentifier "z"+, ESymbol Rel ":"+, EIdentifier "a"+, ESymbol Close "\10217"+]
+ test/regression/296.test view
@@ -0,0 +1,16 @@+<<< tex+a`b x\"y p``q+>>> mml+<?xml version='1.0' ?>+<math display="block" xmlns="http://www.w3.org/1998/Math/MathML">+ <mrow>+ <mi>a</mi>+ <mtext mathvariant="normal">‘</mtext>+ <mi>b</mi>+ <mi>x</mi>+ <mtext mathvariant="normal">ÿ</mtext>+ <mi>p</mi>+ <mtext mathvariant="normal">“</mtext>+ <mi>q</mi>+ </mrow>+</math>
+ test/regression/297.test view
@@ -0,0 +1,4 @@+<<< tex+\text{say "hi"} + \text{a\textbackslash b}+>>> eqn+roman "say \"hi\"" + roman "a\[rs]b"
test/writer/eqn/complex3.test view
@@ -7896,6 +7896,6 @@ ccol{ {x = {y + z}} above {= {k + m}} } }} above {matrix{ lcol{ {roman "College Algebra " roman "Second Edition"} above {roman "James Stewart " roman "McMaster Universitiy"} above {roman "Lothar Redlin" roman " Pennsylvania State University"} above {roman "Saleem Watson" roman " California State University, Long Beach"} above {roman "Copyright 1996, ISBN 0 534-33983-2"} above {roman "Brooks/Cole Publishing Company"} above {roman "An International Thomson Publishing Company"} }-} ~} above {left { {1 over 2} over {1 over 2} "↑" sum from 1 to 2 right }} above {left 〈 {1 over 2} over {1 over 2} "|" sum from 1 to 2 right 〉} above {left ⌈ {1 over 2} over {1 over 2} "|" sum from 1 to 2 right ⌉} above {left "" "⇓" left "" {1 over 2} over {1 over 2} "↕" sum from 1 to 2 right "" "⇓" right ""} above {left [ {1 over 2} over {1 over 2} right ]} above {left ( {1 over 2} over {1 over 2} right )} above {left { {1 over 2} over {1 over 2} right }} above {left 〈 {1 over 2} over {1 over 2} right 〉} above {left ⌊ {1 over 2} over {1 over 2} right ⌋} above {left ⌈ {1 over 2} over {1 over 2} right ⌉} above {left "" "↑" {1 over 2} over {1 over 2} "↑" right ""} above {left "" "↓" {1 over 2} over {1 over 2} "↓" right ""} above {left "" "↕" {1 over 2} over {1 over 2} "↕" right ""} above {left "" "⇑" {1 over 2} over {1 over 2} "⇑" right ""} above {left "" "⇓" {1 over 2} over {1 over 2} "⇓" right ""} above {left "" "⇕" {1 over 2} over {1 over 2} "⇕" right ""} above {{1 over 2} over {1 over 2}} above {left \arrowvert {1 over 2} over {1 over 2} right \arrowvert} above {left \Arrowvert {1 over 2} over {1 over 2} right \Arrowvert} above {left \bracevert {1 over 2} over {1 over 2} right \bracevert} above {left | {1 over 2} over {1 over 2} right |} above {left | {1 over 2} over {1 over 2} right |} above {left | {1 over 2} over {1 over 2} right |} above {left "" "∥" {1 over 2} over {1 over 2} "∥" right ""} above {left "" "∥" {1 over 2} over {1 over 2} "∥" right ""} above {left "" "/" {1 over 2} over {1 over 2} "/" right ""} above {left "" "\" {1 over 2} over {1 over 2} "\" right ""} above {left ⎱ {1 over 2} over {1 over 2} right ⎰} above {left \lgroup {1 over 2} over {1 over 2} right \rgroup} above {left ⌞ {1 over 2} over {1 over 2} right ⌟} above {left ⌜ {1 over 2} over {1 over 2} right ⌝} above {A <- from ^ to {n + mu - 1} B -> from T to {n +- i - 1} C} above {1 over {sqrt 2 + 1 over {sqrt 3 + 1 over {sqrt 4 + 1 over {sqrt 5 + 1 over {sqrt 6 + ...}}}}}} above {1 over {sqrt 2 + 1 over {sqrt 3 + 1 over {sqrt 4 + 1 over {sqrt 5 + 1 over {sqrt 6 + ...}}}}}} above {left ( {sin theta} over M right ⌋} above {left ( {sin theta} over M right ⌋} above {left ( {sin theta} over M right ⌋} above {left ( {sin theta} over M right ⌋} above {left ( {sin theta} over M right ⌋} above {left ( {sin theta} over M right ⌋} above {left ( {sin theta} over M right ⌋} above {left ( {sin theta} over M right ⌋} above {left ( {sin theta} over M right ⌋} above {{sin theta} over M} above {{sin theta} over M} above {{sin theta} over M} above {{sin theta} over M} above {{sin theta} over M} above {{sin theta} over M} above {{sin theta} over M} above {{sin theta} over M} above {{sin theta} over M} }+} ~} above {left { {1 over 2} over {1 over 2} "↑" sum from 1 to 2 right }} above {left 〈 {1 over 2} over {1 over 2} "|" sum from 1 to 2 right 〉} above {left ⌈ {1 over 2} over {1 over 2} "|" sum from 1 to 2 right ⌉} above {left "" "⇓" left "" {1 over 2} over {1 over 2} "↕" sum from 1 to 2 right "" "⇓" right ""} above {left [ {1 over 2} over {1 over 2} right ]} above {left ( {1 over 2} over {1 over 2} right )} above {left { {1 over 2} over {1 over 2} right }} above {left 〈 {1 over 2} over {1 over 2} right 〉} above {left ⌊ {1 over 2} over {1 over 2} right ⌋} above {left ⌈ {1 over 2} over {1 over 2} right ⌉} above {left "" "↑" {1 over 2} over {1 over 2} "↑" right ""} above {left "" "↓" {1 over 2} over {1 over 2} "↓" right ""} above {left "" "↕" {1 over 2} over {1 over 2} "↕" right ""} above {left "" "⇑" {1 over 2} over {1 over 2} "⇑" right ""} above {left "" "⇓" {1 over 2} over {1 over 2} "⇓" right ""} above {left "" "⇕" {1 over 2} over {1 over 2} "⇕" right ""} above {{1 over 2} over {1 over 2}} above {left \arrowvert {1 over 2} over {1 over 2} right \arrowvert} above {left \Arrowvert {1 over 2} over {1 over 2} right \Arrowvert} above {left \bracevert {1 over 2} over {1 over 2} right \bracevert} above {left | {1 over 2} over {1 over 2} right |} above {left | {1 over 2} over {1 over 2} right |} above {left | {1 over 2} over {1 over 2} right |} above {left "" "∥" {1 over 2} over {1 over 2} "∥" right ""} above {left "" "∥" {1 over 2} over {1 over 2} "∥" right ""} above {left "" "/" {1 over 2} over {1 over 2} "/" right ""} above {left "" "\[rs]" {1 over 2} over {1 over 2} "\[rs]" right ""} above {left ⎱ {1 over 2} over {1 over 2} right ⎰} above {left \lgroup {1 over 2} over {1 over 2} right \rgroup} above {left ⌞ {1 over 2} over {1 over 2} right ⌟} above {left ⌜ {1 over 2} over {1 over 2} right ⌝} above {A <- from ^ to {n + mu - 1} B -> from T to {n +- i - 1} C} above {1 over {sqrt 2 + 1 over {sqrt 3 + 1 over {sqrt 4 + 1 over {sqrt 5 + 1 over {sqrt 6 + ...}}}}}} above {1 over {sqrt 2 + 1 over {sqrt 3 + 1 over {sqrt 4 + 1 over {sqrt 5 + 1 over {sqrt 6 + ...}}}}}} above {left ( {sin theta} over M right ⌋} above {left ( {sin theta} over M right ⌋} above {left ( {sin theta} over M right ⌋} above {left ( {sin theta} over M right ⌋} above {left ( {sin theta} over M right ⌋} above {left ( {sin theta} over M right ⌋} above {left ( {sin theta} over M right ⌋} above {left ( {sin theta} over M right ⌋} above {left ( {sin theta} over M right ⌋} above {{sin theta} over M} above {{sin theta} over M} above {{sin theta} over M} above {{sin theta} over M} above {{sin theta} over M} above {{sin theta} over M} above {{sin theta} over M} above {{sin theta} over M} above {{sin theta} over M} } ccol{ {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {x = {1 + y}} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} above {""} } }
test/writer/eqn/ms-15.test view
@@ -4,4 +4,4 @@ , EText TextNormal "\8220string\"" ] >>> eqn-roman ""string”" = roman "“string""+roman "\"string”" = roman "“string\""
test/writer/eqn/ms-16.test view
@@ -4,4 +4,4 @@ , EText TextNormal "\8220string\8221" ] >>> eqn-roman ""string"" = roman "“string”"+roman "\"string\"" = roman "“string”"
test/writer/eqn/sans-serif-bold-italic.test view
@@ -28,5 +28,5 @@ ] >>> eqn {matrix{-lcol{ {roman "!"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} }+lcol{ {roman "!\"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\[rs]]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} } }}
test/writer/eqn/sans-serif-bold.test view
@@ -28,5 +28,5 @@ ] >>> eqn {matrix{-lcol{ {roman "!"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} }+lcol{ {roman "!\"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\[rs]]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} } }}
test/writer/eqn/sans-serif-italic.test view
@@ -28,5 +28,5 @@ ] >>> eqn {matrix{-lcol{ {roman "!"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} }+lcol{ {roman "!\"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\[rs]]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} } }}
test/writer/eqn/sans-serif.test view
@@ -28,5 +28,5 @@ ] >>> eqn {matrix{-lcol{ {roman "!"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} }+lcol{ {roman "!\"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\[rs]]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} } }}
test/writer/eqn/serif-bold-italic.test view
@@ -28,5 +28,5 @@ ] >>> eqn bold italic {matrix{-lcol{ {roman "!"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} }+lcol{ {roman "!\"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\[rs]]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} } }}
test/writer/eqn/serif-bold.test view
@@ -28,5 +28,5 @@ ] >>> eqn bold {matrix{-lcol{ {roman "!"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} }+lcol{ {roman "!\"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\[rs]]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} } }}
test/writer/eqn/serif-italic.test view
@@ -28,5 +28,5 @@ ] >>> eqn italic {matrix{-lcol{ {roman "!"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} }+lcol{ {roman "!\"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\[rs]]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} } }}
test/writer/eqn/serif.test view
@@ -25,5 +25,5 @@ ] >>> eqn matrix{-lcol{ {roman "!"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} }+lcol{ {roman "!\"#$%&'()*+,-./0123456789:;<=>?"} above {roman "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\[rs]]^_"} above {roman "`abcdefghijklmnopqrstuvwxyz{|}~"} above {roman "ıȷ"} above {roman "ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡϴΣΤΥΦΧΨΩ∇"} above {roman "αβγδεζηθικλμνξοπρςστυφχψω∂"} above {roman "ϵϑϰϕϱϖϜϝ"} above {roman "±·×÷‘’“”•−∓∕∗∙≠≤≥⋅"} } }
+ test/writer/omml/scaled_delims.test view
@@ -0,0 +1,27 @@+<<< native+[ EScaled (6 % 5) (ESymbol Open "(")+, EIdentifier "x"+, EScaled (9 % 5) (ESymbol Close ")")+]+>>> omml+<?xml version='1.0' ?>+<m:oMathPara>+ <m:oMathParaPr>+ <m:jc m:val="center" />+ </m:oMathParaPr>+ <m:oMath>+ <m:d>+ <m:dPr>+ <m:begChr m:val="(" />+ <m:sepChr m:val="" />+ <m:endChr m:val=")" />+ <m:grow />+ </m:dPr>+ <m:e>+ <m:r>+ <m:t>x</m:t>+ </m:r>+ </m:e>+ </m:d>+ </m:oMath>+</m:oMathPara>
test/writer/tex/accents1.test view
@@ -88,7 +88,7 @@ >>> tex \begin{array}{l} \text{default: (accent=true)} \\-{\overset{'}{H}\hat{H}\overset{\_}{H}\grave{H}\overset{\sim}{H}\overset{¨}{H}\overline{H}\acute{H}\overset{¸}{H}\widehat{H}\check{H}\breve{H}\overset{˙}{H}\overset{˚}{H}\widetilde{H}\overset{˝}{H}\widehat{H}\overset{̑}{H}\bar{H}\dddot{H}\ddddot{H}\overset{\leftarrow}{H}\overset{\rightarrow}{H}\overset{\leftrightarrow}{H}\overset{\leftharpoonup}{H}\overset{\leftharpoondown}{H}\overset{\rightharpoonup}{H}\overset{\rightharpoondown}{H}\overbracket{H}\overset{⎵}{H}\overset{⏜}{H}\overset{⏝}{H}\overbrace{H}\overset{\underbrace{}}{H}\overset{⥎}{H}\overset{⥐}{H}} \\+{\overset{'}{H}\hat{H}\overset{\_}{H}\grave{H}\overset{\sim}{H}\overset{¨}{H}\overline{H}\acute{H}\overset{¸}{H}\hat{H}\check{H}\breve{H}\overset{˙}{H}\overset{˚}{H}\tilde{H}\overset{˝}{H}\hat{H}\overset{̑}{H}\bar{H}\dddot{H}\ddddot{H}\overset{\leftarrow}{H}\overset{\rightarrow}{H}\overset{\leftrightarrow}{H}\overset{\leftharpoonup}{H}\overset{\leftharpoondown}{H}\overset{\rightharpoonup}{H}\overset{\rightharpoondown}{H}\overbracket{H}\overset{⎵}{H}\overset{⏜}{H}\overset{⏝}{H}\overbrace{H}\overset{\underbrace{}}{H}\overset{⥎}{H}\overset{⥐}{H}} \\ \text{accent=false:} \\-{\overset{'}{H}\overset{\hat{}}{H}\overset{\_}{H}\overset{`}{H}\overset{\sim}{H}\overset{¨}{H}\overset{¯}{H}\overset{´}{H}\overset{¸}{H}\overset{\hat{}}{H}\overset{ˇ}{H}\overset{˘}{H}\overset{˙}{H}\overset{˚}{H}\overset{˜}{H}\overset{˝}{H}\widehat{H}\overset{̑}{H}\overset{‾}{H}\dddot{H}\ddddot{H}\overset{\leftarrow}{H}\overset{\rightarrow}{H}\overset{\leftrightarrow}{H}\overset{\leftharpoonup}{H}\overset{\leftharpoondown}{H}\overset{\rightharpoonup}{H}\overset{\rightharpoondown}{H}\overbracket{H}\overset{⎵}{H}\overset{⏜}{H}\overset{⏝}{H}\overbrace{H}\overset{\underbrace{}}{H}\overset{⥎}{H}\overset{⥐}{H}}+{\overset{'}{H}\overset{\hat{}}{H}\overset{\_}{H}\overset{`}{H}\overset{\sim}{H}\overset{¨}{H}\overset{¯}{H}\overset{´}{H}\overset{¸}{H}\overset{\hat{}}{H}\overset{ˇ}{H}\overset{˘}{H}\overset{˙}{H}\overset{˚}{H}\overset{˜}{H}\overset{˝}{H}\hat{H}\overset{̑}{H}\overset{‾}{H}\dddot{H}\ddddot{H}\overset{\leftarrow}{H}\overset{\rightarrow}{H}\overset{\leftrightarrow}{H}\overset{\leftharpoonup}{H}\overset{\leftharpoondown}{H}\overset{\rightharpoonup}{H}\overset{\rightharpoondown}{H}\overbracket{H}\overset{⎵}{H}\overset{⏜}{H}\overset{⏝}{H}\overbrace{H}\overset{\underbrace{}}{H}\overset{⥎}{H}\overset{⥐}{H}} \end{array}
test/writer/tex/accents2.test view
@@ -88,7 +88,7 @@ >>> tex \begin{array}{l} \text{default: (accent=true)} \\-{\overset{'}{x}\hat{x}\overset{\_}{x}\grave{x}\overset{\sim}{x}\overset{¨}{x}\overline{x}\acute{x}\overset{¸}{x}\widehat{x}\check{x}\breve{x}\overset{˙}{x}\overset{˚}{x}\widetilde{x}\overset{˝}{x}\widehat{x}\overset{̑}{x}\bar{x}\dddot{x}\ddddot{x}\overset{\leftarrow}{x}\overset{\rightarrow}{x}\overset{\leftrightarrow}{x}\overset{\leftharpoonup}{x}\overset{\leftharpoondown}{x}\overset{\rightharpoonup}{x}\overset{\rightharpoondown}{x}\overbracket{x}\overset{⎵}{x}\overset{⏜}{x}\overset{⏝}{x}\overbrace{x}\overset{\underbrace{}}{x}\overset{⥎}{x}\overset{⥐}{x}} \\+{\overset{'}{x}\hat{x}\overset{\_}{x}\grave{x}\overset{\sim}{x}\overset{¨}{x}\overline{x}\acute{x}\overset{¸}{x}\hat{x}\check{x}\breve{x}\overset{˙}{x}\overset{˚}{x}\tilde{x}\overset{˝}{x}\hat{x}\overset{̑}{x}\bar{x}\dddot{x}\ddddot{x}\overset{\leftarrow}{x}\overset{\rightarrow}{x}\overset{\leftrightarrow}{x}\overset{\leftharpoonup}{x}\overset{\leftharpoondown}{x}\overset{\rightharpoonup}{x}\overset{\rightharpoondown}{x}\overbracket{x}\overset{⎵}{x}\overset{⏜}{x}\overset{⏝}{x}\overbrace{x}\overset{\underbrace{}}{x}\overset{⥎}{x}\overset{⥐}{x}} \\ \text{accent=false:} \\-{\overset{'}{x}\overset{\hat{}}{x}\overset{\_}{x}\overset{`}{x}\overset{\sim}{x}\overset{¨}{x}\overset{¯}{x}\overset{´}{x}\overset{¸}{x}\overset{\hat{}}{x}\overset{ˇ}{x}\overset{˘}{x}\overset{˙}{x}\overset{˚}{x}\overset{˜}{x}\overset{˝}{x}\widehat{x}\overset{̑}{x}\overset{‾}{x}\dddot{x}\ddddot{x}\overset{\leftarrow}{x}\overset{\rightarrow}{x}\overset{\leftrightarrow}{x}\overset{\leftharpoonup}{x}\overset{\leftharpoondown}{x}\overset{\rightharpoonup}{x}\overset{\rightharpoondown}{x}\overbracket{x}\overset{⎵}{x}\overset{⏜}{x}\overset{⏝}{x}\overbrace{x}\overset{\underbrace{}}{x}\overset{⥎}{x}\overset{⥐}{x}}+{\overset{'}{x}\overset{\hat{}}{x}\overset{\_}{x}\overset{`}{x}\overset{\sim}{x}\overset{¨}{x}\overset{¯}{x}\overset{´}{x}\overset{¸}{x}\overset{\hat{}}{x}\overset{ˇ}{x}\overset{˘}{x}\overset{˙}{x}\overset{˚}{x}\overset{˜}{x}\overset{˝}{x}\hat{x}\overset{̑}{x}\overset{‾}{x}\dddot{x}\ddddot{x}\overset{\leftarrow}{x}\overset{\rightarrow}{x}\overset{\leftrightarrow}{x}\overset{\leftharpoonup}{x}\overset{\leftharpoondown}{x}\overset{\rightharpoonup}{x}\overset{\rightharpoondown}{x}\overbracket{x}\overset{⎵}{x}\overset{⏜}{x}\overset{⏝}{x}\overbrace{x}\overset{\underbrace{}}{x}\overset{⥎}{x}\overset{⥐}{x}} \end{array}
test/writer/tex/accents5.test view
@@ -295,7 +295,7 @@ >>> tex \begin{array}{l} \text{default: (accent=true)} \\-{\underset{'}{\overset{'}{H}}\underset{\hat{}}{\hat{H}}\underline{\overset{\_}{H}}\underset{`}{\grave{H}}\underset{\sim}{\overset{\sim}{H}}\underset{¨}{\overset{¨}{H}}\underset{¯}{\overline{H}}\underset{´}{\acute{H}}\underset{¸}{\overset{¸}{H}}\underset{\hat{}}{\widehat{H}}\underset{ˇ}{\check{H}}\underset{˘}{\breve{H}}\underset{˙}{\overset{˙}{H}}\underset{˚}{\overset{˚}{H}}\underset{˜}{\widetilde{H}}\underset{˝}{\overset{˝}{H}}\underset{\hat{}}{\widehat{H}}\underset{̑}{\overset{̑}{H}}\underset{‾}{\bar{H}}\underset{\dddot{}}{\dddot{H}}\underset{\ddddot{}}{\ddddot{H}}\underset{\leftarrow}{\overset{\leftarrow}{H}}\underset{\rightarrow}{\overset{\rightarrow}{H}}\underset{\leftrightarrow}{\overset{\leftrightarrow}{H}}\underset{\leftharpoonup}{\overset{\leftharpoonup}{H}}\underset{\leftharpoondown}{\overset{\leftharpoondown}{H}}\underset{\rightharpoonup}{\overset{\rightharpoonup}{H}}\underset{\rightharpoondown}{\overset{\rightharpoondown}{H}}\underset{⎴}{\overbracket{H}}\underbracket{\overset{⎵}{H}}\underset{⏜}{\overset{⏜}{H}}\underset{⏝}{\overset{⏝}{H}}\underset{\overbrace{}}{\overbrace{H}}\underbrace{\overset{\underbrace{}}{H}}\underset{⥎}{\overset{⥎}{H}}\underset{⥐}{\overset{⥐}{H}}} \\+{\underset{'}{\overset{'}{H}}\underset{\hat{}}{\hat{H}}\underline{\overset{\_}{H}}\underset{`}{\grave{H}}\underset{\sim}{\overset{\sim}{H}}\underset{¨}{\overset{¨}{H}}\underset{¯}{\overline{H}}\underset{´}{\acute{H}}\underset{¸}{\overset{¸}{H}}\underset{\hat{}}{\hat{H}}\underset{ˇ}{\check{H}}\underset{˘}{\breve{H}}\underset{˙}{\overset{˙}{H}}\underset{˚}{\overset{˚}{H}}\underset{˜}{\tilde{H}}\underset{˝}{\overset{˝}{H}}\underset{\hat{}}{\hat{H}}\underset{̑}{\overset{̑}{H}}\underset{‾}{\bar{H}}\underset{\dddot{}}{\dddot{H}}\underset{\ddddot{}}{\ddddot{H}}\underset{\leftarrow}{\overset{\leftarrow}{H}}\underset{\rightarrow}{\overset{\rightarrow}{H}}\underset{\leftrightarrow}{\overset{\leftrightarrow}{H}}\underset{\leftharpoonup}{\overset{\leftharpoonup}{H}}\underset{\leftharpoondown}{\overset{\leftharpoondown}{H}}\underset{\rightharpoonup}{\overset{\rightharpoonup}{H}}\underset{\rightharpoondown}{\overset{\rightharpoondown}{H}}\underset{⎴}{\overbracket{H}}\underbracket{\overset{⎵}{H}}\underset{⏜}{\overset{⏜}{H}}\underset{⏝}{\overset{⏝}{H}}\underset{\overbrace{}}{\overbrace{H}}\underbrace{\overset{\underbrace{}}{H}}\underset{⥎}{\overset{⥎}{H}}\underset{⥐}{\overset{⥐}{H}}} \\ \text{accent=false:} \\-{\underset{'}{\overset{'}{H}}\underset{\hat{}}{\overset{\hat{}}{H}}\underset{\_}{\overset{\_}{H}}\underset{`}{\overset{`}{H}}\underset{\sim}{\overset{\sim}{H}}\underset{¨}{\overset{¨}{H}}\underset{¯}{\overset{¯}{H}}\underset{´}{\overset{´}{H}}\underset{¸}{\overset{¸}{H}}\underset{\hat{}}{\overset{\hat{}}{H}}\underset{ˇ}{\overset{ˇ}{H}}\underset{˘}{\overset{˘}{H}}\underset{˙}{\overset{˙}{H}}\underset{˚}{\overset{˚}{H}}\underset{˜}{\overset{˜}{H}}\underset{˝}{\overset{˝}{H}}\underset{\hat{}}{\widehat{H}}\underset{̑}{\overset{̑}{H}}\underset{‾}{\overset{‾}{H}}\underset{\dddot{}}{\dddot{H}}\underset{\ddddot{}}{\ddddot{H}}\underset{\leftarrow}{\overset{\leftarrow}{H}}\underset{\rightarrow}{\overset{\rightarrow}{H}}\underset{\leftrightarrow}{\overset{\leftrightarrow}{H}}\underset{\leftharpoonup}{\overset{\leftharpoonup}{H}}\underset{\leftharpoondown}{\overset{\leftharpoondown}{H}}\underset{\rightharpoonup}{\overset{\rightharpoonup}{H}}\underset{\rightharpoondown}{\overset{\rightharpoondown}{H}}\underset{⎴}{\overbracket{H}}\underbracket{\overset{⎵}{H}}\underset{⏜}{\overset{⏜}{H}}\underset{⏝}{\overset{⏝}{H}}\underset{\overbrace{}}{\overbrace{H}}\underbrace{\overset{\underbrace{}}{H}}\underset{⥎}{\overset{⥎}{H}}\underset{⥐}{\overset{⥐}{H}}}+{\underset{'}{\overset{'}{H}}\underset{\hat{}}{\overset{\hat{}}{H}}\underset{\_}{\overset{\_}{H}}\underset{`}{\overset{`}{H}}\underset{\sim}{\overset{\sim}{H}}\underset{¨}{\overset{¨}{H}}\underset{¯}{\overset{¯}{H}}\underset{´}{\overset{´}{H}}\underset{¸}{\overset{¸}{H}}\underset{\hat{}}{\overset{\hat{}}{H}}\underset{ˇ}{\overset{ˇ}{H}}\underset{˘}{\overset{˘}{H}}\underset{˙}{\overset{˙}{H}}\underset{˚}{\overset{˚}{H}}\underset{˜}{\overset{˜}{H}}\underset{˝}{\overset{˝}{H}}\underset{\hat{}}{\hat{H}}\underset{̑}{\overset{̑}{H}}\underset{‾}{\overset{‾}{H}}\underset{\dddot{}}{\dddot{H}}\underset{\ddddot{}}{\ddddot{H}}\underset{\leftarrow}{\overset{\leftarrow}{H}}\underset{\rightarrow}{\overset{\rightarrow}{H}}\underset{\leftrightarrow}{\overset{\leftrightarrow}{H}}\underset{\leftharpoonup}{\overset{\leftharpoonup}{H}}\underset{\leftharpoondown}{\overset{\leftharpoondown}{H}}\underset{\rightharpoonup}{\overset{\rightharpoonup}{H}}\underset{\rightharpoondown}{\overset{\rightharpoondown}{H}}\underset{⎴}{\overbracket{H}}\underbracket{\overset{⎵}{H}}\underset{⏜}{\overset{⏜}{H}}\underset{⏝}{\overset{⏝}{H}}\underset{\overbrace{}}{\overbrace{H}}\underbrace{\overset{\underbrace{}}{H}}\underset{⥎}{\overset{⥎}{H}}\underset{⥐}{\overset{⥐}{H}}} \end{array}
test/writer/tex/accents6.test view
@@ -295,7 +295,7 @@ >>> tex \begin{array}{l} \text{default: (accent=true)} \\-{\underset{'}{\overset{'}{x}}\underset{\hat{}}{\hat{x}}\underline{\overset{\_}{x}}\underset{`}{\grave{x}}\underset{\sim}{\overset{\sim}{x}}\underset{¨}{\overset{¨}{x}}\underset{¯}{\overline{x}}\underset{´}{\acute{x}}\underset{¸}{\overset{¸}{x}}\underset{\hat{}}{\widehat{x}}\underset{ˇ}{\check{x}}\underset{˘}{\breve{x}}\underset{˙}{\overset{˙}{x}}\underset{˚}{\overset{˚}{x}}\underset{˜}{\widetilde{x}}\underset{˝}{\overset{˝}{x}}\underset{\hat{}}{\widehat{x}}\underset{̑}{\overset{̑}{x}}\underset{‾}{\bar{x}}\underset{\dddot{}}{\dddot{x}}\underset{\ddddot{}}{\ddddot{x}}\underset{\leftarrow}{\overset{\leftarrow}{x}}\underset{\rightarrow}{\overset{\rightarrow}{x}}\underset{\leftrightarrow}{\overset{\leftrightarrow}{x}}\underset{\leftharpoonup}{\overset{\leftharpoonup}{x}}\underset{\leftharpoondown}{\overset{\leftharpoondown}{x}}\underset{\rightharpoonup}{\overset{\rightharpoonup}{x}}\underset{\rightharpoondown}{\overset{\rightharpoondown}{x}}\underset{⎴}{\overbracket{x}}\underbracket{\overset{⎵}{x}}\underset{⏜}{\overset{⏜}{x}}\underset{⏝}{\overset{⏝}{x}}\underset{\overbrace{}}{\overbrace{x}}\underbrace{\overset{\underbrace{}}{x}}\underset{⥎}{\overset{⥎}{x}}\underset{⥐}{\overset{⥐}{x}}} \\+{\underset{'}{\overset{'}{x}}\underset{\hat{}}{\hat{x}}\underline{\overset{\_}{x}}\underset{`}{\grave{x}}\underset{\sim}{\overset{\sim}{x}}\underset{¨}{\overset{¨}{x}}\underset{¯}{\overline{x}}\underset{´}{\acute{x}}\underset{¸}{\overset{¸}{x}}\underset{\hat{}}{\hat{x}}\underset{ˇ}{\check{x}}\underset{˘}{\breve{x}}\underset{˙}{\overset{˙}{x}}\underset{˚}{\overset{˚}{x}}\underset{˜}{\tilde{x}}\underset{˝}{\overset{˝}{x}}\underset{\hat{}}{\hat{x}}\underset{̑}{\overset{̑}{x}}\underset{‾}{\bar{x}}\underset{\dddot{}}{\dddot{x}}\underset{\ddddot{}}{\ddddot{x}}\underset{\leftarrow}{\overset{\leftarrow}{x}}\underset{\rightarrow}{\overset{\rightarrow}{x}}\underset{\leftrightarrow}{\overset{\leftrightarrow}{x}}\underset{\leftharpoonup}{\overset{\leftharpoonup}{x}}\underset{\leftharpoondown}{\overset{\leftharpoondown}{x}}\underset{\rightharpoonup}{\overset{\rightharpoonup}{x}}\underset{\rightharpoondown}{\overset{\rightharpoondown}{x}}\underset{⎴}{\overbracket{x}}\underbracket{\overset{⎵}{x}}\underset{⏜}{\overset{⏜}{x}}\underset{⏝}{\overset{⏝}{x}}\underset{\overbrace{}}{\overbrace{x}}\underbrace{\overset{\underbrace{}}{x}}\underset{⥎}{\overset{⥎}{x}}\underset{⥐}{\overset{⥐}{x}}} \\ \text{accent=false:} \\-{\underset{'}{\overset{'}{x}}\underset{\hat{}}{\overset{\hat{}}{x}}\underset{\_}{\overset{\_}{x}}\underset{`}{\overset{`}{x}}\underset{\sim}{\overset{\sim}{x}}\underset{¨}{\overset{¨}{x}}\underset{¯}{\overset{¯}{x}}\underset{´}{\overset{´}{x}}\underset{¸}{\overset{¸}{x}}\underset{\hat{}}{\overset{\hat{}}{x}}\underset{ˇ}{\overset{ˇ}{x}}\underset{˘}{\overset{˘}{x}}\underset{˙}{\overset{˙}{x}}\underset{˚}{\overset{˚}{x}}\underset{˜}{\overset{˜}{x}}\underset{˝}{\overset{˝}{x}}\underset{\hat{}}{\widehat{x}}\underset{̑}{\overset{̑}{x}}\underset{‾}{\overset{‾}{x}}\underset{\dddot{}}{\dddot{x}}\underset{\ddddot{}}{\ddddot{x}}\underset{\leftarrow}{\overset{\leftarrow}{x}}\underset{\rightarrow}{\overset{\rightarrow}{x}}\underset{\leftrightarrow}{\overset{\leftrightarrow}{x}}\underset{\leftharpoonup}{\overset{\leftharpoonup}{x}}\underset{\leftharpoondown}{\overset{\leftharpoondown}{x}}\underset{\rightharpoonup}{\overset{\rightharpoonup}{x}}\underset{\rightharpoondown}{\overset{\rightharpoondown}{x}}\underset{⎴}{\overbracket{x}}\underbracket{\overset{⎵}{x}}\underset{⏜}{\overset{⏜}{x}}\underset{⏝}{\overset{⏝}{x}}\underset{\overbrace{}}{\overbrace{x}}\underbrace{\overset{\underbrace{}}{x}}\underset{⥎}{\overset{⥎}{x}}\underset{⥐}{\overset{⥐}{x}}}+{\underset{'}{\overset{'}{x}}\underset{\hat{}}{\overset{\hat{}}{x}}\underset{\_}{\overset{\_}{x}}\underset{`}{\overset{`}{x}}\underset{\sim}{\overset{\sim}{x}}\underset{¨}{\overset{¨}{x}}\underset{¯}{\overset{¯}{x}}\underset{´}{\overset{´}{x}}\underset{¸}{\overset{¸}{x}}\underset{\hat{}}{\overset{\hat{}}{x}}\underset{ˇ}{\overset{ˇ}{x}}\underset{˘}{\overset{˘}{x}}\underset{˙}{\overset{˙}{x}}\underset{˚}{\overset{˚}{x}}\underset{˜}{\overset{˜}{x}}\underset{˝}{\overset{˝}{x}}\underset{\hat{}}{\hat{x}}\underset{̑}{\overset{̑}{x}}\underset{‾}{\overset{‾}{x}}\underset{\dddot{}}{\dddot{x}}\underset{\ddddot{}}{\ddddot{x}}\underset{\leftarrow}{\overset{\leftarrow}{x}}\underset{\rightarrow}{\overset{\rightarrow}{x}}\underset{\leftrightarrow}{\overset{\leftrightarrow}{x}}\underset{\leftharpoonup}{\overset{\leftharpoonup}{x}}\underset{\leftharpoondown}{\overset{\leftharpoondown}{x}}\underset{\rightharpoonup}{\overset{\rightharpoonup}{x}}\underset{\rightharpoondown}{\overset{\rightharpoondown}{x}}\underset{⎴}{\overbracket{x}}\underbracket{\overset{⎵}{x}}\underset{⏜}{\overset{⏜}{x}}\underset{⏝}{\overset{⏝}{x}}\underset{\overbrace{}}{\overbrace{x}}\underbrace{\overset{\underbrace{}}{x}}\underset{⥎}{\overset{⥎}{x}}\underset{⥐}{\overset{⥐}{x}}} \end{array}
test/writer/tex/complex3.test view
@@ -8079,7 +8079,7 @@ {\text{testing }\begin{matrix} {\sin\theta} \end{matrix}} & \\-{\widehat{a} + \check{b} + \widetilde{c} + \acute{d} + \grave{e} + \breve{f} + \overline{g} + h + \overset{˚}{i} + \overset{˙}{j} + \overset{¨}{k} + \dddot{l} + \ddddot{m} + \overset{\rightarrow}{n}} & \\+{\hat{a} + \check{b} + \tilde{c} + \acute{d} + \grave{e} + \breve{f} + \overline{g} + h + \overset{˚}{i} + \overset{˙}{j} + \overset{¨}{k} + \dddot{l} + \ddddot{m} + \overset{\rightarrow}{n}} & \\ {{f{({g{(x)}})}} = {{\sin^{3}x^{2}} + {{\sin x^{2}}{\sin\left( {\sin x^{2}} \right)}}}} & \\ {\left( {x^{2} + 12} \right) + 1234} & \\ \begin{matrix}
test/writer/tex/divergence.test view
@@ -22,4 +22,4 @@ (EGrouped [ ESymbol Ord "\8706" , EIdentifier "z" ]) ] >>> tex-\nabla \cdot \overrightarrow{v} = \frac{\partial v_{x}}{\partial x} + \frac{\partial v_{y}}{\partial y} + \frac{\partial v_{z}}{\partial z}+\nabla \cdot \vec{v} = \frac{\partial v_{x}}{\partial x} + \frac{\partial v_{y}}{\partial y} + \frac{\partial v_{z}}{\partial z}
test/writer/tex/mover3.test view
@@ -8,4 +8,4 @@ , EOver False (EIdentifier "x") (ESymbol Alpha "\710") ] >>> tex-\widehat{x} \neq \overset{\hat{}}{x} = \overset{\hat{}}{x} = \overset{\hat{}}{x}+\hat{x} \neq \overset{\hat{}}{x} = \overset{\hat{}}{x} = \overset{\hat{}}{x}
test/writer/tex/mover5.test view
@@ -8,4 +8,4 @@ , EOver False (EIdentifier "x") (ESymbol Ord "\732") ] >>> tex-\widetilde{x} \neq \overset{˜}{x} = \overset{˜}{x} = \overset{˜}{x}+\tilde{x} \neq \overset{˜}{x} = \overset{˜}{x} = \overset{˜}{x}
test/writer/tex/tokens.test view
@@ -9,4 +9,4 @@ , EIdentifier "\958" ] >>> tex-\widetilde{\phi}\sqrt{\phi}\frac{\phi}{\xi}\frac{\phi}{\xi}\frac{\phi}{\xi}(\phi)(\phi)\xi+\tilde{\phi}\sqrt{\phi}\frac{\phi}{\xi}\frac{\phi}{\xi}\frac{\phi}{\xi}(\phi)(\phi)\xi
texmath.cabal view
@@ -1,6 +1,6 @@ Name: texmath-Version: 0.13.2.2-Cabal-Version: >= 1.10+Version: 0.13.3+Cabal-Version: 2.0 Build-type: Simple Synopsis: Conversion between math formats. Description: The texmath library provides functions to read@@ -35,11 +35,11 @@ Author: John MacFarlane, Matthew Pickering Maintainer: jgm@berkeley.edu Homepage: http://github.com/jgm/texmath-Extra-source-files: README.md+Extra-doc-files: README.md changelog.md- man/texmath.1.md- man/Makefile man/man1/texmath.1+Extra-source-files: man/texmath.1.md+ man/Makefile server/texmath.html test/writer/mml/*.test test/writer/omml/*.test@@ -109,6 +109,7 @@ Text.TeXMath.Shared Other-modules: Text.TeXMath.Readers.TeX.Commands Paths_texmath+ Autogen-modules: Paths_texmath if impl(ghc >= 6.12) Ghc-Options: -Wall -fno-warn-unused-do-bind else@@ -121,6 +122,7 @@ Default-Language: Haskell2010 Main-is: texmath.hs Other-Modules: Paths_texmath+ Autogen-modules: Paths_texmath Hs-Source-Dirs: extra if impl(ghc >= 6.12) Ghc-Options: -Wall -fno-warn-unused-do-bind