commit fdebbe3a18838bb4b571fd7add288e9338a5cf10
parent 831c5b8d99092fe57e4113406a7cc52e21924a31
Author: Kevin Barabash <kevinb7@gmail.com>
Date: Thu, 8 Dec 2016 23:38:04 -0500
Merge pull request #579 from kohler/kernarg
Allow unbraced kerns, such as \kern1em.
Diffstat:
3 files changed, 73 insertions(+), 3 deletions(-)
diff --git a/src/Parser.js b/src/Parser.js
@@ -666,6 +666,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) {
@@ -686,11 +715,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() {