mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-08 04:28:41 +00:00
Merge pull request #348 from gagern/splitBuildHandlers
Split groupType literals in buildHTML and buildMathML
This commit is contained in:
2128
src/buildHTML.js
2128
src/buildHTML.js
File diff suppressed because it is too large
Load Diff
@@ -61,397 +61,397 @@ var getVariant = function(group, options) {
|
|||||||
* Functions for handling the different types of groups found in the parse
|
* Functions for handling the different types of groups found in the parse
|
||||||
* tree. Each function should take a parse group and return a MathML node.
|
* tree. Each function should take a parse group and return a MathML node.
|
||||||
*/
|
*/
|
||||||
var groupTypes = {
|
var groupTypes = {};
|
||||||
mathord: function(group, options) {
|
|
||||||
var node = new mathMLTree.MathNode(
|
|
||||||
"mi",
|
|
||||||
[makeText(group.value, group.mode)]);
|
|
||||||
|
|
||||||
var variant = getVariant(group, options);
|
groupTypes.mathord = function(group, options) {
|
||||||
if (variant) {
|
var node = new mathMLTree.MathNode(
|
||||||
|
"mi",
|
||||||
|
[makeText(group.value, group.mode)]);
|
||||||
|
|
||||||
|
var variant = getVariant(group, options);
|
||||||
|
if (variant) {
|
||||||
|
node.setAttribute("mathvariant", variant);
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.textord = function(group, options) {
|
||||||
|
var text = makeText(group.value, group.mode);
|
||||||
|
|
||||||
|
var variant = getVariant(group, options) || "normal";
|
||||||
|
|
||||||
|
var node;
|
||||||
|
if (/[0-9]/.test(group.value)) {
|
||||||
|
// TODO(kevinb) merge adjacent <mn> nodes
|
||||||
|
// do it as a post processing step
|
||||||
|
node = new mathMLTree.MathNode("mn", [text]);
|
||||||
|
if (options.font) {
|
||||||
node.setAttribute("mathvariant", variant);
|
node.setAttribute("mathvariant", variant);
|
||||||
}
|
}
|
||||||
return node;
|
} else {
|
||||||
},
|
node = new mathMLTree.MathNode("mi", [text]);
|
||||||
|
node.setAttribute("mathvariant", variant);
|
||||||
|
}
|
||||||
|
|
||||||
textord: function(group, options) {
|
return node;
|
||||||
var text = makeText(group.value, group.mode);
|
};
|
||||||
|
|
||||||
var variant = getVariant(group, options) || "normal";
|
groupTypes.bin = function(group) {
|
||||||
|
var node = new mathMLTree.MathNode(
|
||||||
|
"mo", [makeText(group.value, group.mode)]);
|
||||||
|
|
||||||
var node;
|
return node;
|
||||||
if (/[0-9]/.test(group.value)) {
|
};
|
||||||
// TODO(kevinb) merge adjacent <mn> nodes
|
|
||||||
// do it as a post processing step
|
groupTypes.rel = function(group) {
|
||||||
node = new mathMLTree.MathNode("mn", [text]);
|
var node = new mathMLTree.MathNode(
|
||||||
if (options.font) {
|
"mo", [makeText(group.value, group.mode)]);
|
||||||
node.setAttribute("mathvariant", variant);
|
|
||||||
}
|
return node;
|
||||||
} else {
|
};
|
||||||
node = new mathMLTree.MathNode("mi", [text]);
|
|
||||||
node.setAttribute("mathvariant", variant);
|
groupTypes.open = function(group) {
|
||||||
|
var node = new mathMLTree.MathNode(
|
||||||
|
"mo", [makeText(group.value, group.mode)]);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.close = function(group) {
|
||||||
|
var node = new mathMLTree.MathNode(
|
||||||
|
"mo", [makeText(group.value, group.mode)]);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.inner = function(group) {
|
||||||
|
var node = new mathMLTree.MathNode(
|
||||||
|
"mo", [makeText(group.value, group.mode)]);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.punct = function(group) {
|
||||||
|
var node = new mathMLTree.MathNode(
|
||||||
|
"mo", [makeText(group.value, group.mode)]);
|
||||||
|
|
||||||
|
node.setAttribute("separator", "true");
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.ordgroup = function(group, options) {
|
||||||
|
var inner = buildExpression(group.value, options);
|
||||||
|
|
||||||
|
var node = new mathMLTree.MathNode("mrow", inner);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.text = function(group, options) {
|
||||||
|
var inner = buildExpression(group.value.body, options);
|
||||||
|
|
||||||
|
var node = new mathMLTree.MathNode("mtext", inner);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.color = function(group, options) {
|
||||||
|
var inner = buildExpression(group.value.value, options);
|
||||||
|
|
||||||
|
var node = new mathMLTree.MathNode("mstyle", inner);
|
||||||
|
|
||||||
|
node.setAttribute("mathcolor", group.value.color);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.supsub = function(group, options) {
|
||||||
|
var children = [buildGroup(group.value.base, options)];
|
||||||
|
|
||||||
|
if (group.value.sub) {
|
||||||
|
children.push(buildGroup(group.value.sub, options));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (group.value.sup) {
|
||||||
|
children.push(buildGroup(group.value.sup, options));
|
||||||
|
}
|
||||||
|
|
||||||
|
var nodeType;
|
||||||
|
if (!group.value.sub) {
|
||||||
|
nodeType = "msup";
|
||||||
|
} else if (!group.value.sup) {
|
||||||
|
nodeType = "msub";
|
||||||
|
} else {
|
||||||
|
nodeType = "msubsup";
|
||||||
|
}
|
||||||
|
|
||||||
|
var node = new mathMLTree.MathNode(nodeType, children);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.genfrac = function(group, options) {
|
||||||
|
var node = new mathMLTree.MathNode(
|
||||||
|
"mfrac",
|
||||||
|
[buildGroup(group.value.numer, options),
|
||||||
|
buildGroup(group.value.denom, options)]);
|
||||||
|
|
||||||
|
if (!group.value.hasBarLine) {
|
||||||
|
node.setAttribute("linethickness", "0px");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (group.value.leftDelim != null || group.value.rightDelim != null) {
|
||||||
|
var withDelims = [];
|
||||||
|
|
||||||
|
if (group.value.leftDelim != null) {
|
||||||
|
var leftOp = new mathMLTree.MathNode(
|
||||||
|
"mo", [new mathMLTree.TextNode(group.value.leftDelim)]);
|
||||||
|
|
||||||
|
leftOp.setAttribute("fence", "true");
|
||||||
|
|
||||||
|
withDelims.push(leftOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
withDelims.push(node);
|
||||||
},
|
|
||||||
|
|
||||||
bin: function(group) {
|
if (group.value.rightDelim != null) {
|
||||||
var node = new mathMLTree.MathNode(
|
var rightOp = new mathMLTree.MathNode(
|
||||||
"mo", [makeText(group.value, group.mode)]);
|
"mo", [new mathMLTree.TextNode(group.value.rightDelim)]);
|
||||||
|
|
||||||
return node;
|
rightOp.setAttribute("fence", "true");
|
||||||
},
|
|
||||||
|
|
||||||
rel: function(group) {
|
withDelims.push(rightOp);
|
||||||
var node = new mathMLTree.MathNode(
|
|
||||||
"mo", [makeText(group.value, group.mode)]);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
open: function(group) {
|
|
||||||
var node = new mathMLTree.MathNode(
|
|
||||||
"mo", [makeText(group.value, group.mode)]);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
close: function(group) {
|
|
||||||
var node = new mathMLTree.MathNode(
|
|
||||||
"mo", [makeText(group.value, group.mode)]);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
inner: function(group) {
|
|
||||||
var node = new mathMLTree.MathNode(
|
|
||||||
"mo", [makeText(group.value, group.mode)]);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
punct: function(group) {
|
|
||||||
var node = new mathMLTree.MathNode(
|
|
||||||
"mo", [makeText(group.value, group.mode)]);
|
|
||||||
|
|
||||||
node.setAttribute("separator", "true");
|
|
||||||
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
ordgroup: function(group, options) {
|
|
||||||
var inner = buildExpression(group.value, options);
|
|
||||||
|
|
||||||
var node = new mathMLTree.MathNode("mrow", inner);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
text: function(group, options) {
|
|
||||||
var inner = buildExpression(group.value.body, options);
|
|
||||||
|
|
||||||
var node = new mathMLTree.MathNode("mtext", inner);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
color: function(group, options) {
|
|
||||||
var inner = buildExpression(group.value.value, options);
|
|
||||||
|
|
||||||
var node = new mathMLTree.MathNode("mstyle", inner);
|
|
||||||
|
|
||||||
node.setAttribute("mathcolor", group.value.color);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
supsub: function(group, options) {
|
|
||||||
var children = [buildGroup(group.value.base, options)];
|
|
||||||
|
|
||||||
if (group.value.sub) {
|
|
||||||
children.push(buildGroup(group.value.sub, options));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (group.value.sup) {
|
var outerNode = new mathMLTree.MathNode("mrow", withDelims);
|
||||||
children.push(buildGroup(group.value.sup, options));
|
|
||||||
}
|
|
||||||
|
|
||||||
var nodeType;
|
|
||||||
if (!group.value.sub) {
|
|
||||||
nodeType = "msup";
|
|
||||||
} else if (!group.value.sup) {
|
|
||||||
nodeType = "msub";
|
|
||||||
} else {
|
|
||||||
nodeType = "msubsup";
|
|
||||||
}
|
|
||||||
|
|
||||||
var node = new mathMLTree.MathNode(nodeType, children);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
genfrac: function(group, options) {
|
|
||||||
var node = new mathMLTree.MathNode(
|
|
||||||
"mfrac",
|
|
||||||
[buildGroup(group.value.numer, options),
|
|
||||||
buildGroup(group.value.denom, options)]);
|
|
||||||
|
|
||||||
if (!group.value.hasBarLine) {
|
|
||||||
node.setAttribute("linethickness", "0px");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (group.value.leftDelim != null || group.value.rightDelim != null) {
|
|
||||||
var withDelims = [];
|
|
||||||
|
|
||||||
if (group.value.leftDelim != null) {
|
|
||||||
var leftOp = new mathMLTree.MathNode(
|
|
||||||
"mo", [new mathMLTree.TextNode(group.value.leftDelim)]);
|
|
||||||
|
|
||||||
leftOp.setAttribute("fence", "true");
|
|
||||||
|
|
||||||
withDelims.push(leftOp);
|
|
||||||
}
|
|
||||||
|
|
||||||
withDelims.push(node);
|
|
||||||
|
|
||||||
if (group.value.rightDelim != null) {
|
|
||||||
var rightOp = new mathMLTree.MathNode(
|
|
||||||
"mo", [new mathMLTree.TextNode(group.value.rightDelim)]);
|
|
||||||
|
|
||||||
rightOp.setAttribute("fence", "true");
|
|
||||||
|
|
||||||
withDelims.push(rightOp);
|
|
||||||
}
|
|
||||||
|
|
||||||
var outerNode = new mathMLTree.MathNode("mrow", withDelims);
|
|
||||||
|
|
||||||
return outerNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
array: function(group, options) {
|
|
||||||
return new mathMLTree.MathNode(
|
|
||||||
"mtable", group.value.body.map(function(row) {
|
|
||||||
return new mathMLTree.MathNode(
|
|
||||||
"mtr", row.map(function(cell) {
|
|
||||||
return new mathMLTree.MathNode(
|
|
||||||
"mtd", [buildGroup(cell, options)]);
|
|
||||||
}));
|
|
||||||
}));
|
|
||||||
},
|
|
||||||
|
|
||||||
sqrt: function(group, options) {
|
|
||||||
var node;
|
|
||||||
if (group.value.index) {
|
|
||||||
node = new mathMLTree.MathNode(
|
|
||||||
"mroot", [
|
|
||||||
buildGroup(group.value.body, options),
|
|
||||||
buildGroup(group.value.index, options)
|
|
||||||
]);
|
|
||||||
} else {
|
|
||||||
node = new mathMLTree.MathNode(
|
|
||||||
"msqrt", [buildGroup(group.value.body, options)]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
leftright: function(group, options) {
|
|
||||||
var inner = buildExpression(group.value.body, options);
|
|
||||||
|
|
||||||
if (group.value.left !== ".") {
|
|
||||||
var leftNode = new mathMLTree.MathNode(
|
|
||||||
"mo", [makeText(group.value.left, group.mode)]);
|
|
||||||
|
|
||||||
leftNode.setAttribute("fence", "true");
|
|
||||||
|
|
||||||
inner.unshift(leftNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (group.value.right !== ".") {
|
|
||||||
var rightNode = new mathMLTree.MathNode(
|
|
||||||
"mo", [makeText(group.value.right, group.mode)]);
|
|
||||||
|
|
||||||
rightNode.setAttribute("fence", "true");
|
|
||||||
|
|
||||||
inner.push(rightNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
var outerNode = new mathMLTree.MathNode("mrow", inner);
|
|
||||||
|
|
||||||
return outerNode;
|
return outerNode;
|
||||||
},
|
|
||||||
|
|
||||||
accent: function(group, options) {
|
|
||||||
var accentNode = new mathMLTree.MathNode(
|
|
||||||
"mo", [makeText(group.value.accent, group.mode)]);
|
|
||||||
|
|
||||||
var node = new mathMLTree.MathNode(
|
|
||||||
"mover",
|
|
||||||
[buildGroup(group.value.base, options),
|
|
||||||
accentNode]);
|
|
||||||
|
|
||||||
node.setAttribute("accent", "true");
|
|
||||||
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
spacing: function(group) {
|
|
||||||
var node;
|
|
||||||
|
|
||||||
if (group.value === "\\ " || group.value === "\\space" ||
|
|
||||||
group.value === " " || group.value === "~") {
|
|
||||||
node = new mathMLTree.MathNode(
|
|
||||||
"mtext", [new mathMLTree.TextNode("\u00a0")]);
|
|
||||||
} else {
|
|
||||||
node = new mathMLTree.MathNode("mspace");
|
|
||||||
|
|
||||||
node.setAttribute(
|
|
||||||
"width", buildCommon.spacingFunctions[group.value].size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
op: function(group) {
|
|
||||||
var node;
|
|
||||||
|
|
||||||
// TODO(emily): handle big operators using the `largeop` attribute
|
|
||||||
|
|
||||||
if (group.value.symbol) {
|
|
||||||
// This is a symbol. Just add the symbol.
|
|
||||||
node = new mathMLTree.MathNode(
|
|
||||||
"mo", [makeText(group.value.body, group.mode)]);
|
|
||||||
} else {
|
|
||||||
// This is a text operator. Add all of the characters from the
|
|
||||||
// operator's name.
|
|
||||||
// TODO(emily): Add a space in the middle of some of these
|
|
||||||
// operators, like \limsup.
|
|
||||||
node = new mathMLTree.MathNode(
|
|
||||||
"mi", [new mathMLTree.TextNode(group.value.body.slice(1))]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
katex: function(group) {
|
|
||||||
var node = new mathMLTree.MathNode(
|
|
||||||
"mtext", [new mathMLTree.TextNode("KaTeX")]);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
font: function(group, options) {
|
|
||||||
var font = group.value.font;
|
|
||||||
return buildGroup(group.value.body, options.withFont(font));
|
|
||||||
},
|
|
||||||
|
|
||||||
delimsizing: function(group) {
|
|
||||||
var children = [];
|
|
||||||
|
|
||||||
if (group.value.value !== ".") {
|
|
||||||
children.push(makeText(group.value.value, group.mode));
|
|
||||||
}
|
|
||||||
|
|
||||||
var node = new mathMLTree.MathNode("mo", children);
|
|
||||||
|
|
||||||
if (group.value.delimType === "open" ||
|
|
||||||
group.value.delimType === "close") {
|
|
||||||
// Only some of the delimsizing functions act as fences, and they
|
|
||||||
// return "open" or "close" delimTypes.
|
|
||||||
node.setAttribute("fence", "true");
|
|
||||||
} else {
|
|
||||||
// Explicitly disable fencing if it's not a fence, to override the
|
|
||||||
// defaults.
|
|
||||||
node.setAttribute("fence", "false");
|
|
||||||
}
|
|
||||||
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
styling: function(group, options) {
|
|
||||||
var inner = buildExpression(group.value.value, options);
|
|
||||||
|
|
||||||
var node = new mathMLTree.MathNode("mstyle", inner);
|
|
||||||
|
|
||||||
var styleAttributes = {
|
|
||||||
"display": ["0", "true"],
|
|
||||||
"text": ["0", "false"],
|
|
||||||
"script": ["1", "false"],
|
|
||||||
"scriptscript": ["2", "false"]
|
|
||||||
};
|
|
||||||
|
|
||||||
var attr = styleAttributes[group.value.style];
|
|
||||||
|
|
||||||
node.setAttribute("scriptlevel", attr[0]);
|
|
||||||
node.setAttribute("displaystyle", attr[1]);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
sizing: function(group, options) {
|
|
||||||
var inner = buildExpression(group.value.value, options);
|
|
||||||
|
|
||||||
var node = new mathMLTree.MathNode("mstyle", inner);
|
|
||||||
|
|
||||||
// TODO(emily): This doesn't produce the correct size for nested size
|
|
||||||
// changes, because we don't keep state of what style we're currently
|
|
||||||
// in, so we can't reset the size to normal before changing it. Now
|
|
||||||
// that we're passing an options parameter we should be able to fix
|
|
||||||
// this.
|
|
||||||
node.setAttribute(
|
|
||||||
"mathsize", buildCommon.sizingMultiplier[group.value.size] + "em");
|
|
||||||
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
overline: function(group, options) {
|
|
||||||
var operator = new mathMLTree.MathNode(
|
|
||||||
"mo", [new mathMLTree.TextNode("\u203e")]);
|
|
||||||
operator.setAttribute("stretchy", "true");
|
|
||||||
|
|
||||||
var node = new mathMLTree.MathNode(
|
|
||||||
"mover",
|
|
||||||
[buildGroup(group.value.body, options),
|
|
||||||
operator]);
|
|
||||||
node.setAttribute("accent", "true");
|
|
||||||
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
rule: function(group) {
|
|
||||||
// TODO(emily): Figure out if there's an actual way to draw black boxes
|
|
||||||
// in MathML.
|
|
||||||
var node = new mathMLTree.MathNode("mrow");
|
|
||||||
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
llap: function(group, options) {
|
|
||||||
var node = new mathMLTree.MathNode(
|
|
||||||
"mpadded", [buildGroup(group.value.body, options)]);
|
|
||||||
|
|
||||||
node.setAttribute("lspace", "-1width");
|
|
||||||
node.setAttribute("width", "0px");
|
|
||||||
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
rlap: function(group, options) {
|
|
||||||
var node = new mathMLTree.MathNode(
|
|
||||||
"mpadded", [buildGroup(group.value.body, options)]);
|
|
||||||
|
|
||||||
node.setAttribute("width", "0px");
|
|
||||||
|
|
||||||
return node;
|
|
||||||
},
|
|
||||||
|
|
||||||
phantom: function(group, options, prev) {
|
|
||||||
var inner = buildExpression(group.value.value, options);
|
|
||||||
return new mathMLTree.MathNode("mphantom", inner);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.array = function(group, options) {
|
||||||
|
return new mathMLTree.MathNode(
|
||||||
|
"mtable", group.value.body.map(function(row) {
|
||||||
|
return new mathMLTree.MathNode(
|
||||||
|
"mtr", row.map(function(cell) {
|
||||||
|
return new mathMLTree.MathNode(
|
||||||
|
"mtd", [buildGroup(cell, options)]);
|
||||||
|
}));
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.sqrt = function(group, options) {
|
||||||
|
var node;
|
||||||
|
if (group.value.index) {
|
||||||
|
node = new mathMLTree.MathNode(
|
||||||
|
"mroot", [
|
||||||
|
buildGroup(group.value.body, options),
|
||||||
|
buildGroup(group.value.index, options)
|
||||||
|
]);
|
||||||
|
} else {
|
||||||
|
node = new mathMLTree.MathNode(
|
||||||
|
"msqrt", [buildGroup(group.value.body, options)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.leftright = function(group, options) {
|
||||||
|
var inner = buildExpression(group.value.body, options);
|
||||||
|
|
||||||
|
if (group.value.left !== ".") {
|
||||||
|
var leftNode = new mathMLTree.MathNode(
|
||||||
|
"mo", [makeText(group.value.left, group.mode)]);
|
||||||
|
|
||||||
|
leftNode.setAttribute("fence", "true");
|
||||||
|
|
||||||
|
inner.unshift(leftNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (group.value.right !== ".") {
|
||||||
|
var rightNode = new mathMLTree.MathNode(
|
||||||
|
"mo", [makeText(group.value.right, group.mode)]);
|
||||||
|
|
||||||
|
rightNode.setAttribute("fence", "true");
|
||||||
|
|
||||||
|
inner.push(rightNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
var outerNode = new mathMLTree.MathNode("mrow", inner);
|
||||||
|
|
||||||
|
return outerNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.accent = function(group, options) {
|
||||||
|
var accentNode = new mathMLTree.MathNode(
|
||||||
|
"mo", [makeText(group.value.accent, group.mode)]);
|
||||||
|
|
||||||
|
var node = new mathMLTree.MathNode(
|
||||||
|
"mover",
|
||||||
|
[buildGroup(group.value.base, options),
|
||||||
|
accentNode]);
|
||||||
|
|
||||||
|
node.setAttribute("accent", "true");
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.spacing = function(group) {
|
||||||
|
var node;
|
||||||
|
|
||||||
|
if (group.value === "\\ " || group.value === "\\space" ||
|
||||||
|
group.value === " " || group.value === "~") {
|
||||||
|
node = new mathMLTree.MathNode(
|
||||||
|
"mtext", [new mathMLTree.TextNode("\u00a0")]);
|
||||||
|
} else {
|
||||||
|
node = new mathMLTree.MathNode("mspace");
|
||||||
|
|
||||||
|
node.setAttribute(
|
||||||
|
"width", buildCommon.spacingFunctions[group.value].size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.op = function(group) {
|
||||||
|
var node;
|
||||||
|
|
||||||
|
// TODO(emily): handle big operators using the `largeop` attribute
|
||||||
|
|
||||||
|
if (group.value.symbol) {
|
||||||
|
// This is a symbol. Just add the symbol.
|
||||||
|
node = new mathMLTree.MathNode(
|
||||||
|
"mo", [makeText(group.value.body, group.mode)]);
|
||||||
|
} else {
|
||||||
|
// This is a text operator. Add all of the characters from the
|
||||||
|
// operator's name.
|
||||||
|
// TODO(emily): Add a space in the middle of some of these
|
||||||
|
// operators, like \limsup.
|
||||||
|
node = new mathMLTree.MathNode(
|
||||||
|
"mi", [new mathMLTree.TextNode(group.value.body.slice(1))]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.katex = function(group) {
|
||||||
|
var node = new mathMLTree.MathNode(
|
||||||
|
"mtext", [new mathMLTree.TextNode("KaTeX")]);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.font = function(group, options) {
|
||||||
|
var font = group.value.font;
|
||||||
|
return buildGroup(group.value.body, options.withFont(font));
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.delimsizing = function(group) {
|
||||||
|
var children = [];
|
||||||
|
|
||||||
|
if (group.value.value !== ".") {
|
||||||
|
children.push(makeText(group.value.value, group.mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
var node = new mathMLTree.MathNode("mo", children);
|
||||||
|
|
||||||
|
if (group.value.delimType === "open" ||
|
||||||
|
group.value.delimType === "close") {
|
||||||
|
// Only some of the delimsizing functions act as fences, and they
|
||||||
|
// return "open" or "close" delimTypes.
|
||||||
|
node.setAttribute("fence", "true");
|
||||||
|
} else {
|
||||||
|
// Explicitly disable fencing if it's not a fence, to override the
|
||||||
|
// defaults.
|
||||||
|
node.setAttribute("fence", "false");
|
||||||
|
}
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.styling = function(group, options) {
|
||||||
|
var inner = buildExpression(group.value.value, options);
|
||||||
|
|
||||||
|
var node = new mathMLTree.MathNode("mstyle", inner);
|
||||||
|
|
||||||
|
var styleAttributes = {
|
||||||
|
"display": ["0", "true"],
|
||||||
|
"text": ["0", "false"],
|
||||||
|
"script": ["1", "false"],
|
||||||
|
"scriptscript": ["2", "false"]
|
||||||
|
};
|
||||||
|
|
||||||
|
var attr = styleAttributes[group.value.style];
|
||||||
|
|
||||||
|
node.setAttribute("scriptlevel", attr[0]);
|
||||||
|
node.setAttribute("displaystyle", attr[1]);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.sizing = function(group, options) {
|
||||||
|
var inner = buildExpression(group.value.value, options);
|
||||||
|
|
||||||
|
var node = new mathMLTree.MathNode("mstyle", inner);
|
||||||
|
|
||||||
|
// TODO(emily): This doesn't produce the correct size for nested size
|
||||||
|
// changes, because we don't keep state of what style we're currently
|
||||||
|
// in, so we can't reset the size to normal before changing it. Now
|
||||||
|
// that we're passing an options parameter we should be able to fix
|
||||||
|
// this.
|
||||||
|
node.setAttribute(
|
||||||
|
"mathsize", buildCommon.sizingMultiplier[group.value.size] + "em");
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.overline = function(group, options) {
|
||||||
|
var operator = new mathMLTree.MathNode(
|
||||||
|
"mo", [new mathMLTree.TextNode("\u203e")]);
|
||||||
|
operator.setAttribute("stretchy", "true");
|
||||||
|
|
||||||
|
var node = new mathMLTree.MathNode(
|
||||||
|
"mover",
|
||||||
|
[buildGroup(group.value.body, options),
|
||||||
|
operator]);
|
||||||
|
node.setAttribute("accent", "true");
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.rule = function(group) {
|
||||||
|
// TODO(emily): Figure out if there's an actual way to draw black boxes
|
||||||
|
// in MathML.
|
||||||
|
var node = new mathMLTree.MathNode("mrow");
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.llap = function(group, options) {
|
||||||
|
var node = new mathMLTree.MathNode(
|
||||||
|
"mpadded", [buildGroup(group.value.body, options)]);
|
||||||
|
|
||||||
|
node.setAttribute("lspace", "-1width");
|
||||||
|
node.setAttribute("width", "0px");
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.rlap = function(group, options) {
|
||||||
|
var node = new mathMLTree.MathNode(
|
||||||
|
"mpadded", [buildGroup(group.value.body, options)]);
|
||||||
|
|
||||||
|
node.setAttribute("width", "0px");
|
||||||
|
|
||||||
|
return node;
|
||||||
|
};
|
||||||
|
|
||||||
|
groupTypes.phantom = function(group, options, prev) {
|
||||||
|
var inner = buildExpression(group.value.value, options);
|
||||||
|
return new mathMLTree.MathNode("mphantom", inner);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user