mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-09 13:08:40 +00:00
add support for unicode angle brackets, single vertical bar, double vertical bar (#1123)
* add support for unicode angle brackets * add tests, remove vertical bar changes * fix 'message not a function' errors
This commit is contained in:
@@ -431,9 +431,9 @@ const sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0];
|
|||||||
*/
|
*/
|
||||||
const makeSizedDelim = function(delim, size, options, mode, classes) {
|
const makeSizedDelim = function(delim, size, options, mode, classes) {
|
||||||
// < and > turn into \langle and \rangle in delimiters
|
// < and > turn into \langle and \rangle in delimiters
|
||||||
if (delim === "<" || delim === "\\lt") {
|
if (delim === "<" || delim === "\\lt" || delim === "\u27e8") {
|
||||||
delim = "\\langle";
|
delim = "\\langle";
|
||||||
} else if (delim === ">" || delim === "\\gt") {
|
} else if (delim === ">" || delim === "\\gt" || delim === "\u27e9") {
|
||||||
delim = "\\rangle";
|
delim = "\\rangle";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -549,9 +549,9 @@ const traverseSequence = function(delim, height, sequence, options) {
|
|||||||
*/
|
*/
|
||||||
const makeCustomSizedDelim = function(delim, height, center, options, mode,
|
const makeCustomSizedDelim = function(delim, height, center, options, mode,
|
||||||
classes) {
|
classes) {
|
||||||
if (delim === "<" || delim === "\\lt") {
|
if (delim === "<" || delim === "\\lt" || delim === "\u27e8") {
|
||||||
delim = "\\langle";
|
delim = "\\langle";
|
||||||
} else if (delim === ">" || delim === "\\gt") {
|
} else if (delim === ">" || delim === "\\gt" || delim === "\u27e9") {
|
||||||
delim = "\\rangle";
|
delim = "\\rangle";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -38,7 +38,7 @@ const delimiters = [
|
|||||||
"(", ")", "[", "\\lbrack", "]", "\\rbrack",
|
"(", ")", "[", "\\lbrack", "]", "\\rbrack",
|
||||||
"\\{", "\\lbrace", "\\}", "\\rbrace",
|
"\\{", "\\lbrace", "\\}", "\\rbrace",
|
||||||
"\\lfloor", "\\rfloor", "\\lceil", "\\rceil",
|
"\\lfloor", "\\rfloor", "\\lceil", "\\rceil",
|
||||||
"<", ">", "\\langle", "\\rangle", "\\lt", "\\gt",
|
"<", ">", "\\langle", "\u27e8", "\\rangle", "\u27e9", "\\lt", "\\gt",
|
||||||
"\\lvert", "\\rvert", "\\lVert", "\\rVert",
|
"\\lvert", "\\rvert", "\\lVert", "\\rVert",
|
||||||
"\\lgroup", "\\rgroup", "\\lmoustache", "\\rmoustache",
|
"\\lgroup", "\\rgroup", "\\lmoustache", "\\rmoustache",
|
||||||
"/", "\\backslash",
|
"/", "\\backslash",
|
||||||
|
@@ -513,14 +513,14 @@ defineSymbol(math, main, bin, "\u2228", "\\vee", true);
|
|||||||
defineSymbol(math, main, textord, "\u221a", "\\surd");
|
defineSymbol(math, main, textord, "\u221a", "\\surd");
|
||||||
defineSymbol(math, main, open, "(", "(");
|
defineSymbol(math, main, open, "(", "(");
|
||||||
defineSymbol(math, main, open, "[", "[");
|
defineSymbol(math, main, open, "[", "[");
|
||||||
defineSymbol(math, main, open, "\u27e8", "\\langle");
|
defineSymbol(math, main, open, "\u27e8", "\\langle", true);
|
||||||
defineSymbol(math, main, open, "\u2223", "\\lvert");
|
defineSymbol(math, main, open, "\u2223", "\\lvert");
|
||||||
defineSymbol(math, main, open, "\u2225", "\\lVert");
|
defineSymbol(math, main, open, "\u2225", "\\lVert");
|
||||||
defineSymbol(math, main, close, ")", ")");
|
defineSymbol(math, main, close, ")", ")");
|
||||||
defineSymbol(math, main, close, "]", "]");
|
defineSymbol(math, main, close, "]", "]");
|
||||||
defineSymbol(math, main, close, "?", "?");
|
defineSymbol(math, main, close, "?", "?");
|
||||||
defineSymbol(math, main, close, "!", "!");
|
defineSymbol(math, main, close, "!", "!");
|
||||||
defineSymbol(math, main, close, "\u27e9", "\\rangle");
|
defineSymbol(math, main, close, "\u27e9", "\\rangle", true);
|
||||||
defineSymbol(math, main, close, "\u2223", "\\rvert");
|
defineSymbol(math, main, close, "\u2223", "\\rvert");
|
||||||
defineSymbol(math, main, close, "\u2225", "\\rVert");
|
defineSymbol(math, main, close, "\u2225", "\\rVert");
|
||||||
defineSymbol(math, main, rel, "=", "=");
|
defineSymbol(math, main, rel, "=", "=");
|
||||||
|
@@ -17,13 +17,13 @@ beforeEach(function() {
|
|||||||
parseTree(actual, defaultSettings);
|
parseTree(actual, defaultSettings);
|
||||||
return {
|
return {
|
||||||
pass: false,
|
pass: false,
|
||||||
message: "'" + actual + "' parsed without error",
|
message: () => "'" + actual + "' parsed without error",
|
||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (expected === undefined) {
|
if (expected === undefined) {
|
||||||
return {
|
return {
|
||||||
pass: true,
|
pass: true,
|
||||||
message: "'" + actual + "' parsed with error",
|
message: () => "'" + actual + "' parsed with error",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const msg = e.message;
|
const msg = e.message;
|
||||||
@@ -31,20 +31,20 @@ beforeEach(function() {
|
|||||||
if (msg === exp) {
|
if (msg === exp) {
|
||||||
return {
|
return {
|
||||||
pass: true,
|
pass: true,
|
||||||
message: "'" + actual + "'" +
|
message: () => "'" + actual + "'" +
|
||||||
" parsed with error '" + expected + "'",
|
" parsed with error '" + expected + "'",
|
||||||
};
|
};
|
||||||
} else if (msg.slice(0, 19) === prefix) {
|
} else if (msg.slice(0, 19) === prefix) {
|
||||||
return {
|
return {
|
||||||
pass: false,
|
pass: false,
|
||||||
message: "'" + actual + "'" +
|
message: () => "'" + actual + "'" +
|
||||||
" parsed with error '" + msg.slice(19) +
|
" parsed with error '" + msg.slice(19) +
|
||||||
"' but expected '" + expected + "'",
|
"' but expected '" + expected + "'",
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
return {
|
return {
|
||||||
pass: false,
|
pass: false,
|
||||||
message: "'" + actual + "'" +
|
message: () => "'" + actual + "'" +
|
||||||
" caused error '" + msg +
|
" caused error '" + msg +
|
||||||
"' but expected '" + exp + "'",
|
"' but expected '" + exp + "'",
|
||||||
};
|
};
|
||||||
|
@@ -107,6 +107,21 @@ const parseAndSetResult = function(expr, result, settings) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const buildAndSetResult = function(expr, result, settings) {
|
||||||
|
try {
|
||||||
|
return _getBuilt(expr, settings || defaultSettings);
|
||||||
|
} catch (e) {
|
||||||
|
result.pass = false;
|
||||||
|
if (e instanceof ParseError) {
|
||||||
|
result.message = "'" + expr + "' failed " +
|
||||||
|
"parsing with error: " + e.message;
|
||||||
|
} else {
|
||||||
|
result.message = "'" + expr + "' failed " +
|
||||||
|
"parsing with unknown error: " + e.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function() {
|
||||||
expect.extend({
|
expect.extend({
|
||||||
toParse: function(actual, settings) {
|
toParse: function(actual, settings) {
|
||||||
@@ -114,7 +129,7 @@ beforeEach(function() {
|
|||||||
|
|
||||||
const result = {
|
const result = {
|
||||||
pass: true,
|
pass: true,
|
||||||
message: "'" + actual + "' succeeded parsing",
|
message: () => "'" + actual + "' succeeded parsing",
|
||||||
};
|
};
|
||||||
parseAndSetResult(actual, result, usedSettings);
|
parseAndSetResult(actual, result, usedSettings);
|
||||||
return result;
|
return result;
|
||||||
@@ -125,7 +140,7 @@ beforeEach(function() {
|
|||||||
|
|
||||||
const result = {
|
const result = {
|
||||||
pass: false,
|
pass: false,
|
||||||
message: "Expected '" + actual + "' to fail " +
|
message: () => "Expected '" + actual + "' to fail " +
|
||||||
"parsing, but it succeeded",
|
"parsing, but it succeeded",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -150,7 +165,7 @@ beforeEach(function() {
|
|||||||
|
|
||||||
const result = {
|
const result = {
|
||||||
pass: true,
|
pass: true,
|
||||||
message: "'" + actual + "' succeeded in building",
|
message: () => "'" + actual + "' succeeded in building",
|
||||||
};
|
};
|
||||||
|
|
||||||
expect(actual).toParse(usedSettings);
|
expect(actual).toParse(usedSettings);
|
||||||
@@ -176,7 +191,7 @@ beforeEach(function() {
|
|||||||
|
|
||||||
const result = {
|
const result = {
|
||||||
pass: true,
|
pass: true,
|
||||||
message: "Parse trees of '" + actual +
|
message: () => "Parse trees of '" + actual +
|
||||||
"' and '" + expected + "' are equivalent",
|
"' and '" + expected + "' are equivalent",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -196,7 +211,38 @@ beforeEach(function() {
|
|||||||
|
|
||||||
if (JSON.stringify(actualTree) !== JSON.stringify(expectedTree)) {
|
if (JSON.stringify(actualTree) !== JSON.stringify(expectedTree)) {
|
||||||
result.pass = false;
|
result.pass = false;
|
||||||
result.message = "Parse trees of '" + actual +
|
result.message = () => "Parse trees of '" + actual +
|
||||||
|
"' and '" + expected + "' are not equivalent";
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
toBuildLike: function(actual, expected, settings) {
|
||||||
|
const usedSettings = settings ? settings : defaultSettings;
|
||||||
|
|
||||||
|
const result = {
|
||||||
|
pass: true,
|
||||||
|
message: () => "Build trees of '" + actual +
|
||||||
|
"' and '" + expected + "' are equivalent",
|
||||||
|
};
|
||||||
|
|
||||||
|
const actualTree = buildAndSetResult(actual, result,
|
||||||
|
usedSettings);
|
||||||
|
if (!actualTree) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
const expectedTree = buildAndSetResult(expected, result,
|
||||||
|
usedSettings);
|
||||||
|
if (!expectedTree) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
stripPositions(actualTree);
|
||||||
|
stripPositions(expectedTree);
|
||||||
|
|
||||||
|
if (JSON.stringify(actualTree) !== JSON.stringify(expectedTree)) {
|
||||||
|
result.pass = false;
|
||||||
|
result.message = () => "Parse trees of '" + actual +
|
||||||
"' and '" + expected + "' are not equivalent";
|
"' and '" + expected + "' are not equivalent";
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@@ -1212,6 +1258,19 @@ describe("A left/right parser", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("left/right builder", () => {
|
||||||
|
const cases = [
|
||||||
|
['\\left\\langle \\right\\rangle', '\\left< \\right>'],
|
||||||
|
['\\left\\langle \\right\\rangle', '\\left\u27e8 \\right\u27e9'],
|
||||||
|
];
|
||||||
|
|
||||||
|
for (const [actual, expected] of cases) {
|
||||||
|
it(`should build "${actual}" like "${expected}"`, () => {
|
||||||
|
expect(actual).toBuildLike(expected);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
describe("A begin/end parser", function() {
|
describe("A begin/end parser", function() {
|
||||||
|
|
||||||
it("should parse a simple environment", function() {
|
it("should parse a simple environment", function() {
|
||||||
|
@@ -16,10 +16,10 @@ const parseAndSetResult = function(expr, result, settings) {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
result.pass = false;
|
result.pass = false;
|
||||||
if (e instanceof ParseError) {
|
if (e instanceof ParseError) {
|
||||||
result.message = "'" + expr + "' failed " +
|
result.message = () => "'" + expr + "' failed " +
|
||||||
"parsing with error: " + e.message;
|
"parsing with error: " + e.message;
|
||||||
} else {
|
} else {
|
||||||
result.message = "'" + expr + "' failed " +
|
result.message = () => "'" + expr + "' failed " +
|
||||||
"parsing with unknown error: " + e.message;
|
"parsing with unknown error: " + e.message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -34,7 +34,7 @@ describe("unicode", function() {
|
|||||||
|
|
||||||
const result = {
|
const result = {
|
||||||
pass: true,
|
pass: true,
|
||||||
message: "'" + actual + "' succeeded parsing",
|
message: () => "'" + actual + "' succeeded parsing",
|
||||||
};
|
};
|
||||||
parseAndSetResult(actual, result, usedSettings);
|
parseAndSetResult(actual, result, usedSettings);
|
||||||
return result;
|
return result;
|
||||||
@@ -45,7 +45,7 @@ describe("unicode", function() {
|
|||||||
|
|
||||||
const result = {
|
const result = {
|
||||||
pass: false,
|
pass: false,
|
||||||
message: "Expected '" + actual + "' to fail " +
|
message: () => "Expected '" + actual + "' to fail " +
|
||||||
"parsing, but it succeeded",
|
"parsing, but it succeeded",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -54,10 +54,10 @@ describe("unicode", function() {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof ParseError) {
|
if (e instanceof ParseError) {
|
||||||
result.pass = true;
|
result.pass = true;
|
||||||
result.message = "'" + actual + "' correctly " +
|
result.message = () => "'" + actual + "' correctly " +
|
||||||
"didn't parse with error: " + e.message;
|
"didn't parse with error: " + e.message;
|
||||||
} else {
|
} else {
|
||||||
result.message = "'" + actual + "' failed " +
|
result.message = () => "'" + actual + "' failed " +
|
||||||
"parsing with unknown error: " + e.message;
|
"parsing with unknown error: " + e.message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user