mirror of
https://github.com/Smaug123/KaTeX
synced 2025-10-07 04:08:43 +00:00
* Introduce MacroExpander The job of the MacroExpander is turning a stream of possibly expandable tokens, as obtained from the Lexer, into a stream of non-expandable tokens (in KaTeX, even though they may well be expandable in TeX) which can be processed by the Parser. The challenge here is that we don't have mode-specific lexer implementations any more, so we need to do everything on the token level, including reassembly of sizes and colors. * Make macros available in development server Now one can specify macro definitions like \foo=bar as part of the query string and use these macros in the formula being typeset. * Add tests for macro expansions * Handle end of input in special groups This avoids an infinite loop if input ends prematurely. * Simplify parseSpecialGroup The parseSpecialGroup methos now returns a single token spanning the whole special group, and leaves matching that string against a suitable regular expression to whoever is calling the method. Suggested by @cbreeden. * Incorporate review suggestions Add improvements suggested by Kevin Barabash during review. * Input range sanity checks Ensure that both tokens of a token range come from the same lexer, and that the range has a non-negative length. * Improved wording of two comments
65 lines
2.0 KiB
JavaScript
65 lines
2.0 KiB
JavaScript
/**
|
|
* This is the ParseError class, which is the main error thrown by KaTeX
|
|
* functions when something has gone wrong. This is used to distinguish internal
|
|
* errors from errors in the expression that the user provided.
|
|
*
|
|
* If possible, a caller should provide a Token or ParseNode with information
|
|
* about where in the source string the problem occurred.
|
|
*
|
|
* @param {string} message The error message
|
|
* @param {(Token|ParseNode)=} token An object providing position information
|
|
*/
|
|
function ParseError(message, token) {
|
|
var error = "KaTeX parse error: " + message;
|
|
var start;
|
|
var end;
|
|
|
|
if (token && token.lexer && token.start <= token.end) {
|
|
// If we have the input and a position, make the error a bit fancier
|
|
|
|
// Get the input
|
|
var input = token.lexer.input;
|
|
|
|
// Prepend some information
|
|
start = token.start;
|
|
end = token.end;
|
|
if (start === input.length) {
|
|
error += " at end of input: ";
|
|
} else {
|
|
error += " at position " + (start + 1) + ": ";
|
|
}
|
|
|
|
// Underline token in question using combining underscores
|
|
var underlined = input.slice(start, end).replace(/[^]/g, "$&\u0332");
|
|
|
|
// Extract some context from the input and add it to the error
|
|
var left;
|
|
if (start > 15) {
|
|
left = "…" + input.slice(start - 15, start);
|
|
} else {
|
|
left = input.slice(0, start);
|
|
}
|
|
var right;
|
|
if (end + 15 < input.length) {
|
|
right = input.slice(end, end + 15) + "…";
|
|
} else {
|
|
right = input.slice(end);
|
|
}
|
|
error += left + underlined + right;
|
|
}
|
|
|
|
// Some hackery to make ParseError a prototype of Error
|
|
// See http://stackoverflow.com/a/8460753
|
|
var self = new Error(error);
|
|
self.name = "ParseError";
|
|
self.__proto__ = ParseError.prototype;
|
|
|
|
self.position = start;
|
|
return self;
|
|
}
|
|
|
|
// More hackery
|
|
ParseError.prototype.__proto__ = Error.prototype;
|
|
|
|
module.exports = ParseError;
|