diff --git a/Lexer.js b/Lexer.js index c4cc026..7839e0e 100644 --- a/Lexer.js +++ b/Lexer.js @@ -1,3 +1,5 @@ +var ParseError = require("./ParseError"); + // The main lexer class function Lexer(input) { this._input = input; @@ -62,7 +64,8 @@ Lexer.prototype.lex = function(pos) { } // We didn't match any of the tokens, so throw an error. - throw "Unexpected character: '" + input[0] + "' at position " + pos; + throw new ParseError("Unexpected character: '" + input[0] + + "' at position " + pos); }; module.exports = Lexer; diff --git a/ParseError.js b/ParseError.js new file mode 100644 index 0000000..6025976 --- /dev/null +++ b/ParseError.js @@ -0,0 +1,7 @@ +function ParseError(message) { + this.message = "TeX parse error: " + message; +} + +ParseError.prototype = Error.prototype; + +module.exports = ParseError; diff --git a/Parser.js b/Parser.js index 6361e66..b97fbea 100644 --- a/Parser.js +++ b/Parser.js @@ -1,6 +1,8 @@ var Lexer = require("./Lexer"); var utils = require("./utils"); +var ParseError = require("./ParseError"); + // Main Parser class function Parser() { }; @@ -22,7 +24,8 @@ function ParseNode(type, value) { // appropriate error otherwise. var expect = function(result, type) { if (result.type !== type) { - throw "Failed parsing: Expected '" + type + "', got '" + result.type + "'"; + throw new ParseError( + "Expected '" + type + "', got '" + result.type + "'"); } }; @@ -76,7 +79,7 @@ Parser.prototype.parseSuperscript = function(pos) { return group; } else { // Throw an error if we didn't find a group - throw "Parse error: Couldn't find group after '^'"; + throw new ParseError("Couldn't find group after '^'"); } } else if (sup.type === "'") { var pos = sup.position; @@ -98,7 +101,7 @@ Parser.prototype.parseSubscript = function(pos) { return group; } else { // Throw an error if we didn't find a group - throw "Parse error: Couldn't find group after '_'"; + throw new ParseError("Couldn't find group after '_'"); } } else { return null; @@ -343,7 +346,8 @@ Parser.prototype.parseNucleus = function(pos) { {color: nucleus.type.slice(1), value: atoms}), group.position); } else { - throw "Parse error: Expected group after '" + nucleus.text + "'"; + throw new ParseError( + "Expected group after '" + nucleus.text + "'"); } } else if (nucleus.type === "\\llap" || nucleus.type === "\\rlap") { // If this is an llap or rlap, parse its argument and return @@ -353,7 +357,8 @@ Parser.prototype.parseNucleus = function(pos) { new ParseNode(nucleus.type.slice(1), group.result), group.position); } else { - throw "Parse error: Expected group after '" + nucleus.text + "'"; + throw new ParseError( + "Expected group after '" + nucleus.text + "'"); } } else if (nucleus.type === "\\dfrac" || nucleus.type === "\\frac" || nucleus.type === "\\tfrac") { @@ -370,12 +375,12 @@ Parser.prototype.parseNucleus = function(pos) { }), denom.position); } else { - throw "Parse error: Expected denominator after '" + - nucleus.type + "'"; + throw new ParseError("Expected denominator after '" + + nucleus.type + "'"); } } else { - throw "Parse error: Expected numerator after '" + nucleus.type + - "'"; + throw new ParseError("Parse error: Expected numerator after '" + + nucleus.type + "'"); } } else if (funcToType[nucleus.type]) { // Otherwise if this is a no-argument function, find the type it diff --git a/katex.js b/katex.js index c42c501..10b899d 100644 --- a/katex.js +++ b/katex.js @@ -1,4 +1,5 @@ var Style = require("./Style"); +var ParseError = require("./ParseError"); var parseTree = require("./parseTree"); var utils = require("./utils"); @@ -240,23 +241,19 @@ var clearNode = function(node) { } }; -var process = function(toParse, baseElem) { - try { - var tree = parseTree(toParse); - } catch (e) { - console.error(e); - return false; - } +var process = function(toParse, baseNode) { + var tree = parseTree(toParse); var style = Style.TEXT; var expression = buildExpression(style, /* color: */ "", tree); var span = makeSpan(style.cls(), expression); + var katexNode = makeSpan("katex", [span]); - clearNode(baseElem); - baseElem.appendChild(span); - return true; + clearNode(baseNode); + baseNode.appendChild(katexNode); }; module.exports = { - process: process + process: process, + ParseError: ParseError }; diff --git a/static/index.html b/static/index.html index 5d7118d..a00ade2 100644 --- a/static/index.html +++ b/static/index.html @@ -9,6 +9,6 @@ -
+
diff --git a/static/katex.css b/static/katex.css index e468675..1eda16b 100644 --- a/static/katex.css +++ b/static/katex.css @@ -14,98 +14,98 @@ things to do: big parens */ -.mathmathmath { +.katex { font: normal 1.21em katex_main; line-height: 1.2; } -.mathit { +.katex .mathit { font-family: katex_math; font-style: italic; } -.textstyle > .mbin + .minner { margin-left: 0.22222em; } -.textstyle > .mbin + .mop { margin-left: 0.22222em; } -.textstyle > .mbin + .mopen { margin-left: 0.22222em; } -.textstyle > .mbin + .mord { margin-left: 0.22222em; } -.textstyle > .mclose + .mbin { margin-left: 0.22222em; } -.textstyle > .mclose + .minner { margin-left: 0.16667em; } - .mclose + .mop { margin-left: 0.16667em; } -.textstyle > .mclose + .mrel { margin-left: 0.27778em; } -.textstyle > .minner + .mbin { margin-left: 0.22222em; } -.textstyle > .minner + .minner { margin-left: 0.16667em; } - .minner + .mop { margin-left: 0.16667em; } -.textstyle > .minner + .mopen { margin-left: 0.16667em; } -.textstyle > .minner + .mord { margin-left: 0.16667em; } -.textstyle > .minner + .mpunct { margin-left: 0.16667em; } -.textstyle > .minner + .mrel { margin-left: 0.27778em; } -.textstyle > .mop + .minner { margin-left: 0.16667em; } - .mop + .mop { margin-left: 0.16667em; } - .mop + .mord { margin-left: 0.16667em; } -.textstyle > .mop + .mrel { margin-left: 0.27778em; } -.textstyle > .mord + .mbin { margin-left: 0.22222em; } -.textstyle > .mord + .minner { margin-left: 0.16667em; } - .mord + .mop { margin-left: 0.16667em; } -.textstyle > .mord + .mrel { margin-left: 0.27778em; } -.textstyle > .mpunct + .mbin { margin-left: 0.16667em; } -.textstyle > .mpunct + .mclose { margin-left: 0.16667em; } -.textstyle > .mpunct + .minner { margin-left: 0.16667em; } -.textstyle > .mpunct + .mop { margin-left: 0.16667em; } -.textstyle > .mpunct + .mopen { margin-left: 0.16667em; } -.textstyle > .mpunct + .mord { margin-left: 0.16667em; } -.textstyle > .mpunct + .mpunct { margin-left: 0.16667em; } -.textstyle > .mpunct + .mrel { margin-left: 0.16667em; } -.textstyle > .mrel + .minner { margin-left: 0.27778em; } -.textstyle > .mrel + .mop { margin-left: 0.27778em; } -.textstyle > .mrel + .mopen { margin-left: 0.27778em; } -.textstyle > .mrel + .mord { margin-left: 0.27778em; } +.katex .textstyle > .mbin + .minner { margin-left: 0.22222em; } +.katex .textstyle > .mbin + .mop { margin-left: 0.22222em; } +.katex .textstyle > .mbin + .mopen { margin-left: 0.22222em; } +.katex .textstyle > .mbin + .mord { margin-left: 0.22222em; } +.katex .textstyle > .mclose + .mbin { margin-left: 0.22222em; } +.katex .textstyle > .mclose + .minner { margin-left: 0.16667em; } +.katex .mclose + .mop { margin-left: 0.16667em; } +.katex .textstyle > .mclose + .mrel { margin-left: 0.27778em; } +.katex .textstyle > .minner + .mbin { margin-left: 0.22222em; } +.katex .textstyle > .minner + .minner { margin-left: 0.16667em; } +.katex .minner + .mop { margin-left: 0.16667em; } +.katex .textstyle > .minner + .mopen { margin-left: 0.16667em; } +.katex .textstyle > .minner + .mord { margin-left: 0.16667em; } +.katex .textstyle > .minner + .mpunct { margin-left: 0.16667em; } +.katex .textstyle > .minner + .mrel { margin-left: 0.27778em; } +.katex .textstyle > .mop + .minner { margin-left: 0.16667em; } +.katex .mop + .mop { margin-left: 0.16667em; } +.katex .mop + .mord { margin-left: 0.16667em; } +.katex .textstyle > .mop + .mrel { margin-left: 0.27778em; } +.katex .textstyle > .mord + .mbin { margin-left: 0.22222em; } +.katex .textstyle > .mord + .minner { margin-left: 0.16667em; } +.katex .mord + .mop { margin-left: 0.16667em; } +.katex .textstyle > .mord + .mrel { margin-left: 0.27778em; } +.katex .textstyle > .mpunct + .mbin { margin-left: 0.16667em; } +.katex .textstyle > .mpunct + .mclose { margin-left: 0.16667em; } +.katex .textstyle > .mpunct + .minner { margin-left: 0.16667em; } +.katex .textstyle > .mpunct + .mop { margin-left: 0.16667em; } +.katex .textstyle > .mpunct + .mopen { margin-left: 0.16667em; } +.katex .textstyle > .mpunct + .mord { margin-left: 0.16667em; } +.katex .textstyle > .mpunct + .mpunct { margin-left: 0.16667em; } +.katex .textstyle > .mpunct + .mrel { margin-left: 0.16667em; } +.katex .textstyle > .mrel + .minner { margin-left: 0.27778em; } +.katex .textstyle > .mrel + .mop { margin-left: 0.27778em; } +.katex .textstyle > .mrel + .mopen { margin-left: 0.27778em; } +.katex .textstyle > .mrel + .mord { margin-left: 0.27778em; } -.textstyle > .scriptstyle { font-size: 0.66667em; } -.scriptstyle > .scriptscriptstyle { font-size: 0.75em; } +.katex .textstyle > .scriptstyle { font-size: 0.66667em; } +.katex .scriptstyle > .scriptscriptstyle { font-size: 0.75em; } -.msub { +.katex .msub { vertical-align: bottom; position: relative; top: 0.2em; } -.msup { +.katex .msup { position: relative; top: -0.5em; } -.msupsub { +.katex .msupsub { display: inline-table; table-layout: fixed; vertical-align: middle; } -.msupsub > .msup, .msupsub > .msub { +.katex .msupsub > .msup, .katex .msupsub > .msub { display: table-row; vertical-align: baseline; } -.mfrac { display: inline-table; } +.katex .mfrac { display: inline-table; } /* TODO(alpert): Where do these numbers come from? */ -.mfrac.textstyle.displaystyle { vertical-align: 0.58em; } -.mfrac.textstyle { vertical-align: 0.50em; } -.mfrac.scriptstyle { vertical-align: 0.50em; } -.mfrac.scriptscriptstyle { vertical-align: 0.6em; } +.katex .mfrac.textstyle.displaystyle { vertical-align: 0.58em; } +.katex .mfrac.textstyle { vertical-align: 0.50em; } +.katex .mfrac.scriptstyle { vertical-align: 0.50em; } +.katex .mfrac.scriptscriptstyle { vertical-align: 0.6em; } -.mfracnum, .mfracmid, .mfracden { +.katex .mfracnum, .katex .mfracmid, .katex .mfracden { display: table-row; text-align: center; } -.mfracmid:before { +.katex .mfracmid:before { border-bottom-style: solid; border-bottom-width: 1px; content: ""; display: block; } -.mfracmid:after { +.katex .mfracmid:after { border-bottom-style: solid; border-bottom-width: 0.05em; content: ""; @@ -113,54 +113,54 @@ big parens margin-top: -1px; } -.mfracnum > span { +.katex .mfracnum > span { display: inline-block; vertical-align: bottom; } -.mspace { +.katex .mspace { display: inline-block; } -.mspace.thinspace { +.katex .mspace.thinspace { width: 0.16667em; } -.mspace.mediumspace { +.katex .mspace.mediumspace { width: 0.22222em; } -.mspace.thickspace { +.katex .mspace.thickspace { width: 0.27778em; } -.mspace.quad { +.katex .mspace.quad { width: 1em; } -.mspace.qquad { +.katex .mspace.qquad { width: 2em; } -.llap, .rlap { +.katex .llap, .katex .rlap { width: 0; position: relative; } -.llap > span { +.katex .llap > span { position: absolute; right: 0; } -.rlap > span { +.katex .rlap > span { position: absolute; left: 0; } -.blue { color: #6495ed; } -.orange { color: #ffa500; } -.pink { color: #ff00af; } -.red { color: #df0030; } -.green { color: #28ae7b; } -.gray { color: gray; } -.purple { color: #9d38bd; } +.katex .blue { color: #6495ed; } +.katex .orange { color: #ffa500; } +.katex .pink { color: #ff00af; } +.katex .red { color: #df0030; } +.katex .green { color: #28ae7b; } +.katex .gray { color: gray; } +.katex .purple { color: #9d38bd; }