mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-05 19:28:39 +00:00
Flatten a bunch of non-pervasive ParseNode types (part 1) (#1551)
* Flatten "url" ParseNode. * Flatten "href" ParseNode. * Flatten "verb" ParseNode. * Flatten "tag" ParseNode. * Flatten "cr" ParseNode. * Flatten "delimsizing" ParseNode. * Flatten "middle" ParseNode. * Flatten "leftright" ParseNode. * Flatten "leftright-right" ParseNode. * Flatten "mathchoice" ParseNode. * Remove unused ParseNode type "mod". * Flatten "mclass" ParseNode. * Flatten "font" ParseNode. * Flatten "phantom" ParseNode. * Flatten "hphantom" ParseNode. * Flatten "vphantom" ParseNode.
This commit is contained in:
@@ -942,10 +942,7 @@ export default class Parser {
|
||||
const urlArg = {
|
||||
type: "url",
|
||||
mode: this.mode,
|
||||
value: {
|
||||
type: "url",
|
||||
value: url,
|
||||
},
|
||||
url,
|
||||
};
|
||||
this.consume();
|
||||
if (funcName === "\\href") { // two arguments
|
||||
@@ -983,11 +980,8 @@ export default class Parser {
|
||||
return newArgument({
|
||||
type: "verb",
|
||||
mode: "text",
|
||||
value: {
|
||||
type: "verb",
|
||||
body: arg,
|
||||
star: star,
|
||||
},
|
||||
body: arg,
|
||||
star,
|
||||
}, nucleus);
|
||||
}
|
||||
// At this point, we should have a symbol, possibly with accents.
|
||||
|
@@ -613,8 +613,8 @@ const makeVList = function(params: VListParam, options: Options): DomSpan {
|
||||
|
||||
// Converts verb group into body string, dealing with \verb* form
|
||||
const makeVerb = function(group: ParseNode<"verb">, options: Options): string {
|
||||
let text = group.value.body;
|
||||
if (group.value.star) {
|
||||
let text = group.body;
|
||||
if (group.star) {
|
||||
text = text.replace(/ /g, '\u2423'); // Open Box
|
||||
} else {
|
||||
text = text.replace(/ /g, '\xA0'); // No-Break Space
|
||||
|
@@ -309,8 +309,8 @@ export default function buildHTML(tree: AnyParseNode[], options: Options): DomSp
|
||||
// Strip off outer tag wrapper for processing below.
|
||||
let tag = null;
|
||||
if (tree.length === 1 && tree[0].type === "tag") {
|
||||
tag = tree[0].value.tag;
|
||||
tree = tree[0].value.body;
|
||||
tag = tree[0].tag;
|
||||
tree = tree[0].body;
|
||||
}
|
||||
|
||||
// Build the expression contained in the tree
|
||||
|
@@ -139,7 +139,7 @@ function parseArray(
|
||||
if (!cr) {
|
||||
throw new ParseError(`Failed to parse function after ${next}`);
|
||||
}
|
||||
rowGaps.push(assertNodeType(cr, "cr").value.size);
|
||||
rowGaps.push(assertNodeType(cr, "cr").size);
|
||||
|
||||
// check for \hline(s) following the row separator
|
||||
hLinesBeforeRow.push(getHLines(parser));
|
||||
@@ -563,12 +563,9 @@ defineEnvironment({
|
||||
return delimiters ? {
|
||||
type: "leftright",
|
||||
mode: context.mode,
|
||||
value: {
|
||||
type: "leftright",
|
||||
body: [res],
|
||||
left: delimiters[0],
|
||||
right: delimiters[1],
|
||||
},
|
||||
body: [res],
|
||||
left: delimiters[0],
|
||||
right: delimiters[1],
|
||||
} : res;
|
||||
},
|
||||
htmlBuilder,
|
||||
@@ -614,12 +611,9 @@ defineEnvironment({
|
||||
return {
|
||||
type: "leftright",
|
||||
mode: context.mode,
|
||||
value: {
|
||||
type: "leftright",
|
||||
body: [res],
|
||||
left: "\\{",
|
||||
right: ".",
|
||||
},
|
||||
body: [res],
|
||||
left: "\\{",
|
||||
right: ".",
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
|
@@ -40,12 +40,9 @@ defineFunction({
|
||||
return {
|
||||
type: "cr",
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "cr",
|
||||
newLine,
|
||||
newRow,
|
||||
size: size && assertNodeType(size, "size"),
|
||||
},
|
||||
newLine,
|
||||
newRow,
|
||||
size: size && assertNodeType(size, "size"),
|
||||
};
|
||||
},
|
||||
|
||||
@@ -53,16 +50,16 @@ defineFunction({
|
||||
// not within tabular/array environments.
|
||||
|
||||
htmlBuilder: (group, options) => {
|
||||
if (group.value.newRow) {
|
||||
if (group.newRow) {
|
||||
throw new ParseError(
|
||||
"\\cr valid only within a tabular/array environment");
|
||||
}
|
||||
const span = buildCommon.makeSpan(["mspace"], [], options);
|
||||
if (group.value.newLine) {
|
||||
if (group.newLine) {
|
||||
span.classes.push("newline");
|
||||
if (group.value.size) {
|
||||
if (group.size) {
|
||||
span.style.marginTop =
|
||||
calculateSize(group.value.size.value.value, options) + "em";
|
||||
calculateSize(group.size.value.value, options) + "em";
|
||||
}
|
||||
}
|
||||
return span;
|
||||
@@ -70,11 +67,11 @@ defineFunction({
|
||||
|
||||
mathmlBuilder: (group, options) => {
|
||||
const node = new mathMLTree.MathNode("mspace");
|
||||
if (group.value.newLine) {
|
||||
if (group.newLine) {
|
||||
node.setAttribute("linebreak", "newline");
|
||||
if (group.value.size) {
|
||||
if (group.size) {
|
||||
node.setAttribute("height",
|
||||
calculateSize(group.value.size.value.value, options) + "em");
|
||||
calculateSize(group.size.value.value, options) + "em");
|
||||
}
|
||||
}
|
||||
return node;
|
||||
|
@@ -12,7 +12,6 @@ import * as mml from "../buildMathML";
|
||||
|
||||
import type Options from "../Options";
|
||||
import type {AnyParseNode, ParseNode, SymbolParseNode} from "../parseNode";
|
||||
import type {LeftRightDelimType} from "../parseNode";
|
||||
import type {FunctionContext} from "../defineFunction";
|
||||
|
||||
// Extra data needed for the delimiter handler down below
|
||||
@@ -52,7 +51,7 @@ const delimiters = [
|
||||
".",
|
||||
];
|
||||
|
||||
type IsMiddle = {value: string, options: Options};
|
||||
type IsMiddle = {delim: string, options: Options};
|
||||
|
||||
// Delimiter functions
|
||||
function checkDelimiter(
|
||||
@@ -87,39 +86,33 @@ defineFunction({
|
||||
return {
|
||||
type: "delimsizing",
|
||||
mode: context.parser.mode,
|
||||
value: {
|
||||
type: "delimsizing",
|
||||
size: delimiterSizes[context.funcName].size,
|
||||
mclass: delimiterSizes[context.funcName].mclass,
|
||||
value: delim.value,
|
||||
},
|
||||
size: delimiterSizes[context.funcName].size,
|
||||
mclass: delimiterSizes[context.funcName].mclass,
|
||||
delim: delim.value,
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
const delim = group.value.value;
|
||||
|
||||
if (delim === ".") {
|
||||
if (group.delim === ".") {
|
||||
// Empty delimiters still count as elements, even though they don't
|
||||
// show anything.
|
||||
return buildCommon.makeSpan([group.value.mclass]);
|
||||
return buildCommon.makeSpan([group.mclass]);
|
||||
}
|
||||
|
||||
// Use delimiter.sizedDelim to generate the delimiter.
|
||||
return delimiter.sizedDelim(
|
||||
delim, group.value.size, options, group.mode,
|
||||
[group.value.mclass]);
|
||||
group.delim, group.size, options, group.mode, [group.mclass]);
|
||||
},
|
||||
mathmlBuilder: (group) => {
|
||||
const children = [];
|
||||
|
||||
if (group.value.value !== ".") {
|
||||
children.push(mml.makeText(group.value.value, group.mode));
|
||||
if (group.delim !== ".") {
|
||||
children.push(mml.makeText(group.delim, group.mode));
|
||||
}
|
||||
|
||||
const node = new mathMLTree.MathNode("mo", children);
|
||||
|
||||
if (group.value.mclass === "mopen" ||
|
||||
group.value.mclass === "mclose") {
|
||||
if (group.mclass === "mopen" ||
|
||||
group.mclass === "mclose") {
|
||||
// Only some of the delimsizing functions act as fences, and they
|
||||
// return "mopen" or "mclose" mclass.
|
||||
node.setAttribute("fence", "true");
|
||||
@@ -134,11 +127,10 @@ defineFunction({
|
||||
});
|
||||
|
||||
|
||||
function leftRightGroupValue(group: ParseNode<"leftright">): LeftRightDelimType {
|
||||
if (!group.value.body) {
|
||||
function assertParsed(group: ParseNode<"leftright">) {
|
||||
if (!group.body) {
|
||||
throw new Error("Bug: The leftright ParseNode wasn't fully parsed.");
|
||||
}
|
||||
return group.value;
|
||||
}
|
||||
|
||||
|
||||
@@ -155,10 +147,7 @@ defineFunction({
|
||||
return {
|
||||
type: "leftright-right",
|
||||
mode: context.parser.mode,
|
||||
value: {
|
||||
type: "leftright-right",
|
||||
value: checkDelimiter(args[0], context).value,
|
||||
},
|
||||
delim: checkDelimiter(args[0], context).value,
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -188,18 +177,15 @@ defineFunction({
|
||||
return {
|
||||
type: "leftright",
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "leftright",
|
||||
body: body,
|
||||
left: delim.value,
|
||||
right: assertNodeType(right, "leftright-right").value.value,
|
||||
},
|
||||
body,
|
||||
left: delim.value,
|
||||
right: assertNodeType(right, "leftright-right").delim,
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
const groupValue = leftRightGroupValue(group);
|
||||
assertParsed(group);
|
||||
// Build the inner expression
|
||||
const inner = html.buildExpression(groupValue.body, options, true,
|
||||
const inner = html.buildExpression(group.body, options, true,
|
||||
[null, "mclose"]);
|
||||
|
||||
let innerHeight = 0;
|
||||
@@ -226,14 +212,14 @@ defineFunction({
|
||||
innerDepth *= options.sizeMultiplier;
|
||||
|
||||
let leftDelim;
|
||||
if (groupValue.left === ".") {
|
||||
if (group.left === ".") {
|
||||
// Empty delimiters in \left and \right make null delimiter spaces.
|
||||
leftDelim = html.makeNullDelimiter(options, ["mopen"]);
|
||||
} else {
|
||||
// Otherwise, use leftRightDelim to generate the correct sized
|
||||
// delimiter.
|
||||
leftDelim = delimiter.leftRightDelim(
|
||||
groupValue.left, innerHeight, innerDepth, options,
|
||||
group.left, innerHeight, innerDepth, options,
|
||||
group.mode, ["mopen"]);
|
||||
}
|
||||
// Add it to the beginning of the expression
|
||||
@@ -250,7 +236,7 @@ defineFunction({
|
||||
if (isMiddle) {
|
||||
// Apply the options that were active when \middle was called
|
||||
inner[i] = delimiter.leftRightDelim(
|
||||
isMiddle.value, innerHeight, innerDepth,
|
||||
isMiddle.delim, innerHeight, innerDepth,
|
||||
isMiddle.options, group.mode, []);
|
||||
}
|
||||
}
|
||||
@@ -258,11 +244,11 @@ defineFunction({
|
||||
|
||||
let rightDelim;
|
||||
// Same for the right delimiter
|
||||
if (groupValue.right === ".") {
|
||||
if (group.right === ".") {
|
||||
rightDelim = html.makeNullDelimiter(options, ["mclose"]);
|
||||
} else {
|
||||
rightDelim = delimiter.leftRightDelim(
|
||||
groupValue.right, innerHeight, innerDepth, options,
|
||||
group.right, innerHeight, innerDepth, options,
|
||||
group.mode, ["mclose"]);
|
||||
}
|
||||
// Add it to the end of the expression.
|
||||
@@ -271,21 +257,21 @@ defineFunction({
|
||||
return buildCommon.makeSpan(["minner"], inner, options);
|
||||
},
|
||||
mathmlBuilder: (group, options) => {
|
||||
const groupValue = leftRightGroupValue(group);
|
||||
const inner = mml.buildExpression(groupValue.body, options);
|
||||
assertParsed(group);
|
||||
const inner = mml.buildExpression(group.body, options);
|
||||
|
||||
if (groupValue.left !== ".") {
|
||||
if (group.left !== ".") {
|
||||
const leftNode = new mathMLTree.MathNode(
|
||||
"mo", [mml.makeText(groupValue.left, group.mode)]);
|
||||
"mo", [mml.makeText(group.left, group.mode)]);
|
||||
|
||||
leftNode.setAttribute("fence", "true");
|
||||
|
||||
inner.unshift(leftNode);
|
||||
}
|
||||
|
||||
if (groupValue.right !== ".") {
|
||||
if (group.right !== ".") {
|
||||
const rightNode = new mathMLTree.MathNode(
|
||||
"mo", [mml.makeText(groupValue.right, group.mode)]);
|
||||
"mo", [mml.makeText(group.right, group.mode)]);
|
||||
|
||||
rightNode.setAttribute("fence", "true");
|
||||
|
||||
@@ -311,22 +297,19 @@ defineFunction({
|
||||
return {
|
||||
type: "middle",
|
||||
mode: context.parser.mode,
|
||||
value: {
|
||||
type: "middle",
|
||||
value: delim.value,
|
||||
},
|
||||
delim: delim.value,
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
let middleDelim;
|
||||
if (group.value.value === ".") {
|
||||
if (group.delim === ".") {
|
||||
middleDelim = html.makeNullDelimiter(options, []);
|
||||
} else {
|
||||
middleDelim = delimiter.sizedDelim(
|
||||
group.value.value, 1, options,
|
||||
group.delim, 1, options,
|
||||
group.mode, []);
|
||||
|
||||
const isMiddle: IsMiddle = {value: group.value.value, options};
|
||||
const isMiddle: IsMiddle = {delim: group.delim, options};
|
||||
// Property `isMiddle` not defined on `span`. It is only used in
|
||||
// this file above.
|
||||
// TODO: Fix this violation of the `span` type and possibly rename
|
||||
@@ -338,7 +321,7 @@ defineFunction({
|
||||
},
|
||||
mathmlBuilder: (group, options) => {
|
||||
const middleNode = new mathMLTree.MathNode(
|
||||
"mo", [mml.makeText(group.value.value, group.mode)]);
|
||||
"mo", [mml.makeText(group.delim, group.mode)]);
|
||||
middleNode.setAttribute("fence", "true");
|
||||
return middleNode;
|
||||
},
|
||||
|
@@ -7,17 +7,18 @@ import defineFunction from "../defineFunction";
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
|
||||
import type {ParseNode} from "../parseNode";
|
||||
|
||||
const htmlBuilder = (group, options) => {
|
||||
const font = group.value.font;
|
||||
const htmlBuilder = (group: ParseNode<"font">, options) => {
|
||||
const font = group.font;
|
||||
const newOptions = options.withFont(font);
|
||||
return html.buildGroup(group.value.body, newOptions);
|
||||
return html.buildGroup(group.body, newOptions);
|
||||
};
|
||||
|
||||
const mathmlBuilder = (group, options) => {
|
||||
const font = group.value.font;
|
||||
const mathmlBuilder = (group: ParseNode<"font">, options) => {
|
||||
const font = group.font;
|
||||
const newOptions = options.withFont(font);
|
||||
return mml.buildGroup(group.value.body, newOptions);
|
||||
return mml.buildGroup(group.body, newOptions);
|
||||
};
|
||||
|
||||
const fontAliases = {
|
||||
@@ -53,11 +54,8 @@ defineFunction({
|
||||
return {
|
||||
type: "font",
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "font",
|
||||
font: func.slice(1),
|
||||
body,
|
||||
},
|
||||
font: func.slice(1),
|
||||
body,
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
@@ -78,21 +76,15 @@ defineFunction({
|
||||
return {
|
||||
type: "mclass",
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "mclass",
|
||||
mclass: binrelClass(body),
|
||||
value: [
|
||||
{
|
||||
type: "font",
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "font",
|
||||
font: "boldsymbol",
|
||||
body,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
mclass: binrelClass(body),
|
||||
body: [
|
||||
{
|
||||
type: "font",
|
||||
mode: parser.mode,
|
||||
font: "boldsymbol",
|
||||
body,
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -114,14 +106,11 @@ defineFunction({
|
||||
return {
|
||||
type: "font",
|
||||
mode: mode,
|
||||
value: {
|
||||
type: "font",
|
||||
font: style,
|
||||
body: {
|
||||
type: "ordgroup",
|
||||
mode: parser.mode,
|
||||
value: body,
|
||||
},
|
||||
font: style,
|
||||
body: {
|
||||
type: "ordgroup",
|
||||
mode: parser.mode,
|
||||
value: body,
|
||||
},
|
||||
};
|
||||
},
|
||||
|
@@ -18,31 +18,21 @@ defineFunction({
|
||||
},
|
||||
handler: ({parser}, args) => {
|
||||
const body = args[1];
|
||||
const href = assertNodeType(args[0], "url").value.value;
|
||||
const href = assertNodeType(args[0], "url").url;
|
||||
return {
|
||||
type: "href",
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "href",
|
||||
href: href,
|
||||
body: ordargument(body),
|
||||
},
|
||||
href,
|
||||
body: ordargument(body),
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
const elements = html.buildExpression(
|
||||
group.value.body,
|
||||
options,
|
||||
false
|
||||
);
|
||||
|
||||
const href = group.value.href;
|
||||
|
||||
return new buildCommon.makeAnchor(href, [], elements, options);
|
||||
const elements = html.buildExpression(group.body, options, false);
|
||||
return new buildCommon.makeAnchor(group.href, [], elements, options);
|
||||
},
|
||||
mathmlBuilder: (group, options) => {
|
||||
const math = mml.buildExpressionRow(group.value.body, options);
|
||||
assertType(math, MathNode).setAttribute("href", group.value.href);
|
||||
const math = mml.buildExpressionRow(group.body, options);
|
||||
assertType(math, MathNode).setAttribute("href", group.href);
|
||||
return math;
|
||||
},
|
||||
});
|
||||
@@ -56,7 +46,7 @@ defineFunction({
|
||||
allowedInText: true,
|
||||
},
|
||||
handler: ({parser}, args) => {
|
||||
const href = assertNodeType(args[0], "url").value.value;
|
||||
const href = assertNodeType(args[0], "url").url;
|
||||
const chars = [];
|
||||
for (let i = 0; i < href.length; i++) {
|
||||
let c = href[i];
|
||||
@@ -81,11 +71,8 @@ defineFunction({
|
||||
return {
|
||||
type: "href",
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "href",
|
||||
href: href,
|
||||
body: ordargument(body),
|
||||
},
|
||||
href,
|
||||
body: ordargument(body),
|
||||
};
|
||||
},
|
||||
});
|
||||
|
@@ -6,19 +6,16 @@ import Style from "../Style";
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
|
||||
const chooseMathStyle = (group, options) => {
|
||||
const style = options.style;
|
||||
if (style.size === Style.DISPLAY.size) {
|
||||
return group.value.display;
|
||||
} else if (style.size === Style.TEXT.size) {
|
||||
return group.value.text;
|
||||
} else if (style.size === Style.SCRIPT.size) {
|
||||
return group.value.script;
|
||||
} else if (style.size === Style.SCRIPTSCRIPT.size) {
|
||||
return group.value.scriptscript;
|
||||
}
|
||||
return group.value.text;
|
||||
import type {ParseNode} from "../parseNode";
|
||||
|
||||
const chooseMathStyle = (group: ParseNode<"mathchoice">, options) => {
|
||||
switch (options.style.size) {
|
||||
case Style.DISPLAY.size: return group.display;
|
||||
case Style.TEXT.size: return group.text;
|
||||
case Style.SCRIPT.size: return group.script;
|
||||
case Style.SCRIPTSCRIPT.size: return group.scriptscript;
|
||||
default: return group.text;
|
||||
}
|
||||
};
|
||||
|
||||
defineFunction({
|
||||
@@ -31,13 +28,10 @@ defineFunction({
|
||||
return {
|
||||
type: "mathchoice",
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "mathchoice",
|
||||
display: ordargument(args[0]),
|
||||
text: ordargument(args[1]),
|
||||
script: ordargument(args[2]),
|
||||
scriptscript: ordargument(args[3]),
|
||||
},
|
||||
display: ordargument(args[0]),
|
||||
text: ordargument(args[1]),
|
||||
script: ordargument(args[2]),
|
||||
scriptscript: ordargument(args[3]),
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
|
@@ -7,15 +7,17 @@ import type {AnyParseNode} from "../parseNode";
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
|
||||
import type {ParseNode} from "../parseNode";
|
||||
|
||||
const makeSpan = buildCommon.makeSpan;
|
||||
|
||||
function htmlBuilder(group, options) {
|
||||
const elements = html.buildExpression(group.value.value, options, true);
|
||||
return makeSpan([group.value.mclass], elements, options);
|
||||
function htmlBuilder(group: ParseNode<"mclass">, options) {
|
||||
const elements = html.buildExpression(group.body, options, true);
|
||||
return makeSpan([group.mclass], elements, options);
|
||||
}
|
||||
|
||||
function mathmlBuilder(group, options) {
|
||||
const inner = mml.buildExpression(group.value.value, options);
|
||||
function mathmlBuilder(group: ParseNode<"mclass">, options) {
|
||||
const inner = mml.buildExpression(group.body, options);
|
||||
return mathMLTree.newDocumentFragment(inner);
|
||||
}
|
||||
|
||||
@@ -34,11 +36,8 @@ defineFunction({
|
||||
return {
|
||||
type: "mclass",
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "mclass",
|
||||
mclass: "m" + funcName.substr(5),
|
||||
value: ordargument(body),
|
||||
},
|
||||
mclass: "m" + funcName.substr(5),
|
||||
body: ordargument(body),
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
@@ -70,11 +69,8 @@ defineFunction({
|
||||
return {
|
||||
type: "mclass",
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "mclass",
|
||||
mclass: binrelClass(args[0]),
|
||||
value: [args[1]],
|
||||
},
|
||||
mclass: binrelClass(args[0]),
|
||||
body: [args[1]],
|
||||
};
|
||||
},
|
||||
});
|
||||
@@ -119,11 +115,8 @@ defineFunction({
|
||||
return {
|
||||
type: "mclass",
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "mclass",
|
||||
mclass: mclass,
|
||||
value: [supsub],
|
||||
},
|
||||
mclass,
|
||||
body: [supsub],
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
|
@@ -18,15 +18,12 @@ defineFunction({
|
||||
return {
|
||||
type: "phantom",
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "phantom",
|
||||
value: ordargument(body),
|
||||
},
|
||||
body: ordargument(body),
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
const elements = html.buildExpression(
|
||||
group.value.value,
|
||||
group.body,
|
||||
options.withPhantom(),
|
||||
false
|
||||
);
|
||||
@@ -36,7 +33,7 @@ defineFunction({
|
||||
return new buildCommon.makeFragment(elements);
|
||||
},
|
||||
mathmlBuilder: (group, options) => {
|
||||
const inner = mml.buildExpression(group.value.value, options);
|
||||
const inner = mml.buildExpression(group.body, options);
|
||||
return new mathMLTree.MathNode("mphantom", inner);
|
||||
},
|
||||
});
|
||||
@@ -53,16 +50,12 @@ defineFunction({
|
||||
return {
|
||||
type: "hphantom",
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "hphantom",
|
||||
value: ordargument(body),
|
||||
body: body,
|
||||
},
|
||||
body,
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
let node = buildCommon.makeSpan(
|
||||
[], [html.buildGroup(group.value.body, options.withPhantom())]);
|
||||
[], [html.buildGroup(group.body, options.withPhantom())]);
|
||||
node.height = 0;
|
||||
node.depth = 0;
|
||||
if (node.children) {
|
||||
@@ -81,7 +74,7 @@ defineFunction({
|
||||
return node;
|
||||
},
|
||||
mathmlBuilder: (group, options) => {
|
||||
const inner = mml.buildExpression(group.value.value, options);
|
||||
const inner = mml.buildExpression(ordargument(group.body), options);
|
||||
const node = new mathMLTree.MathNode("mphantom", inner);
|
||||
node.setAttribute("height", "0px");
|
||||
return node;
|
||||
@@ -100,23 +93,19 @@ defineFunction({
|
||||
return {
|
||||
type: "vphantom",
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "vphantom",
|
||||
value: ordargument(body),
|
||||
body: body,
|
||||
},
|
||||
body,
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
const inner = buildCommon.makeSpan(
|
||||
["inner"],
|
||||
[html.buildGroup(group.value.body, options.withPhantom())]);
|
||||
[html.buildGroup(group.body, options.withPhantom())]);
|
||||
const fix = buildCommon.makeSpan(["fix"], []);
|
||||
return buildCommon.makeSpan(
|
||||
["mord", "rlap"], [inner, fix], options);
|
||||
},
|
||||
mathmlBuilder: (group, options) => {
|
||||
const inner = mml.buildExpression(group.value.value, options);
|
||||
const inner = mml.buildExpression(ordargument(group.body), options);
|
||||
const node = new mathMLTree.MathNode("mphantom", inner);
|
||||
node.setAttribute("width", "0px");
|
||||
return node;
|
||||
|
@@ -10,10 +10,10 @@ defineFunctionBuilders({
|
||||
const table = new mathMLTree.MathNode("mtable", [
|
||||
new mathMLTree.MathNode("mlabeledtr", [
|
||||
new mathMLTree.MathNode("mtd", [
|
||||
mml.buildExpressionRow(group.value.tag, options),
|
||||
mml.buildExpressionRow(group.tag, options),
|
||||
]),
|
||||
new mathMLTree.MathNode("mtd", [
|
||||
mml.buildExpressionRow(group.value.body, options),
|
||||
mml.buildExpressionRow(group.body, options),
|
||||
]),
|
||||
]),
|
||||
]);
|
||||
|
117
src/parseNode.js
117
src/parseNode.js
@@ -10,13 +10,6 @@ import type {Measurement} from "./units";
|
||||
export type NodeType = $Keys<ParseNodeTypes>;
|
||||
export type ParseNode<TYPE: NodeType> = $ElementType<ParseNodeTypes, TYPE>;
|
||||
|
||||
export type LeftRightDelimType = {|
|
||||
type: "leftright",
|
||||
body: AnyParseNode[],
|
||||
left: string,
|
||||
right: string,
|
||||
|};
|
||||
|
||||
// ParseNode's corresponding to Symbol `Group`s in symbols.js.
|
||||
export type SymbolParseNode =
|
||||
ParseNode<"atom"> |
|
||||
@@ -116,11 +109,8 @@ type ParseNodeTypes = {
|
||||
type: "tag",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "tag",
|
||||
body: AnyParseNode[],
|
||||
tag: AnyParseNode[],
|
||||
|},
|
||||
body: AnyParseNode[],
|
||||
tag: AnyParseNode[],
|
||||
|},
|
||||
"text": {|
|
||||
type: "text",
|
||||
@@ -136,20 +126,14 @@ type ParseNodeTypes = {
|
||||
type: "url",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "url",
|
||||
value: string,
|
||||
|},
|
||||
url: string,
|
||||
|},
|
||||
"verb": {|
|
||||
type: "verb",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "verb",
|
||||
body: string,
|
||||
star: boolean,
|
||||
|},
|
||||
body: string,
|
||||
star: boolean,
|
||||
|},
|
||||
// From symbol groups, constructed in Parser.js via `symbols` lookup.
|
||||
// (Some of these have "-token" suffix to distinguish them from existing
|
||||
@@ -216,23 +200,17 @@ type ParseNodeTypes = {
|
||||
type: "cr",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "cr",
|
||||
newRow: boolean,
|
||||
newLine: boolean,
|
||||
size: ?ParseNode<"size">,
|
||||
|},
|
||||
newRow: boolean,
|
||||
newLine: boolean,
|
||||
size: ?ParseNode<"size">,
|
||||
|},
|
||||
"delimsizing": {|
|
||||
type: "delimsizing",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "delimsizing",
|
||||
size: 1 | 2 | 3 | 4,
|
||||
mclass: "mopen" | "mclose" | "mrel" | "mord",
|
||||
value: string,
|
||||
|},
|
||||
size: 1 | 2 | 3 | 4,
|
||||
mclass: "mopen" | "mclose" | "mrel" | "mord",
|
||||
delim: string,
|
||||
|},
|
||||
"enclose": {|
|
||||
type: "enclose",
|
||||
@@ -260,11 +238,8 @@ type ParseNodeTypes = {
|
||||
type: "font",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "font",
|
||||
font: string,
|
||||
body: AnyParseNode,
|
||||
|},
|
||||
font: string,
|
||||
body: AnyParseNode,
|
||||
|},
|
||||
"genfrac": {|
|
||||
type: "genfrac",
|
||||
@@ -294,11 +269,8 @@ type ParseNodeTypes = {
|
||||
type: "href",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "href",
|
||||
href: string,
|
||||
body: AnyParseNode[],
|
||||
|},
|
||||
href: string,
|
||||
body: AnyParseNode[],
|
||||
|},
|
||||
"htmlmathml": {|
|
||||
type: "htmlmathml",
|
||||
@@ -344,57 +316,37 @@ type ParseNodeTypes = {
|
||||
type: "leftright",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: LeftRightDelimType,
|
||||
body: AnyParseNode[],
|
||||
left: string,
|
||||
right: string,
|
||||
|},
|
||||
"leftright-right": {|
|
||||
type: "leftright-right",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "leftright-right",
|
||||
value: string,
|
||||
|},
|
||||
delim: string,
|
||||
|},
|
||||
"mathchoice": {|
|
||||
type: "mathchoice",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "mathchoice",
|
||||
display: AnyParseNode[],
|
||||
text: AnyParseNode[],
|
||||
script: AnyParseNode[],
|
||||
scriptscript: AnyParseNode[],
|
||||
|},
|
||||
display: AnyParseNode[],
|
||||
text: AnyParseNode[],
|
||||
script: AnyParseNode[],
|
||||
scriptscript: AnyParseNode[],
|
||||
|},
|
||||
"middle": {|
|
||||
type: "middle",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "middle",
|
||||
value: string,
|
||||
|},
|
||||
delim: string,
|
||||
|},
|
||||
"mclass": {|
|
||||
type: "mclass",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "mclass",
|
||||
mclass: string,
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
|},
|
||||
"mod": {|
|
||||
type: "mod",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "mod",
|
||||
modType: string,
|
||||
value: ?AnyParseNode[],
|
||||
|},
|
||||
mclass: string,
|
||||
body: AnyParseNode[],
|
||||
|},
|
||||
"operatorname": {|
|
||||
type: "operatorname",
|
||||
@@ -418,30 +370,19 @@ type ParseNodeTypes = {
|
||||
type: "phantom",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "phantom",
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
body: AnyParseNode[],
|
||||
|},
|
||||
"hphantom": {|
|
||||
type: "hphantom",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "hphantom",
|
||||
body: AnyParseNode,
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
body: AnyParseNode,
|
||||
|},
|
||||
"vphantom": {|
|
||||
type: "vphantom",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "vphantom",
|
||||
body: AnyParseNode,
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
body: AnyParseNode,
|
||||
|},
|
||||
"raisebox": {|
|
||||
type: "raisebox",
|
||||
|
@@ -32,11 +32,8 @@ const parseTree = function(toParse: string, settings: Settings): AnyParseNode[]
|
||||
tree = [{
|
||||
type: "tag",
|
||||
mode: "text",
|
||||
value: {
|
||||
type: "tag",
|
||||
body: tree,
|
||||
tag: parser.parse(),
|
||||
},
|
||||
body: tree,
|
||||
tag: parser.parse(),
|
||||
}];
|
||||
}
|
||||
|
||||
|
@@ -110,7 +110,7 @@ const getBaseElem = function(group: AnyParseNode): AnyParseNode {
|
||||
return group;
|
||||
}
|
||||
} else if (group.type === "font") {
|
||||
return getBaseElem(group.value.body);
|
||||
return getBaseElem(group.body);
|
||||
} else {
|
||||
return group;
|
||||
}
|
||||
|
@@ -751,22 +751,19 @@ exports[`An implicit group parser within optional groups should work with old fo
|
||||
"value": [
|
||||
{
|
||||
"type": "font",
|
||||
"mode": "math",
|
||||
"value": {
|
||||
"type": "font",
|
||||
"body": {
|
||||
"type": "ordgroup",
|
||||
"mode": "math",
|
||||
"value": [
|
||||
{
|
||||
"type": "textord",
|
||||
"mode": "math",
|
||||
"value": "3"
|
||||
}
|
||||
]
|
||||
},
|
||||
"font": "mathtt"
|
||||
}
|
||||
"body": {
|
||||
"type": "ordgroup",
|
||||
"mode": "math",
|
||||
"value": [
|
||||
{
|
||||
"type": "textord",
|
||||
"mode": "math",
|
||||
"value": "3"
|
||||
}
|
||||
]
|
||||
},
|
||||
"font": "mathtt",
|
||||
"mode": "math"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@@ -95,7 +95,7 @@ describe("A rel parser", function() {
|
||||
group = group.value.html[0];
|
||||
}
|
||||
if (group.type === "mclass") {
|
||||
expect(group.value.mclass).toEqual("mrel");
|
||||
expect(group.mclass).toEqual("mrel");
|
||||
} else {
|
||||
expect(group.type).toEqual("atom");
|
||||
expect(group.family).toEqual("rel");
|
||||
@@ -895,16 +895,16 @@ describe("A delimiter sizing parser", function() {
|
||||
const leftParse = getParsed(normalDelim)[0];
|
||||
const rightParse = getParsed(bigDelim)[0];
|
||||
|
||||
expect(leftParse.value.mclass).toEqual("mopen");
|
||||
expect(rightParse.value.mclass).toEqual("mclose");
|
||||
expect(leftParse.mclass).toEqual("mopen");
|
||||
expect(rightParse.mclass).toEqual("mclose");
|
||||
});
|
||||
|
||||
it("should parse the correct size delimiter", function() {
|
||||
const smallParse = getParsed(normalDelim)[0];
|
||||
const bigParse = getParsed(bigDelim)[0];
|
||||
|
||||
expect(smallParse.value.size).toEqual(1);
|
||||
expect(bigParse.value.size).toEqual(4);
|
||||
expect(smallParse.size).toEqual(1);
|
||||
expect(bigParse.size).toEqual(4);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1122,8 +1122,8 @@ describe("A left/right parser", function() {
|
||||
const parse = getParsed(normalLeftRight)[0];
|
||||
|
||||
expect(parse.type).toEqual("leftright");
|
||||
expect(parse.value.left).toEqual("(");
|
||||
expect(parse.value.right).toEqual(")");
|
||||
expect(parse.left).toEqual("(");
|
||||
expect(parse.right).toEqual(")");
|
||||
});
|
||||
|
||||
it("should error when it is mismatched", function() {
|
||||
@@ -1476,37 +1476,37 @@ describe("A font parser", function() {
|
||||
|
||||
it("should produce the correct fonts", function() {
|
||||
const mathbbParse = getParsed`\mathbb x`[0];
|
||||
expect(mathbbParse.value.font).toEqual("mathbb");
|
||||
expect(mathbbParse.value.type).toEqual("font");
|
||||
expect(mathbbParse.font).toEqual("mathbb");
|
||||
expect(mathbbParse.type).toEqual("font");
|
||||
|
||||
const mathrmParse = getParsed`\mathrm x`[0];
|
||||
expect(mathrmParse.value.font).toEqual("mathrm");
|
||||
expect(mathrmParse.value.type).toEqual("font");
|
||||
expect(mathrmParse.font).toEqual("mathrm");
|
||||
expect(mathrmParse.type).toEqual("font");
|
||||
|
||||
const mathitParse = getParsed`\mathit x`[0];
|
||||
expect(mathitParse.value.font).toEqual("mathit");
|
||||
expect(mathitParse.value.type).toEqual("font");
|
||||
expect(mathitParse.font).toEqual("mathit");
|
||||
expect(mathitParse.type).toEqual("font");
|
||||
|
||||
const mathcalParse = getParsed`\mathcal C`[0];
|
||||
expect(mathcalParse.value.font).toEqual("mathcal");
|
||||
expect(mathcalParse.value.type).toEqual("font");
|
||||
expect(mathcalParse.font).toEqual("mathcal");
|
||||
expect(mathcalParse.type).toEqual("font");
|
||||
|
||||
const mathfrakParse = getParsed`\mathfrak C`[0];
|
||||
expect(mathfrakParse.value.font).toEqual("mathfrak");
|
||||
expect(mathfrakParse.value.type).toEqual("font");
|
||||
expect(mathfrakParse.font).toEqual("mathfrak");
|
||||
expect(mathfrakParse.type).toEqual("font");
|
||||
});
|
||||
|
||||
it("should parse nested font commands", function() {
|
||||
const nestedParse = getParsed`\mathbb{R \neq \mathrm{R}}`[0];
|
||||
expect(nestedParse.value.font).toEqual("mathbb");
|
||||
expect(nestedParse.value.type).toEqual("font");
|
||||
expect(nestedParse.font).toEqual("mathbb");
|
||||
expect(nestedParse.type).toEqual("font");
|
||||
|
||||
const bbBody = nestedParse.value.body.value;
|
||||
const bbBody = nestedParse.body.value;
|
||||
expect(bbBody).toHaveLength(3);
|
||||
expect(bbBody[0].type).toEqual("mathord");
|
||||
expect(bbBody[2].type).toEqual("font");
|
||||
expect(bbBody[2].value.font).toEqual("mathrm");
|
||||
expect(bbBody[2].value.type).toEqual("font");
|
||||
expect(bbBody[2].font).toEqual("mathrm");
|
||||
expect(bbBody[2].type).toEqual("font");
|
||||
});
|
||||
|
||||
it("should work with \\textcolor", function() {
|
||||
@@ -1515,8 +1515,8 @@ describe("A font parser", function() {
|
||||
expect(colorMathbbParse.value.color).toEqual("blue");
|
||||
const body = colorMathbbParse.value.value;
|
||||
expect(body).toHaveLength(1);
|
||||
expect(body[0].value.type).toEqual("font");
|
||||
expect(body[0].value.font).toEqual("mathbb");
|
||||
expect(body[0].type).toEqual("font");
|
||||
expect(body[0].font).toEqual("mathbb");
|
||||
});
|
||||
|
||||
it("should not parse a series of font commands", function() {
|
||||
@@ -1525,13 +1525,13 @@ describe("A font parser", function() {
|
||||
|
||||
it("should nest fonts correctly", function() {
|
||||
const bf = getParsed`\mathbf{a\mathrm{b}c}`[0];
|
||||
expect(bf.value.type).toEqual("font");
|
||||
expect(bf.value.font).toEqual("mathbf");
|
||||
expect(bf.value.body.value).toHaveLength(3);
|
||||
expect(bf.value.body.value[0].value).toEqual("a");
|
||||
expect(bf.value.body.value[1].value.type).toEqual("font");
|
||||
expect(bf.value.body.value[1].value.font).toEqual("mathrm");
|
||||
expect(bf.value.body.value[2].value).toEqual("c");
|
||||
expect(bf.type).toEqual("font");
|
||||
expect(bf.font).toEqual("mathbf");
|
||||
expect(bf.body.value).toHaveLength(3);
|
||||
expect(bf.body.value[0].value).toEqual("a");
|
||||
expect(bf.body.value[1].type).toEqual("font");
|
||||
expect(bf.body.value[1].font).toEqual("mathrm");
|
||||
expect(bf.body.value[2].value).toEqual("c");
|
||||
});
|
||||
|
||||
it("should have the correct greediness", function() {
|
||||
@@ -2292,7 +2292,7 @@ describe("A phantom parser", function() {
|
||||
const parse = getParsed`\phantom{x}`[0];
|
||||
|
||||
expect(parse.type).toEqual("phantom");
|
||||
expect(parse.value.value).toBeDefined();
|
||||
expect(parse.body).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2499,17 +2499,17 @@ describe("href and url commands", function() {
|
||||
it("should allow letters [#$%&~_^] without escaping", function() {
|
||||
const url = "http://example.org/~bar/#top?foo=$foo&bar=ba^r_boo%20baz";
|
||||
const parsed1 = getParsed(`\\href{${url}}{\\alpha}`)[0];
|
||||
expect(parsed1.value.href).toBe(url);
|
||||
expect(parsed1.href).toBe(url);
|
||||
const parsed2 = getParsed(`\\url{${url}}`)[0];
|
||||
expect(parsed2.value.href).toBe(url);
|
||||
expect(parsed2.href).toBe(url);
|
||||
});
|
||||
|
||||
it("should allow balanced braces in url", function() {
|
||||
const url = "http://example.org/{too}";
|
||||
const parsed1 = getParsed(`\\href{${url}}{\\alpha}`)[0];
|
||||
expect(parsed1.value.href).toBe(url);
|
||||
expect(parsed1.href).toBe(url);
|
||||
const parsed2 = getParsed(`\\url{${url}}`)[0];
|
||||
expect(parsed2.value.href).toBe(url);
|
||||
expect(parsed2.href).toBe(url);
|
||||
});
|
||||
|
||||
it("should not allow unbalanced brace(s) in url", function() {
|
||||
@@ -2523,9 +2523,9 @@ describe("href and url commands", function() {
|
||||
const url = "http://example.org/~bar/#top?foo=$}foo{&bar=bar^r_boo%20baz";
|
||||
const input = url.replace(/([#$%&~_^{}])/g, '\\$1');
|
||||
const parsed1 = getParsed(`\\href{${input}}{\\alpha}`)[0];
|
||||
expect(parsed1.value.href).toBe(url);
|
||||
expect(parsed1.href).toBe(url);
|
||||
const parsed2 = getParsed(`\\url{${input}}`)[0];
|
||||
expect(parsed2.value.href).toBe(url);
|
||||
expect(parsed2.href).toBe(url);
|
||||
});
|
||||
|
||||
it("should be marked up correctly", function() {
|
||||
|
Reference in New Issue
Block a user