Sync with Khan-exercises

Summary:
Add some things in to make this more useful to khan-exercises.
Notably, make KaTeX.process create and clean up its own .katex node, and rename
.mathmathmath -> .katex.

Test Plan: Make test, make sure the main page still renders stuff

Reviewers: alpert

Reviewed By: alpert

Differential Revision: http://phabricator.khanacademy.org/D3061
This commit is contained in:
Emily Eisenberg 2013-07-17 15:43:55 -07:00
parent b101582aac
commit 383ca01434
6 changed files with 102 additions and 90 deletions

View File

@ -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;

7
ParseError.js Normal file
View File

@ -0,0 +1,7 @@
function ParseError(message) {
this.message = "TeX parse error: " + message;
}
ParseError.prototype = Error.prototype;
module.exports = ParseError;

View File

@ -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

View File

@ -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
};

View File

@ -9,6 +9,6 @@
</head>
<body>
<input type="text" value="\blue\dfrac{2(y-z)}{3} \div \orange{\arctan x^{4/3}}" id="input" />
<div id="math" class="mathmathmath"></div>
<div id="math"></div>
</body>
</html>

View File

@ -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; }