diff --git a/src/functions.js b/src/functions.js index c53ecb37..dce57095 100644 --- a/src/functions.js +++ b/src/functions.js @@ -566,3 +566,6 @@ defineFunction(["\\verb"], { throw new ParseError( "\\verb ended by end of line instead of matching delimiter"); }); + +// MathChoice +import "./functions/mathchoice"; diff --git a/src/functions/mathchoice.js b/src/functions/mathchoice.js new file mode 100644 index 00000000..561c2b25 --- /dev/null +++ b/src/functions/mathchoice.js @@ -0,0 +1,57 @@ +// @flow +import defineFunction, {ordargument} from "../defineFunction"; +import buildCommon from "../buildCommon"; +import mathMLTree from "../mathMLTree"; +import Style from "../Style"; +import * as html from "../buildHTML"; +import * as mml from "../buildMathML"; + +const chooseMathStyle = (group, options) => { + const style = options.style; + if (style.size === Style.DISPLAY.size) { + return group.value.display; + } else if (style.size === Style.TEXT.size) { + return group.value.text; + } else if (style.size === Style.SCRIPT.size) { + return group.value.script; + } else if (style.size === Style.SCRIPTSCRIPT.size) { + return group.value.scriptscript; + } + return group.value.text; + +}; + +defineFunction({ + type: "mathchoice", + names: ["\\mathchoice"], + props: { + numArgs: 4, + }, + handler: (context, args) => { + return { + 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); + const elements = html.buildExpression( + body, + options, + false + ); + return new buildCommon.makeFragment(elements); + }, + mathmlBuilder: (group, options) => { + const body = chooseMathStyle(group, options); + const elements = mml.buildExpression( + body, + options, + false + ); + return new mathMLTree.MathNode("mrow", elements); + }, +}); diff --git a/test/__snapshots__/mathml-spec.js.snap b/test/__snapshots__/mathml-spec.js.snap index 3edca120..ad4b36d7 100644 --- a/test/__snapshots__/mathml-spec.js.snap +++ b/test/__snapshots__/mathml-spec.js.snap @@ -74,6 +74,149 @@ exports[`A MathML builder should make prime operators into nodes 1`] = ` `; +exports[`A MathML builder should render mathchoice as if there was nothing 1`] = ` + + + + + + + + + ∑ + + + + k + + + = + + + 0 + + + + ∞ + + + + + x + + + k + + + + + + + \\displaystyle\\mathchoice{\\sum_{k = 0}^{\\infty} x^k}{T}{S}{SS} + + + + +`; + +exports[`A MathML builder should render mathchoice as if there was nothing 2`] = ` + + + + + + + + ∑ + + + + k + + + = + + + 0 + + + + ∞ + + + + + x + + + k + + + + + + \\mathchoice{D}{\\sum_{k = 0}^{\\infty} x^k}{S}{SS} + + + + +`; + +exports[`A MathML builder should render mathchoice as if there was nothing 3`] = ` + + + + + + + x + + + + T + + + + + + x_{\\mathchoice{D}{T}{\\sum_{k = 0}^{\\infty} x^k}{SS}} + + + + +`; + +exports[`A MathML builder should render mathchoice as if there was nothing 4`] = ` + + + + + + + x + + + + y + + + + T + + + + + + + x_{y_{\\mathchoice{D}{T}{S}{\\sum_{k = 0}^{\\infty} x^k}}} + + + + +`; + exports[`A MathML builder should use for colorbox 1`] = ` diff --git a/test/katex-spec.js b/test/katex-spec.js index 2f23a763..7bf73b8f 100644 --- a/test/katex-spec.js +++ b/test/katex-spec.js @@ -2660,3 +2660,31 @@ describe("The maxSize setting", function() { expect(built.style.borderTopWidth).toEqual("0em"); }); }); + +describe("The \\mathchoice function", function() { + const cmd = "\\sum_{k = 0}^{\\infty} x^k"; + + it("should render as if there is nothing other in display math", function() { + const plain = getBuilt("\\displaystyle" + cmd)[0]; + const built = getBuilt(`\\displaystyle\\mathchoice{${cmd}}{T}{S}{SS}`)[0]; + expect(built).toEqual(plain); + }); + + it("should render as if there is nothing other in text", function() { + const plain = getBuilt(cmd)[0]; + const built = getBuilt(`\\mathchoice{D}{${cmd}}{S}{SS}`)[0]; + expect(built).toEqual(plain); + }); + + it("should render as if there is nothing other in scriptstyle", function() { + const plain = getBuilt(`x_{${cmd}}`)[0]; + const built = getBuilt(`x_{\\mathchoice{D}{T}{${cmd}}{SS}}`)[0]; + expect(built).toEqual(plain); + }); + + it("should render as if there is nothing other in scriptscriptstyle", function() { + const plain = getBuilt(`x_{y_{${cmd}}}`)[0]; + const built = getBuilt(`x_{y_{\\mathchoice{D}{T}{S}{${cmd}}}}`)[0]; + expect(built).toEqual(plain); + }); +}); diff --git a/test/mathml-spec.js b/test/mathml-spec.js index 5c6c61fc..2eabf49a 100644 --- a/test/mathml-spec.js +++ b/test/mathml-spec.js @@ -58,4 +58,16 @@ describe("A MathML builder", function() { it('should use for colorbox', () => { expect(getMathML("\\colorbox{red}{b}")).toMatchSnapshot(); }); + + it('should render mathchoice as if there was nothing', () => { + const cmd = "\\sum_{k = 0}^{\\infty} x^k"; + expect(getMathML(`\\displaystyle\\mathchoice{${cmd}}{T}{S}{SS}`)) + .toMatchSnapshot(); + expect(getMathML(`\\mathchoice{D}{${cmd}}{S}{SS}`)) + .toMatchSnapshot(); + expect(getMathML(`x_{\\mathchoice{D}{T}{${cmd}}{SS}}`)) + .toMatchSnapshot(); + expect(getMathML(`x_{y_{\\mathchoice{D}{T}{S}{${cmd}}}}`)) + .toMatchSnapshot(); + }); }); diff --git a/test/screenshotter/images/MathChoice-chrome.png b/test/screenshotter/images/MathChoice-chrome.png new file mode 100644 index 00000000..af3b6d1e Binary files /dev/null and b/test/screenshotter/images/MathChoice-chrome.png differ diff --git a/test/screenshotter/images/MathChoice-firefox.png b/test/screenshotter/images/MathChoice-firefox.png new file mode 100644 index 00000000..2e608e6c Binary files /dev/null and b/test/screenshotter/images/MathChoice-firefox.png differ diff --git a/test/screenshotter/ss_data.yaml b/test/screenshotter/ss_data.yaml index 959dd276..8d1384de 100644 --- a/test/screenshotter/ss_data.yaml +++ b/test/screenshotter/ss_data.yaml @@ -144,6 +144,8 @@ LowerAccent: | \end{matrix} MathAtom: a\mathrel{\mathop{=}\limits^{\blue ?}}b MathAtom2: \mathop{\overline{\mathrm{lim}}}\limits_{x\to\infty}f(x) +MathChoice: | + {\displaystyle\mathchoice{D}{T}{S}{SS}} {\textstyle\mathchoice{D}{T}{S}{SS}} {\scriptstyle \mathchoice{D}{T}{S}{SS}} {\scriptscriptstyle\mathchoice{D}{T}{S}{SS}} \displaystyle X_{\mathchoice{D}{T}{S}{SS}_{\mathchoice{D}{T}{S}{SS}}} MathDefaultFonts: Ax2k\breve{a}\omega\Omega\imath+\KaTeX MathBb: \mathbb{Ax2k\breve{a}\omega\Omega\imath+\KaTeX} MathBf: \mathbf{Ax2k\breve{a}\omega\Omega\imath+\KaTeX}