Fix \operatorname (#1461)
* Fix operatorname * Update MathML * Update screenshots * Fix lint error * Pick up comment * Remove duplicate lines * Fix lint error * Remove duplicate code * Replace \pi with \Pi in test * Revise RegEx * Update RegEx
@@ -25,64 +25,80 @@ defineFunction({
|
||||
},
|
||||
|
||||
htmlBuilder: (group, options) => {
|
||||
const output = [];
|
||||
if (group.value.value.length > 0) {
|
||||
let letter = "";
|
||||
let mode = "";
|
||||
|
||||
const groupValue = group.value.value.map(child => {
|
||||
const childValue = child.value;
|
||||
// In the amsopn package, \newmcodes@ changes four
|
||||
// characters, *-/:’, from math operators back into text.
|
||||
if (typeof childValue === "string" &&
|
||||
"*-/:".indexOf(childValue) !== -1) {
|
||||
if (typeof childValue === "string") {
|
||||
return new ParseNode("textord", childValue, child.mode);
|
||||
} else {
|
||||
return child;
|
||||
}
|
||||
});
|
||||
|
||||
// Consolidate Greek letter function names into symbol characters.
|
||||
const temp = html.buildExpression(
|
||||
// Consolidate function names into symbol characters.
|
||||
const expression = html.buildExpression(
|
||||
groupValue, options.withFont("mathrm"), true);
|
||||
|
||||
// All we want from temp are the letters. With them, we'll
|
||||
// create a text operator similar to \tan or \cos.
|
||||
for (const child of temp) {
|
||||
for (const child of expression) {
|
||||
if (child instanceof domTree.symbolNode) {
|
||||
letter = child.value;
|
||||
|
||||
// In the amsopn package, \newmcodes@ changes four
|
||||
// characters, *-/:’, from math operators back into text.
|
||||
// Given what is in temp, we have to address two of them.
|
||||
letter = letter.replace(/\u2212/, "-"); // minus => hyphen
|
||||
letter = letter.replace(/\u2217/, "*");
|
||||
|
||||
// Use math mode for Greek letters
|
||||
mode = (/[\u0391-\u03D7]/.test(letter) ? "math" : "text");
|
||||
output.push(buildCommon.mathsym(letter, mode));
|
||||
} else {
|
||||
output.push(child);
|
||||
// Per amsopn package,
|
||||
// change minus to hyphen and \ast to asterisk
|
||||
child.value = child.value.replace(/\u2212/, "-")
|
||||
.replace(/\u2217/, "*");
|
||||
}
|
||||
}
|
||||
return buildCommon.makeSpan(["mop"], expression, options);
|
||||
} else {
|
||||
return buildCommon.makeSpan(["mop"], [], options);
|
||||
}
|
||||
return buildCommon.makeSpan(["mop"], output, options);
|
||||
},
|
||||
|
||||
mathmlBuilder: (group, options) => {
|
||||
// The steps taken here are similar to the html version.
|
||||
let output = [];
|
||||
if (group.value.value.length > 0) {
|
||||
const temp = mml.buildExpression(
|
||||
group.value.value, options.withFont("mathrm"));
|
||||
let expression = mml.buildExpression(
|
||||
group.value.value, options.withFont("mathrm"));
|
||||
|
||||
let word = temp.map(node => node.toText()).join("");
|
||||
word = word.replace(/\u2212/g, "-");
|
||||
word = word.replace(/\u2217/g, "*");
|
||||
// word has already been escaped by `node.toText()`
|
||||
output = [new mathMLTree.TextNode(word, false)];
|
||||
// Is expression a string or has it something like a fraction?
|
||||
let isAllString = true; // default
|
||||
for (const node of expression) {
|
||||
if (node instanceof mathMLTree.SpaceNode) {
|
||||
// Do nothing
|
||||
} else {
|
||||
switch (node.type) {
|
||||
case "mi":
|
||||
case "mn":
|
||||
case "ms":
|
||||
case "mspace":
|
||||
case "mtext":
|
||||
break; // Do nothing yet.
|
||||
case "mo":
|
||||
if (node.children.length === 1) {
|
||||
if (node.children[0] instanceof mathMLTree.TextNode ===
|
||||
false) {
|
||||
isAllString = false;
|
||||
} else {
|
||||
node.children[0].text =
|
||||
node.children[0].text.replace(/\u2212/, "-")
|
||||
.replace(/\u2217/, "*");
|
||||
}
|
||||
} else {
|
||||
isAllString = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
isAllString = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
const identifier = new mathMLTree.MathNode("mi", output);
|
||||
|
||||
if (isAllString) {
|
||||
// Write a single TextNode instead of multiple nested tags.
|
||||
const word = expression.map(node => node.toText()).join("");
|
||||
// word has already been escaped by `node.toText()`
|
||||
expression = [new mathMLTree.TextNode(word, false)];
|
||||
}
|
||||
|
||||
const identifier = new mathMLTree.MathNode("mi", expression);
|
||||
identifier.setAttribute("mathvariant", "normal");
|
||||
|
||||
// \u2061 is the same as ⁡
|
||||
|
@@ -2471,6 +2471,12 @@ describe("An aligned environment", function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe("operatorname support", function() {
|
||||
it("should not fail", function() {
|
||||
expect("\\operatorname{x*Π∑\\Pi\\sum\\frac a b}").toBuild();
|
||||
});
|
||||
});
|
||||
|
||||
describe("An href command", function() {
|
||||
it("should parse its input", function() {
|
||||
expect("\\href{http://example.com/}{example here}").toParse();
|
||||
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 14 KiB |