diff --git a/src/Parser.js b/src/Parser.js index 31f51e5..82d0777 100644 --- a/src/Parser.js +++ b/src/Parser.js @@ -343,6 +343,9 @@ Parser.prototype.parseAtom = function() { subscript = this.handleSupSubscript("subscript"); } else if (lex.text === "'") { // We got a prime + if (superscript) { + throw new ParseError("Double superscript", lex); + } const prime = new ParseNode("textord", "\\prime", this.mode); // Many primes can be grouped together, so we handle this here @@ -354,7 +357,12 @@ Parser.prototype.parseAtom = function() { primes.push(prime); this.consume(); } - // Put them into an ordgroup as the superscript + // If there's a superscript following the primes, combine that + // superscript in with the primes. + if (this.nextToken.text === "^") { + primes.push(this.handleSupSubscript("superscript")); + } + // Put everything into an ordgroup as the superscript superscript = new ParseNode("ordgroup", primes, this.mode); } else { // If it wasn't ^, _, or ', stop parsing super/subscripts diff --git a/test/errors-spec.js b/test/errors-spec.js index 641863c..190e75c 100644 --- a/test/errors-spec.js +++ b/test/errors-spec.js @@ -106,6 +106,16 @@ describe("Parser:", function() { expect("1^{2+3}_4^5").toFailWithParseError( "Double superscript at position 10: 1^{2+3}_4^̲5"); }); + it("rejects double superscripts involving primes", function() { + expect("1'_2^3").toFailWithParseError( + "Double superscript at position 5: 1'_2^̲3"); + expect("1^2'").toFailWithParseError( + "Double superscript at position 4: 1^2'̲"); + expect("1^2_3'").toFailWithParseError( + "Double superscript at position 6: 1^2_3'̲"); + expect("1'_2'").toFailWithParseError( + "Double superscript at position 5: 1'_2'̲"); + }); it("rejects double subscripts", function() { expect("1_2_3").toFailWithParseError( "Double subscript at position 4: 1_2_̲3"); diff --git a/test/katex-spec.js b/test/katex-spec.js index 15012f7..36dd5f5 100644 --- a/test/katex-spec.js +++ b/test/katex-spec.js @@ -1260,7 +1260,6 @@ describe("A TeX-compliant parser", function() { expect("x''''").toParse(); expect("x_2''").toParse(); expect("x''_2").toParse(); - expect("x'_2'").toParse(); }); it("should fail when sup/subscripts are interspersed with arguments", function() { diff --git a/test/screenshotter/images/PrimeSuper-chrome.png b/test/screenshotter/images/PrimeSuper-chrome.png new file mode 100644 index 0000000..4a4c689 Binary files /dev/null and b/test/screenshotter/images/PrimeSuper-chrome.png differ diff --git a/test/screenshotter/images/PrimeSuper-firefox.png b/test/screenshotter/images/PrimeSuper-firefox.png new file mode 100644 index 0000000..41352b3 Binary files /dev/null and b/test/screenshotter/images/PrimeSuper-firefox.png differ diff --git a/test/screenshotter/ss_data.yaml b/test/screenshotter/ss_data.yaml index bef0d7b..8838e48 100644 --- a/test/screenshotter/ss_data.yaml +++ b/test/screenshotter/ss_data.yaml @@ -124,6 +124,7 @@ OpLimits: | OverUnderline: x\underline{x}\underline{\underline{x}}\underline{x_{x_{x_x}}}\underline{x^{x^{x^x}}}\overline{x}\overline{x}\overline{x^{x^{x^x}}} \blue{\overline{\underline{x}}\underline{\overline{x}}} Phantom: \dfrac{1+\phantom{x^{\blue{2}}} = x}{1+x^{\blue{2}} = x} PrimeSpacing: f'+f_2'+f^{f'} +PrimeSuper: x'^2+x'''^2+x'^2_3+x_3'^2 RlapBug: \frac{\rlap{x}}{2} Rule: \rule{1em}{0.5em}\rule{1ex}{2ex}\rule{1em}{1ex}\rule{1em}{0.431ex} SizingBaseline: