www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

commit 530ec97e74769422b313a872920df7ec438db845
parent 7433638fdaccdfbe0c5b661844c8e99c393a7d25
Author: Eddie Kohler <ekohler@gmail.com>
Date:   Thu,  8 Dec 2016 14:47:20 -0500

Allow unbraced kerns, such as \kern1em.

This is actually the *only* syntax TeX allows; braced kern units
are invalid.

Diffstat:
Msrc/Parser.js | 39+++++++++++++++++++++++++++++++++++++--
Mtest/errors-spec.js | 2+-
Mtest/katex-spec.js | 35+++++++++++++++++++++++++++++++++++
3 files changed, 73 insertions(+), 3 deletions(-)

diff --git a/src/Parser.js b/src/Parser.js @@ -662,6 +662,35 @@ Parser.prototype.parseStringGroup = function(modeName, optional) { }; /** + * Parses a regex-delimited group: the largest sequence of tokens + * whose concatenated strings match `regex`. Returns the string + * formed by the tokens plus some position information. + * + * @param {RegExp} regex + * @param {string} modeName Used to describe the mode in error messages + */ +Parser.prototype.parseRegexGroup = function(regex, modeName) { + var outerMode = this.mode; + this.mode = "text"; + var firstToken = this.nextToken; + var lastToken = firstToken; + var str = ""; + while (this.nextToken.text !== "EOF" + && regex.test(str + this.nextToken.text)) { + lastToken = this.nextToken; + str += lastToken.text; + this.consume(); + } + if (str === "") { + throw new ParseError( + "Invalid " + modeName + ": '" + firstToken.text + "'", + firstToken); + } + this.mode = outerMode; + return firstToken.range(lastToken, str); +}; + +/** * Parses a color description. */ Parser.prototype.parseColorGroup = function(optional) { @@ -682,11 +711,17 @@ Parser.prototype.parseColorGroup = function(optional) { * Parses a size specification, consisting of magnitude and unit. */ Parser.prototype.parseSizeGroup = function(optional) { - var res = this.parseStringGroup("size", optional); + var res; + if (!optional && this.nextToken.text !== "{") { + res = this.parseRegexGroup( + /^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2}$/, "size"); + } else { + res = this.parseStringGroup("size", optional); + } if (!res) { return null; } - var match = (/(-?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/).exec(res.text); + var match = (/([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/).exec(res.text); if (!match) { throw new ParseError("Invalid size: '" + res.text + "'", res); } diff --git a/test/errors-spec.js b/test/errors-spec.js @@ -220,7 +220,7 @@ describe("Parser.expect calls:", function() { }); it("complains about missing { for size", function() { expect("\\rule{1em}[2em]").toFailWithParseError( - "Expected '{', got '[' at position 11: \\rule{1em}[̲2em]"); + "Invalid size: '[' at position 11: \\rule{1em}[̲2em]"); }); // Can't test for the [ of an optional group since it's optional it("complains about missing } for color", function() { diff --git a/test/katex-spec.js b/test/katex-spec.js @@ -997,6 +997,41 @@ describe("A kern parser", function() { var parse = getParsed("\\kern{-1em}")[0]; expect(parse.value.dimension.number).toBeCloseTo(-1); }); + + it("should parse positive sizes", function() { + var parse = getParsed("\\kern{+1em}")[0]; + expect(parse.value.dimension.number).toBeCloseTo(1); + }); +}); + +describe("A non-braced kern parser", function() { + var emKern = "\\kern1em"; + var exKern = "\\kern 1 ex"; + var badUnitRule = "\\kern1px"; + var noNumberRule = "\\kern em"; + + it("should list the correct units", function() { + var emParse = getParsed(emKern)[0]; + var exParse = getParsed(exKern)[0]; + + expect(emParse.value.dimension.unit).toEqual("em"); + expect(exParse.value.dimension.unit).toEqual("ex"); + }); + + it("should not parse invalid units", function() { + expect(badUnitRule).toNotParse(); + expect(noNumberRule).toNotParse(); + }); + + it("should parse negative sizes", function() { + var parse = getParsed("\\kern-1em")[0]; + expect(parse.value.dimension.number).toBeCloseTo(-1); + }); + + it("should parse positive sizes", function() { + var parse = getParsed("\\kern+1em")[0]; + expect(parse.value.dimension.number).toBeCloseTo(1); + }); }); describe("A left/right parser", function() {