From 9d2722f879f8f8d5dca896c354a3f98672513b37 Mon Sep 17 00:00:00 2001 From: Kevin Barabash Date: Sat, 2 Jun 2018 13:05:15 -0400 Subject: [PATCH] update function handlers to return a ParseNode (#1393) * update function handlers to return a ParseNode * remove FlowFixMes --- src/Parser.js | 17 +++++++------ src/defineFunction.js | 4 +-- src/functions/accent.js | 11 ++++---- src/functions/accentunder.js | 11 ++++---- src/functions/arrow.js | 11 ++++---- src/functions/color.js | 24 ++++++++---------- src/functions/cr.js | 14 +++++------ src/functions/delimsizing.js | 19 +++++++------- src/functions/enclose.js | 26 +++++++++---------- src/functions/environment.js | 7 +++--- src/functions/font.js | 17 ++++++------- src/functions/genfrac.js | 21 ++++++++-------- src/functions/horizBrace.js | 13 +++++----- src/functions/href.js | 8 +++--- src/functions/kern.js | 26 +++++++++---------- src/functions/lap.js | 9 ++++--- src/functions/math.js | 8 +++--- src/functions/mathchoice.js | 8 +++--- src/functions/mclass.js | 22 ++++++++-------- src/functions/op.js | 47 +++++++++++++++++------------------ src/functions/operatorname.js | 6 ++--- src/functions/overline.js | 7 +++--- src/functions/phantom.js | 19 +++++++------- src/functions/raisebox.js | 6 ++--- src/functions/rule.js | 8 +++--- src/functions/sizing.js | 9 +++---- src/functions/smash.js | 7 +++--- src/functions/sqrt.js | 7 +++--- src/functions/styling.js | 9 +++---- src/functions/text.js | 9 ++++--- src/functions/underline.js | 7 +++--- 31 files changed, 209 insertions(+), 208 deletions(-) diff --git a/src/Parser.js b/src/Parser.js index 90b27113..3c18d343 100644 --- a/src/Parser.js +++ b/src/Parser.js @@ -9,7 +9,7 @@ import {validUnit} from "./units"; import {supportedCodepoint} from "./unicodeScripts"; import unicodeAccents from "./unicodeAccents"; import unicodeSymbols from "./unicodeSymbols"; -import ParseNode from "./ParseNode"; +import ParseNode, {assertNodeType} from "./ParseNode"; import ParseError from "./ParseError"; import {combiningDiacriticalMarksEndRegex} from "./Lexer.js"; import Settings from "./Settings"; @@ -244,8 +244,8 @@ export default class Parser { denomNode = new ParseNode("ordgroup", denomBody, this.mode); } - const value = this.callFunction(funcName, [numerNode, denomNode], []); - return [new ParseNode(value.type, value, this.mode)]; + const node = this.callFunction(funcName, [numerNode, denomNode], []); + return [node]; } else { return body; } @@ -442,7 +442,9 @@ export default class Parser { if (func === "\\begin") { // begin...end is similar to left...right - const begin = this.parseGivenFunction(start); + const begin = + assertNodeType(this.parseGivenFunction(start), "environment"); + const envName = begin.value.name; if (!environments.hasOwnProperty(envName)) { throw new ParseError( @@ -461,7 +463,7 @@ export default class Parser { const result = env.handler(context, args, optArgs); this.expect("\\end", false); const endNameToken = this.nextToken; - const end = this.parseFunction(); + const end = assertNodeType(this.parseFunction(), "environment"); if (!end) { throw new ParseError("failed to parse function after \\end"); } else if (end.value.name !== envName) { @@ -521,9 +523,8 @@ export default class Parser { } const {args, optArgs} = this.parseArguments(func, funcData); const token = baseGroup.token; - const result = this.callFunction( + return this.callFunction( func, args, optArgs, token, breakOnTokenText); - return new ParseNode(result.type, result, this.mode); } else { return baseGroup.result; } @@ -538,7 +539,7 @@ export default class Parser { optArgs: (?ParseNode<*>)[], token?: Token, breakOnTokenText?: BreakToken, - ): * { + ): ParseNode<*> { const context: FunctionContext = { funcName: name, parser: this, diff --git a/src/defineFunction.js b/src/defineFunction.js index 4d1cfb8c..ae547e51 100644 --- a/src/defineFunction.js +++ b/src/defineFunction.js @@ -3,7 +3,7 @@ import {checkNodeType} from "./ParseNode"; import domTree from "./domTree"; import type Parser from "./Parser"; -import type ParseNode, {NodeType, NodeValue} from "./ParseNode"; +import type ParseNode, {NodeType} from "./ParseNode"; import type Options from "./Options"; import type {ArgType, BreakToken, Mode} from "./types"; import type {HtmlDomNode} from "./domTree"; @@ -22,7 +22,7 @@ export type FunctionHandler = ( context: FunctionContext, args: ParseNode<*>[], optArgs: (?ParseNode<*>)[], -) => NodeValue; +) => ParseNode; export type HtmlBuilder = (ParseNode, Options) => HtmlDomNode; export type MathMLBuilder = ( diff --git a/src/functions/accent.js b/src/functions/accent.js index 95c18759..4b702257 100644 --- a/src/functions/accent.js +++ b/src/functions/accent.js @@ -4,12 +4,11 @@ import buildCommon from "../buildCommon"; import mathMLTree from "../mathMLTree"; import utils from "../utils"; import stretchy from "../stretchy"; -import {assertNodeType, checkNodeType} from "../ParseNode"; +import ParseNode, {assertNodeType, checkNodeType} from "../ParseNode"; import * as html from "../buildHTML"; import * as mml from "../buildMathML"; -import type ParseNode from "../ParseNode"; import type {HtmlBuilderSupSub, MathMLBuilder} from "../defineFunction"; // NOTE: Unlike most `htmlBuilder`s, this one handles not only "accent", but @@ -225,13 +224,13 @@ defineFunction({ context.funcName === "\\widehat" || context.funcName === "\\widetilde"; - return { + return new ParseNode("accent", { type: "accent", label: context.funcName, isStretchy: isStretchy, isShifty: isShifty, base: base, - }; + }, context.parser.mode); }, htmlBuilder, mathmlBuilder, @@ -252,13 +251,13 @@ defineFunction({ handler: (context, args) => { const base = args[0]; - return { + return new ParseNode("accent", { type: "accent", label: context.funcName, isStretchy: false, isShifty: true, base: base, - }; + }, context.parser.mode); }, htmlBuilder, mathmlBuilder, diff --git a/src/functions/accentunder.js b/src/functions/accentunder.js index 78d68c7d..01e53825 100644 --- a/src/functions/accentunder.js +++ b/src/functions/accentunder.js @@ -4,12 +4,11 @@ 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: [ @@ -19,13 +18,13 @@ defineFunction({ props: { numArgs: 1, }, - handler: (context, args) => { + handler: ({parser, funcName}, args) => { const base = args[0]; - return { + return new ParseNode("accentUnder", { type: "accentUnder", - label: context.funcName, + label: funcName, base: base, - }; + }, parser.mode); }, htmlBuilder: (group: ParseNode<"accentUnder">, options) => { // Treat under accents much like underlines. diff --git a/src/functions/arrow.js b/src/functions/arrow.js index ce544199..f6b927e0 100644 --- a/src/functions/arrow.js +++ b/src/functions/arrow.js @@ -3,12 +3,11 @@ 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.js"; - // Stretchy arrows with an optional argument defineFunction({ type: "xArrow", @@ -27,13 +26,13 @@ defineFunction({ numArgs: 1, numOptionalArgs: 1, }, - handler(context, args, optArgs) { - return { + handler({parser, funcName}, args, optArgs) { + return new ParseNode("xArrow", { type: "xArrow", // x for extensible - label: context.funcName, + label: funcName, body: args[0], below: optArgs[0], - }; + }, parser.mode); }, // Flow is unable to correctly infer the type of `group`, even though it's // unamibiguously determined from the passed-in `type` above. diff --git a/src/functions/color.js b/src/functions/color.js index 226086f6..6b328192 100644 --- a/src/functions/color.js +++ b/src/functions/color.js @@ -3,7 +3,7 @@ import defineFunction, {ordargument} from "../defineFunction"; import buildCommon from "../buildCommon"; import mathMLTree from "../mathMLTree"; import ParseError from "../ParseError"; -import {assertNodeType} from "../ParseNode"; +import ParseNode, {assertNodeType} from "../ParseNode"; import * as html from "../buildHTML"; import * as mml from "../buildMathML"; @@ -41,14 +41,14 @@ defineFunction({ greediness: 3, argTypes: ["color", "original"], }, - handler(context, args) { + handler({parser}, args) { const color = assertNodeType(args[0], "color-token"); const body = args[1]; - return { + return new ParseNode("color", { type: "color", color: color.value, value: ordargument(body), - }; + }, parser.mode); }, htmlBuilder, mathmlBuilder, @@ -77,13 +77,13 @@ defineFunction({ allowedInText: true, greediness: 3, }, - handler(context, args) { + handler({parser, funcName}, args) { const body = args[0]; - return { + return new ParseNode("color", { type: "color", - color: "katex-" + context.funcName.slice(1), + color: "katex-" + funcName.slice(1), value: ordargument(body), - }; + }, parser.mode); }, htmlBuilder, mathmlBuilder, @@ -98,9 +98,7 @@ defineFunction({ greediness: 3, argTypes: ["color"], }, - handler(context, args) { - const {parser, breakOnTokenText} = context; - + handler({parser, breakOnTokenText}, args) { const color = args[0]; if (!color) { throw new ParseError("\\color not followed by color"); @@ -109,11 +107,11 @@ defineFunction({ // If we see a styling function, parse out the implicit body const body = parser.parseExpression(true, breakOnTokenText); - return { + return new ParseNode("color", { type: "color", color: color.value, value: body, - }; + }, parser.mode); }, htmlBuilder, mathmlBuilder, diff --git a/src/functions/cr.js b/src/functions/cr.js index eff73fb2..ee06d8bd 100644 --- a/src/functions/cr.js +++ b/src/functions/cr.js @@ -6,7 +6,7 @@ import buildCommon from "../buildCommon"; import mathMLTree from "../mathMLTree"; import {calculateSize} from "../units"; import ParseError from "../ParseError"; -import {assertNodeType} from "../ParseNode"; +import ParseNode, {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 @@ -23,13 +23,13 @@ defineFunction({ allowedInText: true, }, - handler: (context, args, optArgs) => { + handler: ({parser, funcName}, args, optArgs) => { const size = optArgs[0]; - const newRow = (context.funcName === "\\cr"); + const newRow = (funcName === "\\cr"); let newLine = false; if (!newRow) { - if (context.parser.settings.displayMode && - context.parser.settings.useStrictBehavior( + if (parser.settings.displayMode && + parser.settings.useStrictBehavior( "newLineInDisplayMode", "In LaTeX, \\\\ or \\newline " + "does nothing in display mode")) { newLine = false; @@ -37,12 +37,12 @@ defineFunction({ newLine = true; } } - return { + return new ParseNode("cr", { type: "cr", newLine, newRow, size: size && assertNodeType(size, "size"), - }; + }, parser.mode); }, // The following builders are called only at the top level, diff --git a/src/functions/delimsizing.js b/src/functions/delimsizing.js index 2483da7e..415a7731 100644 --- a/src/functions/delimsizing.js +++ b/src/functions/delimsizing.js @@ -5,12 +5,11 @@ import delimiter from "../delimiter"; import mathMLTree from "../mathMLTree"; import ParseError from "../ParseError"; import utils from "../utils"; -import {assertNodeType} from "../ParseNode"; +import ParseNode, {assertNodeType} from "../ParseNode"; import * as html from "../buildHTML"; import * as mml from "../buildMathML"; -import type ParseNode from "../ParseNode"; import type {LeftRightDelimType} from "../ParseNode"; import type {FunctionContext} from "../defineFunction"; @@ -79,12 +78,12 @@ defineFunction({ handler: (context, args) => { const delim = checkDelimiter(args[0], context); - return { + return new ParseNode("delimsizing", { type: "delimsizing", size: delimiterSizes[context.funcName].size, mclass: delimiterSizes[context.funcName].mclass, value: delim.value, - }; + }, context.parser.mode); }, htmlBuilder: (group, options) => { const delim = group.value.value; @@ -143,10 +142,10 @@ defineFunction({ // \left case below triggers parsing of \right in // `const right = parser.parseFunction();` // uses this return value. - return { + return new ParseNode("leftright-right", { type: "leftright-right", value: checkDelimiter(args[0], context).value, - }; + }, context.parser.mode); }, }); @@ -172,12 +171,12 @@ defineFunction({ if (!right) { throw new ParseError('failed to parse function after \\right'); } - return { + return new ParseNode("leftright", { type: "leftright", body: body, left: delim.value, right: assertNodeType(right, "leftright-right").value.value, - }; + }, parser.mode); }, htmlBuilder: (group, options) => { const groupValue = leftRightGroupValue(group); @@ -284,10 +283,10 @@ defineFunction({ throw new ParseError("\\middle without preceding \\left", delim); } - return { + return new ParseNode("middle", { type: "middle", value: delim.value, - }; + }, context.parser.mode); }, htmlBuilder: (group, options) => { let middleDelim; diff --git a/src/functions/enclose.js b/src/functions/enclose.js index e33515ba..476f8be5 100644 --- a/src/functions/enclose.js +++ b/src/functions/enclose.js @@ -4,7 +4,7 @@ import buildCommon from "../buildCommon"; import mathMLTree from "../mathMLTree"; import utils from "../utils"; import stretchy from "../stretchy"; -import {assertNodeType} from "../ParseNode"; +import ParseNode, {assertNodeType} from "../ParseNode"; import * as html from "../buildHTML"; import * as mml from "../buildMathML"; @@ -127,15 +127,15 @@ defineFunction({ greediness: 3, argTypes: ["color", "text"], }, - handler(context, args, optArgs) { + handler({parser, funcName}, args, optArgs) { const color = assertNodeType(args[0], "color-token"); const body = args[1]; - return { + return new ParseNode("enclose", { type: "enclose", - label: context.funcName, + label: funcName, backgroundColor: color, body: body, - }; + }, parser.mode); }, htmlBuilder, mathmlBuilder, @@ -150,17 +150,17 @@ defineFunction({ greediness: 3, argTypes: ["color", "color", "text"], }, - handler(context, args, optArgs) { + handler({parser, funcName}, args, optArgs) { const borderColor = assertNodeType(args[0], "color-token"); const backgroundColor = assertNodeType(args[1], "color-token"); const body = args[2]; - return { + return new ParseNode("enclose", { type: "enclose", - label: context.funcName, + label: funcName, backgroundColor: backgroundColor, borderColor: borderColor, body: body, - }; + }, parser.mode); }, htmlBuilder, mathmlBuilder, @@ -172,13 +172,13 @@ defineFunction({ props: { numArgs: 1, }, - handler(context, args, optArgs) { + handler({parser, funcName}, args, optArgs) { const body = args[0]; - return { + return new ParseNode("enclose", { type: "enclose", - label: context.funcName, + label: funcName, body: body, - }; + }, parser.mode); }, htmlBuilder, mathmlBuilder, diff --git a/src/functions/environment.js b/src/functions/environment.js index d6aa651b..dcc5c146 100644 --- a/src/functions/environment.js +++ b/src/functions/environment.js @@ -1,6 +1,7 @@ // @flow import defineFunction from "../defineFunction"; import ParseError from "../ParseError"; +import ParseNode from "../ParseNode"; // Environment delimiters. HTML/MathML rendering is defined in the corresponding // defineEnvironment definitions. @@ -11,7 +12,7 @@ defineFunction({ numArgs: 1, argTypes: ["text"], }, - handler(context, args) { + handler({parser}, args) { const nameGroup = args[0]; if (nameGroup.type !== "ordgroup") { throw new ParseError("Invalid environment name", nameGroup); @@ -20,10 +21,10 @@ defineFunction({ for (let i = 0; i < nameGroup.value.length; ++i) { name += nameGroup.value[i].value; } - return { + return new ParseNode("environment", { type: "environment", name: name, nameGroup: nameGroup, - }; + }, parser.mode); }, }); diff --git a/src/functions/font.js b/src/functions/font.js index ea155e26..78a1083d 100644 --- a/src/functions/font.js +++ b/src/functions/font.js @@ -44,17 +44,17 @@ defineFunction({ numArgs: 1, greediness: 2, }, - handler: (context, args) => { + handler: ({parser, funcName}, args) => { const body = args[0]; - let func = context.funcName; + let func = funcName; if (func in fontAliases) { func = fontAliases[func]; } - return { + return new ParseNode("font", { type: "font", font: func.slice(1), body: body, - }; + }, parser.mode); }, htmlBuilder, mathmlBuilder, @@ -76,18 +76,17 @@ defineFunction({ numArgs: 0, allowedInText: true, }, - handler: (context, args) => { - const {parser, funcName, breakOnTokenText} = context; - + handler: ({parser, funcName, breakOnTokenText}, args) => { + const {mode} = parser; parser.consumeSpaces(); const body = parser.parseExpression(true, breakOnTokenText); const style = oldFontFuncsMap[funcName]; - return { + return new ParseNode("font", { type: "font", font: style, body: new ParseNode("ordgroup", body, parser.mode), - }; + }, mode); }, htmlBuilder, mathmlBuilder, diff --git a/src/functions/genfrac.js b/src/functions/genfrac.js index 5a4c5f23..e62c980d 100644 --- a/src/functions/genfrac.js +++ b/src/functions/genfrac.js @@ -4,6 +4,7 @@ import buildCommon from "../buildCommon"; import delimiter from "../delimiter"; import mathMLTree from "../mathMLTree"; import Style from "../Style"; +import ParseNode from "../ParseNode"; import * as html from "../buildHTML"; import * as mml from "../buildMathML"; @@ -19,7 +20,7 @@ defineFunction({ numArgs: 2, greediness: 2, }, - handler: (context, args) => { + handler: ({parser, funcName}, args) => { const numer = args[0]; const denom = args[1]; let hasBarLine; @@ -27,7 +28,7 @@ defineFunction({ let rightDelim = null; let size = "auto"; - switch (context.funcName) { + switch (funcName) { case "\\dfrac": case "\\frac": case "\\tfrac": @@ -47,7 +48,7 @@ defineFunction({ throw new Error("Unrecognized genfrac command"); } - switch (context.funcName) { + switch (funcName) { case "\\dfrac": case "\\dbinom": size = "display"; @@ -58,7 +59,7 @@ defineFunction({ break; } - return { + return new ParseNode("genfrac", { type: "genfrac", numer: numer, denom: denom, @@ -66,7 +67,7 @@ defineFunction({ leftDelim: leftDelim, rightDelim: rightDelim, size: size, - }; + }, parser.mode); }, htmlBuilder: (group, options) => { // Fractions are handled in the TeXbook on pages 444-445, rules 15(a-e). @@ -261,9 +262,9 @@ defineFunction({ numArgs: 0, infix: true, }, - handler(context) { + handler({parser, funcName, token}) { let replaceWith; - switch (context.funcName) { + switch (funcName) { case "\\over": replaceWith = "\\frac"; break; @@ -276,11 +277,11 @@ defineFunction({ default: throw new Error("Unrecognized infix genfrac command"); } - return { + return new ParseNode("infix", { type: "infix", replaceWith: replaceWith, - token: context.token, - }; + token: token, + }, parser.mode); }, }); diff --git a/src/functions/horizBrace.js b/src/functions/horizBrace.js index 48bc0ad6..348ee76b 100644 --- a/src/functions/horizBrace.js +++ b/src/functions/horizBrace.js @@ -4,12 +4,11 @@ import buildCommon from "../buildCommon"; import mathMLTree from "../mathMLTree"; import stretchy from "../stretchy"; import Style from "../Style"; -import {assertNodeType, checkNodeType} from "../ParseNode"; +import ParseNode, {assertNodeType, checkNodeType} from "../ParseNode"; import * as html from "../buildHTML"; import * as mml from "../buildMathML"; -import type ParseNode from "../ParseNode"; import type {HtmlBuilderSupSub, MathMLBuilder} from "../defineFunction"; // NOTE: Unlike most `htmlBuilder`s, this one handles not only "horizBrace", but @@ -126,13 +125,13 @@ defineFunction({ props: { numArgs: 1, }, - handler(context, args) { - return { + handler({parser, funcName}, args) { + return new ParseNode("horizBrace", { type: "horizBrace", - label: context.funcName, - isOver: /^\\over/.test(context.funcName), + label: funcName, + isOver: /^\\over/.test(funcName), base: args[0], - }; + }, parser.mode); }, htmlBuilder, mathmlBuilder, diff --git a/src/functions/href.js b/src/functions/href.js index abb5cc20..6e75c272 100644 --- a/src/functions/href.js +++ b/src/functions/href.js @@ -1,7 +1,7 @@ // @flow import defineFunction, {ordargument} from "../defineFunction"; import buildCommon from "../buildCommon"; -import {assertNodeType} from "../ParseNode"; +import ParseNode, {assertNodeType} from "../ParseNode"; import * as html from "../buildHTML"; import * as mml from "../buildMathML"; @@ -13,14 +13,14 @@ defineFunction({ numArgs: 2, argTypes: ["url", "original"], }, - handler: (context, args) => { + handler: ({parser}, args) => { const body = args[1]; const href = assertNodeType(args[0], "url").value.value; - return { + return new ParseNode("href", { type: "href", href: href, body: ordargument(body), - }; + }, parser.mode); }, htmlBuilder: (group, options) => { const elements = html.buildExpression( diff --git a/src/functions/kern.js b/src/functions/kern.js index 8fd353fc..fd044947 100644 --- a/src/functions/kern.js +++ b/src/functions/kern.js @@ -5,7 +5,7 @@ import defineFunction from "../defineFunction"; import buildCommon from "../buildCommon"; import mathMLTree from "../mathMLTree"; import {calculateSize} from "../units"; -import {assertNodeType} from "../ParseNode"; +import ParseNode, {assertNodeType} from "../ParseNode"; // TODO: \hskip and \mskip should support plus and minus in lengths @@ -17,32 +17,32 @@ defineFunction({ argTypes: ["size"], allowedInText: true, }, - handler: (context, args) => { + handler: ({parser, funcName}, args) => { const size = assertNodeType(args[0], "size"); - if (context.parser.settings.strict) { - const mathFunction = (context.funcName[1] === 'm'); // \mkern, \mskip + if (parser.settings.strict) { + const mathFunction = (funcName[1] === 'm'); // \mkern, \mskip const muUnit = (size.value.value.unit === 'mu'); if (mathFunction) { if (!muUnit) { - context.parser.settings.reportNonstrict("mathVsTextUnits", - `LaTeX's ${context.funcName} supports only mu units, ` + + parser.settings.reportNonstrict("mathVsTextUnits", + `LaTeX's ${funcName} supports only mu units, ` + `not ${size.value.value.unit} units`); } - if (context.parser.mode !== "math") { - context.parser.settings.reportNonstrict("mathVsTextUnits", - `LaTeX's ${context.funcName} works only in math mode`); + if (parser.mode !== "math") { + parser.settings.reportNonstrict("mathVsTextUnits", + `LaTeX's ${funcName} works only in math mode`); } } else { // !mathFunction if (muUnit) { - context.parser.settings.reportNonstrict("mathVsTextUnits", - `LaTeX's ${context.funcName} doesn't support mu units`); + parser.settings.reportNonstrict("mathVsTextUnits", + `LaTeX's ${funcName} doesn't support mu units`); } } } - return { + return new ParseNode("kern", { type: "kern", dimension: size.value.value, - }; + }, parser.mode); }, htmlBuilder: (group, options) => { return buildCommon.makeGlue(group.value.dimension, options); diff --git a/src/functions/lap.js b/src/functions/lap.js index 135dbeae..2a39025f 100644 --- a/src/functions/lap.js +++ b/src/functions/lap.js @@ -3,6 +3,7 @@ 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"; @@ -14,13 +15,13 @@ defineFunction({ numArgs: 1, allowedInText: true, }, - handler: (context, args) => { + handler: ({parser, funcName}, args) => { const body = args[0]; - return { + return new ParseNode("lap", { type: "lap", - alignment: context.funcName.slice(5), + alignment: funcName.slice(5), body: body, - }; + }, parser.mode); }, htmlBuilder: (group, options) => { // mathllap, mathrlap, mathclap diff --git a/src/functions/math.js b/src/functions/math.js index cee0d50e..a05b83be 100644 --- a/src/functions/math.js +++ b/src/functions/math.js @@ -1,6 +1,7 @@ // @flow import defineFunction from "../defineFunction"; import ParseError from "../ParseError"; +import ParseNode from "../ParseNode"; // Switching from text mode back to math mode defineFunction({ @@ -12,8 +13,7 @@ defineFunction({ allowedInMath: false, consumeMode: "math", }, - handler(context, args) { - const {funcName, parser} = context; + handler({funcName, parser}, args) { const outerMode = parser.mode; parser.switchMode("math"); const close = (funcName === "\\(" ? "\\)" : "$"); @@ -23,11 +23,11 @@ defineFunction({ parser.expect(close, false); parser.switchMode(outerMode); parser.consume(); - return { + return new ParseNode("styling", { type: "styling", style: "text", value: body, - }; + }, parser.mode); }, }); diff --git a/src/functions/mathchoice.js b/src/functions/mathchoice.js index 05509289..19316b96 100644 --- a/src/functions/mathchoice.js +++ b/src/functions/mathchoice.js @@ -2,6 +2,8 @@ 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"; @@ -26,14 +28,14 @@ defineFunction({ props: { numArgs: 4, }, - handler: (context, args) => { - return { + handler: ({parser}, args) => { + return new ParseNode("mathchoice", { type: "mathchoice", display: ordargument(args[0]), text: ordargument(args[1]), script: ordargument(args[2]), scriptscript: ordargument(args[3]), - }; + }, parser.mode); }, htmlBuilder: (group, options) => { const body = chooseMathStyle(group, options); diff --git a/src/functions/mclass.js b/src/functions/mclass.js index 5e695421..32a160a1 100644 --- a/src/functions/mclass.js +++ b/src/functions/mclass.js @@ -29,13 +29,13 @@ defineFunction({ props: { numArgs: 1, }, - handler(context, args) { + handler({parser, funcName}, args) { const body = args[0]; - return { + return new ParseNode("mclass", { type: "mclass", - mclass: "m" + context.funcName.substr(5), + mclass: "m" + funcName.substr(5), value: ordargument(body), - }; + }, parser.mode); }, htmlBuilder, mathmlBuilder, @@ -48,12 +48,12 @@ defineFunction({ props: { numArgs: 2, }, - handler(context, args) { + handler({parser, funcName}, args) { const baseArg = args[1]; const shiftedArg = args[0]; let mclass = "mrel"; // default. May change below. - if (context.funcName !== "\\stackrel") { + if (funcName !== "\\stackrel") { // LaTeX applies \binrel spacing to \overset and \underset. \binrel // spacing varies with (bin|rel|ord) of the atom in the argument. // We'll do the same. @@ -78,22 +78,22 @@ defineFunction({ limits: true, alwaysHandleSupSub: true, symbol: false, - suppressBaseShift: context.funcName !== "\\stackrel", + suppressBaseShift: funcName !== "\\stackrel", value: ordargument(baseArg), }, baseArg.mode); const supsub = new ParseNode("supsub", { type: "supsub", base: baseOp, - sup: context.funcName === "\\underset" ? null : shiftedArg, - sub: context.funcName === "\\underset" ? shiftedArg : null, + sup: funcName === "\\underset" ? null : shiftedArg, + sub: funcName === "\\underset" ? shiftedArg : null, }, shiftedArg.mode); - return { + return new ParseNode("mclass", { type: "mclass", mclass: mclass, value: [supsub], - }; + }, parser.mode); }, htmlBuilder, mathmlBuilder, diff --git a/src/functions/op.js b/src/functions/op.js index 4727c9f9..c60aa5ca 100644 --- a/src/functions/op.js +++ b/src/functions/op.js @@ -6,12 +6,11 @@ import domTree from "../domTree"; import mathMLTree from "../mathMLTree"; import utils from "../utils"; import Style from "../Style"; -import {assertNodeType, checkNodeType} from "../ParseNode"; +import ParseNode, {assertNodeType, checkNodeType} from "../ParseNode"; import * as html from "../buildHTML"; import * as mml from "../buildMathML"; -import type ParseNode from "../ParseNode"; import type {HtmlBuilderSupSub, MathMLBuilder} from "../defineFunction"; // NOTE: Unlike most `htmlBuilder`s, this one handles not only "op", but also @@ -263,17 +262,17 @@ defineFunction({ props: { numArgs: 0, }, - handler: (context, args) => { - let fName = context.funcName; + handler: ({parser, funcName}, args) => { + let fName = funcName; if (fName.length === 1) { fName = singleCharBigOps[fName]; } - return { + return new ParseNode("op", { type: "op", limits: true, symbol: true, body: fName, - }; + }, parser.mode); }, htmlBuilder, mathmlBuilder, @@ -287,14 +286,14 @@ defineFunction({ props: { numArgs: 1, }, - handler: (context, args) => { + handler: ({parser}, args) => { const body = args[0]; - return { + return new ParseNode("op", { type: "op", limits: false, symbol: false, value: ordargument(body), - }; + }, parser.mode); }, htmlBuilder, mathmlBuilder, @@ -317,14 +316,14 @@ defineFunction({ props: { numArgs: 1, }, - handler: (context, args) => { + handler: ({parser}, args) => { const body = args[0]; - return { + return new ParseNode("op", { type: "op", limits: false, symbol: false, value: ordargument(body), - }; + }, parser.mode); }, htmlBuilder, mathmlBuilder, @@ -343,13 +342,13 @@ defineFunction({ props: { numArgs: 0, }, - handler(context) { - return { + handler({parser, funcName}) { + return new ParseNode("op", { type: "op", limits: false, symbol: false, - body: context.funcName, - }; + body: funcName, + }, parser.mode); }, htmlBuilder, mathmlBuilder, @@ -364,13 +363,13 @@ defineFunction({ props: { numArgs: 0, }, - handler(context) { - return { + handler({parser, funcName}) { + return new ParseNode("op", { type: "op", limits: true, symbol: false, - body: context.funcName, - }; + body: funcName, + }, parser.mode); }, htmlBuilder, mathmlBuilder, @@ -386,17 +385,17 @@ defineFunction({ props: { numArgs: 0, }, - handler(context) { - let fName = context.funcName; + handler({parser, funcName}) { + let fName = funcName; if (fName.length === 1) { fName = singleCharIntegrals[fName]; } - return { + return new ParseNode("op", { type: "op", limits: false, symbol: true, body: fName, - }; + }, parser.mode); }, htmlBuilder, mathmlBuilder, diff --git a/src/functions/operatorname.js b/src/functions/operatorname.js index b67052af..0f2f7ca4 100644 --- a/src/functions/operatorname.js +++ b/src/functions/operatorname.js @@ -16,12 +16,12 @@ defineFunction({ props: { numArgs: 1, }, - handler: (context, args) => { + handler: ({parser}, args) => { const body = args[0]; - return { + return new ParseNode("operatorname", { type: "operatorname", value: ordargument(body), - }; + }, parser.mode); }, htmlBuilder: (group, options) => { diff --git a/src/functions/overline.js b/src/functions/overline.js index e6f3eab5..97159d2e 100644 --- a/src/functions/overline.js +++ b/src/functions/overline.js @@ -2,6 +2,7 @@ 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"; @@ -12,12 +13,12 @@ defineFunction({ props: { numArgs: 1, }, - handler(context, args) { + handler({parser}, args) { const body = args[0]; - return { + return new ParseNode("overline", { type: "overline", body: body, - }; + }, parser.mode); }, htmlBuilder(group, options) { // Overlines are handled in the TeXbook pg 443, Rule 9. diff --git a/src/functions/phantom.js b/src/functions/phantom.js index 3bdf39a1..0320cf3c 100644 --- a/src/functions/phantom.js +++ b/src/functions/phantom.js @@ -2,6 +2,7 @@ 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"; @@ -12,12 +13,12 @@ defineFunction({ props: { numArgs: 1, }, - handler: (context, args) => { + handler: ({parser}, args) => { const body = args[0]; - return { + return new ParseNode("phantom", { type: "phantom", value: ordargument(body), - }; + }, parser.mode); }, htmlBuilder: (group, options) => { const elements = html.buildExpression( @@ -42,13 +43,13 @@ defineFunction({ props: { numArgs: 1, }, - handler: (context, args) => { + handler: ({parser}, args) => { const body = args[0]; - return { + return new ParseNode("hphantom", { type: "hphantom", value: ordargument(body), body: body, - }; + }, parser.mode); }, htmlBuilder: (group, options) => { let node = buildCommon.makeSpan( @@ -84,13 +85,13 @@ defineFunction({ props: { numArgs: 1, }, - handler: (context, args) => { + handler: ({parser}, args) => { const body = args[0]; - return { + return new ParseNode("vphantom", { type: "vphantom", value: ordargument(body), body: body, - }; + }, parser.mode); }, htmlBuilder: (group, options) => { const inner = buildCommon.makeSpan( diff --git a/src/functions/raisebox.js b/src/functions/raisebox.js index a5f68ec4..41782e39 100644 --- a/src/functions/raisebox.js +++ b/src/functions/raisebox.js @@ -17,15 +17,15 @@ defineFunction({ argTypes: ["size", "text"], allowedInText: true, }, - handler(context, args) { + handler({parser}, args) { const amount = assertNodeType(args[0], "size"); const body = args[1]; - return { + return new ParseNode("raisebox", { type: "raisebox", dy: amount, body: body, value: ordargument(body), - }; + }, parser.mode); }, htmlBuilder(group, options) { const text = new ParseNode("text", { diff --git a/src/functions/rule.js b/src/functions/rule.js index bdc6fc1d..b42f3afe 100644 --- a/src/functions/rule.js +++ b/src/functions/rule.js @@ -2,7 +2,7 @@ import buildCommon from "../buildCommon"; import defineFunction from "../defineFunction"; import mathMLTree from "../mathMLTree"; -import {assertNodeType} from "../ParseNode"; +import ParseNode, {assertNodeType} from "../ParseNode"; import {calculateSize} from "../units"; defineFunction({ @@ -13,16 +13,16 @@ defineFunction({ numOptionalArgs: 1, argTypes: ["size", "size", "size"], }, - handler(context, args, optArgs) { + handler({parser}, args, optArgs) { const shift = optArgs[0]; const width = assertNodeType(args[0], "size"); const height = assertNodeType(args[1], "size"); - return { + return new ParseNode("rule", { type: "rule", shift: shift && shift.value, width: width.value.value, height: height.value.value, - }; + }, parser.mode); }, htmlBuilder(group, options) { // Make an empty span for the rule diff --git a/src/functions/sizing.js b/src/functions/sizing.js index 105bb48e..960d2f11 100644 --- a/src/functions/sizing.js +++ b/src/functions/sizing.js @@ -3,6 +3,7 @@ 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"; @@ -55,18 +56,16 @@ defineFunction({ numArgs: 0, allowedInText: true, }, - handler: (context, args) => { - const {breakOnTokenText, funcName, parser} = context; - + handler: ({breakOnTokenText, funcName, parser}, args) => { parser.consumeSpaces(); const body = parser.parseExpression(false, breakOnTokenText); - return { + return new ParseNode("sizing", { 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); }, htmlBuilder, mathmlBuilder: (group, options) => { diff --git a/src/functions/smash.js b/src/functions/smash.js index 56fd74f0..0053995f 100644 --- a/src/functions/smash.js +++ b/src/functions/smash.js @@ -3,6 +3,7 @@ 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,7 +16,7 @@ defineFunction({ numOptionalArgs: 1, allowedInText: true, }, - handler: (context, args, optArgs) => { + handler: ({parser}, args, optArgs) => { let smashHeight = false; let smashDepth = false; const tbArg = optArgs[0]; @@ -42,12 +43,12 @@ defineFunction({ } const body = args[0]; - return { + return new ParseNode("smash", { type: "smash", body: body, smashHeight: smashHeight, smashDepth: smashDepth, - }; + }, parser.mode); }, htmlBuilder: (group, options) => { const node = buildCommon.makeSpan( diff --git a/src/functions/sqrt.js b/src/functions/sqrt.js index e9716482..dcd43868 100644 --- a/src/functions/sqrt.js +++ b/src/functions/sqrt.js @@ -5,6 +5,7 @@ import domTree from "../domTree"; import mathMLTree from "../mathMLTree"; import delimiter from "../delimiter"; import Style from "../Style"; +import ParseNode from "../ParseNode"; import * as html from "../buildHTML"; import * as mml from "../buildMathML"; @@ -16,14 +17,14 @@ defineFunction({ numArgs: 1, numOptionalArgs: 1, }, - handler(context, args, optArgs) { + handler({parser}, args, optArgs) { const index = optArgs[0]; const body = args[0]; - return { + return new ParseNode("sqrt", { type: "sqrt", body: body, index: index, - }; + }, parser.mode); }, htmlBuilder(group, options) { // Square roots are handled in the TeXbook pg. 443, Rule 11. diff --git a/src/functions/styling.js b/src/functions/styling.js index d3558dc3..42499509 100644 --- a/src/functions/styling.js +++ b/src/functions/styling.js @@ -3,6 +3,7 @@ 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"; @@ -23,9 +24,7 @@ defineFunction({ numArgs: 0, allowedInText: true, }, - handler: (context, args) => { - const {breakOnTokenText, funcName, parser} = context; - + handler: ({breakOnTokenText, funcName, parser}, args) => { // parse out the implicit body parser.consumeSpaces(); const body = parser.parseExpression(true, breakOnTokenText); @@ -34,13 +33,13 @@ 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 { + return new ParseNode("styling", { type: "styling", // Figure out what style to use by pulling out the style from // the function name style, value: body, - }; + }, parser.mode); }, htmlBuilder: (group, options) => { // Style changes are handled in the TeXbook on pg. 442, Rule 3. diff --git a/src/functions/text.js b/src/functions/text.js index 9888b150..a210bbc7 100644 --- a/src/functions/text.js +++ b/src/functions/text.js @@ -1,6 +1,7 @@ // @flow import defineFunction, {ordargument} from "../defineFunction"; import buildCommon from "../buildCommon"; +import ParseNode from "../ParseNode"; import * as html from "../buildHTML"; import * as mml from "../buildMathML"; @@ -36,13 +37,13 @@ defineFunction({ allowedInText: true, consumeMode: "text", }, - handler(context, args) { + handler({parser, funcName}, args) { const body = args[0]; - return { + return new ParseNode("text", { type: "text", body: ordargument(body), - font: context.funcName, - }; + font: funcName, + }, parser.mode); }, htmlBuilder(group, options) { const font = group.value.font; diff --git a/src/functions/underline.js b/src/functions/underline.js index ff9e3f38..91ff9d54 100644 --- a/src/functions/underline.js +++ b/src/functions/underline.js @@ -2,6 +2,7 @@ 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"; @@ -13,12 +14,12 @@ defineFunction({ numArgs: 1, allowedInText: true, }, - handler(context, args) { + handler({parser}, args) { const body = args[0]; - return { + return new ParseNode("underline", { type: "underline", body: body, - }; + }, parser.mode); }, htmlBuilder(group, options) { // Underlines are handled in the TeXbook pg 443, Rule 10.