Implement $...$ within \text via styling node (#637)

This commit is contained in:
Erik Demaine
2017-06-10 15:03:22 -05:00
committed by Kevin Barabash
parent 9913242245
commit 7fdb1eed81
6 changed files with 85 additions and 17 deletions

View File

@@ -507,6 +507,20 @@ Parser.prototype.parseImplicitGroup = function() {
body: new ParseNode("ordgroup", body, this.mode),
}, this.mode);
}
} else if (func === "$") {
if (this.mode === "math") {
throw new ParseError("$ within math mode");
}
this.consume();
const outerMode = this.mode;
this.switchMode("math");
const body = this.parseExpression(false, "$");
this.expect("$", true);
this.switchMode(outerMode);
return new ParseNode("styling", {
style: "text",
value: body,
}, "math");
} else {
// Defer to parseFunction if it's not a function we handle
return this.parseFunction(start);
@@ -878,6 +892,10 @@ Parser.prototype.parseSymbol = function() {
return new ParseFuncOrArgument(
new ParseNode("textord", nucleus.text, this.mode, nucleus),
false, nucleus);
} else if (nucleus.text === "$") {
return new ParseFuncOrArgument(
nucleus.text,
false, nucleus);
} else {
return null;
}

View File

@@ -63,13 +63,19 @@ const getVariant = function(group, options) {
*/
const groupTypes = {};
const defaultVariant = {
"mi": "italic",
"mn": "normal",
"mtext": "normal",
};
groupTypes.mathord = function(group, options) {
const node = new mathMLTree.MathNode(
"mi",
[makeText(group.value, group.mode)]);
const variant = getVariant(group, options);
if (variant) {
const variant = getVariant(group, options) || "italic";
if (variant !== defaultVariant[node.type]) {
node.setAttribute("mathvariant", variant);
}
return node;
@@ -81,15 +87,16 @@ groupTypes.textord = function(group, options) {
const variant = getVariant(group, options) || "normal";
let node;
if (/[0-9]/.test(group.value)) {
if (group.mode === 'text') {
node = new mathMLTree.MathNode("mtext", [text]);
} else 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);
}
} else {
node = new mathMLTree.MathNode("mi", [text]);
}
if (variant !== defaultVariant[node.type]) {
node.setAttribute("mathvariant", variant);
}
@@ -149,11 +156,32 @@ groupTypes.ordgroup = function(group, options) {
};
groupTypes.text = function(group, options) {
const inner = buildExpression(group.value.body, options);
const body = group.value.body;
const node = new mathMLTree.MathNode("mtext", inner);
// Convert each element of the body into MathML, and combine consecutive
// <mtext> outputs into a single <mtext> tag. In this way, we don't
// nest non-text items (e.g., $nested-math$) within an <mtext>.
const inner = [];
let currentText = null;
for (let i = 0; i < body.length; i++) {
const group = buildGroup(body[i], options);
if (group.type === 'mtext' && currentText != null) {
Array.prototype.push.apply(currentText.children, group.children);
} else {
inner.push(group);
if (group.type === 'mtext') {
currentText = group;
}
}
}
return node;
// If there is a single tag in the end (presumably <mtext>),
// just return it. Otherwise, wrap them in an <mrow>.
if (inner.length === 1) {
return inner[0];
} else {
return new mathMLTree.MathNode("mrow", inner);
}
};
groupTypes.color = function(group, options) {