mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-05 11:18:39 +00:00
Convert ParseNode to struct (#1534)
* Define the nested version of ParseNodes structs explicitly. Passes test:jest, but fails test:flow. * Fix additional type errors reported by flow. * Migrate rebased code from master. * Rename ParseNode.js to parseNode.js. * Update defineEnvironment output type to fix the flow errors in environment/array.js.
This commit is contained in:
2
katex.js
2
katex.js
@@ -18,7 +18,7 @@ import domTree from "./src/domTree";
|
||||
import utils from "./src/utils";
|
||||
|
||||
import type {SettingsOptions} from "./src/Settings";
|
||||
import type {AnyParseNode} from "./src/ParseNode";
|
||||
import type {AnyParseNode} from "./src/parseNode";
|
||||
|
||||
import {defineSymbol} from './src/symbols';
|
||||
import {defineMacro} from './src/macros';
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// @flow
|
||||
import {Token} from "./Token";
|
||||
|
||||
import type {AnyParseNode} from "./ParseNode";
|
||||
import type {AnyParseNode} from "./parseNode";
|
||||
|
||||
/**
|
||||
* This is the ParseError class, which is the main error thrown by KaTeX
|
||||
|
426
src/ParseNode.js
426
src/ParseNode.js
@@ -1,426 +0,0 @@
|
||||
// @flow
|
||||
import SourceLocation from "./SourceLocation";
|
||||
import {GROUPS} from "./symbols";
|
||||
import type {ArrayEnvNodeData} from "./environments/array";
|
||||
import type {Mode, StyleStr} from "./types";
|
||||
import type {Token} from "./Token";
|
||||
import type {Measurement} from "./units";
|
||||
|
||||
/**
|
||||
* The resulting parse tree nodes of the parse tree.
|
||||
*
|
||||
* It is possible to provide position information, so that a `ParseNode` can
|
||||
* fulfill a role similar to a `Token` in error reporting.
|
||||
* For details on the corresponding properties see `Token` constructor.
|
||||
* Providing such information can lead to better error reporting.
|
||||
*/
|
||||
export default class ParseNode<TYPE: NodeType> {
|
||||
type: TYPE;
|
||||
value: NodeValue<TYPE>;
|
||||
mode: Mode;
|
||||
loc: ?SourceLocation;
|
||||
|
||||
constructor(
|
||||
type: TYPE, // type of node, like e.g. "ordgroup"
|
||||
value: NodeValue<TYPE>, // type-specific representation of the node
|
||||
mode: Mode, // parse mode in action for this node, "math" or "text"
|
||||
first?: {loc: ?SourceLocation}, // first token or node of the input for
|
||||
// this node, will omit position information if unset
|
||||
last?: {loc: ?SourceLocation}, // last token or node of the input for this
|
||||
// node, will default to firstToken if unset
|
||||
) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
this.mode = mode;
|
||||
this.loc = SourceLocation.range(first, last);
|
||||
}
|
||||
}
|
||||
|
||||
export type NodeType = $Keys<ParseNodeTypes>;
|
||||
export type NodeValue<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<"accent-token"> |
|
||||
ParseNode<"bin"> |
|
||||
ParseNode<"close"> |
|
||||
ParseNode<"inner"> |
|
||||
ParseNode<"mathord"> |
|
||||
ParseNode<"op-token"> |
|
||||
ParseNode<"open"> |
|
||||
ParseNode<"punct"> |
|
||||
ParseNode<"rel"> |
|
||||
ParseNode<"spacing"> |
|
||||
ParseNode<"textord">;
|
||||
|
||||
// Union of all possible `ParseNode<>` types.
|
||||
// Unable to derive this directly from `ParseNodeTypes` due to
|
||||
// https://github.com/facebook/flow/issues/6369.
|
||||
// Cannot use `ParseNode<NodeType>` since `ParseNode` is not strictly co-variant
|
||||
// w.r.t. its type parameter due to the way the value type is computed.
|
||||
export type AnyParseNode =
|
||||
SymbolParseNode |
|
||||
ParseNode<"array"> |
|
||||
ParseNode<"color"> |
|
||||
ParseNode<"color-token"> |
|
||||
ParseNode<"op"> |
|
||||
ParseNode<"ordgroup"> |
|
||||
ParseNode<"size"> |
|
||||
ParseNode<"styling"> |
|
||||
ParseNode<"supsub"> |
|
||||
ParseNode<"tag"> |
|
||||
ParseNode<"text"> |
|
||||
ParseNode<"url"> |
|
||||
ParseNode<"verb"> |
|
||||
ParseNode<"accent"> |
|
||||
ParseNode<"accentUnder"> |
|
||||
ParseNode<"cr"> |
|
||||
ParseNode<"delimsizing"> |
|
||||
ParseNode<"enclose"> |
|
||||
ParseNode<"environment"> |
|
||||
ParseNode<"font"> |
|
||||
ParseNode<"genfrac"> |
|
||||
ParseNode<"horizBrace"> |
|
||||
ParseNode<"href"> |
|
||||
ParseNode<"htmlmathml"> |
|
||||
ParseNode<"infix"> |
|
||||
ParseNode<"kern"> |
|
||||
ParseNode<"lap"> |
|
||||
ParseNode<"leftright"> |
|
||||
ParseNode<"leftright-right"> |
|
||||
ParseNode<"mathchoice"> |
|
||||
ParseNode<"middle"> |
|
||||
ParseNode<"mclass"> |
|
||||
ParseNode<"mod"> |
|
||||
ParseNode<"operatorname"> |
|
||||
ParseNode<"overline"> |
|
||||
ParseNode<"phantom"> |
|
||||
ParseNode<"hphantom"> |
|
||||
ParseNode<"vphantom"> |
|
||||
ParseNode<"raisebox"> |
|
||||
ParseNode<"rule"> |
|
||||
ParseNode<"sizing"> |
|
||||
ParseNode<"smash"> |
|
||||
ParseNode<"sqrt"> |
|
||||
ParseNode<"underline"> |
|
||||
ParseNode<"xArrow">;
|
||||
|
||||
// Map from `type` field value to corresponding `value` type.
|
||||
export type ParseNodeTypes = {
|
||||
"array": ArrayEnvNodeData,
|
||||
"color": {|
|
||||
type: "color",
|
||||
color: string,
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
"color-token": string,
|
||||
// To avoid requiring run-time type assertions, this more carefully captures
|
||||
// the requirements on the fields per the op.js htmlBuilder logic:
|
||||
// - `body` and `value` are NEVER set simultanouesly.
|
||||
// - When `symbol` is true, `body` is set.
|
||||
"op": {|
|
||||
type: "op",
|
||||
limits: boolean,
|
||||
alwaysHandleSupSub?: boolean,
|
||||
suppressBaseShift?: boolean,
|
||||
symbol: boolean,
|
||||
body: string,
|
||||
value?: void,
|
||||
|} | {|
|
||||
type: "op",
|
||||
limits: boolean,
|
||||
alwaysHandleSupSub?: boolean,
|
||||
suppressBaseShift?: boolean,
|
||||
symbol: false, // If 'symbol' is true, `body` *must* be set.
|
||||
body?: void,
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
"ordgroup": AnyParseNode[],
|
||||
"size": {|
|
||||
type: "size",
|
||||
value: Measurement,
|
||||
isBlank: boolean,
|
||||
|},
|
||||
"styling": {|
|
||||
type: "styling",
|
||||
style: StyleStr,
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
"supsub": {|
|
||||
type: "supsub",
|
||||
base: ?AnyParseNode,
|
||||
sup?: ?AnyParseNode,
|
||||
sub?: ?AnyParseNode,
|
||||
|},
|
||||
"tag": {|
|
||||
type: "tag",
|
||||
body: AnyParseNode[],
|
||||
tag: AnyParseNode[],
|
||||
|},
|
||||
"text": {|
|
||||
type: "text",
|
||||
body: AnyParseNode[],
|
||||
font?: string,
|
||||
|},
|
||||
"url": {|
|
||||
type: "url",
|
||||
value: string,
|
||||
|},
|
||||
"verb": {|
|
||||
type: "verb",
|
||||
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
|
||||
// `ParseNode` types.)
|
||||
"accent-token": string,
|
||||
"bin": string,
|
||||
"close": string,
|
||||
"inner": string,
|
||||
"mathord": string,
|
||||
"op-token": string,
|
||||
"open": string,
|
||||
"punct": string,
|
||||
"rel": string,
|
||||
"spacing": string,
|
||||
"textord": string,
|
||||
// From functions.js and functions/*.js. See also "color", "op", "styling",
|
||||
// and "text" above.
|
||||
"accent": {|
|
||||
type: "accent",
|
||||
label: string,
|
||||
isStretchy?: boolean,
|
||||
isShifty?: boolean,
|
||||
base: AnyParseNode,
|
||||
|},
|
||||
"accentUnder": {|
|
||||
type: "accentUnder",
|
||||
label: string,
|
||||
isStretchy?: boolean,
|
||||
isShifty?: boolean,
|
||||
base: AnyParseNode,
|
||||
|},
|
||||
"cr": {|
|
||||
type: "cr",
|
||||
newRow: boolean,
|
||||
newLine: boolean,
|
||||
size: ?ParseNode<"size">,
|
||||
|},
|
||||
"delimsizing": {|
|
||||
type: "delimsizing",
|
||||
size: 1 | 2 | 3 | 4,
|
||||
mclass: "mopen" | "mclose" | "mrel" | "mord",
|
||||
value: string,
|
||||
|},
|
||||
"enclose": {|
|
||||
type: "enclose",
|
||||
label: string,
|
||||
backgroundColor?: ParseNode<"color-token">,
|
||||
borderColor?: ParseNode<"color-token">,
|
||||
body: AnyParseNode,
|
||||
|},
|
||||
"environment": {|
|
||||
type: "environment",
|
||||
name: string,
|
||||
nameGroup: AnyParseNode,
|
||||
|},
|
||||
"font": {|
|
||||
type: "font",
|
||||
font: string,
|
||||
body: AnyParseNode,
|
||||
|},
|
||||
"genfrac": {|
|
||||
type: "genfrac",
|
||||
continued: boolean,
|
||||
numer: AnyParseNode,
|
||||
denom: AnyParseNode,
|
||||
hasBarLine: boolean,
|
||||
leftDelim: ?string,
|
||||
rightDelim: ?string,
|
||||
size: StyleStr | "auto",
|
||||
barSize: Measurement | null,
|
||||
|},
|
||||
"horizBrace": {|
|
||||
type: "horizBrace",
|
||||
label: string,
|
||||
isOver: boolean,
|
||||
base: AnyParseNode,
|
||||
|},
|
||||
"href": {|
|
||||
type: "href",
|
||||
href: string,
|
||||
body: AnyParseNode[],
|
||||
|},
|
||||
"htmlmathml": {|
|
||||
type: "htmlmathml",
|
||||
html: AnyParseNode[],
|
||||
mathml: AnyParseNode[],
|
||||
|},
|
||||
"infix": {|
|
||||
type: "infix",
|
||||
replaceWith: string,
|
||||
sizeNode?: ParseNode<"size">,
|
||||
token: ?Token,
|
||||
|},
|
||||
"kern": {|
|
||||
type: "kern",
|
||||
dimension: Measurement,
|
||||
|},
|
||||
"lap": {|
|
||||
type: "lap",
|
||||
alignment: string,
|
||||
body: AnyParseNode,
|
||||
|},
|
||||
"leftright": LeftRightDelimType,
|
||||
"leftright-right": {|
|
||||
type: "leftright-right",
|
||||
value: string,
|
||||
|},
|
||||
"mathchoice": {|
|
||||
type: "mathchoice",
|
||||
display: AnyParseNode[],
|
||||
text: AnyParseNode[],
|
||||
script: AnyParseNode[],
|
||||
scriptscript: AnyParseNode[],
|
||||
|},
|
||||
"middle": {|
|
||||
type: "middle",
|
||||
value: string,
|
||||
|},
|
||||
"mclass": {|
|
||||
type: "mclass",
|
||||
mclass: string,
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
"mod": {|
|
||||
type: "mod",
|
||||
modType: string,
|
||||
value: ?AnyParseNode[],
|
||||
|},
|
||||
"operatorname": {|
|
||||
type: "operatorname",
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
"overline": {|
|
||||
type: "overline",
|
||||
body: AnyParseNode,
|
||||
|},
|
||||
"phantom": {|
|
||||
type: "phantom",
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
"hphantom": {|
|
||||
type: "hphantom",
|
||||
body: AnyParseNode,
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
"vphantom": {|
|
||||
type: "vphantom",
|
||||
body: AnyParseNode,
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
"raisebox": {|
|
||||
type: "raisebox",
|
||||
dy: ParseNode<"size">,
|
||||
body: AnyParseNode,
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
"rule": {|
|
||||
type: "rule",
|
||||
shift: ?Measurement,
|
||||
width: Measurement,
|
||||
height: Measurement,
|
||||
|},
|
||||
"sizing": {|
|
||||
type: "sizing",
|
||||
size: number,
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
"smash": {|
|
||||
type: "smash",
|
||||
body: AnyParseNode,
|
||||
smashHeight: boolean,
|
||||
smashDepth: boolean,
|
||||
|},
|
||||
"sqrt": {|
|
||||
type: "sqrt",
|
||||
body: AnyParseNode,
|
||||
index: ?AnyParseNode,
|
||||
|},
|
||||
"underline": {|
|
||||
type: "underline",
|
||||
body: AnyParseNode,
|
||||
|},
|
||||
"xArrow": {|
|
||||
type: "xArrow",
|
||||
label: string,
|
||||
body: AnyParseNode,
|
||||
below: ?AnyParseNode,
|
||||
|},
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 assertNodeType<NODETYPE: NodeType>(
|
||||
node: ?AnyParseNode,
|
||||
type: NODETYPE,
|
||||
): ParseNode<NODETYPE> {
|
||||
const typedNode = checkNodeType(node, type);
|
||||
if (!typedNode) {
|
||||
throw new Error(
|
||||
`Expected node of type ${type}, but got ` +
|
||||
(node ? `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 checkNodeType<NODETYPE: NodeType>(
|
||||
node: ?AnyParseNode,
|
||||
type: NODETYPE,
|
||||
): ?ParseNode<NODETYPE> {
|
||||
if (node && node.type === type) {
|
||||
// $FlowFixMe: Inference not sophisticated enough to figure this out.
|
||||
return node;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the node more strictly typed iff it is of the given type. Otherwise,
|
||||
* returns null.
|
||||
*/
|
||||
export function assertSymbolNodeType(node: ?AnyParseNode): SymbolParseNode {
|
||||
const typedNode = checkSymbolNodeType(node);
|
||||
if (!typedNode) {
|
||||
throw new Error(
|
||||
`Expected node of symbol group type, but got ` +
|
||||
(node ? `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 checkSymbolNodeType(node: ?AnyParseNode): ?SymbolParseNode {
|
||||
if (node && GROUPS.hasOwnProperty(node.type)) {
|
||||
// $FlowFixMe
|
||||
return node;
|
||||
}
|
||||
return null;
|
||||
}
|
159
src/Parser.js
159
src/Parser.js
@@ -9,12 +9,13 @@ import {supportedCodepoint} from "./unicodeScripts";
|
||||
import unicodeAccents from "./unicodeAccents";
|
||||
import unicodeSymbols from "./unicodeSymbols";
|
||||
import utils from "./utils";
|
||||
import ParseNode, {assertNodeType, checkNodeType} from "./ParseNode";
|
||||
import {assertNodeType, checkNodeType} from "./parseNode";
|
||||
import ParseError from "./ParseError";
|
||||
import {combiningDiacriticalMarksEndRegex, urlFunctionRegex} from "./Lexer.js";
|
||||
import Settings from "./Settings";
|
||||
import SourceLocation from "./SourceLocation";
|
||||
import {Token} from "./Token";
|
||||
import type {AnyParseNode} from "./ParseNode";
|
||||
import type {AnyParseNode, SymbolParseNode} from "./parseNode";
|
||||
import type {Mode, ArgType, BreakToken} from "./types";
|
||||
import type {FunctionContext, FunctionSpec} from "./defineFunction";
|
||||
import type {EnvSpec} from "./defineEnvironment";
|
||||
@@ -238,13 +239,13 @@ export default class Parser {
|
||||
if (numerBody.length === 1 && numerBody[0].type === "ordgroup") {
|
||||
numerNode = numerBody[0];
|
||||
} else {
|
||||
numerNode = new ParseNode("ordgroup", numerBody, this.mode);
|
||||
numerNode = {type: "ordgroup", mode: this.mode, value: numerBody};
|
||||
}
|
||||
|
||||
if (denomBody.length === 1 && denomBody[0].type === "ordgroup") {
|
||||
denomNode = denomBody[0];
|
||||
} else {
|
||||
denomNode = new ParseNode("ordgroup", denomBody, this.mode);
|
||||
denomNode = {type: "ordgroup", mode: this.mode, value: denomBody};
|
||||
}
|
||||
|
||||
let node;
|
||||
@@ -311,25 +312,27 @@ export default class Parser {
|
||||
const textordArray = [];
|
||||
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
textordArray.push(new ParseNode("textord", text[i], "text"));
|
||||
textordArray.push({type: "textord", mode: "text", value: text[i]});
|
||||
}
|
||||
|
||||
const textNode = new ParseNode(
|
||||
"text",
|
||||
{
|
||||
body: textordArray,
|
||||
const textNode = {
|
||||
type: "text",
|
||||
mode: this.mode,
|
||||
value: {
|
||||
type: "text",
|
||||
body: textordArray,
|
||||
},
|
||||
this.mode);
|
||||
};
|
||||
|
||||
const colorNode = new ParseNode(
|
||||
"color",
|
||||
{
|
||||
const colorNode = {
|
||||
type: "color",
|
||||
value: {
|
||||
type: "color",
|
||||
color: this.settings.errorColor,
|
||||
value: [textNode],
|
||||
type: "color",
|
||||
},
|
||||
this.mode);
|
||||
mode: this.mode,
|
||||
};
|
||||
|
||||
this.consume();
|
||||
return colorNode;
|
||||
@@ -389,7 +392,7 @@ export default class Parser {
|
||||
if (superscript) {
|
||||
throw new ParseError("Double superscript", lex);
|
||||
}
|
||||
const prime = new ParseNode("textord", "\\prime", this.mode);
|
||||
const prime = {type: "textord", mode: this.mode, value: "\\prime"};
|
||||
|
||||
// Many primes can be grouped together, so we handle this here
|
||||
const primes = [prime];
|
||||
@@ -406,7 +409,7 @@ export default class Parser {
|
||||
primes.push(this.handleSupSubscript("superscript"));
|
||||
}
|
||||
// Put everything into an ordgroup as the superscript
|
||||
superscript = new ParseNode("ordgroup", primes, this.mode);
|
||||
superscript = {type: "ordgroup", mode: this.mode, value: primes};
|
||||
} else {
|
||||
// If it wasn't ^, _, or ', stop parsing super/subscripts
|
||||
break;
|
||||
@@ -417,12 +420,16 @@ export default class Parser {
|
||||
// but need to check here for type check to pass.
|
||||
if (superscript || subscript) {
|
||||
// If we got either a superscript or subscript, create a supsub
|
||||
return new ParseNode("supsub", {
|
||||
return {
|
||||
type: "supsub",
|
||||
base: base,
|
||||
sup: superscript,
|
||||
sub: subscript,
|
||||
}, this.mode);
|
||||
mode: this.mode,
|
||||
value: {
|
||||
type: "supsub",
|
||||
base: base,
|
||||
sup: superscript,
|
||||
sub: subscript,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
// Otherwise return the original body
|
||||
return base;
|
||||
@@ -749,7 +756,11 @@ export default class Parser {
|
||||
if (!match) {
|
||||
throw new ParseError("Invalid color: '" + res.text + "'", res);
|
||||
}
|
||||
return newArgument(new ParseNode("color-token", match[0], this.mode), res);
|
||||
return newArgument({
|
||||
type: "color-token",
|
||||
mode: this.mode,
|
||||
value: match[0],
|
||||
}, res);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -785,11 +796,15 @@ export default class Parser {
|
||||
if (!validUnit(data)) {
|
||||
throw new ParseError("Invalid unit: '" + data.unit + "'", res);
|
||||
}
|
||||
return newArgument(new ParseNode("size", {
|
||||
return newArgument({
|
||||
type: "size",
|
||||
value: data,
|
||||
isBlank: isBlank,
|
||||
}, this.mode), res);
|
||||
mode: this.mode,
|
||||
value: {
|
||||
type: "size",
|
||||
value: data,
|
||||
isBlank: isBlank,
|
||||
},
|
||||
}, res);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -825,10 +840,12 @@ export default class Parser {
|
||||
this.gullet.endGroup();
|
||||
// Make sure we get a close brace
|
||||
this.expect(optional ? "]" : "}");
|
||||
return newArgument(
|
||||
new ParseNode(
|
||||
"ordgroup", expression, this.mode, firstToken, lastToken),
|
||||
firstToken.range(lastToken, firstToken.text));
|
||||
return newArgument({
|
||||
type: "ordgroup",
|
||||
mode: this.mode,
|
||||
loc: SourceLocation.range(firstToken, lastToken),
|
||||
value: expression,
|
||||
}, firstToken.range(lastToken, firstToken.text));
|
||||
} else {
|
||||
// Otherwise, just return a nucleus, or nothing for an optional group
|
||||
if (mode) {
|
||||
@@ -857,18 +874,30 @@ export default class Parser {
|
||||
const v = a.value;
|
||||
if (v === "-" && group[i + 1].value === "-") {
|
||||
if (i + 1 < n && group[i + 2].value === "-") {
|
||||
group.splice(i, 3, new ParseNode(
|
||||
"textord", "---", "text", a, group[i + 2]));
|
||||
group.splice(i, 3, {
|
||||
type: "textord",
|
||||
mode: "text",
|
||||
loc: SourceLocation.range(a, group[i + 2]),
|
||||
value: "---",
|
||||
});
|
||||
n -= 2;
|
||||
} else {
|
||||
group.splice(i, 2, new ParseNode(
|
||||
"textord", "--", "text", a, group[i + 1]));
|
||||
group.splice(i, 2, {
|
||||
type: "textord",
|
||||
mode: "text",
|
||||
loc: SourceLocation.range(a, group[i + 1]),
|
||||
value: "--",
|
||||
});
|
||||
n -= 1;
|
||||
}
|
||||
}
|
||||
if ((v === "'" || v === "`") && group[i + 1].value === v) {
|
||||
group.splice(i, 2, new ParseNode(
|
||||
"textord", v + v, "text", a, group[i + 1]));
|
||||
group.splice(i, 2, {
|
||||
type: "textord",
|
||||
mode: "text",
|
||||
loc: SourceLocation.range(a, group[i + 1]),
|
||||
value: v + v,
|
||||
});
|
||||
n -= 1;
|
||||
}
|
||||
}
|
||||
@@ -911,10 +940,14 @@ export default class Parser {
|
||||
throw new ParseError(
|
||||
`Forbidden protocol '${protocol}' in ${funcName}`, nucleus);
|
||||
}
|
||||
const urlArg = new ParseNode("url", {
|
||||
const urlArg = {
|
||||
type: "url",
|
||||
value: url,
|
||||
}, this.mode);
|
||||
mode: this.mode,
|
||||
value: {
|
||||
type: "url",
|
||||
value: url,
|
||||
},
|
||||
};
|
||||
this.consume();
|
||||
if (funcName === "\\href") { // two arguments
|
||||
this.consumeSpaces(); // ignore spaces between arguments
|
||||
@@ -948,12 +981,15 @@ export default class Parser {
|
||||
please report what input caused this bug`);
|
||||
}
|
||||
arg = arg.slice(1, -1); // remove first and last char
|
||||
return newArgument(
|
||||
new ParseNode("verb", {
|
||||
return newArgument({
|
||||
type: "verb",
|
||||
mode: "text",
|
||||
value: {
|
||||
type: "verb",
|
||||
body: arg,
|
||||
star: star,
|
||||
}, "text"), nucleus);
|
||||
},
|
||||
}, nucleus);
|
||||
}
|
||||
// At this point, we should have a symbol, possibly with accents.
|
||||
// First expand any accented base symbol according to unicodeSymbols.
|
||||
@@ -978,7 +1014,7 @@ export default class Parser {
|
||||
}
|
||||
}
|
||||
// Recognize base symbol
|
||||
let symbol = null;
|
||||
let symbol: AnyParseNode;
|
||||
if (symbols[this.mode][text]) {
|
||||
if (this.settings.strict && this.mode === 'math' &&
|
||||
extraLatin.indexOf(text) >= 0) {
|
||||
@@ -986,8 +1022,15 @@ export default class Parser {
|
||||
`Latin-1/Unicode text character "${text[0]}" used in ` +
|
||||
`math mode`, nucleus);
|
||||
}
|
||||
symbol = new ParseNode(symbols[this.mode][text].group,
|
||||
text, this.mode, nucleus);
|
||||
// TODO(#1492): Remove this override once this becomes an "atom" type.
|
||||
// $FlowFixMe
|
||||
const s: SymbolParseNode = {
|
||||
type: symbols[this.mode][text].group,
|
||||
mode: this.mode,
|
||||
loc: SourceLocation.range(nucleus),
|
||||
value: text,
|
||||
};
|
||||
symbol = s;
|
||||
} else if (text.charCodeAt(0) >= 0x80) { // no symbol for e.g. ^
|
||||
if (this.settings.strict) {
|
||||
if (!supportedCodepoint(text.charCodeAt(0))) {
|
||||
@@ -1000,7 +1043,12 @@ export default class Parser {
|
||||
nucleus);
|
||||
}
|
||||
}
|
||||
symbol = new ParseNode("textord", text, this.mode, nucleus);
|
||||
symbol = {
|
||||
type: "textord",
|
||||
mode: this.mode,
|
||||
loc: SourceLocation.range(nucleus),
|
||||
value: text,
|
||||
};
|
||||
} else {
|
||||
return null; // EOF, ^, _, {, }, etc.
|
||||
}
|
||||
@@ -1018,13 +1066,18 @@ export default class Parser {
|
||||
`Accent ${accent} unsupported in ${this.mode} mode`,
|
||||
nucleus);
|
||||
}
|
||||
symbol = new ParseNode("accent", {
|
||||
symbol = {
|
||||
type: "accent",
|
||||
label: command,
|
||||
isStretchy: false,
|
||||
isShifty: true,
|
||||
base: symbol,
|
||||
}, this.mode, nucleus);
|
||||
mode: this.mode,
|
||||
loc: SourceLocation.range(nucleus),
|
||||
value: {
|
||||
type: "accent",
|
||||
label: command,
|
||||
isStretchy: false,
|
||||
isShifty: true,
|
||||
base: symbol,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
return newArgument(symbol, nucleus);
|
||||
|
@@ -9,7 +9,7 @@ import utils from "./utils";
|
||||
import ParseError from "./ParseError.js";
|
||||
import {Token} from "./Token";
|
||||
|
||||
import type {AnyParseNode} from "./ParseNode";
|
||||
import type {AnyParseNode} from "./parseNode";
|
||||
import type {MacroMap} from "./macros";
|
||||
|
||||
export type StrictFunction =
|
||||
|
@@ -14,8 +14,8 @@ import {calculateSize} from "./units";
|
||||
import * as tree from "./tree";
|
||||
|
||||
import type Options from "./Options";
|
||||
import type ParseNode from "./ParseNode";
|
||||
import type {NodeType} from "./ParseNode";
|
||||
import type {ParseNode} from "./parseNode";
|
||||
import type {NodeType} from "./parseNode";
|
||||
import type {CharacterMetrics} from "./fontMetrics";
|
||||
import type {FontVariant, Mode} from "./types";
|
||||
import type {documentFragment as HtmlDocumentFragment} from "./domTree";
|
||||
|
@@ -11,13 +11,13 @@ import Style from "./Style";
|
||||
import buildCommon from "./buildCommon";
|
||||
import domTree from "./domTree";
|
||||
import utils, {assert} from "./utils";
|
||||
import {checkNodeType} from "./ParseNode";
|
||||
import {checkNodeType} from "./parseNode";
|
||||
import {spacings, tightSpacings} from "./spacingData";
|
||||
import {_htmlGroupBuilders as groupBuilders} from "./defineFunction";
|
||||
import * as tree from "./tree";
|
||||
|
||||
import type Options from "./Options";
|
||||
import type {AnyParseNode} from "./ParseNode";
|
||||
import type {AnyParseNode} from "./parseNode";
|
||||
import type {HtmlDomNode, DomSpan} from "./domTree";
|
||||
|
||||
const makeSpan = buildCommon.makeSpan;
|
||||
|
@@ -15,7 +15,7 @@ import {_mathmlGroupBuilders as groupBuilders} from "./defineFunction";
|
||||
import {MathNode, TextNode} from "./mathMLTree";
|
||||
|
||||
import type Options from "./Options";
|
||||
import type {AnyParseNode, SymbolParseNode} from "./ParseNode";
|
||||
import type {AnyParseNode, SymbolParseNode} from "./parseNode";
|
||||
import type {DomSpan} from "./domTree";
|
||||
import type {MathDomNode} from "./mathMLTree";
|
||||
import type {FontVariant, Mode} from "./types";
|
||||
|
@@ -6,7 +6,7 @@ import Options from "./Options";
|
||||
import Settings from "./Settings";
|
||||
import Style from "./Style";
|
||||
|
||||
import type {AnyParseNode} from "./ParseNode";
|
||||
import type {AnyParseNode} from "./parseNode";
|
||||
import type {DomSpan} from "./domTree";
|
||||
|
||||
const optionsFromSettings = function(settings: Settings) {
|
||||
|
@@ -1,12 +1,10 @@
|
||||
// @flow
|
||||
import {_htmlGroupBuilders, _mathmlGroupBuilders} from "./defineFunction";
|
||||
|
||||
import ParseNode from "./ParseNode";
|
||||
|
||||
import type Parser from "./Parser";
|
||||
import type {AnyParseNode} from "./ParseNode";
|
||||
import type {AnyParseNode} from "./parseNode";
|
||||
import type {ArgType, Mode} from "./types";
|
||||
import type {NodeType} from "./ParseNode";
|
||||
import type {NodeType} from "./parseNode";
|
||||
import type {HtmlBuilder, MathMLBuilder} from "./defineFunction";
|
||||
|
||||
/**
|
||||
@@ -26,11 +24,11 @@ type EnvContext = {|
|
||||
* - args: an array of arguments passed to \begin{name}
|
||||
* - optArgs: an array of optional arguments passed to \begin{name}
|
||||
*/
|
||||
type EnvHandler<NODETYPE: NodeType> = (
|
||||
type EnvHandler = (
|
||||
context: EnvContext,
|
||||
args: AnyParseNode[],
|
||||
optArgs: (?AnyParseNode)[],
|
||||
) => ParseNode<NODETYPE>;
|
||||
) => AnyParseNode;
|
||||
|
||||
/**
|
||||
* - numArgs: (default 0) The number of arguments after the \begin{name} function.
|
||||
@@ -57,9 +55,7 @@ export type EnvSpec<NODETYPE: NodeType> = {|
|
||||
greediness: number,
|
||||
allowedInText: boolean,
|
||||
numOptionalArgs: number,
|
||||
// FLOW TYPE NOTES: Same issue as the notes on the handler of FunctionSpec
|
||||
// in defineFunction.
|
||||
handler: EnvHandler<*>,
|
||||
handler: EnvHandler,
|
||||
|};
|
||||
|
||||
/**
|
||||
@@ -80,7 +76,7 @@ type EnvDefSpec<NODETYPE: NodeType> = {|
|
||||
// Properties that control how the environments are parsed.
|
||||
props: EnvProps,
|
||||
|
||||
handler: EnvHandler<NODETYPE>,
|
||||
handler: EnvHandler,
|
||||
|
||||
// This function returns an object representing the DOM structure to be
|
||||
// created when rendering the defined LaTeX function.
|
||||
|
@@ -1,8 +1,8 @@
|
||||
// @flow
|
||||
import {checkNodeType} from "./ParseNode";
|
||||
import {checkNodeType} from "./parseNode";
|
||||
|
||||
import type Parser from "./Parser";
|
||||
import type ParseNode, {AnyParseNode, NodeType} from "./ParseNode";
|
||||
import type {ParseNode, AnyParseNode, NodeType} from "./parseNode";
|
||||
import type Options from "./Options";
|
||||
import type {ArgType, BreakToken, Mode} from "./types";
|
||||
import type {HtmlDomNode} from "./domTree";
|
||||
|
@@ -4,9 +4,8 @@ import defineEnvironment from "../defineEnvironment";
|
||||
import defineFunction from "../defineFunction";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import ParseError from "../ParseError";
|
||||
import ParseNode from "../ParseNode";
|
||||
import {assertNodeType, assertSymbolNodeType} from "../ParseNode";
|
||||
import {checkNodeType, checkSymbolNodeType} from "../ParseNode";
|
||||
import {assertNodeType, assertSymbolNodeType} from "../parseNode";
|
||||
import {checkNodeType, checkSymbolNodeType} from "../parseNode";
|
||||
import {calculateSize} from "../units";
|
||||
import utils from "../utils";
|
||||
|
||||
@@ -14,7 +13,7 @@ import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
|
||||
import type Parser from "../Parser";
|
||||
import type {AnyParseNode} from "../ParseNode";
|
||||
import type {ParseNode, AnyParseNode} from "../parseNode";
|
||||
import type {StyleStr} from "../types";
|
||||
import type {HtmlBuilder, MathMLBuilder} from "../defineFunction";
|
||||
|
||||
@@ -29,9 +28,9 @@ type AlignSpec = { type: "separator", separator: string } | {
|
||||
export type ArrayEnvNodeData = {|
|
||||
type: "array",
|
||||
hskipBeforeAndAfter?: boolean,
|
||||
arraystretch: number,
|
||||
addJot?: boolean,
|
||||
cols?: AlignSpec[],
|
||||
arraystretch: number,
|
||||
body: AnyParseNode[][], // List of rows in the (2D) array.
|
||||
rowGaps: (?ParseNode<"size">)[],
|
||||
hLinesBeforeRow: Array<boolean[]>,
|
||||
@@ -40,10 +39,10 @@ export type ArrayEnvNodeData = {|
|
||||
type ArrayEnvNodeDataIncomplete = {|
|
||||
type: "array",
|
||||
hskipBeforeAndAfter?: boolean,
|
||||
arraystretch?: number,
|
||||
addJot?: boolean,
|
||||
cols?: AlignSpec[],
|
||||
// Before these fields are filled.
|
||||
arraystretch?: number,
|
||||
body?: AnyParseNode[][],
|
||||
rowGaps?: (?ParseNode<"size">)[],
|
||||
hLinesBeforeRow?: Array<boolean[]>,
|
||||
@@ -103,13 +102,21 @@ function parseArray(
|
||||
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
let cell = parser.parseExpression(false, "\\cr");
|
||||
cell = new ParseNode("ordgroup", cell, parser.mode);
|
||||
cell = {
|
||||
type: "ordgroup",
|
||||
mode: parser.mode,
|
||||
value: cell,
|
||||
};
|
||||
if (style) {
|
||||
cell = new ParseNode("styling", {
|
||||
cell = {
|
||||
type: "styling",
|
||||
style: style,
|
||||
value: [cell],
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "styling",
|
||||
style: style,
|
||||
value: [cell],
|
||||
},
|
||||
};
|
||||
}
|
||||
row.push(cell);
|
||||
const next = parser.nextToken.text;
|
||||
@@ -119,7 +126,8 @@ function parseArray(
|
||||
// Arrays terminate newlines with `\crcr` which consumes a `\cr` if
|
||||
// the last line is empty.
|
||||
// NOTE: Currently, `cell` is the last item added into `row`.
|
||||
if (row.length === 1 && cell.value.value[0].value.length === 0) {
|
||||
if (row.length === 1 && cell.type === "styling" &&
|
||||
cell.value.value[0].value.length === 0) {
|
||||
body.pop();
|
||||
}
|
||||
if (hLinesBeforeRow.length < body.length + 1) {
|
||||
@@ -149,7 +157,11 @@ function parseArray(
|
||||
// $FlowFixMe: The required fields were added immediately above.
|
||||
const res: ArrayEnvNodeData = result;
|
||||
parser.gullet.endGroup();
|
||||
return new ParseNode("array", res, parser.mode);
|
||||
return {
|
||||
type: "array",
|
||||
mode: parser.mode,
|
||||
value: res,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -410,7 +422,11 @@ const alignedHandler = function(context, args) {
|
||||
// binary. This behavior is implemented in amsmath's \start@aligned.
|
||||
let numMaths;
|
||||
let numCols = 0;
|
||||
const emptyGroup = new ParseNode("ordgroup", [], context.mode);
|
||||
const emptyGroup = {
|
||||
type: "ordgroup",
|
||||
mode: context.mode,
|
||||
value: [],
|
||||
};
|
||||
const ordgroup = checkNodeType(args[0], "ordgroup");
|
||||
if (ordgroup) {
|
||||
let arg0 = "";
|
||||
@@ -529,7 +545,7 @@ defineEnvironment({
|
||||
props: {
|
||||
numArgs: 0,
|
||||
},
|
||||
handler: function(context) {
|
||||
handler(context) {
|
||||
const delimiters = {
|
||||
"matrix": null,
|
||||
"pmatrix": ["(", ")"],
|
||||
@@ -538,20 +554,22 @@ defineEnvironment({
|
||||
"vmatrix": ["|", "|"],
|
||||
"Vmatrix": ["\\Vert", "\\Vert"],
|
||||
}[context.envName];
|
||||
let res = {
|
||||
const payload = {
|
||||
type: "array",
|
||||
hskipBeforeAndAfter: false, // \hskip -\arraycolsep in amsmath
|
||||
};
|
||||
res = parseArray(context.parser, res, dCellStyle(context.envName));
|
||||
if (delimiters) {
|
||||
res = new ParseNode("leftright", {
|
||||
const res: ParseNode<"array"> =
|
||||
parseArray(context.parser, payload, dCellStyle(context.envName));
|
||||
return delimiters ? {
|
||||
type: "leftright",
|
||||
mode: context.mode,
|
||||
value: {
|
||||
type: "leftright",
|
||||
body: [res],
|
||||
left: delimiters[0],
|
||||
right: delimiters[1],
|
||||
}, context.mode);
|
||||
}
|
||||
return res;
|
||||
},
|
||||
} : res;
|
||||
},
|
||||
htmlBuilder,
|
||||
mathmlBuilder,
|
||||
@@ -571,8 +589,8 @@ defineEnvironment({
|
||||
props: {
|
||||
numArgs: 0,
|
||||
},
|
||||
handler: function(context) {
|
||||
let res = {
|
||||
handler(context) {
|
||||
const payload = {
|
||||
type: "array",
|
||||
arraystretch: 1.2,
|
||||
cols: [{
|
||||
@@ -591,14 +609,18 @@ defineEnvironment({
|
||||
postgap: 0,
|
||||
}],
|
||||
};
|
||||
res = parseArray(context.parser, res, dCellStyle(context.envName));
|
||||
res = new ParseNode("leftright", {
|
||||
const res: ParseNode<"array"> =
|
||||
parseArray(context.parser, payload, dCellStyle(context.envName));
|
||||
return {
|
||||
type: "leftright",
|
||||
body: [res],
|
||||
left: "\\{",
|
||||
right: ".",
|
||||
}, context.mode);
|
||||
return res;
|
||||
mode: context.mode,
|
||||
value: {
|
||||
type: "leftright",
|
||||
body: [res],
|
||||
left: "\\{",
|
||||
right: ".",
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
mathmlBuilder,
|
||||
|
@@ -4,13 +4,13 @@ import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import utils from "../utils";
|
||||
import stretchy from "../stretchy";
|
||||
import ParseNode, {assertNodeType, checkNodeType} from "../ParseNode";
|
||||
import {assertNodeType, checkNodeType} from "../parseNode";
|
||||
import {assertSpan, assertSymbolDomNode} from "../domTree";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
|
||||
import type {AnyParseNode} from "../ParseNode";
|
||||
import type {ParseNode, AnyParseNode} from "../parseNode";
|
||||
import type {HtmlBuilderSupSub, MathMLBuilder} from "../defineFunction";
|
||||
|
||||
// NOTE: Unlike most `htmlBuilder`s, this one handles not only "accent", but
|
||||
@@ -230,13 +230,17 @@ defineFunction({
|
||||
context.funcName === "\\widetilde" ||
|
||||
context.funcName === "\\widecheck";
|
||||
|
||||
return new ParseNode("accent", {
|
||||
return {
|
||||
type: "accent",
|
||||
label: context.funcName,
|
||||
isStretchy: isStretchy,
|
||||
isShifty: isShifty,
|
||||
base: base,
|
||||
}, context.parser.mode);
|
||||
mode: context.parser.mode,
|
||||
value: {
|
||||
type: "accent",
|
||||
label: context.funcName,
|
||||
isStretchy: isStretchy,
|
||||
isShifty: isShifty,
|
||||
base: base,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
mathmlBuilder,
|
||||
@@ -257,13 +261,17 @@ defineFunction({
|
||||
handler: (context, args) => {
|
||||
const base = args[0];
|
||||
|
||||
return new ParseNode("accent", {
|
||||
return {
|
||||
type: "accent",
|
||||
label: context.funcName,
|
||||
isStretchy: false,
|
||||
isShifty: true,
|
||||
base: base,
|
||||
}, context.parser.mode);
|
||||
mode: context.parser.mode,
|
||||
value: {
|
||||
type: "accent",
|
||||
label: context.funcName,
|
||||
isStretchy: false,
|
||||
isShifty: true,
|
||||
base: base,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
mathmlBuilder,
|
||||
|
@@ -4,11 +4,12 @@ import defineFunction from "../defineFunction";
|
||||
import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import stretchy from "../stretchy";
|
||||
import ParseNode from "../ParseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
|
||||
import type {ParseNode} from "../parseNode";
|
||||
|
||||
defineFunction({
|
||||
type: "accentUnder",
|
||||
names: [
|
||||
@@ -20,11 +21,15 @@ defineFunction({
|
||||
},
|
||||
handler: ({parser, funcName}, args) => {
|
||||
const base = args[0];
|
||||
return new ParseNode("accentUnder", {
|
||||
return {
|
||||
type: "accentUnder",
|
||||
label: funcName,
|
||||
base: base,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "accentUnder",
|
||||
label: funcName,
|
||||
base: base,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group: ParseNode<"accentUnder">, options) => {
|
||||
// Treat under accents much like underlines.
|
||||
|
@@ -3,11 +3,12 @@ import defineFunction from "../defineFunction";
|
||||
import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import stretchy from "../stretchy";
|
||||
import ParseNode from "../ParseNode.js";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
|
||||
import type {ParseNode} from "../parseNode";
|
||||
|
||||
// Stretchy arrows with an optional argument
|
||||
defineFunction({
|
||||
type: "xArrow",
|
||||
@@ -27,12 +28,16 @@ defineFunction({
|
||||
numOptionalArgs: 1,
|
||||
},
|
||||
handler({parser, funcName}, args, optArgs) {
|
||||
return new ParseNode("xArrow", {
|
||||
type: "xArrow", // x for extensible
|
||||
label: funcName,
|
||||
body: args[0],
|
||||
below: optArgs[0],
|
||||
}, parser.mode);
|
||||
return {
|
||||
type: "xArrow",
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "xArrow", // x for extensible
|
||||
label: funcName,
|
||||
body: args[0],
|
||||
below: optArgs[0],
|
||||
},
|
||||
};
|
||||
},
|
||||
// Flow is unable to correctly infer the type of `group`, even though it's
|
||||
// unamibiguously determined from the passed-in `type` above.
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// @flow
|
||||
import defineFunction from "../defineFunction";
|
||||
import ParseError from "../ParseError";
|
||||
import ParseNode, {assertNodeType} from "../ParseNode";
|
||||
import {assertNodeType} from "../parseNode";
|
||||
|
||||
// \@char is an internal function that takes a grouped decimal argument like
|
||||
// {123} and converts into symbol with code 123. It is used by the *macro*
|
||||
@@ -25,6 +25,10 @@ defineFunction({
|
||||
if (isNaN(code)) {
|
||||
throw new ParseError(`\\@char has non-numeric argument ${number}`);
|
||||
}
|
||||
return new ParseNode("textord", String.fromCharCode(code), parser.mode);
|
||||
return {
|
||||
type: "textord",
|
||||
mode: parser.mode,
|
||||
value: String.fromCharCode(code),
|
||||
};
|
||||
},
|
||||
});
|
||||
|
@@ -2,7 +2,7 @@
|
||||
import defineFunction, {ordargument} from "../defineFunction";
|
||||
import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import ParseNode, {assertNodeType} from "../ParseNode";
|
||||
import {assertNodeType} from "../parseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
@@ -43,11 +43,15 @@ defineFunction({
|
||||
handler({parser}, args) {
|
||||
const color = assertNodeType(args[0], "color-token");
|
||||
const body = args[1];
|
||||
return new ParseNode("color", {
|
||||
return {
|
||||
type: "color",
|
||||
color: color.value,
|
||||
value: ordargument(body),
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "color",
|
||||
color: color.value,
|
||||
value: ordargument(body),
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
mathmlBuilder,
|
||||
@@ -78,11 +82,15 @@ defineFunction({
|
||||
},
|
||||
handler({parser, funcName}, args) {
|
||||
const body = args[0];
|
||||
return new ParseNode("color", {
|
||||
return {
|
||||
type: "color",
|
||||
color: "katex-" + funcName.slice(1),
|
||||
value: ordargument(body),
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "color",
|
||||
color: "katex-" + funcName.slice(1),
|
||||
value: ordargument(body),
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
mathmlBuilder,
|
||||
@@ -103,11 +111,15 @@ defineFunction({
|
||||
// If we see a styling function, parse out the implicit body
|
||||
const body = parser.parseExpression(true, breakOnTokenText);
|
||||
|
||||
return new ParseNode("color", {
|
||||
return {
|
||||
type: "color",
|
||||
color: color.value,
|
||||
value: body,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "color",
|
||||
color: color.value,
|
||||
value: body,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
mathmlBuilder,
|
||||
|
@@ -6,7 +6,7 @@ import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import {calculateSize} from "../units";
|
||||
import ParseError from "../ParseError";
|
||||
import ParseNode, {assertNodeType} from "../ParseNode";
|
||||
import {assertNodeType} from "../parseNode";
|
||||
|
||||
// \\ is a macro mapping to either \cr or \newline. Because they have the
|
||||
// same signature, we implement them as one megafunction, with newRow
|
||||
@@ -37,12 +37,16 @@ defineFunction({
|
||||
newLine = true;
|
||||
}
|
||||
}
|
||||
return new ParseNode("cr", {
|
||||
return {
|
||||
type: "cr",
|
||||
newLine,
|
||||
newRow,
|
||||
size: size && assertNodeType(size, "size"),
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "cr",
|
||||
newLine,
|
||||
newRow,
|
||||
size: size && assertNodeType(size, "size"),
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
// The following builders are called only at the top level,
|
||||
|
@@ -5,14 +5,14 @@ import delimiter from "../delimiter";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import ParseError from "../ParseError";
|
||||
import utils from "../utils";
|
||||
import ParseNode, {assertNodeType, checkSymbolNodeType} from "../ParseNode";
|
||||
import {assertNodeType, checkSymbolNodeType} from "../parseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
|
||||
import type Options from "../Options";
|
||||
import type {AnyParseNode, SymbolParseNode} from "../ParseNode";
|
||||
import type {LeftRightDelimType} from "../ParseNode";
|
||||
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
|
||||
@@ -83,12 +83,16 @@ defineFunction({
|
||||
handler: (context, args) => {
|
||||
const delim = checkDelimiter(args[0], context);
|
||||
|
||||
return new ParseNode("delimsizing", {
|
||||
return {
|
||||
type: "delimsizing",
|
||||
size: delimiterSizes[context.funcName].size,
|
||||
mclass: delimiterSizes[context.funcName].mclass,
|
||||
value: delim.value,
|
||||
}, context.parser.mode);
|
||||
mode: context.parser.mode,
|
||||
value: {
|
||||
type: "delimsizing",
|
||||
size: delimiterSizes[context.funcName].size,
|
||||
mclass: delimiterSizes[context.funcName].mclass,
|
||||
value: delim.value,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
const delim = group.value.value;
|
||||
@@ -147,10 +151,14 @@ defineFunction({
|
||||
// \left case below triggers parsing of \right in
|
||||
// `const right = parser.parseFunction();`
|
||||
// uses this return value.
|
||||
return new ParseNode("leftright-right", {
|
||||
return {
|
||||
type: "leftright-right",
|
||||
value: checkDelimiter(args[0], context).value,
|
||||
}, context.parser.mode);
|
||||
mode: context.parser.mode,
|
||||
value: {
|
||||
type: "leftright-right",
|
||||
value: checkDelimiter(args[0], context).value,
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -176,12 +184,16 @@ defineFunction({
|
||||
if (!right) {
|
||||
throw new ParseError('failed to parse function after \\right');
|
||||
}
|
||||
return new ParseNode("leftright", {
|
||||
return {
|
||||
type: "leftright",
|
||||
body: body,
|
||||
left: delim.value,
|
||||
right: assertNodeType(right, "leftright-right").value.value,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "leftright",
|
||||
body: body,
|
||||
left: delim.value,
|
||||
right: assertNodeType(right, "leftright-right").value.value,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
const groupValue = leftRightGroupValue(group);
|
||||
@@ -295,10 +307,14 @@ defineFunction({
|
||||
throw new ParseError("\\middle without preceding \\left", delim);
|
||||
}
|
||||
|
||||
return new ParseNode("middle", {
|
||||
return {
|
||||
type: "middle",
|
||||
value: delim.value,
|
||||
}, context.parser.mode);
|
||||
mode: context.parser.mode,
|
||||
value: {
|
||||
type: "middle",
|
||||
value: delim.value,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
let middleDelim;
|
||||
|
@@ -4,7 +4,7 @@ import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import utils from "../utils";
|
||||
import stretchy from "../stretchy";
|
||||
import ParseNode, {assertNodeType} from "../ParseNode";
|
||||
import {assertNodeType} from "../parseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
@@ -149,12 +149,16 @@ defineFunction({
|
||||
handler({parser, funcName}, args, optArgs) {
|
||||
const color = assertNodeType(args[0], "color-token");
|
||||
const body = args[1];
|
||||
return new ParseNode("enclose", {
|
||||
return {
|
||||
type: "enclose",
|
||||
label: funcName,
|
||||
backgroundColor: color,
|
||||
body: body,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "enclose",
|
||||
label: funcName,
|
||||
backgroundColor: color,
|
||||
body: body,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
mathmlBuilder,
|
||||
@@ -173,13 +177,17 @@ defineFunction({
|
||||
const borderColor = assertNodeType(args[0], "color-token");
|
||||
const backgroundColor = assertNodeType(args[1], "color-token");
|
||||
const body = args[2];
|
||||
return new ParseNode("enclose", {
|
||||
return {
|
||||
type: "enclose",
|
||||
label: funcName,
|
||||
backgroundColor: backgroundColor,
|
||||
borderColor: borderColor,
|
||||
body: body,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "enclose",
|
||||
label: funcName,
|
||||
backgroundColor: backgroundColor,
|
||||
borderColor: borderColor,
|
||||
body: body,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
mathmlBuilder,
|
||||
@@ -193,11 +201,15 @@ defineFunction({
|
||||
},
|
||||
handler({parser, funcName}, args, optArgs) {
|
||||
const body = args[0];
|
||||
return new ParseNode("enclose", {
|
||||
return {
|
||||
type: "enclose",
|
||||
label: funcName,
|
||||
body: body,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "enclose",
|
||||
label: funcName,
|
||||
body: body,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
mathmlBuilder,
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// @flow
|
||||
import defineFunction from "../defineFunction";
|
||||
import ParseError from "../ParseError";
|
||||
import ParseNode, {assertNodeType} from "../ParseNode";
|
||||
import {assertNodeType} from "../parseNode";
|
||||
|
||||
// Environment delimiters. HTML/MathML rendering is defined in the corresponding
|
||||
// defineEnvironment definitions.
|
||||
@@ -21,10 +21,14 @@ defineFunction({
|
||||
for (let i = 0; i < nameGroup.value.length; ++i) {
|
||||
name += assertNodeType(nameGroup.value[i], "textord").value;
|
||||
}
|
||||
return new ParseNode("environment", {
|
||||
return {
|
||||
type: "environment",
|
||||
name: name,
|
||||
nameGroup: nameGroup,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "environment",
|
||||
name: name,
|
||||
nameGroup: nameGroup,
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
@@ -3,7 +3,6 @@
|
||||
|
||||
import {binrelClass} from "./mclass";
|
||||
import defineFunction from "../defineFunction";
|
||||
import ParseNode from "../ParseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
@@ -51,11 +50,15 @@ defineFunction({
|
||||
if (func in fontAliases) {
|
||||
func = fontAliases[func];
|
||||
}
|
||||
return new ParseNode("font", {
|
||||
return {
|
||||
type: "font",
|
||||
font: func.slice(1),
|
||||
body,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "font",
|
||||
font: func.slice(1),
|
||||
body,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
mathmlBuilder,
|
||||
@@ -72,17 +75,25 @@ defineFunction({
|
||||
const body = args[0];
|
||||
// amsbsy.sty's \boldsymbol uses \binrel spacing to inherit the
|
||||
// argument's bin|rel|ord status
|
||||
return new ParseNode("mclass", {
|
||||
return {
|
||||
type: "mclass",
|
||||
mclass: binrelClass(body),
|
||||
value: [
|
||||
new ParseNode("font", {
|
||||
type: "font",
|
||||
font: "boldsymbol",
|
||||
body,
|
||||
}, parser.mode),
|
||||
],
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "mclass",
|
||||
mclass: binrelClass(body),
|
||||
value: [
|
||||
{
|
||||
type: "font",
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "font",
|
||||
font: "boldsymbol",
|
||||
body,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -100,11 +111,19 @@ defineFunction({
|
||||
const body = parser.parseExpression(true, breakOnTokenText);
|
||||
const style = `math${funcName.slice(1)}`;
|
||||
|
||||
return new ParseNode("font", {
|
||||
return {
|
||||
type: "font",
|
||||
font: style,
|
||||
body: new ParseNode("ordgroup", body, parser.mode),
|
||||
}, mode);
|
||||
mode: mode,
|
||||
value: {
|
||||
type: "font",
|
||||
font: style,
|
||||
body: {
|
||||
type: "ordgroup",
|
||||
mode: parser.mode,
|
||||
value: body,
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
mathmlBuilder,
|
||||
|
@@ -4,7 +4,7 @@ import buildCommon from "../buildCommon";
|
||||
import delimiter from "../delimiter";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import Style from "../Style";
|
||||
import ParseNode, {assertNodeType, checkNodeType} from "../ParseNode";
|
||||
import {assertNodeType, checkNodeType} from "../parseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
@@ -281,17 +281,21 @@ defineFunction({
|
||||
break;
|
||||
}
|
||||
|
||||
return new ParseNode("genfrac", {
|
||||
return {
|
||||
type: "genfrac",
|
||||
continued: funcName === "\\cfrac",
|
||||
numer: numer,
|
||||
denom: denom,
|
||||
hasBarLine: hasBarLine,
|
||||
leftDelim: leftDelim,
|
||||
rightDelim: rightDelim,
|
||||
size: size,
|
||||
barSize: null,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "genfrac",
|
||||
continued: funcName === "\\cfrac",
|
||||
numer: numer,
|
||||
denom: denom,
|
||||
hasBarLine: hasBarLine,
|
||||
leftDelim: leftDelim,
|
||||
rightDelim: rightDelim,
|
||||
size: size,
|
||||
barSize: null,
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
htmlBuilder,
|
||||
@@ -328,11 +332,15 @@ defineFunction({
|
||||
default:
|
||||
throw new Error("Unrecognized infix genfrac command");
|
||||
}
|
||||
return new ParseNode("infix", {
|
||||
return {
|
||||
type: "infix",
|
||||
replaceWith: replaceWith,
|
||||
token: token,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "infix",
|
||||
replaceWith: replaceWith,
|
||||
token: token,
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -401,17 +409,21 @@ defineFunction({
|
||||
size = stylArray[Number(styl.value)];
|
||||
}
|
||||
|
||||
return new ParseNode("genfrac", {
|
||||
return {
|
||||
type: "genfrac",
|
||||
numer: numer,
|
||||
denom: denom,
|
||||
continued: false,
|
||||
hasBarLine: hasBarLine,
|
||||
barSize: barSize,
|
||||
leftDelim: leftDelim,
|
||||
rightDelim: rightDelim,
|
||||
size: size,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "genfrac",
|
||||
numer: numer,
|
||||
denom: denom,
|
||||
continued: false,
|
||||
hasBarLine: hasBarLine,
|
||||
barSize: barSize,
|
||||
leftDelim: leftDelim,
|
||||
rightDelim: rightDelim,
|
||||
size: size,
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
htmlBuilder,
|
||||
@@ -429,12 +441,16 @@ defineFunction({
|
||||
},
|
||||
handler({parser, funcName, token}, args) {
|
||||
const sizeNode = assertNodeType(args[0], "size");
|
||||
return new ParseNode("infix", {
|
||||
return {
|
||||
type: "infix",
|
||||
replaceWith: "\\\\abovefrac",
|
||||
sizeNode: sizeNode,
|
||||
token: token,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "infix",
|
||||
replaceWith: "\\\\abovefrac",
|
||||
sizeNode: sizeNode,
|
||||
token: token,
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -453,17 +469,21 @@ defineFunction({
|
||||
|
||||
const barSize = sizeNode.value.value;
|
||||
const hasBarLine = barSize.number > 0;
|
||||
return new ParseNode("genfrac", {
|
||||
return {
|
||||
type: "genfrac",
|
||||
numer: numer,
|
||||
denom: denom,
|
||||
continued: false,
|
||||
hasBarLine: hasBarLine,
|
||||
barSize: barSize,
|
||||
leftDelim: null,
|
||||
rightDelim: null,
|
||||
size: "auto",
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "genfrac",
|
||||
numer: numer,
|
||||
denom: denom,
|
||||
continued: false,
|
||||
hasBarLine: hasBarLine,
|
||||
barSize: barSize,
|
||||
leftDelim: null,
|
||||
rightDelim: null,
|
||||
size: "auto",
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
htmlBuilder,
|
||||
|
@@ -4,12 +4,13 @@ import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import stretchy from "../stretchy";
|
||||
import Style from "../Style";
|
||||
import ParseNode, {assertNodeType, checkNodeType} from "../ParseNode";
|
||||
import {assertNodeType, checkNodeType} from "../parseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
|
||||
import type {HtmlBuilderSupSub, MathMLBuilder} from "../defineFunction";
|
||||
import type {ParseNode} from "../parseNode";
|
||||
|
||||
// NOTE: Unlike most `htmlBuilder`s, this one handles not only "horizBrace", but
|
||||
// also "supsub" since an over/underbrace can affect super/subscripting.
|
||||
@@ -126,12 +127,16 @@ defineFunction({
|
||||
numArgs: 1,
|
||||
},
|
||||
handler({parser, funcName}, args) {
|
||||
return new ParseNode("horizBrace", {
|
||||
return {
|
||||
type: "horizBrace",
|
||||
label: funcName,
|
||||
isOver: /^\\over/.test(funcName),
|
||||
base: args[0],
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "horizBrace",
|
||||
label: funcName,
|
||||
isOver: /^\\over/.test(funcName),
|
||||
base: args[0],
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
mathmlBuilder,
|
||||
|
@@ -1,7 +1,7 @@
|
||||
// @flow
|
||||
import defineFunction, {ordargument} from "../defineFunction";
|
||||
import buildCommon from "../buildCommon";
|
||||
import ParseNode, {assertNodeType} from "../ParseNode";
|
||||
import {assertNodeType} from "../parseNode";
|
||||
import {assertType} from "../utils";
|
||||
import {MathNode} from "../mathMLTree";
|
||||
|
||||
@@ -19,11 +19,15 @@ defineFunction({
|
||||
handler: ({parser}, args) => {
|
||||
const body = args[1];
|
||||
const href = assertNodeType(args[0], "url").value.value;
|
||||
return new ParseNode("href", {
|
||||
return {
|
||||
type: "href",
|
||||
href: href,
|
||||
body: ordargument(body),
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "href",
|
||||
href: href,
|
||||
body: ordargument(body),
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
const elements = html.buildExpression(
|
||||
@@ -59,17 +63,29 @@ defineFunction({
|
||||
if (c === "~") {
|
||||
c = "\\textasciitilde";
|
||||
}
|
||||
chars.push(new ParseNode("textord", c, "text"));
|
||||
chars.push({
|
||||
type: "textord",
|
||||
mode: "text",
|
||||
value: c,
|
||||
});
|
||||
}
|
||||
const body = new ParseNode("text", {
|
||||
const body = {
|
||||
type: "text",
|
||||
font: "\\texttt",
|
||||
body: chars,
|
||||
}, parser.mode);
|
||||
return new ParseNode("href", {
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "text",
|
||||
font: "\\texttt",
|
||||
body: chars,
|
||||
},
|
||||
};
|
||||
return {
|
||||
type: "href",
|
||||
href: href,
|
||||
body: ordargument(body),
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "href",
|
||||
href: href,
|
||||
body: ordargument(body),
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
@@ -1,7 +1,6 @@
|
||||
// @flow
|
||||
import defineFunction, {ordargument} from "../defineFunction";
|
||||
import buildCommon from "../buildCommon";
|
||||
import ParseNode from "../ParseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
@@ -14,11 +13,15 @@ defineFunction({
|
||||
allowedInText: true,
|
||||
},
|
||||
handler: ({parser}, args) => {
|
||||
return new ParseNode("htmlmathml", {
|
||||
return {
|
||||
type: "htmlmathml",
|
||||
html: ordargument(args[0]),
|
||||
mathml: ordargument(args[1]),
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "htmlmathml",
|
||||
html: ordargument(args[0]),
|
||||
mathml: ordargument(args[1]),
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
const elements = html.buildExpression(
|
||||
|
@@ -5,7 +5,7 @@ import defineFunction from "../defineFunction";
|
||||
import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import {calculateSize} from "../units";
|
||||
import ParseNode, {assertNodeType} from "../ParseNode";
|
||||
import {assertNodeType} from "../parseNode";
|
||||
|
||||
// TODO: \hskip and \mskip should support plus and minus in lengths
|
||||
|
||||
@@ -39,10 +39,14 @@ defineFunction({
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ParseNode("kern", {
|
||||
return {
|
||||
type: "kern",
|
||||
dimension: size.value.value,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "kern",
|
||||
dimension: size.value.value,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
return buildCommon.makeGlue(group.value.dimension, options);
|
||||
|
@@ -3,7 +3,6 @@
|
||||
import defineFunction from "../defineFunction";
|
||||
import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import ParseNode from "../ParseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
@@ -17,11 +16,15 @@ defineFunction({
|
||||
},
|
||||
handler: ({parser, funcName}, args) => {
|
||||
const body = args[0];
|
||||
return new ParseNode("lap", {
|
||||
return {
|
||||
type: "lap",
|
||||
alignment: funcName.slice(5),
|
||||
body: body,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "lap",
|
||||
alignment: funcName.slice(5),
|
||||
body: body,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
// mathllap, mathrlap, mathclap
|
||||
|
@@ -1,7 +1,6 @@
|
||||
// @flow
|
||||
import defineFunction from "../defineFunction";
|
||||
import ParseError from "../ParseError";
|
||||
import ParseNode from "../ParseNode";
|
||||
|
||||
// Switching from text mode back to math mode
|
||||
defineFunction({
|
||||
@@ -23,11 +22,15 @@ defineFunction({
|
||||
parser.expect(close, false);
|
||||
parser.switchMode(outerMode);
|
||||
parser.consume();
|
||||
return new ParseNode("styling", {
|
||||
return {
|
||||
type: "styling",
|
||||
style: "text",
|
||||
value: body,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "styling",
|
||||
style: "text",
|
||||
value: body,
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
|
@@ -2,7 +2,6 @@
|
||||
import defineFunction, {ordargument} from "../defineFunction";
|
||||
import buildCommon from "../buildCommon";
|
||||
import Style from "../Style";
|
||||
import ParseNode from "../ParseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
@@ -29,13 +28,17 @@ defineFunction({
|
||||
numArgs: 4,
|
||||
},
|
||||
handler: ({parser}, args) => {
|
||||
return new ParseNode("mathchoice", {
|
||||
return {
|
||||
type: "mathchoice",
|
||||
display: ordargument(args[0]),
|
||||
text: ordargument(args[1]),
|
||||
script: ordargument(args[2]),
|
||||
scriptscript: ordargument(args[3]),
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "mathchoice",
|
||||
display: ordargument(args[0]),
|
||||
text: ordargument(args[1]),
|
||||
script: ordargument(args[2]),
|
||||
scriptscript: ordargument(args[3]),
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
const body = chooseMathStyle(group, options);
|
||||
|
@@ -2,8 +2,7 @@
|
||||
import defineFunction, {ordargument} from "../defineFunction";
|
||||
import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import ParseNode from "../ParseNode";
|
||||
import type {AnyParseNode} from "../ParseNode";
|
||||
import type {AnyParseNode} from "../parseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
@@ -32,11 +31,15 @@ defineFunction({
|
||||
},
|
||||
handler({parser, funcName}, args) {
|
||||
const body = args[0];
|
||||
return new ParseNode("mclass", {
|
||||
return {
|
||||
type: "mclass",
|
||||
mclass: "m" + funcName.substr(5),
|
||||
value: ordargument(body),
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "mclass",
|
||||
mclass: "m" + funcName.substr(5),
|
||||
value: ordargument(body),
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
mathmlBuilder,
|
||||
@@ -65,11 +68,15 @@ defineFunction({
|
||||
numArgs: 2,
|
||||
},
|
||||
handler({parser}, args) {
|
||||
return new ParseNode("mclass", {
|
||||
return {
|
||||
type: "mclass",
|
||||
mclass: binrelClass(args[0]),
|
||||
value: [args[1]],
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "mclass",
|
||||
mclass: binrelClass(args[0]),
|
||||
value: [args[1]],
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
|
||||
@@ -92,27 +99,39 @@ defineFunction({
|
||||
mclass = "mrel"; // for \stackrel
|
||||
}
|
||||
|
||||
const baseOp = new ParseNode("op", {
|
||||
const baseOp = {
|
||||
type: "op",
|
||||
limits: true,
|
||||
alwaysHandleSupSub: true,
|
||||
symbol: false,
|
||||
suppressBaseShift: funcName !== "\\stackrel",
|
||||
value: ordargument(baseArg),
|
||||
}, baseArg.mode);
|
||||
mode: baseArg.mode,
|
||||
value: {
|
||||
type: "op",
|
||||
limits: true,
|
||||
alwaysHandleSupSub: true,
|
||||
symbol: false,
|
||||
suppressBaseShift: funcName !== "\\stackrel",
|
||||
value: ordargument(baseArg),
|
||||
},
|
||||
};
|
||||
|
||||
const supsub = new ParseNode("supsub", {
|
||||
const supsub = {
|
||||
type: "supsub",
|
||||
base: baseOp,
|
||||
sup: funcName === "\\underset" ? null : shiftedArg,
|
||||
sub: funcName === "\\underset" ? shiftedArg : null,
|
||||
}, shiftedArg.mode);
|
||||
mode: shiftedArg.mode,
|
||||
value: {
|
||||
type: "supsub",
|
||||
base: baseOp,
|
||||
sup: funcName === "\\underset" ? null : shiftedArg,
|
||||
sub: funcName === "\\underset" ? shiftedArg : null,
|
||||
},
|
||||
};
|
||||
|
||||
return new ParseNode("mclass", {
|
||||
return {
|
||||
type: "mclass",
|
||||
mclass: mclass,
|
||||
value: [supsub],
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "mclass",
|
||||
mclass: mclass,
|
||||
value: [supsub],
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
mathmlBuilder,
|
||||
|
@@ -6,12 +6,13 @@ import domTree from "../domTree";
|
||||
import * as mathMLTree from "../mathMLTree";
|
||||
import utils from "../utils";
|
||||
import Style from "../Style";
|
||||
import ParseNode, {assertNodeType, checkNodeType} from "../ParseNode";
|
||||
import {assertNodeType, checkNodeType} from "../parseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
|
||||
import type {HtmlBuilderSupSub, MathMLBuilder} from "../defineFunction";
|
||||
import type {ParseNode} from "../parseNode";
|
||||
|
||||
// NOTE: Unlike most `htmlBuilder`s, this one handles not only "op", but also
|
||||
// "supsub" since some of them (like \int) can affect super/subscripting.
|
||||
@@ -296,12 +297,16 @@ defineFunction({
|
||||
if (fName.length === 1) {
|
||||
fName = singleCharBigOps[fName];
|
||||
}
|
||||
return new ParseNode("op", {
|
||||
return {
|
||||
type: "op",
|
||||
limits: true,
|
||||
symbol: true,
|
||||
body: fName,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "op",
|
||||
limits: true,
|
||||
symbol: true,
|
||||
body: fName,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
mathmlBuilder,
|
||||
@@ -317,12 +322,16 @@ defineFunction({
|
||||
},
|
||||
handler: ({parser}, args) => {
|
||||
const body = args[0];
|
||||
return new ParseNode("op", {
|
||||
return {
|
||||
type: "op",
|
||||
limits: false,
|
||||
symbol: false,
|
||||
value: ordargument(body),
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "op",
|
||||
limits: false,
|
||||
symbol: false,
|
||||
value: ordargument(body),
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
mathmlBuilder,
|
||||
@@ -349,12 +358,16 @@ defineFunction({
|
||||
},
|
||||
handler: ({parser}, args) => {
|
||||
const body = args[0];
|
||||
return new ParseNode("op", {
|
||||
return {
|
||||
type: "op",
|
||||
limits: false,
|
||||
symbol: false,
|
||||
value: ordargument(body),
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "op",
|
||||
limits: false,
|
||||
symbol: false,
|
||||
value: ordargument(body),
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
mathmlBuilder,
|
||||
@@ -374,12 +387,16 @@ defineFunction({
|
||||
numArgs: 0,
|
||||
},
|
||||
handler({parser, funcName}) {
|
||||
return new ParseNode("op", {
|
||||
return {
|
||||
type: "op",
|
||||
limits: false,
|
||||
symbol: false,
|
||||
body: funcName,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "op",
|
||||
limits: false,
|
||||
symbol: false,
|
||||
body: funcName,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
mathmlBuilder,
|
||||
@@ -395,12 +412,16 @@ defineFunction({
|
||||
numArgs: 0,
|
||||
},
|
||||
handler({parser, funcName}) {
|
||||
return new ParseNode("op", {
|
||||
return {
|
||||
type: "op",
|
||||
limits: true,
|
||||
symbol: false,
|
||||
body: funcName,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "op",
|
||||
limits: true,
|
||||
symbol: false,
|
||||
body: funcName,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
mathmlBuilder,
|
||||
@@ -421,12 +442,16 @@ defineFunction({
|
||||
if (fName.length === 1) {
|
||||
fName = singleCharIntegrals[fName];
|
||||
}
|
||||
return new ParseNode("op", {
|
||||
return {
|
||||
type: "op",
|
||||
limits: false,
|
||||
symbol: true,
|
||||
body: fName,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "op",
|
||||
limits: false,
|
||||
symbol: true,
|
||||
body: fName,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
mathmlBuilder,
|
||||
|
@@ -1,5 +1,4 @@
|
||||
// @flow
|
||||
import ParseNode from "../ParseNode";
|
||||
import defineFunction, {ordargument} from "../defineFunction";
|
||||
import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
@@ -18,10 +17,14 @@ defineFunction({
|
||||
},
|
||||
handler: ({parser}, args) => {
|
||||
const body = args[0];
|
||||
return new ParseNode("operatorname", {
|
||||
return {
|
||||
type: "operatorname",
|
||||
value: ordargument(body),
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "operatorname",
|
||||
value: ordargument(body),
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
htmlBuilder: (group, options) => {
|
||||
@@ -29,7 +32,11 @@ defineFunction({
|
||||
const groupValue = group.value.value.map(child => {
|
||||
const childValue = child.value;
|
||||
if (typeof childValue === "string") {
|
||||
return new ParseNode("textord", childValue, child.mode);
|
||||
return {
|
||||
type: "textord",
|
||||
mode: child.mode,
|
||||
value: childValue,
|
||||
};
|
||||
} else {
|
||||
return child;
|
||||
}
|
||||
|
@@ -2,7 +2,6 @@
|
||||
import defineFunction from "../defineFunction";
|
||||
import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import ParseNode from "../ParseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
@@ -15,10 +14,14 @@ defineFunction({
|
||||
},
|
||||
handler({parser}, args) {
|
||||
const body = args[0];
|
||||
return new ParseNode("overline", {
|
||||
return {
|
||||
type: "overline",
|
||||
body: body,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "overline",
|
||||
body: body,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder(group, options) {
|
||||
// Overlines are handled in the TeXbook pg 443, Rule 9.
|
||||
|
@@ -2,7 +2,6 @@
|
||||
import defineFunction, {ordargument} from "../defineFunction";
|
||||
import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import ParseNode from "../ParseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
@@ -16,10 +15,14 @@ defineFunction({
|
||||
},
|
||||
handler: ({parser}, args) => {
|
||||
const body = args[0];
|
||||
return new ParseNode("phantom", {
|
||||
return {
|
||||
type: "phantom",
|
||||
value: ordargument(body),
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "phantom",
|
||||
value: ordargument(body),
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
const elements = html.buildExpression(
|
||||
@@ -47,11 +50,15 @@ defineFunction({
|
||||
},
|
||||
handler: ({parser}, args) => {
|
||||
const body = args[0];
|
||||
return new ParseNode("hphantom", {
|
||||
return {
|
||||
type: "hphantom",
|
||||
value: ordargument(body),
|
||||
body: body,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "hphantom",
|
||||
value: ordargument(body),
|
||||
body: body,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
let node = buildCommon.makeSpan(
|
||||
@@ -90,11 +97,15 @@ defineFunction({
|
||||
},
|
||||
handler: ({parser}, args) => {
|
||||
const body = args[0];
|
||||
return new ParseNode("vphantom", {
|
||||
return {
|
||||
type: "vphantom",
|
||||
value: ordargument(body),
|
||||
body: body,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "vphantom",
|
||||
value: ordargument(body),
|
||||
body: body,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
const inner = buildCommon.makeSpan(
|
||||
|
@@ -2,7 +2,7 @@
|
||||
import defineFunction, {ordargument} from "../defineFunction";
|
||||
import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import ParseNode, {assertNodeType} from "../ParseNode";
|
||||
import {assertNodeType} from "../parseNode";
|
||||
import {calculateSize} from "../units";
|
||||
|
||||
import * as mml from "../buildMathML";
|
||||
@@ -20,24 +20,36 @@ defineFunction({
|
||||
handler({parser}, args) {
|
||||
const amount = assertNodeType(args[0], "size");
|
||||
const body = args[1];
|
||||
return new ParseNode("raisebox", {
|
||||
return {
|
||||
type: "raisebox",
|
||||
dy: amount,
|
||||
body: body,
|
||||
value: ordargument(body),
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "raisebox",
|
||||
dy: amount,
|
||||
body: body,
|
||||
value: ordargument(body),
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder(group, options) {
|
||||
const text = new ParseNode("text", {
|
||||
const text = {
|
||||
type: "text",
|
||||
body: group.value.value,
|
||||
font: "mathrm", // simulate \textrm
|
||||
}, group.mode);
|
||||
const sizedText = new ParseNode("sizing", {
|
||||
mode: group.mode,
|
||||
value: {
|
||||
type: "text",
|
||||
body: group.value.value,
|
||||
font: "mathrm", // simulate \textrm
|
||||
},
|
||||
};
|
||||
const sizedText = {
|
||||
type: "sizing",
|
||||
value: [text],
|
||||
size: 6, // simulate \normalsize
|
||||
}, group.mode);
|
||||
mode: group.mode,
|
||||
value: {
|
||||
type: "sizing",
|
||||
value: [text],
|
||||
size: 6, // simulate \normalsize
|
||||
},
|
||||
};
|
||||
const body = sizing.htmlBuilder(sizedText, options);
|
||||
const dy = calculateSize(group.value.dy.value.value, options);
|
||||
return buildCommon.makeVList({
|
||||
|
@@ -2,7 +2,7 @@
|
||||
import buildCommon from "../buildCommon";
|
||||
import defineFunction from "../defineFunction";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import ParseNode, {assertNodeType} from "../ParseNode";
|
||||
import {assertNodeType} from "../parseNode";
|
||||
import {calculateSize} from "../units";
|
||||
|
||||
defineFunction({
|
||||
@@ -17,12 +17,16 @@ defineFunction({
|
||||
const shift = optArgs[0];
|
||||
const width = assertNodeType(args[0], "size");
|
||||
const height = assertNodeType(args[1], "size");
|
||||
return new ParseNode("rule", {
|
||||
return {
|
||||
type: "rule",
|
||||
shift: shift && assertNodeType(shift, "size").value.value,
|
||||
width: width.value.value,
|
||||
height: height.value.value,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "rule",
|
||||
shift: shift && assertNodeType(shift, "size").value.value,
|
||||
width: width.value.value,
|
||||
height: height.value.value,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder(group, options) {
|
||||
// Make an empty span for the rule
|
||||
|
@@ -3,7 +3,6 @@ import buildCommon from "../buildCommon";
|
||||
import defineFunction from "../defineFunction";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import utils from "../utils";
|
||||
import ParseNode from "../ParseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
@@ -60,12 +59,16 @@ defineFunction({
|
||||
parser.consumeSpaces();
|
||||
const body = parser.parseExpression(false, breakOnTokenText);
|
||||
|
||||
return new ParseNode("sizing", {
|
||||
return {
|
||||
type: "sizing",
|
||||
// Figure out what size to use based on the list of functions above
|
||||
size: utils.indexOf(sizeFuncs, funcName) + 1,
|
||||
value: body,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "sizing",
|
||||
// Figure out what size to use based on the list of functions above
|
||||
size: utils.indexOf(sizeFuncs, funcName) + 1,
|
||||
value: body,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder,
|
||||
mathmlBuilder: (group, options) => {
|
||||
|
@@ -3,7 +3,7 @@
|
||||
import defineFunction from "../defineFunction";
|
||||
import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import ParseNode, {assertNodeType} from "../ParseNode";
|
||||
import {assertNodeType} from "../parseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
@@ -43,12 +43,16 @@ defineFunction({
|
||||
}
|
||||
|
||||
const body = args[0];
|
||||
return new ParseNode("smash", {
|
||||
return {
|
||||
type: "smash",
|
||||
body: body,
|
||||
smashHeight: smashHeight,
|
||||
smashDepth: smashDepth,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "smash",
|
||||
body: body,
|
||||
smashHeight: smashHeight,
|
||||
smashDepth: smashDepth,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
const node = buildCommon.makeSpan(
|
||||
|
@@ -4,7 +4,6 @@ import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import delimiter from "../delimiter";
|
||||
import Style from "../Style";
|
||||
import ParseNode from "../ParseNode";
|
||||
|
||||
import * as tree from "../tree";
|
||||
import * as html from "../buildHTML";
|
||||
@@ -20,11 +19,15 @@ defineFunction({
|
||||
handler({parser}, args, optArgs) {
|
||||
const index = optArgs[0];
|
||||
const body = args[0];
|
||||
return new ParseNode("sqrt", {
|
||||
return {
|
||||
type: "sqrt",
|
||||
body: body,
|
||||
index: index,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "sqrt",
|
||||
body: body,
|
||||
index: index,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder(group, options) {
|
||||
// Square roots are handled in the TeXbook pg. 443, Rule 11.
|
||||
|
@@ -3,7 +3,6 @@ import defineFunction from "../defineFunction";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import Style from "../Style";
|
||||
import {sizingGroup} from "./sizing";
|
||||
import ParseNode from "../ParseNode";
|
||||
|
||||
import * as mml from "../buildMathML";
|
||||
|
||||
@@ -33,13 +32,17 @@ defineFunction({
|
||||
// here and in buildHTML and de-dupe the enumeration of all the styles).
|
||||
// $FlowFixMe: The names above exactly match the styles.
|
||||
const style: StyleStr = funcName.slice(1, funcName.length - 5);
|
||||
return new ParseNode("styling", {
|
||||
return {
|
||||
type: "styling",
|
||||
// Figure out what style to use by pulling out the style from
|
||||
// the function name
|
||||
style,
|
||||
value: body,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "styling",
|
||||
// Figure out what style to use by pulling out the style from
|
||||
// the function name
|
||||
style,
|
||||
value: body,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder: (group, options) => {
|
||||
// Style changes are handled in the TeXbook on pg. 442, Rule 3.
|
||||
|
@@ -5,7 +5,7 @@ import domTree from "../domTree";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import utils from "../utils";
|
||||
import Style from "../Style";
|
||||
import {checkNodeType} from "../ParseNode";
|
||||
import {checkNodeType} from "../parseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
@@ -14,7 +14,7 @@ import * as horizBrace from "./horizBrace";
|
||||
import * as op from "./op";
|
||||
|
||||
import type Options from "../Options";
|
||||
import type ParseNode from "../ParseNode";
|
||||
import type {ParseNode} from "../parseNode";
|
||||
import type {HtmlBuilder} from "../defineFunction";
|
||||
import type {MathNodeType} from "../mathMLTree";
|
||||
|
||||
|
@@ -6,7 +6,7 @@ import mathMLTree from "../mathMLTree";
|
||||
import * as mml from "../buildMathML";
|
||||
|
||||
import type Options from "../Options";
|
||||
import type ParseNode from "../ParseNode";
|
||||
import type {ParseNode} from "../parseNode";
|
||||
import type {Group} from "../symbols";
|
||||
|
||||
// Operator ParseNodes created in Parser.js from symbol Groups in src/symbols.js.
|
||||
|
@@ -5,7 +5,7 @@ import mathMLTree from "../mathMLTree";
|
||||
|
||||
import * as mml from "../buildMathML";
|
||||
|
||||
import type ParseNode from "../ParseNode";
|
||||
import type {ParseNode} from "../parseNode";
|
||||
|
||||
// "mathord" and "textord" ParseNodes created in Parser.js from symbol Groups in
|
||||
// src/symbols.js.
|
||||
|
@@ -1,7 +1,6 @@
|
||||
// @flow
|
||||
import defineFunction, {ordargument} from "../defineFunction";
|
||||
import buildCommon from "../buildCommon";
|
||||
import ParseNode from "../ParseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
@@ -53,11 +52,15 @@ defineFunction({
|
||||
},
|
||||
handler({parser, funcName}, args) {
|
||||
const body = args[0];
|
||||
return new ParseNode("text", {
|
||||
return {
|
||||
type: "text",
|
||||
body: ordargument(body),
|
||||
font: funcName,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "text",
|
||||
body: ordargument(body),
|
||||
font: funcName,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder(group, options) {
|
||||
const newOptions = optionsWithFont(group, options);
|
||||
|
@@ -2,7 +2,6 @@
|
||||
import defineFunction from "../defineFunction";
|
||||
import buildCommon from "../buildCommon";
|
||||
import mathMLTree from "../mathMLTree";
|
||||
import ParseNode from "../ParseNode";
|
||||
|
||||
import * as html from "../buildHTML";
|
||||
import * as mml from "../buildMathML";
|
||||
@@ -16,10 +15,14 @@ defineFunction({
|
||||
},
|
||||
handler({parser}, args) {
|
||||
const body = args[0];
|
||||
return new ParseNode("underline", {
|
||||
return {
|
||||
type: "underline",
|
||||
body: body,
|
||||
}, parser.mode);
|
||||
mode: parser.mode,
|
||||
value: {
|
||||
type: "underline",
|
||||
body: body,
|
||||
},
|
||||
};
|
||||
},
|
||||
htmlBuilder(group, options) {
|
||||
// Underlines are handled in the TeXbook pg 443, Rule 10.
|
||||
|
626
src/parseNode.js
Normal file
626
src/parseNode.js
Normal file
@@ -0,0 +1,626 @@
|
||||
// @flow
|
||||
import {GROUPS} from "./symbols";
|
||||
import type SourceLocation from "./SourceLocation";
|
||||
import type {ArrayEnvNodeData} from "./environments/array";
|
||||
import type {Mode, StyleStr} from "./types";
|
||||
import type {Token} from "./Token";
|
||||
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<"accent-token"> |
|
||||
ParseNode<"bin"> |
|
||||
ParseNode<"close"> |
|
||||
ParseNode<"inner"> |
|
||||
ParseNode<"mathord"> |
|
||||
ParseNode<"op-token"> |
|
||||
ParseNode<"open"> |
|
||||
ParseNode<"punct"> |
|
||||
ParseNode<"rel"> |
|
||||
ParseNode<"spacing"> |
|
||||
ParseNode<"textord">;
|
||||
|
||||
// Union of all possible `ParseNode<>` types.
|
||||
export type AnyParseNode = $Values<ParseNodeTypes>;
|
||||
|
||||
// Map from `NodeType` to the corresponding `ParseNode`.
|
||||
type ParseNodeTypes = {
|
||||
"array": {|
|
||||
type: "array",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: ArrayEnvNodeData,
|
||||
|},
|
||||
"color": {|
|
||||
type: "color",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "color",
|
||||
color: string,
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
|},
|
||||
"color-token": {|
|
||||
type: "color-token",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: string,
|
||||
|},
|
||||
// To avoid requiring run-time type assertions, this more carefully captures
|
||||
// the requirements on the fields per the op.js htmlBuilder logic:
|
||||
// - `body` and `value` are NEVER set simultanouesly.
|
||||
// - When `symbol` is true, `body` is set.
|
||||
"op": {|
|
||||
type: "op",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "op",
|
||||
limits: boolean,
|
||||
alwaysHandleSupSub?: boolean,
|
||||
suppressBaseShift?: boolean,
|
||||
symbol: boolean,
|
||||
body: string,
|
||||
value?: void,
|
||||
|} | {|
|
||||
type: "op",
|
||||
limits: boolean,
|
||||
alwaysHandleSupSub?: boolean,
|
||||
suppressBaseShift?: boolean,
|
||||
symbol: false, // If 'symbol' is true, `body` *must* be set.
|
||||
body?: void,
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
|},
|
||||
"ordgroup": {|
|
||||
type: "ordgroup",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
"size": {|
|
||||
type: "size",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "size",
|
||||
value: Measurement,
|
||||
isBlank: boolean,
|
||||
|},
|
||||
|},
|
||||
"styling": {|
|
||||
type: "styling",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "styling",
|
||||
style: StyleStr,
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
|},
|
||||
"supsub": {|
|
||||
type: "supsub",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "supsub",
|
||||
base: ?AnyParseNode,
|
||||
sup?: ?AnyParseNode,
|
||||
sub?: ?AnyParseNode,
|
||||
|},
|
||||
|},
|
||||
"tag": {|
|
||||
type: "tag",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "tag",
|
||||
body: AnyParseNode[],
|
||||
tag: AnyParseNode[],
|
||||
|},
|
||||
|},
|
||||
"text": {|
|
||||
type: "text",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "text",
|
||||
body: AnyParseNode[],
|
||||
font?: string,
|
||||
|},
|
||||
|},
|
||||
"url": {|
|
||||
type: "url",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "url",
|
||||
value: string,
|
||||
|},
|
||||
|},
|
||||
"verb": {|
|
||||
type: "verb",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "verb",
|
||||
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
|
||||
// `ParseNode` types.)
|
||||
"accent-token": {|
|
||||
type: "accent-token",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: string,
|
||||
|},
|
||||
"bin": {|
|
||||
type: "bin",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: string,
|
||||
|},
|
||||
"close": {|
|
||||
type: "close",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: string,
|
||||
|},
|
||||
"inner": {|
|
||||
type: "inner",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: string,
|
||||
|},
|
||||
"mathord": {|
|
||||
type: "mathord",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: string,
|
||||
|},
|
||||
"op-token": {|
|
||||
type: "op-token",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: string,
|
||||
|},
|
||||
"open": {|
|
||||
type: "open",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: string,
|
||||
|},
|
||||
"punct": {|
|
||||
type: "punct",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: string,
|
||||
|},
|
||||
"rel": {|
|
||||
type: "rel",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: string,
|
||||
|},
|
||||
"spacing": {|
|
||||
type: "spacing",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: string,
|
||||
|},
|
||||
"textord": {|
|
||||
type: "textord",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: string,
|
||||
|},
|
||||
// From functions.js and functions/*.js. See also "color", "op", "styling",
|
||||
// and "text" above.
|
||||
"accent": {|
|
||||
type: "accent",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "accent",
|
||||
label: string,
|
||||
isStretchy?: boolean,
|
||||
isShifty?: boolean,
|
||||
base: AnyParseNode,
|
||||
|},
|
||||
|},
|
||||
"accentUnder": {|
|
||||
type: "accentUnder",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "accentUnder",
|
||||
label: string,
|
||||
isStretchy?: boolean,
|
||||
isShifty?: boolean,
|
||||
base: AnyParseNode,
|
||||
|},
|
||||
|},
|
||||
"cr": {|
|
||||
type: "cr",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "cr",
|
||||
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,
|
||||
|},
|
||||
|},
|
||||
"enclose": {|
|
||||
type: "enclose",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "enclose",
|
||||
label: string,
|
||||
backgroundColor?: ParseNode<"color-token">,
|
||||
borderColor?: ParseNode<"color-token">,
|
||||
body: AnyParseNode,
|
||||
|},
|
||||
|},
|
||||
"environment": {|
|
||||
type: "environment",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "environment",
|
||||
name: string,
|
||||
nameGroup: AnyParseNode,
|
||||
|},
|
||||
|},
|
||||
"font": {|
|
||||
type: "font",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "font",
|
||||
font: string,
|
||||
body: AnyParseNode,
|
||||
|},
|
||||
|},
|
||||
"genfrac": {|
|
||||
type: "genfrac",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "genfrac",
|
||||
continued: boolean,
|
||||
numer: AnyParseNode,
|
||||
denom: AnyParseNode,
|
||||
hasBarLine: boolean,
|
||||
leftDelim: ?string,
|
||||
rightDelim: ?string,
|
||||
size: StyleStr | "auto",
|
||||
barSize: Measurement | null,
|
||||
|},
|
||||
|},
|
||||
"horizBrace": {|
|
||||
type: "horizBrace",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "horizBrace",
|
||||
label: string,
|
||||
isOver: boolean,
|
||||
base: AnyParseNode,
|
||||
|},
|
||||
|},
|
||||
"href": {|
|
||||
type: "href",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "href",
|
||||
href: string,
|
||||
body: AnyParseNode[],
|
||||
|},
|
||||
|},
|
||||
"htmlmathml": {|
|
||||
type: "htmlmathml",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "htmlmathml",
|
||||
html: AnyParseNode[],
|
||||
mathml: AnyParseNode[],
|
||||
|},
|
||||
|},
|
||||
"infix": {|
|
||||
type: "infix",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "infix",
|
||||
replaceWith: string,
|
||||
sizeNode?: ParseNode<"size">,
|
||||
token: ?Token,
|
||||
|},
|
||||
|},
|
||||
"kern": {|
|
||||
type: "kern",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "kern",
|
||||
dimension: Measurement,
|
||||
|},
|
||||
|},
|
||||
"lap": {|
|
||||
type: "lap",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "lap",
|
||||
alignment: string,
|
||||
body: AnyParseNode,
|
||||
|},
|
||||
|},
|
||||
"leftright": {|
|
||||
type: "leftright",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: LeftRightDelimType,
|
||||
|},
|
||||
"leftright-right": {|
|
||||
type: "leftright-right",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "leftright-right",
|
||||
value: string,
|
||||
|},
|
||||
|},
|
||||
"mathchoice": {|
|
||||
type: "mathchoice",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "mathchoice",
|
||||
display: AnyParseNode[],
|
||||
text: AnyParseNode[],
|
||||
script: AnyParseNode[],
|
||||
scriptscript: AnyParseNode[],
|
||||
|},
|
||||
|},
|
||||
"middle": {|
|
||||
type: "middle",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "middle",
|
||||
value: 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[],
|
||||
|},
|
||||
|},
|
||||
"operatorname": {|
|
||||
type: "operatorname",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "operatorname",
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
|},
|
||||
"overline": {|
|
||||
type: "overline",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "overline",
|
||||
body: AnyParseNode,
|
||||
|},
|
||||
|},
|
||||
"phantom": {|
|
||||
type: "phantom",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "phantom",
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
|},
|
||||
"hphantom": {|
|
||||
type: "hphantom",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "hphantom",
|
||||
body: AnyParseNode,
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
|},
|
||||
"vphantom": {|
|
||||
type: "vphantom",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "vphantom",
|
||||
body: AnyParseNode,
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
|},
|
||||
"raisebox": {|
|
||||
type: "raisebox",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "raisebox",
|
||||
dy: ParseNode<"size">,
|
||||
body: AnyParseNode,
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
|},
|
||||
"rule": {|
|
||||
type: "rule",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "rule",
|
||||
shift: ?Measurement,
|
||||
width: Measurement,
|
||||
height: Measurement,
|
||||
|},
|
||||
|},
|
||||
"sizing": {|
|
||||
type: "sizing",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "sizing",
|
||||
size: number,
|
||||
value: AnyParseNode[],
|
||||
|},
|
||||
|},
|
||||
"smash": {|
|
||||
type: "smash",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "smash",
|
||||
body: AnyParseNode,
|
||||
smashHeight: boolean,
|
||||
smashDepth: boolean,
|
||||
|},
|
||||
|},
|
||||
"sqrt": {|
|
||||
type: "sqrt",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "sqrt",
|
||||
body: AnyParseNode,
|
||||
index: ?AnyParseNode,
|
||||
|},
|
||||
|},
|
||||
"underline": {|
|
||||
type: "underline",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "underline",
|
||||
body: AnyParseNode,
|
||||
|},
|
||||
|},
|
||||
"xArrow": {|
|
||||
type: "xArrow",
|
||||
mode: Mode,
|
||||
loc?: ?SourceLocation,
|
||||
value: {|
|
||||
type: "xArrow",
|
||||
label: string,
|
||||
body: AnyParseNode,
|
||||
below: ?AnyParseNode,
|
||||
|},
|
||||
|},
|
||||
};
|
||||
|
||||
/**
|
||||
* 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 assertNodeType<NODETYPE: NodeType>(
|
||||
node: ?AnyParseNode,
|
||||
type: NODETYPE,
|
||||
): ParseNode<NODETYPE> {
|
||||
const typedNode = checkNodeType(node, type);
|
||||
if (!typedNode) {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the node more strictly typed iff it is of the given type. Otherwise,
|
||||
* returns null.
|
||||
*/
|
||||
export function assertSymbolNodeType(node: ?AnyParseNode): SymbolParseNode {
|
||||
const typedNode = checkSymbolNodeType(node);
|
||||
if (!typedNode) {
|
||||
throw new Error(
|
||||
`Expected node of symbol group type, but got ` +
|
||||
(node ? `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 checkSymbolNodeType(node: ?AnyParseNode): ?SymbolParseNode {
|
||||
if (node && GROUPS.hasOwnProperty(node.type)) {
|
||||
// $FlowFixMe
|
||||
return node;
|
||||
}
|
||||
return null;
|
||||
}
|
@@ -6,10 +6,9 @@
|
||||
|
||||
import Parser from "./Parser";
|
||||
import ParseError from "./ParseError";
|
||||
import ParseNode from "./ParseNode";
|
||||
|
||||
import type Settings from "./Settings";
|
||||
import type {AnyParseNode} from "./ParseNode";
|
||||
import type {AnyParseNode} from "./parseNode";
|
||||
|
||||
/**
|
||||
* Parses an expression using a Parser, then returns the parsed result.
|
||||
@@ -30,11 +29,15 @@ const parseTree = function(toParse: string, settings: Settings): AnyParseNode[]
|
||||
throw new ParseError("\\tag works only in display equations");
|
||||
}
|
||||
parser.gullet.feed("\\df@tag");
|
||||
tree = [new ParseNode("tag", {
|
||||
tree = [{
|
||||
type: "tag",
|
||||
body: tree,
|
||||
tag: parser.parse(),
|
||||
}, "text")];
|
||||
mode: "text",
|
||||
value: {
|
||||
type: "tag",
|
||||
body: tree,
|
||||
tag: parser.parse(),
|
||||
},
|
||||
}];
|
||||
}
|
||||
|
||||
return tree;
|
||||
|
@@ -11,7 +11,7 @@ import mathMLTree from "./mathMLTree";
|
||||
import utils from "./utils";
|
||||
|
||||
import type Options from "./Options";
|
||||
import type ParseNode, {AnyParseNode} from "./ParseNode";
|
||||
import type {ParseNode, AnyParseNode} from "./parseNode";
|
||||
import type {DomSpan, HtmlDomNode, SvgSpan} from "./domTree";
|
||||
|
||||
const stretchyCodePoint: {[string]: string} = {
|
||||
|
@@ -4,7 +4,7 @@
|
||||
* files.
|
||||
*/
|
||||
|
||||
import type {AnyParseNode} from "./ParseNode";
|
||||
import type {AnyParseNode} from "./parseNode";
|
||||
|
||||
/**
|
||||
* Provide an `indexOf` function which works in IE8, but defers to native if
|
||||
|
Reference in New Issue
Block a user