mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-05 19:28:39 +00:00
Remove checkNodeType and assert/checkAtomFamily (#2137)
We used functions with $FlowFixMe as Flow couldn't refine ParseNode using its type. It seems the issue has been fixed and complicated function calls can be removed.
This commit is contained in:
committed by
Kevin Barabash
parent
981a9ea3a0
commit
fa8fbc0c18
@@ -7,7 +7,6 @@ import {validUnit} from "./units";
|
||||
import {supportedCodepoint} from "./unicodeScripts";
|
||||
import unicodeAccents from "./unicodeAccents";
|
||||
import unicodeSymbols from "./unicodeSymbols";
|
||||
import {checkNodeType} from "./parseNode";
|
||||
import ParseError from "./ParseError";
|
||||
import {combiningDiacriticalMarksEndRegex} from "./Lexer";
|
||||
import Settings from "./Settings";
|
||||
@@ -206,15 +205,14 @@ export default class Parser {
|
||||
let funcName;
|
||||
|
||||
for (let i = 0; i < body.length; i++) {
|
||||
const node = checkNodeType(body[i], "infix");
|
||||
if (node) {
|
||||
if (body[i].type === "infix") {
|
||||
if (overIndex !== -1) {
|
||||
throw new ParseError(
|
||||
"only one infix operator per group",
|
||||
node.token);
|
||||
body[i].token);
|
||||
}
|
||||
overIndex = i;
|
||||
funcName = node.replaceWith;
|
||||
funcName = body[i].replaceWith;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,21 +327,18 @@ export default class Parser {
|
||||
|
||||
if (lex.text === "\\limits" || lex.text === "\\nolimits") {
|
||||
// We got a limit control
|
||||
let opNode = checkNodeType(base, "op");
|
||||
if (opNode) {
|
||||
if (base && base.type === "op") {
|
||||
const limits = lex.text === "\\limits";
|
||||
opNode.limits = limits;
|
||||
opNode.alwaysHandleSupSub = true;
|
||||
base.limits = limits;
|
||||
base.alwaysHandleSupSub = true;
|
||||
} else if (base && base.type === "operatorname"
|
||||
&& base.alwaysHandleSupSub) {
|
||||
const limits = lex.text === "\\limits";
|
||||
base.limits = limits;
|
||||
} else {
|
||||
opNode = checkNodeType(base, "operatorname");
|
||||
if (opNode && opNode.alwaysHandleSupSub) {
|
||||
const limits = lex.text === "\\limits";
|
||||
opNode.limits = limits;
|
||||
} else {
|
||||
throw new ParseError(
|
||||
"Limit controls must follow a math operator",
|
||||
lex);
|
||||
}
|
||||
throw new ParseError(
|
||||
"Limit controls must follow a math operator",
|
||||
lex);
|
||||
}
|
||||
this.consume();
|
||||
} else if (lex.text === "^") {
|
||||
|
@@ -11,7 +11,6 @@ import Style from "./Style";
|
||||
import buildCommon from "./buildCommon";
|
||||
import {Anchor} from "./domTree";
|
||||
import utils from "./utils";
|
||||
import {checkNodeType} from "./parseNode";
|
||||
import {spacings, tightSpacings} from "./spacingData";
|
||||
import {_htmlGroupBuilders as groupBuilders} from "./defineFunction";
|
||||
import {DocumentFragment} from "./tree";
|
||||
@@ -83,11 +82,8 @@ export const buildExpression = function(
|
||||
|
||||
let glueOptions = options;
|
||||
if (expression.length === 1) {
|
||||
const node = checkNodeType(expression[0], "sizing") ||
|
||||
checkNodeType(expression[0], "styling");
|
||||
if (!node) {
|
||||
// No match.
|
||||
} else if (node.type === "sizing") {
|
||||
const node = expression[0];
|
||||
if (node.type === "sizing") {
|
||||
glueOptions = options.havingSize(node.size);
|
||||
} else if (node.type === "styling") {
|
||||
glueOptions = options.havingStyle(styleMap[node.style]);
|
||||
|
@@ -1,6 +1,4 @@
|
||||
// @flow
|
||||
import {checkNodeType} from "./parseNode";
|
||||
|
||||
import type Parser from "./Parser";
|
||||
import type {ParseNode, AnyParseNode, NodeType, UnsupportedCmdParseNode}
|
||||
from "./parseNode";
|
||||
@@ -228,6 +226,5 @@ export function defineFunctionBuilders<NODETYPE: NodeType>({
|
||||
// Since the corresponding buildHTML/buildMathML function expects a
|
||||
// list of elements, we normalize for different kinds of arguments
|
||||
export const ordargument = function(arg: AnyParseNode): AnyParseNode[] {
|
||||
const node = checkNodeType(arg, "ordgroup");
|
||||
return node ? node.body : [arg];
|
||||
return arg.type === "ordgroup" ? arg.body : [arg];
|
||||
};
|
||||
|
@@ -6,7 +6,7 @@ import defineFunction from "../defineFunction";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import ParseError from "../ParseError";
|
||||
import {assertNodeType, assertSymbolNodeType} from "../parseNode";
|
||||
import {checkNodeType, checkSymbolNodeType} from "../parseNode";
|
||||
import {checkSymbolNodeType} from "../parseNode";
|
||||
import {calculateSize} from "../units";
|
||||
import utils from "../utils";
|
||||
|
||||
@@ -547,11 +547,10 @@ const alignedHandler = function(context, args) {
|
||||
mode: context.mode,
|
||||
body: [],
|
||||
};
|
||||
const ordgroup = checkNodeType(args[0], "ordgroup");
|
||||
if (ordgroup) {
|
||||
if (args[0] && args[0].type === "ordgroup") {
|
||||
let arg0 = "";
|
||||
for (let i = 0; i < ordgroup.body.length; i++) {
|
||||
const textord = assertNodeType(ordgroup.body[i], "textord");
|
||||
for (let i = 0; i < args[0].body.length; i++) {
|
||||
const textord = assertNodeType(args[0].body[i], "textord");
|
||||
arg0 += textord.text;
|
||||
}
|
||||
numMaths = Number(arg0);
|
||||
|
@@ -4,7 +4,7 @@ import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import utils from "../utils";
|
||||
import stretchy from "../stretchy";
|
||||
import {assertNodeType, checkNodeType} from "../parseNode";
|
||||
import {assertNodeType} from "../parseNode";
|
||||
import {assertSpan, assertSymbolDomNode} from "../domTree";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
@@ -20,9 +20,8 @@ export const htmlBuilder: HtmlBuilderSupSub<"accent"> = (grp, options) => {
|
||||
let base: AnyParseNode;
|
||||
let group: ParseNode<"accent">;
|
||||
|
||||
const supSub: ?ParseNode<"supsub"> = checkNodeType(grp, "supsub");
|
||||
let supSubGroup;
|
||||
if (supSub) {
|
||||
if (grp && grp.type === "supsub") {
|
||||
// If our base is a character box, and we have superscripts and
|
||||
// subscripts, the supsub will defer to us. In particular, we want
|
||||
// to attach the superscripts and subscripts to the inner body (so
|
||||
@@ -32,18 +31,18 @@ export const htmlBuilder: HtmlBuilderSupSub<"accent"> = (grp, options) => {
|
||||
// rendering that, while keeping track of where the accent is.
|
||||
|
||||
// The real accent group is the base of the supsub group
|
||||
group = assertNodeType(supSub.base, "accent");
|
||||
group = assertNodeType(grp.base, "accent");
|
||||
// The character box is the base of the accent group
|
||||
base = group.base;
|
||||
// Stick the character box into the base of the supsub group
|
||||
supSub.base = base;
|
||||
grp.base = base;
|
||||
|
||||
// Rerender the supsub group with its new base, and store that
|
||||
// result.
|
||||
supSubGroup = assertSpan(html.buildGroup(supSub, options));
|
||||
supSubGroup = assertSpan(html.buildGroup(grp, options));
|
||||
|
||||
// reset original base
|
||||
supSub.base = group;
|
||||
grp.base = group;
|
||||
} else {
|
||||
group = assertNodeType(grp, "accent");
|
||||
base = group.base;
|
||||
|
@@ -4,7 +4,7 @@ import buildCommon from "../buildCommon";
|
||||
import delimiter from "../delimiter";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import Style from "../Style";
|
||||
import {assertNodeType, assertAtomFamily, checkNodeType} from "../parseNode";
|
||||
import {assertNodeType} from "../parseNode";
|
||||
import {assert} from "../utils";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
@@ -382,17 +382,10 @@ defineFunction({
|
||||
const denom = args[5];
|
||||
|
||||
// Look into the parse nodes to get the desired delimiters.
|
||||
let leftNode = checkNodeType(args[0], "atom");
|
||||
if (leftNode) {
|
||||
leftNode = assertAtomFamily(args[0], "open");
|
||||
}
|
||||
const leftDelim = leftNode ? delimFromValue(leftNode.text) : null;
|
||||
|
||||
let rightNode = checkNodeType(args[1], "atom");
|
||||
if (rightNode) {
|
||||
rightNode = assertAtomFamily(args[1], "close");
|
||||
}
|
||||
const rightDelim = rightNode ? delimFromValue(rightNode.text) : null;
|
||||
const leftDelim = args[0].type === "atom" && args[0].family === "open"
|
||||
? delimFromValue(args[0].text) : null;
|
||||
const rightDelim = args[1].type === "atom" && args[1].family === "close"
|
||||
? delimFromValue(args[1].text) : null;
|
||||
|
||||
const barNode = assertNodeType(args[2], "size");
|
||||
let hasBarLine;
|
||||
@@ -409,14 +402,14 @@ defineFunction({
|
||||
|
||||
// Find out if we want displaystyle, textstyle, etc.
|
||||
let size = "auto";
|
||||
let styl = checkNodeType(args[3], "ordgroup");
|
||||
if (styl) {
|
||||
let styl = args[3];
|
||||
if (styl.type === "ordgroup") {
|
||||
if (styl.body.length > 0) {
|
||||
const textOrd = assertNodeType(styl.body[0], "textord");
|
||||
size = stylArray[Number(textOrd.text)];
|
||||
}
|
||||
} else {
|
||||
styl = assertNodeType(args[3], "textord");
|
||||
styl = assertNodeType(styl, "textord");
|
||||
size = stylArray[Number(styl.text)];
|
||||
}
|
||||
|
||||
|
@@ -4,7 +4,7 @@ import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import stretchy from "../stretchy";
|
||||
import Style from "../Style";
|
||||
import {assertNodeType, checkNodeType} from "../parseNode";
|
||||
import {assertNodeType} from "../parseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
@@ -20,15 +20,14 @@ export const htmlBuilder: HtmlBuilderSupSub<"horizBrace"> = (grp, options) => {
|
||||
// Pull out the `ParseNode<"horizBrace">` if `grp` is a "supsub" node.
|
||||
let supSubGroup;
|
||||
let group: ParseNode<"horizBrace">;
|
||||
const supSub = checkNodeType(grp, "supsub");
|
||||
if (supSub) {
|
||||
if (grp.type === "supsub") {
|
||||
// Ref: LaTeX source2e: }}}}\limits}
|
||||
// i.e. LaTeX treats the brace similar to an op and passes it
|
||||
// with \limits, so we need to assign supsub style.
|
||||
supSubGroup = supSub.sup ?
|
||||
html.buildGroup(supSub.sup, options.havingStyle(style.sup()), options) :
|
||||
html.buildGroup(supSub.sub, options.havingStyle(style.sub()), options);
|
||||
group = assertNodeType(supSub.base, "horizBrace");
|
||||
supSubGroup = grp.sup ?
|
||||
html.buildGroup(grp.sup, options.havingStyle(style.sup()), options) :
|
||||
html.buildGroup(grp.sub, options.havingStyle(style.sub()), options);
|
||||
group = assertNodeType(grp.base, "horizBrace");
|
||||
} else {
|
||||
group = assertNodeType(grp, "horizBrace");
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@ import * as mathMLTree from "../mathMLTree";
|
||||
import utils from "../utils";
|
||||
import Style from "../Style";
|
||||
import {assembleSupSub} from "./utils/assembleSupSub";
|
||||
import {assertNodeType, checkNodeType} from "../parseNode";
|
||||
import {assertNodeType} from "../parseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
@@ -28,14 +28,13 @@ export const htmlBuilder: HtmlBuilderSupSub<"op"> = (grp, options) => {
|
||||
let subGroup;
|
||||
let hasLimits = false;
|
||||
let group: ParseNode<"op">;
|
||||
const supSub = checkNodeType(grp, "supsub");
|
||||
if (supSub) {
|
||||
if (grp.type === "supsub") {
|
||||
// If we have limits, supsub will pass us its group to handle. Pull
|
||||
// out the superscript and subscript and set the group to the op in
|
||||
// its base.
|
||||
supGroup = supSub.sup;
|
||||
subGroup = supSub.sub;
|
||||
group = assertNodeType(supSub.base, "op");
|
||||
supGroup = grp.sup;
|
||||
subGroup = grp.sub;
|
||||
group = assertNodeType(grp.base, "op");
|
||||
hasLimits = true;
|
||||
} else {
|
||||
group = assertNodeType(grp, "op");
|
||||
|
@@ -4,7 +4,7 @@ import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import {SymbolNode} from "../domTree";
|
||||
import {assembleSupSub} from "./utils/assembleSupSub";
|
||||
import {assertNodeType, checkNodeType} from "../parseNode";
|
||||
import {assertNodeType} from "../parseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
@@ -21,14 +21,13 @@ export const htmlBuilder: HtmlBuilderSupSub<"operatorname"> = (grp, options) =>
|
||||
let subGroup;
|
||||
let hasLimits = false;
|
||||
let group: ParseNode<"operatorname">;
|
||||
const supSub = checkNodeType(grp, "supsub");
|
||||
if (supSub) {
|
||||
if (grp.type === "supsub") {
|
||||
// If we have limits, supsub will pass us its group to handle. Pull
|
||||
// out the superscript and subscript and set the group to the op in
|
||||
// its base.
|
||||
supGroup = supSub.sup;
|
||||
subGroup = supSub.sub;
|
||||
group = assertNodeType(supSub.base, "operatorname");
|
||||
supGroup = grp.sup;
|
||||
subGroup = grp.sub;
|
||||
group = assertNodeType(grp.base, "operatorname");
|
||||
hasLimits = true;
|
||||
} else {
|
||||
group = assertNodeType(grp, "operatorname");
|
||||
|
@@ -5,7 +5,6 @@ import {SymbolNode} from "../domTree";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import utils from "../utils";
|
||||
import Style from "../Style";
|
||||
import {checkNodeType} from "../parseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
@@ -197,12 +196,11 @@ defineFunctionBuilders({
|
||||
let isOver;
|
||||
let isSup;
|
||||
|
||||
const horizBrace = checkNodeType(group.base, "horizBrace");
|
||||
if (horizBrace) {
|
||||
if (group.base && group.base.type === "horizBrace") {
|
||||
isSup = !!group.sup;
|
||||
if (isSup === horizBrace.isOver) {
|
||||
if (isSup === group.base.isOver) {
|
||||
isBrace = true;
|
||||
isOver = horizBrace.isOver;
|
||||
isOver = group.base.isOver;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -441,66 +441,12 @@ export function assertNodeType<NODETYPE: NodeType>(
|
||||
node: ?AnyParseNode,
|
||||
type: NODETYPE,
|
||||
): ParseNode<NODETYPE> {
|
||||
const typedNode = checkNodeType(node, type);
|
||||
if (!typedNode) {
|
||||
if (!node || node.type !== type) {
|
||||
throw new Error(
|
||||
`Expected node of type ${type}, but got ` +
|
||||
(node ? `node of type ${node.type}` : String(node)));
|
||||
}
|
||||
// $FlowFixMe: Unsure why.
|
||||
return typedNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the node more strictly typed iff it is of the given type. Otherwise,
|
||||
* returns null.
|
||||
*/
|
||||
export function checkNodeType<NODETYPE: NodeType>(
|
||||
node: ?AnyParseNode,
|
||||
type: NODETYPE,
|
||||
): ?ParseNode<NODETYPE> {
|
||||
if (node && node.type === type) {
|
||||
// The definition of ParseNode<TYPE> doesn't communicate to flow that
|
||||
// `type: TYPE` (as that's not explicitly mentioned anywhere), though that
|
||||
// happens to be true for all our value types.
|
||||
// $FlowFixMe
|
||||
return node;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the node is of the given type and returns it with stricter
|
||||
* typing. Throws if the node's type does not match.
|
||||
*/
|
||||
export function assertAtomFamily(
|
||||
node: ?AnyParseNode,
|
||||
family: Atom,
|
||||
): ParseNode<"atom"> {
|
||||
const typedNode = checkAtomFamily(node, family);
|
||||
if (!typedNode) {
|
||||
throw new Error(
|
||||
`Expected node of type "atom" and family "${family}", but got ` +
|
||||
(node ?
|
||||
(node.type === "atom" ?
|
||||
`atom of family ${node.family}` :
|
||||
`node of type ${node.type}`) :
|
||||
String(node)));
|
||||
}
|
||||
return typedNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the node more strictly typed iff it is of the given type. Otherwise,
|
||||
* returns null.
|
||||
*/
|
||||
export function checkAtomFamily(
|
||||
node: ?AnyParseNode,
|
||||
family: Atom,
|
||||
): ?ParseNode<"atom"> {
|
||||
return node && node.type === "atom" && node.family === family ?
|
||||
node :
|
||||
null;
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user