temml 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- package/LICENSE +21 -0
- package/README.md +44 -0
- package/contrib/auto-render/README.md +89 -0
- package/contrib/auto-render/auto-render.js +128 -0
- package/contrib/auto-render/dist/auto-render.js +217 -0
- package/contrib/auto-render/dist/auto-render.min.js +1 -0
- package/contrib/auto-render/splitAtDelimiters.js +84 -0
- package/contrib/auto-render/test/auto-render-spec.js +234 -0
- package/contrib/auto-render/test/auto-render.js +217 -0
- package/contrib/auto-render/test/test_page.html +59 -0
- package/contrib/mhchem/README.md +26 -0
- package/contrib/mhchem/mhchem.js +1705 -0
- package/contrib/mhchem/mhchem.min.js +1 -0
- package/contrib/physics/README.md +20 -0
- package/contrib/physics/physics.js +131 -0
- package/contrib/texvc/README.md +23 -0
- package/contrib/texvc/texvc.js +61 -0
- package/dist/Temml-Asana.css +201 -0
- package/dist/Temml-Latin-Modern.css +216 -0
- package/dist/Temml-Libertinus.css +214 -0
- package/dist/Temml-Local.css +194 -0
- package/dist/Temml-STIX2.css +203 -0
- package/dist/Temml.woff2 +0 -0
- package/dist/temml.cjs +13122 -0
- package/dist/temml.js +11225 -0
- package/dist/temml.min.js +1 -0
- package/dist/temml.mjs +13120 -0
- package/dist/temmlPostProcess.js +70 -0
- package/package.json +34 -0
- package/src/Lexer.js +121 -0
- package/src/MacroExpander.js +437 -0
- package/src/Namespace.js +107 -0
- package/src/ParseError.js +64 -0
- package/src/Parser.js +977 -0
- package/src/Settings.js +49 -0
- package/src/SourceLocation.js +29 -0
- package/src/Style.js +144 -0
- package/src/Token.js +40 -0
- package/src/buildMathML.js +235 -0
- package/src/constants.js +25 -0
- package/src/defineEnvironment.js +25 -0
- package/src/defineFunction.js +69 -0
- package/src/defineMacro.js +11 -0
- package/src/domTree.js +185 -0
- package/src/environments/array.js +791 -0
- package/src/environments/cd.js +252 -0
- package/src/environments.js +8 -0
- package/src/functions/accent.js +127 -0
- package/src/functions/accentunder.js +38 -0
- package/src/functions/arrow.js +204 -0
- package/src/functions/cancelto.js +36 -0
- package/src/functions/char.js +33 -0
- package/src/functions/color.js +253 -0
- package/src/functions/cr.js +46 -0
- package/src/functions/def.js +259 -0
- package/src/functions/delimsizing.js +304 -0
- package/src/functions/enclose.js +193 -0
- package/src/functions/envTag.js +38 -0
- package/src/functions/environment.js +59 -0
- package/src/functions/font.js +123 -0
- package/src/functions/genfrac.js +333 -0
- package/src/functions/hbox.js +29 -0
- package/src/functions/horizBrace.js +32 -0
- package/src/functions/href.js +90 -0
- package/src/functions/html.js +95 -0
- package/src/functions/includegraphics.js +131 -0
- package/src/functions/kern.js +75 -0
- package/src/functions/label.js +29 -0
- package/src/functions/lap.js +75 -0
- package/src/functions/math.js +40 -0
- package/src/functions/mathchoice.js +41 -0
- package/src/functions/mclass.js +201 -0
- package/src/functions/multiscript.js +91 -0
- package/src/functions/not.js +46 -0
- package/src/functions/op.js +338 -0
- package/src/functions/operatorname.js +139 -0
- package/src/functions/ordgroup.js +9 -0
- package/src/functions/phantom.js +73 -0
- package/src/functions/pmb.js +31 -0
- package/src/functions/raise.js +68 -0
- package/src/functions/ref.js +28 -0
- package/src/functions/relax.js +16 -0
- package/src/functions/rule.js +52 -0
- package/src/functions/sizing.js +64 -0
- package/src/functions/smash.js +66 -0
- package/src/functions/sqrt.js +31 -0
- package/src/functions/styling.js +58 -0
- package/src/functions/supsub.js +135 -0
- package/src/functions/symbolsOp.js +53 -0
- package/src/functions/symbolsOrd.js +102 -0
- package/src/functions/symbolsSpacing.js +53 -0
- package/src/functions/tag.js +8 -0
- package/src/functions/text.js +75 -0
- package/src/functions/tip.js +63 -0
- package/src/functions/toggle.js +13 -0
- package/src/functions/verb.js +33 -0
- package/src/functions.js +57 -0
- package/src/linebreaking.js +159 -0
- package/src/macros.js +708 -0
- package/src/mathMLTree.js +175 -0
- package/src/parseNode.js +42 -0
- package/src/parseTree.js +40 -0
- package/src/postProcess.js +57 -0
- package/src/replace.js +225 -0
- package/src/stretchy.js +66 -0
- package/src/svg.js +110 -0
- package/src/symbols.js +972 -0
- package/src/tree.js +50 -0
- package/src/unicodeAccents.js +16 -0
- package/src/unicodeScripts.js +119 -0
- package/src/unicodeSupOrSub.js +108 -0
- package/src/unicodeSymbolBuilder.js +31 -0
- package/src/unicodeSymbols.js +320 -0
- package/src/units.js +109 -0
- package/src/utils.js +109 -0
- package/src/variant.js +103 -0
- package/temml.js +181 -0
@@ -0,0 +1,75 @@
|
|
1
|
+
import defineFunction, { ordargument } from "../defineFunction";
|
2
|
+
import * as mml from "../buildMathML";
|
3
|
+
|
4
|
+
// Non-mathy text, possibly in a font
|
5
|
+
const textFontFamilies = {
|
6
|
+
"\\text": undefined,
|
7
|
+
"\\textrm": "textrm",
|
8
|
+
"\\textsf": "textsf",
|
9
|
+
"\\texttt": "texttt",
|
10
|
+
"\\textnormal": "textrm",
|
11
|
+
"\\textsc": "textsc" // small caps
|
12
|
+
};
|
13
|
+
|
14
|
+
const textFontWeights = {
|
15
|
+
"\\textbf": "textbf",
|
16
|
+
"\\textmd": "textmd"
|
17
|
+
};
|
18
|
+
|
19
|
+
const textFontShapes = {
|
20
|
+
"\\textit": "textit",
|
21
|
+
"\\textup": "textup"
|
22
|
+
};
|
23
|
+
|
24
|
+
const styleWithFont = (group, style) => {
|
25
|
+
const font = group.font;
|
26
|
+
// Checks if the argument is a font family or a font style.
|
27
|
+
if (!font) {
|
28
|
+
return style;
|
29
|
+
} else if (textFontFamilies[font]) {
|
30
|
+
return style.withTextFontFamily(textFontFamilies[font]);
|
31
|
+
} else if (textFontWeights[font]) {
|
32
|
+
return style.withTextFontWeight(textFontWeights[font]);
|
33
|
+
} else {
|
34
|
+
return style.withTextFontShape(textFontShapes[font]);
|
35
|
+
}
|
36
|
+
};
|
37
|
+
|
38
|
+
defineFunction({
|
39
|
+
type: "text",
|
40
|
+
names: [
|
41
|
+
// Font families
|
42
|
+
"\\text",
|
43
|
+
"\\textrm",
|
44
|
+
"\\textsf",
|
45
|
+
"\\texttt",
|
46
|
+
"\\textnormal",
|
47
|
+
"\\textsc",
|
48
|
+
// Font weights
|
49
|
+
"\\textbf",
|
50
|
+
"\\textmd",
|
51
|
+
// Font Shapes
|
52
|
+
"\\textit",
|
53
|
+
"\\textup"
|
54
|
+
],
|
55
|
+
props: {
|
56
|
+
numArgs: 1,
|
57
|
+
argTypes: ["text"],
|
58
|
+
allowedInArgument: true,
|
59
|
+
allowedInText: true
|
60
|
+
},
|
61
|
+
handler({ parser, funcName }, args) {
|
62
|
+
const body = args[0];
|
63
|
+
return {
|
64
|
+
type: "text",
|
65
|
+
mode: parser.mode,
|
66
|
+
body: ordargument(body),
|
67
|
+
font: funcName
|
68
|
+
};
|
69
|
+
},
|
70
|
+
mathmlBuilder(group, style) {
|
71
|
+
const newStyle = styleWithFont(group, style)
|
72
|
+
const mrow = mml.buildExpressionRow(group.body, newStyle)
|
73
|
+
return mml.consolidateText(mrow)
|
74
|
+
}
|
75
|
+
});
|
@@ -0,0 +1,63 @@
|
|
1
|
+
import defineFunction from "../defineFunction";
|
2
|
+
import mathMLTree from "../mathMLTree";
|
3
|
+
import * as mml from "../buildMathML";
|
4
|
+
|
5
|
+
// Two functions included to enable migration from Mathjax.
|
6
|
+
|
7
|
+
defineFunction({
|
8
|
+
type: "tip",
|
9
|
+
names: ["\\mathtip"],
|
10
|
+
props: {
|
11
|
+
numArgs: 2
|
12
|
+
},
|
13
|
+
handler({ parser }, args) {
|
14
|
+
return {
|
15
|
+
type: "tip",
|
16
|
+
mode: parser.mode,
|
17
|
+
body: args[0],
|
18
|
+
tip: args[1]
|
19
|
+
};
|
20
|
+
},
|
21
|
+
mathmlBuilder: (group, style) => {
|
22
|
+
const math = mml.buildGroup(group.body, style)
|
23
|
+
const tip = mml.buildGroup(group.tip, style)
|
24
|
+
// Browsers don't support the tooltip actiontype.
|
25
|
+
// TODO: Come back and fix \mathtip when it can be done via CSS w/o a JS event.
|
26
|
+
const node = new mathMLTree.MathNode("maction", [math, tip], ["tml-tip"])
|
27
|
+
node.setAttribute("actiontype", "tooltip")
|
28
|
+
return node
|
29
|
+
}
|
30
|
+
})
|
31
|
+
|
32
|
+
defineFunction({
|
33
|
+
type: "tip",
|
34
|
+
names: ["\\texttip"],
|
35
|
+
props: {
|
36
|
+
numArgs: 2,
|
37
|
+
argTypes: ["math", "text"]
|
38
|
+
},
|
39
|
+
handler({ parser }, args) {
|
40
|
+
return {
|
41
|
+
type: "tip",
|
42
|
+
mode: parser.mode,
|
43
|
+
body: args[0],
|
44
|
+
tip: args[1]
|
45
|
+
};
|
46
|
+
},
|
47
|
+
mathmlBuilder: (group, style) => {
|
48
|
+
const math = mml.buildGroup(group.body, style)
|
49
|
+
const tip = mml.buildGroup(group.tip, style)
|
50
|
+
// args[1] only accepted text, so tip is a <mtext> element or a <mrow> of them.
|
51
|
+
let str = ""
|
52
|
+
if (tip.type === "mtext") {
|
53
|
+
str = tip.children[0].text
|
54
|
+
} else {
|
55
|
+
for (const child of tip.children) {
|
56
|
+
str += child.children[0].text
|
57
|
+
}
|
58
|
+
}
|
59
|
+
// Implement \texttip via a title attribute.
|
60
|
+
math.setAttribute("title", str)
|
61
|
+
return math
|
62
|
+
}
|
63
|
+
})
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import { defineFunctionBuilders } from "../defineFunction";
|
2
|
+
import mathMLTree from "../mathMLTree";
|
3
|
+
import * as mml from "../buildMathML";
|
4
|
+
|
5
|
+
defineFunctionBuilders({
|
6
|
+
type: "toggle",
|
7
|
+
mathmlBuilder(group, style) {
|
8
|
+
const expression = mml.buildExpression(group.body, style)
|
9
|
+
const node = new mathMLTree.MathNode("maction", expression, [], { cursor: "default" })
|
10
|
+
node.setAttribute("actiontype", "toggle")
|
11
|
+
return node
|
12
|
+
}
|
13
|
+
})
|
@@ -0,0 +1,33 @@
|
|
1
|
+
import defineFunction from "../defineFunction";
|
2
|
+
import mathMLTree from "../mathMLTree";
|
3
|
+
import ParseError from "../ParseError";
|
4
|
+
|
5
|
+
defineFunction({
|
6
|
+
type: "verb",
|
7
|
+
names: ["\\verb"],
|
8
|
+
props: {
|
9
|
+
numArgs: 0,
|
10
|
+
allowedInText: true
|
11
|
+
},
|
12
|
+
handler(context, args, optArgs) {
|
13
|
+
// \verb and \verb* are dealt with directly in Parser.js.
|
14
|
+
// If we end up here, it's because of a failure to match the two delimiters
|
15
|
+
// in the regex in Lexer.js. LaTeX raises the following error when \verb is
|
16
|
+
// terminated by end of line (or file).
|
17
|
+
throw new ParseError("\\verb ended by end of line instead of matching delimiter");
|
18
|
+
},
|
19
|
+
mathmlBuilder(group, style) {
|
20
|
+
const text = new mathMLTree.TextNode(makeVerb(group));
|
21
|
+
const node = new mathMLTree.MathNode("mtext", [text]);
|
22
|
+
node.setAttribute("mathvariant", "monospace");
|
23
|
+
return node;
|
24
|
+
}
|
25
|
+
});
|
26
|
+
|
27
|
+
/**
|
28
|
+
* Converts verb group into body string.
|
29
|
+
*
|
30
|
+
* \verb* replaces each space with an open box \u2423
|
31
|
+
* \verb replaces each space with a no-break space \xA0
|
32
|
+
*/
|
33
|
+
const makeVerb = (group) => group.body.replace(/ /g, group.star ? "\u2423" : "\xA0");
|
package/src/functions.js
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
/** Include this to ensure that all functions are defined. */
|
2
|
+
import { _functions } from "./defineFunction";
|
3
|
+
|
4
|
+
const functions = _functions;
|
5
|
+
export default functions;
|
6
|
+
|
7
|
+
// TODO(kevinb): have functions return an object and call defineFunction with
|
8
|
+
// that object in this file instead of relying on side-effects.
|
9
|
+
import "./functions/accent";
|
10
|
+
import "./functions/accentunder";
|
11
|
+
import "./functions/arrow";
|
12
|
+
//import "./functions/cancelto";
|
13
|
+
import "./environments/cd";
|
14
|
+
import "./functions/char";
|
15
|
+
import "./functions/color";
|
16
|
+
import "./functions/cr";
|
17
|
+
import "./functions/def";
|
18
|
+
import "./functions/delimsizing";
|
19
|
+
import "./functions/enclose";
|
20
|
+
import "./functions/environment";
|
21
|
+
import "./functions/envTag";
|
22
|
+
import "./functions/font";
|
23
|
+
import "./functions/genfrac";
|
24
|
+
import "./functions/horizBrace";
|
25
|
+
import "./functions/href";
|
26
|
+
import "./functions/html";
|
27
|
+
import "./functions/includegraphics";
|
28
|
+
import "./functions/kern";
|
29
|
+
import "./functions/label";
|
30
|
+
import "./functions/lap";
|
31
|
+
import "./functions/math";
|
32
|
+
import "./functions/mathchoice";
|
33
|
+
import "./functions/mclass";
|
34
|
+
import "./functions/multiscript";
|
35
|
+
import "./functions/not";
|
36
|
+
import "./functions/op";
|
37
|
+
import "./functions/operatorname";
|
38
|
+
import "./functions/ordgroup";
|
39
|
+
import "./functions/phantom";
|
40
|
+
import "./functions/pmb";
|
41
|
+
import "./functions/raise";
|
42
|
+
import "./functions/ref";
|
43
|
+
import "./functions/relax";
|
44
|
+
import "./functions/rule";
|
45
|
+
import "./functions/sizing";
|
46
|
+
import "./functions/smash";
|
47
|
+
import "./functions/sqrt";
|
48
|
+
import "./functions/styling";
|
49
|
+
import "./functions/supsub";
|
50
|
+
import "./functions/symbolsOp";
|
51
|
+
import "./functions/symbolsOrd";
|
52
|
+
import "./functions/symbolsSpacing";
|
53
|
+
import "./functions/tag";
|
54
|
+
import "./functions/text";
|
55
|
+
// import "./functions/tip";
|
56
|
+
// import "./functions/toggle";
|
57
|
+
import "./functions/verb";
|
@@ -0,0 +1,159 @@
|
|
1
|
+
import mathMLTree from "./mathMLTree"
|
2
|
+
|
3
|
+
/*
|
4
|
+
* Neither Firefox nor Chrome support hard line breaks or soft line breaks.
|
5
|
+
* (Despite https://www.w3.org/Math/draft-spec/mathml.html#chapter3_presm.lbattrs)
|
6
|
+
* So Temml has work-arounds for both hard and soft breaks.
|
7
|
+
* The work-arounds sadly do not work simultaneously. Any top-level hard
|
8
|
+
* break makes soft line breaks impossible.
|
9
|
+
*
|
10
|
+
* Hard breaks are simulated by creating a <mtable> and putting each line in its own <mtr>.
|
11
|
+
*
|
12
|
+
* To create soft line breaks, Temml avoids using the <semantics> and <annotation> tags.
|
13
|
+
* Then the top level of a <math> element can be occupied by <mrow> elements, and the browser
|
14
|
+
* will break after a <mrow> if the expression extends beyond the container limit.
|
15
|
+
*
|
16
|
+
* We want the expression to render with soft line breaks after each top-level binary or
|
17
|
+
* relational operator, per TeXbook p. 173. So we gather the expression into <mrow>s so that
|
18
|
+
* each <mrow> ends in a binary or relational operator.
|
19
|
+
*
|
20
|
+
* Soft line breaks will not work in Chromium and Safari, only Firefox.
|
21
|
+
*
|
22
|
+
* Hopefully browsers will someday do their own linebreaking and we will be able to delete
|
23
|
+
* much of this module.
|
24
|
+
*/
|
25
|
+
|
26
|
+
export default function setLineBreaks(expression, wrapMode, isDisplayMode, color) {
|
27
|
+
if (color === undefined && wrapMode !== "none") {
|
28
|
+
// First, make one pass through the expression and split any color nodes.
|
29
|
+
const upperLimit = expression.length - 1
|
30
|
+
for (let i = upperLimit; i >= 0; i--) {
|
31
|
+
const node = expression[i];
|
32
|
+
if (node.type === "mstyle" && node.attributes.mathcolor) {
|
33
|
+
const color = node.attributes.mathcolor
|
34
|
+
const fragment = setLineBreaks(node.children, wrapMode, isDisplayMode, color)
|
35
|
+
if (!(fragment.type && fragment.type !== "mtable")) {
|
36
|
+
expression.splice(i, 1, ...fragment.children)
|
37
|
+
}
|
38
|
+
}
|
39
|
+
}
|
40
|
+
}
|
41
|
+
|
42
|
+
const tagName = color ? "mstyle" : "mrow"
|
43
|
+
|
44
|
+
const mtrs = [];
|
45
|
+
let mrows = [];
|
46
|
+
let block = [];
|
47
|
+
let numTopLevelEquals = 0
|
48
|
+
let canBeBIN = false // The first node cannot be an infix binary operator.
|
49
|
+
for (let i = 0; i < expression.length; i++) {
|
50
|
+
const node = expression[i];
|
51
|
+
if (node.type && node.type === "mstyle" && node.attributes.mathcolor) {
|
52
|
+
if (block.length > 0) {
|
53
|
+
// Start a new block. (Insert a soft linebreak.)
|
54
|
+
mrows.push(new mathMLTree.MathNode(tagName, block))
|
55
|
+
}
|
56
|
+
// Insert the mstyle
|
57
|
+
mrows.push(node)
|
58
|
+
block = [];
|
59
|
+
continue
|
60
|
+
}
|
61
|
+
if (node.attributes && node.attributes.linebreak &&
|
62
|
+
node.attributes.linebreak === "newline") {
|
63
|
+
// A hard line break. Create a <mtr> for the current block.
|
64
|
+
if (block.length > 0) {
|
65
|
+
const element = new mathMLTree.MathNode(tagName, block)
|
66
|
+
if (color) { element.setAttribute("mathcolor", color) }
|
67
|
+
mrows.push(new mathMLTree.MathNode(tagName, block))
|
68
|
+
}
|
69
|
+
mrows.push(node)
|
70
|
+
block = [];
|
71
|
+
const mtd = new mathMLTree.MathNode("mtd", mrows)
|
72
|
+
mtrs.push(new mathMLTree.MathNode("mtr", [mtd]))
|
73
|
+
mrows = [];
|
74
|
+
continue
|
75
|
+
}
|
76
|
+
block.push(node);
|
77
|
+
if (node.type && node.type === "mo" && wrapMode === "=") {
|
78
|
+
if (node.children.length === 1 && node.children[0].text === "=") {
|
79
|
+
numTopLevelEquals += 1
|
80
|
+
if (numTopLevelEquals > 1) {
|
81
|
+
block.pop()
|
82
|
+
// Start a new block. (Insert a soft linebreak.)
|
83
|
+
const element = new mathMLTree.MathNode(tagName, block)
|
84
|
+
if (color) { element.setAttribute("mathcolor", color) }
|
85
|
+
mrows.push(element)
|
86
|
+
block = [node];
|
87
|
+
}
|
88
|
+
}
|
89
|
+
} else if (node.type && node.type === "mo" && wrapMode === "tex") {
|
90
|
+
// This may be a place for a soft line break.
|
91
|
+
if (canBeBIN && !node.attributes.form) {
|
92
|
+
// Check if the following node is a \nobreak text node, e.g. "~""
|
93
|
+
const next = i < expression.length - 1 ? expression[i + 1] : null;
|
94
|
+
let glueIsFreeOfNobreak = true;
|
95
|
+
if (
|
96
|
+
!(
|
97
|
+
next &&
|
98
|
+
next.type === "mtext" &&
|
99
|
+
next.attributes.linebreak &&
|
100
|
+
next.attributes.linebreak === "nobreak"
|
101
|
+
)
|
102
|
+
) {
|
103
|
+
// We may need to start a new block.
|
104
|
+
// First, put any post-operator glue on same line as operator.
|
105
|
+
for (let j = i + 1; j < expression.length; j++) {
|
106
|
+
const nd = expression[j];
|
107
|
+
if (
|
108
|
+
nd.type &&
|
109
|
+
nd.type === "mspace" &&
|
110
|
+
!(nd.attributes.linebreak && nd.attributes.linebreak === "newline")
|
111
|
+
) {
|
112
|
+
block.push(nd);
|
113
|
+
i += 1;
|
114
|
+
if (
|
115
|
+
nd.attributes &&
|
116
|
+
nd.attributes.linebreak &&
|
117
|
+
nd.attributes.linebreak === "nobreak"
|
118
|
+
) {
|
119
|
+
glueIsFreeOfNobreak = false;
|
120
|
+
}
|
121
|
+
} else {
|
122
|
+
break;
|
123
|
+
}
|
124
|
+
}
|
125
|
+
}
|
126
|
+
if (glueIsFreeOfNobreak) {
|
127
|
+
// Start a new block. (Insert a soft linebreak.)
|
128
|
+
const element = new mathMLTree.MathNode(tagName, block)
|
129
|
+
if (color) { element.setAttribute("mathcolor", color) }
|
130
|
+
mrows.push(element)
|
131
|
+
block = [];
|
132
|
+
}
|
133
|
+
canBeBIN = false;
|
134
|
+
}
|
135
|
+
const isOpenDelimiter = node.attributes.form && node.attributes.form === "prefix";
|
136
|
+
// Any operator that follows an open delimiter is unary.
|
137
|
+
canBeBIN = !(node.attributes.separator || isOpenDelimiter);
|
138
|
+
} else {
|
139
|
+
canBeBIN = true;
|
140
|
+
}
|
141
|
+
}
|
142
|
+
if (block.length > 0) {
|
143
|
+
const element = new mathMLTree.MathNode(tagName, block)
|
144
|
+
if (color) { element.setAttribute("mathcolor", color) }
|
145
|
+
mrows.push(element)
|
146
|
+
}
|
147
|
+
if (mtrs.length > 0) {
|
148
|
+
const mtd = new mathMLTree.MathNode("mtd", mrows)
|
149
|
+
const mtr = new mathMLTree.MathNode("mtr", [mtd])
|
150
|
+
mtrs.push(mtr)
|
151
|
+
const mtable = new mathMLTree.MathNode("mtable", mtrs)
|
152
|
+
if (!isDisplayMode) {
|
153
|
+
mtable.setAttribute("columnalign", "left")
|
154
|
+
mtable.setAttribute("rowspacing", "0em")
|
155
|
+
}
|
156
|
+
return mtable
|
157
|
+
}
|
158
|
+
return mathMLTree.newDocumentFragment(mrows);
|
159
|
+
}
|