mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-06 11:48:41 +00:00
Allow unbraced kerns, such as \kern1em.
This is actually the *only* syntax TeX allows; braced kern units are invalid.
This commit is contained in:
@@ -661,6 +661,35 @@ Parser.prototype.parseStringGroup = function(modeName, optional) {
|
|||||||
return firstToken.range(lastToken, str);
|
return firstToken.range(lastToken, str);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
* Parses a color description.
|
||||||
*/
|
*/
|
||||||
@@ -682,11 +711,17 @@ Parser.prototype.parseColorGroup = function(optional) {
|
|||||||
* Parses a size specification, consisting of magnitude and unit.
|
* Parses a size specification, consisting of magnitude and unit.
|
||||||
*/
|
*/
|
||||||
Parser.prototype.parseSizeGroup = function(optional) {
|
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) {
|
if (!res) {
|
||||||
return null;
|
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) {
|
if (!match) {
|
||||||
throw new ParseError("Invalid size: '" + res.text + "'", res);
|
throw new ParseError("Invalid size: '" + res.text + "'", res);
|
||||||
}
|
}
|
||||||
|
@@ -220,7 +220,7 @@ describe("Parser.expect calls:", function() {
|
|||||||
});
|
});
|
||||||
it("complains about missing { for size", function() {
|
it("complains about missing { for size", function() {
|
||||||
expect("\\rule{1em}[2em]").toFailWithParseError(
|
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
|
// Can't test for the [ of an optional group since it's optional
|
||||||
it("complains about missing } for color", function() {
|
it("complains about missing } for color", function() {
|
||||||
|
@@ -997,6 +997,41 @@ describe("A kern parser", function() {
|
|||||||
var parse = getParsed("\\kern{-1em}")[0];
|
var parse = getParsed("\\kern{-1em}")[0];
|
||||||
expect(parse.value.dimension.number).toBeCloseTo(-1);
|
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() {
|
describe("A left/right parser", function() {
|
||||||
|
Reference in New Issue
Block a user