commit 5d83bb8cc013763c611c27808a16378dbfbe7185
parent 476eebf3c5d187eb1ce84ffe2fbd4ede2dfb91ec
Author: Jeff Everett <everett.jeff.w@gmail.com>
Date: Mon, 20 Jul 2015 13:30:23 -0600
Added support for \limits and \nolimits controls
Diffstat:
5 files changed, 47 insertions(+), 1 deletion(-)
diff --git a/src/Parser.js b/src/Parser.js
@@ -254,7 +254,18 @@ Parser.prototype.parseAtom = function(pos, mode) {
// Lex the first token
var lex = this.lexer.lex(currPos, mode);
- if (lex.text === "^") {
+ if (lex.text === "\\limits" || lex.text === "\\nolimits") {
+ // We got a limit control
+ if (!base || base.result.type !== "op") {
+ throw new ParseError("Limit controls must follow a math operator",
+ this.lexer, currPos);
+ }
+ else {
+ var limits = lex.text == "\\limits";
+ base.result.value.limits = limits;
+ currPos = lex.position;
+ }
+ } else if (lex.text === "^") {
// We got a superscript start
if (superscript) {
throw new ParseError(
diff --git a/test/katex-spec.js b/test/katex-spec.js
@@ -360,6 +360,40 @@ describe("A subscript and superscript tree-builder", function() {
});
});
+describe("A parser with limit controls", function() {
+ it("should fail when the limit control is not preceded by an op node", function() {
+ expect("3\\nolimits_2^2").toNotParse();
+ expect("\\sqrt\\limits_2^2").toNotParse();
+ expect("45 +\\nolimits 45").toNotParse();
+ });
+
+ it("should parse when the limit control directly follows an op node", function() {
+ expect("\\int\\limits_2^2 3").toParse();
+ expect("\\sum\\nolimits_3^4 4").toParse();
+ });
+
+ it("should parse when the limit control is in the sup/sub area of an op node", function() {
+ expect("\\int_2^2\\limits").toParse();
+ expect("\\int^2\\nolimits_2").toParse();
+ expect("\\int_2\\limits^2").toParse();
+ });
+
+ it("should allow multiple limit controls in the sup/sub area of an op node", function() {
+ expect("\\int_2\\nolimits^2\\limits 3").toParse();
+ expect("\\int\\nolimits\\limits_2^2").toParse();
+ expect("\\int\\limits\\limits\\limits_2^2").toParse();
+ });
+
+ it("should have the rightmost limit control determine the limits property " +
+ "of the preceding op node", function() {
+ var parsedInput = getParsed("\\int\\nolimits\\limits_2^2");
+ expect(parsedInput[0].value.base.value.limits).toBe(true);
+
+ parsedInput = getParsed("\\int\\limits_2\\nolimits^2");
+ expect(parsedInput[0].value.base.value.limits).toBe(false);
+ });
+});
+
describe("A group parser", function() {
it("should not fail", function() {
expect("{xy}").toParse();
diff --git a/test/screenshotter/images/LimitControls-chrome.png b/test/screenshotter/images/LimitControls-chrome.png
Binary files differ.
diff --git a/test/screenshotter/images/LimitControls-firefox.png b/test/screenshotter/images/LimitControls-firefox.png
Binary files differ.
diff --git a/test/screenshotter/ss_data.json b/test/screenshotter/ss_data.json
@@ -20,6 +20,7 @@
"LeftRight": "http://localhost:7936/test/screenshotter/test.html?m=\\left( x^2 \\right) \\left\\{ x^{x^{x^{x^x}}} \\right.",
"LeftRightListStyling": "http://localhost:7936/test/screenshotter/test.html?m=a+\\left(x+y\\right)-x",
"LeftRightStyleSizing": "http://localhost:7936/test/screenshotter/test.html?m=+\\left\\{\\rule{0.1em}{1em}\\right.x^{+\\left\\{\\rule{0.1em}{1em}\\right.x^{+\\left\\{\\rule{0.1em}{1em}\\right.}}",
+ "LimitControls": "http://localhost:7936/test/screenshotter/test.html?m=\\displaystyle\\int\\limits_2^3 3x^2\\,dx + \\sum\\nolimits^n_{i=1}i",
"NestedFractions": "http://localhost:7936/test/screenshotter/test.html?m=\\dfrac{\\frac{a}{b}}{\\frac{c}{d}}\\dfrac{\\dfrac{a}{b}}{\\dfrac{c}{d}}\\frac{\\frac{a}{b}}{\\frac{c}{d}}",
"NullDelimiterInteraction": "http://localhost:7936/test/screenshotter/test.html?m=a \\bigl. + 2 \\quad \\left. + a \\right)",
"OpLimits": "http://localhost:7936/test/screenshotter/test.html?m={\\sin_2^2 \\lim_2^2 \\int_2^2 \\sum_2^2}{\\displaystyle \\lim_2^2 \\int_2^2 \\intop_2^2 \\sum_2^2}",