Add an optional settings argument to render calls
Summary: Add the ability to pass in options to the render calls which contain information about the parse. This information is passed around to the parser and builder, which parse and render differently depending on the options. Currently, this includes an option to render the math in display mode (i.e. centered, block level, and in displaystyle). Also added some changes to make it easier to add new data to functions (now that new data doesn't need to be copied into the ParseFuncOrArg data structure, it is looked up when it is needed) and has more sane support for the `'original'` argType (as suggested by pull request #93). Test Plan: - Make sure tests and lint pass - Make sure huxley screenshots didn't change, and new screenshot looks correct Reviewers: alpert Reviewed By: alpert Differential Revision: https://phabricator.khanacademy.org/D13810
This commit is contained in:
parent
d61a04c80d
commit
fd18f6979e
18
README.md
18
README.md
|
@ -18,13 +18,17 @@ You can [download KaTeX](https://github.com/khan/katex/releases) and host it on
|
|||
<script src="//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.1.1/katex.min.js"></script>
|
||||
```
|
||||
|
||||
#### In-browser rendering
|
||||
|
||||
Call `katex.render` with a TeX expression and a DOM element to render into:
|
||||
|
||||
```js
|
||||
katex.render("c = \\pm\\sqrt{a^2 + b^2}", element);
|
||||
```
|
||||
|
||||
To generate HTML on the server, you can use `katex.renderToString`:
|
||||
#### Server side rendering or rendering to a string
|
||||
|
||||
To generate HTML on the server or to generate an HTML string of the rendered math, you can use `katex.renderToString`:
|
||||
|
||||
```js
|
||||
var html = katex.renderToString("c = \\pm\\sqrt{a^2 + b^2}");
|
||||
|
@ -33,12 +37,16 @@ var html = katex.renderToString("c = \\pm\\sqrt{a^2 + b^2}");
|
|||
|
||||
Make sure to include the CSS and font files, but there is no need to include the JavaScript.
|
||||
|
||||
These APIs default to inline math typesetting; for display math you can prepend `\displaystyle` ([#66](https://github.com/Khan/KaTeX/issues/66)):
|
||||
#### Rendering options
|
||||
|
||||
You can provide an object of options as the last argument to `katex.render` and `katex.renderToString`. Available options are:
|
||||
|
||||
- `displayMode`: `boolean`. If `true` the math will be rendered in display mode, which will put the math in display style (so `\int` and `\sum` are large, for example), and will center the math on the page on its own line. If `false` the math will be rendered in inline mode. (default: `false`)
|
||||
|
||||
For example:
|
||||
|
||||
```js
|
||||
katex.render("\\displaystyle {" + formula + "}", element);
|
||||
// OR
|
||||
var html = katex.renderToString("\\displaystyle {" + formula + "}");
|
||||
katex.render("c = \\pm\\sqrt{a^2 + b^2}", element, { displayMode: true });
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
|
17
katex.js
17
katex.js
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
var ParseError = require("./src/ParseError");
|
||||
var Settings = require("./src/Settings");
|
||||
|
||||
var buildTree = require("./src/buildTree");
|
||||
var parseTree = require("./src/parseTree");
|
||||
|
@ -16,11 +17,13 @@ var utils = require("./src/utils");
|
|||
* Parse and build an expression, and place that expression in the DOM node
|
||||
* given.
|
||||
*/
|
||||
var render = function(toParse, baseNode) {
|
||||
var render = function(toParse, baseNode, options) {
|
||||
utils.clearNode(baseNode);
|
||||
|
||||
var tree = parseTree(toParse);
|
||||
var node = buildTree(tree).toNode();
|
||||
var settings = new Settings(options);
|
||||
|
||||
var tree = parseTree(toParse, settings);
|
||||
var node = buildTree(tree, settings).toNode();
|
||||
|
||||
baseNode.appendChild(node);
|
||||
};
|
||||
|
@ -42,9 +45,11 @@ if (typeof document !== "undefined") {
|
|||
/**
|
||||
* Parse and build an expression, and return the markup for that.
|
||||
*/
|
||||
var renderToString = function(toParse) {
|
||||
var tree = parseTree(toParse);
|
||||
return buildTree(tree).toMarkup();
|
||||
var renderToString = function(toParse, options) {
|
||||
var settings = new Settings(options);
|
||||
|
||||
var tree = parseTree(toParse, settings);
|
||||
return buildTree(tree, settings).toMarkup();
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
|
|
|
@ -43,9 +43,11 @@ var ParseError = require("./ParseError");
|
|||
/**
|
||||
* Main Parser class
|
||||
*/
|
||||
function Parser(input) {
|
||||
function Parser(input, settings) {
|
||||
// Make a new lexer
|
||||
this.lexer = new Lexer(input);
|
||||
// Store the settings for use in parsing
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -69,18 +71,10 @@ function ParseResult(result, newPosition) {
|
|||
* An initial function (without its arguments), or an argument to a function.
|
||||
* The `result` argument should be a ParseResult.
|
||||
*/
|
||||
function ParseFuncOrArgument(result, isFunction, allowedInText, numArgs, numOptionalArgs, argTypes) {
|
||||
function ParseFuncOrArgument(result, isFunction) {
|
||||
this.result = result;
|
||||
// Is this a function (i.e. is it something defined in functions.js)?
|
||||
this.isFunction = isFunction;
|
||||
// Is it allowed in text mode?
|
||||
this.allowedInText = allowedInText;
|
||||
// How many arguments?
|
||||
this.numArgs = numArgs;
|
||||
// How many optional arguments?
|
||||
this.numOptionalArgs = numOptionalArgs;
|
||||
// What types of arguments?
|
||||
this.argTypes = argTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -217,10 +211,10 @@ Parser.prototype.handleSupSubscript = function(pos, mode, symbol, name) {
|
|||
if (!group) {
|
||||
throw new ParseError(
|
||||
"Expected group after '" + symbol + "'", this.lexer, pos);
|
||||
} else if (group.numArgs > 0) {
|
||||
} else if (group.isFunction) {
|
||||
// ^ and _ have a greediness, so handle interactions with functions'
|
||||
// greediness
|
||||
var funcGreediness = functions.getGreediness(group.result.result);
|
||||
var funcGreediness = functions.funcs[group.result.result].greediness;
|
||||
if (funcGreediness > SUPSUB_GREEDINESS) {
|
||||
return this.parseFunction(pos, mode);
|
||||
} else {
|
||||
|
@ -419,7 +413,8 @@ Parser.prototype.parseFunction = function(pos, mode) {
|
|||
if (baseGroup) {
|
||||
if (baseGroup.isFunction) {
|
||||
var func = baseGroup.result.result;
|
||||
if (mode === "text" && !baseGroup.allowedInText) {
|
||||
var funcData = functions.funcs[func];
|
||||
if (mode === "text" && !funcData.allowedInText) {
|
||||
throw new ParseError(
|
||||
"Can't use function '" + func + "' in text mode",
|
||||
this.lexer, baseGroup.position);
|
||||
|
@ -428,17 +423,17 @@ Parser.prototype.parseFunction = function(pos, mode) {
|
|||
var newPos = baseGroup.result.position;
|
||||
var result;
|
||||
|
||||
var totalArgs = baseGroup.numArgs + baseGroup.numOptionalArgs;
|
||||
var totalArgs = funcData.numArgs + funcData.numOptionalArgs;
|
||||
|
||||
if (totalArgs > 0) {
|
||||
var baseGreediness = functions.getGreediness(func);
|
||||
var baseGreediness = funcData.greediness;
|
||||
var args = [func];
|
||||
var positions = [newPos];
|
||||
|
||||
for (var i = 0; i < totalArgs; i++) {
|
||||
var argType = baseGroup.argTypes && baseGroup.argTypes[i];
|
||||
var argType = funcData.argTypes && funcData.argTypes[i];
|
||||
var arg;
|
||||
if (i < baseGroup.numOptionalArgs) {
|
||||
if (i < funcData.numOptionalArgs) {
|
||||
if (argType) {
|
||||
arg = this.parseSpecialGroup(newPos, argType, mode, true);
|
||||
} else {
|
||||
|
@ -463,8 +458,9 @@ Parser.prototype.parseFunction = function(pos, mode) {
|
|||
}
|
||||
}
|
||||
var argNode;
|
||||
if (arg.numArgs > 0) {
|
||||
var argGreediness = functions.getGreediness(arg.result.result);
|
||||
if (arg.isFunction) {
|
||||
var argGreediness =
|
||||
functions.funcs[arg.result.result].greediness;
|
||||
if (argGreediness > baseGreediness) {
|
||||
argNode = this.parseFunction(newPos, mode);
|
||||
} else {
|
||||
|
@ -507,6 +503,11 @@ Parser.prototype.parseFunction = function(pos, mode) {
|
|||
* @return {?ParseFuncOrArgument}
|
||||
*/
|
||||
Parser.prototype.parseSpecialGroup = function(pos, mode, outerMode, optional) {
|
||||
// Handle `original` argTypes
|
||||
if (mode === "original") {
|
||||
mode = outerMode;
|
||||
}
|
||||
|
||||
if (mode === "color" || mode === "size") {
|
||||
// color and size modes are special because they should have braces and
|
||||
// should only lex a single symbol inside
|
||||
|
@ -605,23 +606,11 @@ Parser.prototype.parseSymbol = function(pos, mode) {
|
|||
var nucleus = this.lexer.lex(pos, mode);
|
||||
|
||||
if (functions.funcs[nucleus.text]) {
|
||||
// If there is a function with this name, we use its data
|
||||
var func = functions.funcs[nucleus.text];
|
||||
|
||||
// Here, we replace "original" argTypes with the current mode
|
||||
var argTypes = func.argTypes;
|
||||
if (argTypes) {
|
||||
argTypes = argTypes.slice();
|
||||
for (var i = 0; i < argTypes.length; i++) {
|
||||
if (argTypes[i] === "original") {
|
||||
argTypes[i] = mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If there exists a function with this name, we return the function and
|
||||
// say that it is a function.
|
||||
return new ParseFuncOrArgument(
|
||||
new ParseResult(nucleus.text, nucleus.position),
|
||||
true, func.allowedInText, func.numArgs, func.numOptionalArgs, argTypes);
|
||||
true);
|
||||
} else if (symbols[mode][nucleus.text]) {
|
||||
// Otherwise if this is a no-argument function, find the type it
|
||||
// corresponds to in the symbols map
|
||||
|
|
26
src/Settings.js
Normal file
26
src/Settings.js
Normal file
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* This is a module for storing settings passed into KaTeX. It correctly handles
|
||||
* default settings.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Helper function for getting a default value if the value is undefined
|
||||
*/
|
||||
function get(option, defaultValue) {
|
||||
return option === undefined ? defaultValue : option;
|
||||
}
|
||||
|
||||
/**
|
||||
* The main Settings object
|
||||
*
|
||||
* The current options stored are:
|
||||
* - displayMode: Whether the expression should be typeset by default in
|
||||
* textstyle or displaystyle (default false)
|
||||
*/
|
||||
function Settings(options) {
|
||||
// allow null options
|
||||
options = options || {};
|
||||
this.displayMode = get(options.displayMode, false);
|
||||
}
|
||||
|
||||
module.exports = Settings;
|
|
@ -1135,9 +1135,14 @@ var buildGroup = function(group, options, prev) {
|
|||
/**
|
||||
* Take an entire parse tree, and build it into an appropriate set of nodes.
|
||||
*/
|
||||
var buildTree = function(tree) {
|
||||
var buildTree = function(tree, settings) {
|
||||
var startStyle = Style.TEXT;
|
||||
if (settings.displayMode) {
|
||||
startStyle = Style.DISPLAY;
|
||||
}
|
||||
|
||||
// Setup the default options
|
||||
var options = new Options(Style.TEXT, "size5", "");
|
||||
var options = new Options(startStyle, "size5", "");
|
||||
|
||||
// Build the expression contained in the tree
|
||||
var expression = buildExpression(tree, options);
|
||||
|
@ -1161,7 +1166,11 @@ var buildTree = function(tree) {
|
|||
makeSpan(["katex-inner"], [topStrut, bottomStrut, body])
|
||||
]);
|
||||
|
||||
return katexNode;
|
||||
if (settings.displayMode) {
|
||||
return makeSpan(["katex-display"], [katexNode]);
|
||||
} else {
|
||||
return katexNode;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = buildTree;
|
||||
|
|
|
@ -506,16 +506,6 @@ for (var i = 0; i < duplicatedFunctions.length; i++) {
|
|||
addFuncsWithData(duplicatedFunctions[i].funcs, duplicatedFunctions[i].data);
|
||||
}
|
||||
|
||||
// Returns the greediness of a given function. Since greediness is optional, we
|
||||
// use this function to put in the default value if it is undefined.
|
||||
var getGreediness = function(func) {
|
||||
if (functions[func].greediness === undefined) {
|
||||
return 1;
|
||||
} else {
|
||||
return functions[func].greediness;
|
||||
}
|
||||
};
|
||||
|
||||
// Set default values of functions
|
||||
for (var f in functions) {
|
||||
if (functions.hasOwnProperty(f)) {
|
||||
|
@ -534,6 +524,5 @@ for (var f in functions) {
|
|||
}
|
||||
|
||||
module.exports = {
|
||||
funcs: functions,
|
||||
getGreediness: getGreediness
|
||||
funcs: functions
|
||||
};
|
||||
|
|
|
@ -8,8 +8,8 @@ var Parser = require("./Parser");
|
|||
/**
|
||||
* Parses an expression using a Parser, then returns the parsed result.
|
||||
*/
|
||||
var parseTree = function(toParse) {
|
||||
var parser = new Parser(toParse);
|
||||
var parseTree = function(toParse, settings) {
|
||||
var parser = new Parser(toParse, settings);
|
||||
|
||||
return parser.parse();
|
||||
};
|
||||
|
|
|
@ -1,5 +1,15 @@
|
|||
@import "fonts.less";
|
||||
|
||||
.katex-display {
|
||||
display: block;
|
||||
margin: 1em 0;
|
||||
text-align: center;
|
||||
|
||||
> .katex {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.katex {
|
||||
font: normal 1.21em KaTeX_Main;
|
||||
line-height: 1.2;
|
||||
|
|
|
@ -195,5 +195,11 @@
|
|||
"name": "Accents",
|
||||
"screenSize": [1024, 768],
|
||||
"url": "http://localhost:7936/test/huxley/test.html?m=\\vec{A}\\vec{x}\\vec x^2\\vec{x}_2^2\\vec{A}^2\\vec{xA}^2"
|
||||
},
|
||||
|
||||
{
|
||||
"name": "DisplayMode",
|
||||
"screenSize": [1024, 768],
|
||||
"url": "http://localhost:7936/test/huxley/test.html?m=\\sum_{i=0}^\\infty \\frac{1}{i}&pre=pre&post=post&display=1"
|
||||
}
|
||||
]
|
||||
|
|
BIN
test/huxley/Huxleyfolder/DisplayMode.hux/firefox-1.png
Normal file
BIN
test/huxley/Huxleyfolder/DisplayMode.hux/firefox-1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
5
test/huxley/Huxleyfolder/DisplayMode.record.json
Normal file
5
test/huxley/Huxleyfolder/DisplayMode.record.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
[
|
||||
{
|
||||
"action": "screenshot"
|
||||
}
|
||||
]
|
Binary file not shown.
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 16 KiB |
|
@ -16,13 +16,15 @@
|
|||
<span id="post"></span>
|
||||
<script type="text/javascript">
|
||||
var query = {};
|
||||
var queryVars = window.location.search.slice(1).split("&");
|
||||
for (var i = 0; i < queryVars.length; i++) {
|
||||
var split = queryVars[i].split("=");
|
||||
query[split[0]] = decodeURIComponent(split[1]);
|
||||
var re = /(?:^\?|&)([^&=]+)(?:=([^&]+))?/g;
|
||||
var match;
|
||||
while (match = re.exec(window.location.search)) {
|
||||
query[match[1]] = decodeURIComponent(match[2]);
|
||||
}
|
||||
var mathNode = document.getElementById("math");
|
||||
katex.render(query["m"], mathNode);
|
||||
katex.render(query["m"], mathNode, {
|
||||
displayMode: !!query["display"]
|
||||
});
|
||||
document.getElementById("pre").innerHTML = query["pre"] || "";
|
||||
document.getElementById("post").innerHTML = query["post"] || "";
|
||||
</script>
|
||||
|
|
|
@ -1,17 +1,26 @@
|
|||
var katex = require("../katex");
|
||||
var buildTree = require("../src/buildTree");
|
||||
var parseTree = require("../src/parseTree");
|
||||
var katex = require("../katex");
|
||||
var ParseError = require("../src/ParseError");
|
||||
var parseTree = require("../src/parseTree");
|
||||
var Settings = require("../src/Settings");
|
||||
|
||||
var defaultSettings = new Settings({});
|
||||
|
||||
var getBuilt = function(expr) {
|
||||
expect(expr).toBuild();
|
||||
|
||||
var built = buildTree(parseTree(expr));
|
||||
var built = buildTree(parseTree(expr), defaultSettings);
|
||||
|
||||
// Remove the outer .katex and .katex-inner layers
|
||||
return built.children[0].children[2].children;
|
||||
};
|
||||
|
||||
var getParsed = function(expr) {
|
||||
expect(expr).toParse();
|
||||
|
||||
return parseTree(expr, defaultSettings);
|
||||
};
|
||||
|
||||
beforeEach(function() {
|
||||
jasmine.addMatchers({
|
||||
toParse: function() {
|
||||
|
@ -23,7 +32,7 @@ beforeEach(function() {
|
|||
};
|
||||
|
||||
try {
|
||||
parseTree(actual);
|
||||
parseTree(actual, defaultSettings);
|
||||
} catch (e) {
|
||||
result.pass = false;
|
||||
if (e instanceof ParseError) {
|
||||
|
@ -50,7 +59,7 @@ beforeEach(function() {
|
|||
};
|
||||
|
||||
try {
|
||||
parseTree(actual);
|
||||
parseTree(actual, defaultSettings);
|
||||
} catch (e) {
|
||||
if (e instanceof ParseError) {
|
||||
result.pass = true;
|
||||
|
@ -78,7 +87,7 @@ beforeEach(function() {
|
|||
expect(actual).toParse();
|
||||
|
||||
try {
|
||||
buildTree(parseTree(actual));
|
||||
buildTree(parseTree(actual), defaultSettings);
|
||||
} catch (e) {
|
||||
result.pass = false;
|
||||
if (e instanceof ParseError) {
|
||||
|
@ -103,8 +112,8 @@ describe("A parser", function() {
|
|||
});
|
||||
|
||||
it("should ignore whitespace", function() {
|
||||
var parseA = parseTree(" x y ");
|
||||
var parseB = parseTree("xy");
|
||||
var parseA = getParsed(" x y ");
|
||||
var parseB = getParsed("xy");
|
||||
expect(parseA).toEqual(parseB);
|
||||
});
|
||||
});
|
||||
|
@ -117,7 +126,7 @@ describe("An ord parser", function() {
|
|||
});
|
||||
|
||||
it("should build a list of ords", function() {
|
||||
var parse = parseTree(expression);
|
||||
var parse = getParsed(expression);
|
||||
|
||||
expect(parse).toBeTruthy();
|
||||
|
||||
|
@ -128,7 +137,7 @@ describe("An ord parser", function() {
|
|||
});
|
||||
|
||||
it("should parse the right number of ords", function() {
|
||||
var parse = parseTree(expression);
|
||||
var parse = getParsed(expression);
|
||||
|
||||
expect(parse.length).toBe(expression.length);
|
||||
});
|
||||
|
@ -142,7 +151,7 @@ describe("A bin parser", function() {
|
|||
});
|
||||
|
||||
it("should build a list of bins", function() {
|
||||
var parse = parseTree(expression);
|
||||
var parse = getParsed(expression);
|
||||
expect(parse).toBeTruthy();
|
||||
|
||||
for (var i = 0; i < parse.length; i++) {
|
||||
|
@ -160,7 +169,7 @@ describe("A rel parser", function() {
|
|||
});
|
||||
|
||||
it("should build a list of rels", function() {
|
||||
var parse = parseTree(expression);
|
||||
var parse = getParsed(expression);
|
||||
expect(parse).toBeTruthy();
|
||||
|
||||
for (var i = 0; i < parse.length; i++) {
|
||||
|
@ -178,7 +187,7 @@ describe("A punct parser", function() {
|
|||
});
|
||||
|
||||
it("should build a list of puncts", function() {
|
||||
var parse = parseTree(expression);
|
||||
var parse = getParsed(expression);
|
||||
expect(parse).toBeTruthy();
|
||||
|
||||
for (var i = 0; i < parse.length; i++) {
|
||||
|
@ -196,7 +205,7 @@ describe("An open parser", function() {
|
|||
});
|
||||
|
||||
it("should build a list of opens", function() {
|
||||
var parse = parseTree(expression);
|
||||
var parse = getParsed(expression);
|
||||
expect(parse).toBeTruthy();
|
||||
|
||||
for (var i = 0; i < parse.length; i++) {
|
||||
|
@ -214,7 +223,7 @@ describe("A close parser", function() {
|
|||
});
|
||||
|
||||
it("should build a list of closes", function() {
|
||||
var parse = parseTree(expression);
|
||||
var parse = getParsed(expression);
|
||||
expect(parse).toBeTruthy();
|
||||
|
||||
for (var i = 0; i < parse.length; i++) {
|
||||
|
@ -253,7 +262,7 @@ describe("A subscript and superscript parser", function() {
|
|||
});
|
||||
|
||||
it("should produce supsubs for superscript", function() {
|
||||
var parse = parseTree("x^2")[0];
|
||||
var parse = getParsed("x^2")[0];
|
||||
|
||||
expect(parse.type).toBe("supsub");
|
||||
expect(parse.value.base).toBeDefined();
|
||||
|
@ -262,7 +271,7 @@ describe("A subscript and superscript parser", function() {
|
|||
});
|
||||
|
||||
it("should produce supsubs for subscript", function() {
|
||||
var parse = parseTree("x_3")[0];
|
||||
var parse = getParsed("x_3")[0];
|
||||
|
||||
expect(parse.type).toBe("supsub");
|
||||
expect(parse.value.base).toBeDefined();
|
||||
|
@ -271,7 +280,7 @@ describe("A subscript and superscript parser", function() {
|
|||
});
|
||||
|
||||
it("should produce supsubs for ^_", function() {
|
||||
var parse = parseTree("x^2_3")[0];
|
||||
var parse = getParsed("x^2_3")[0];
|
||||
|
||||
expect(parse.type).toBe("supsub");
|
||||
expect(parse.value.base).toBeDefined();
|
||||
|
@ -280,7 +289,7 @@ describe("A subscript and superscript parser", function() {
|
|||
});
|
||||
|
||||
it("should produce supsubs for _^", function() {
|
||||
var parse = parseTree("x_3^2")[0];
|
||||
var parse = getParsed("x_3^2")[0];
|
||||
|
||||
expect(parse.type).toBe("supsub");
|
||||
expect(parse.value.base).toBeDefined();
|
||||
|
@ -289,8 +298,8 @@ describe("A subscript and superscript parser", function() {
|
|||
});
|
||||
|
||||
it("should produce the same thing regardless of order", function() {
|
||||
var parseA = parseTree("x^2_3");
|
||||
var parseB = parseTree("x_3^2");
|
||||
var parseA = getParsed("x^2_3");
|
||||
var parseB = getParsed("x_3^2");
|
||||
|
||||
expect(parseA).toEqual(parseB);
|
||||
});
|
||||
|
@ -350,7 +359,7 @@ describe("A group parser", function() {
|
|||
});
|
||||
|
||||
it("should produce a single ord", function() {
|
||||
var parse = parseTree("{xy}");
|
||||
var parse = getParsed("{xy}");
|
||||
|
||||
expect(parse.length).toBe(1);
|
||||
|
||||
|
@ -368,7 +377,7 @@ describe("An implicit group parser", function() {
|
|||
});
|
||||
|
||||
it("should produce a single object", function() {
|
||||
var parse = parseTree("\\Large abc");
|
||||
var parse = getParsed("\\Large abc");
|
||||
|
||||
expect(parse.length).toBe(1);
|
||||
|
||||
|
@ -379,7 +388,7 @@ describe("An implicit group parser", function() {
|
|||
});
|
||||
|
||||
it("should apply only after the function", function() {
|
||||
var parse = parseTree("a \\Large abc");
|
||||
var parse = getParsed("a \\Large abc");
|
||||
|
||||
expect(parse.length).toBe(2);
|
||||
|
||||
|
@ -390,7 +399,7 @@ describe("An implicit group parser", function() {
|
|||
});
|
||||
|
||||
it("should stop at the ends of groups", function() {
|
||||
var parse = parseTree("a { b \\Large c } d");
|
||||
var parse = getParsed("a { b \\Large c } d");
|
||||
|
||||
var group = parse[1];
|
||||
var sizing = group.value[1];
|
||||
|
@ -446,7 +455,7 @@ describe("A frac parser", function() {
|
|||
});
|
||||
|
||||
it("should produce a frac", function() {
|
||||
var parse = parseTree(expression)[0];
|
||||
var parse = getParsed(expression)[0];
|
||||
|
||||
expect(parse.type).toMatch("frac");
|
||||
expect(parse.value.numer).toBeDefined();
|
||||
|
@ -460,13 +469,13 @@ describe("A frac parser", function() {
|
|||
});
|
||||
|
||||
it("should parse dfrac and tfrac as fracs", function() {
|
||||
var dfracParse = parseTree(dfracExpression)[0];
|
||||
var dfracParse = getParsed(dfracExpression)[0];
|
||||
|
||||
expect(dfracParse.type).toMatch("frac");
|
||||
expect(dfracParse.value.numer).toBeDefined();
|
||||
expect(dfracParse.value.denom).toBeDefined();
|
||||
|
||||
var tfracParse = parseTree(tfracExpression)[0];
|
||||
var tfracParse = getParsed(tfracExpression)[0];
|
||||
|
||||
expect(tfracParse.type).toMatch("frac");
|
||||
expect(tfracParse.value.numer).toBeDefined();
|
||||
|
@ -486,13 +495,13 @@ describe("An over parser", function() {
|
|||
it("should produce a frac", function() {
|
||||
var parse;
|
||||
|
||||
parse = parseTree(simpleOver)[0];
|
||||
parse = getParsed(simpleOver)[0];
|
||||
|
||||
expect(parse.type).toMatch("frac");
|
||||
expect(parse.value.numer).toBeDefined();
|
||||
expect(parse.value.denom).toBeDefined();
|
||||
|
||||
parse = parseTree(complexOver)[0];
|
||||
parse = getParsed(complexOver)[0];
|
||||
|
||||
expect(parse.type).toMatch("frac");
|
||||
expect(parse.value.numer).toBeDefined();
|
||||
|
@ -500,14 +509,14 @@ describe("An over parser", function() {
|
|||
});
|
||||
|
||||
it("should create a numerator from the atoms before \\over", function () {
|
||||
var parse = parseTree(complexOver)[0];
|
||||
var parse = getParsed(complexOver)[0];
|
||||
|
||||
var numer = parse.value.numer;
|
||||
expect(numer.value.length).toEqual(4);
|
||||
});
|
||||
|
||||
it("should create a demonimator from the atoms after \\over", function () {
|
||||
var parse = parseTree(complexOver)[0];
|
||||
var parse = getParsed(complexOver)[0];
|
||||
|
||||
var denom = parse.value.numer;
|
||||
expect(denom.value.length).toEqual(4);
|
||||
|
@ -515,9 +524,7 @@ describe("An over parser", function() {
|
|||
|
||||
it("should handle empty numerators", function () {
|
||||
var emptyNumerator = "\\over x";
|
||||
expect(emptyNumerator).toParse();
|
||||
|
||||
var parse = parseTree(emptyNumerator)[0];
|
||||
var parse = getParsed(emptyNumerator)[0];
|
||||
expect(parse.type).toMatch("frac");
|
||||
expect(parse.value.numer).toBeDefined();
|
||||
expect(parse.value.denom).toBeDefined();
|
||||
|
@ -525,9 +532,7 @@ describe("An over parser", function() {
|
|||
|
||||
it("should handle empty denominators", function () {
|
||||
var emptyDenominator = "1 \\over";
|
||||
expect(emptyDenominator).toParse();
|
||||
|
||||
var parse = parseTree(emptyDenominator)[0];
|
||||
var parse = getParsed(emptyDenominator)[0];
|
||||
expect(parse.type).toMatch("frac");
|
||||
expect(parse.value.numer).toBeDefined();
|
||||
expect(parse.value.denom).toBeDefined();
|
||||
|
@ -535,9 +540,7 @@ describe("An over parser", function() {
|
|||
|
||||
it("should handle \\displaystyle correctly", function () {
|
||||
var displaystyleExpression = "\\displaystyle 1 \\over 2";
|
||||
expect(displaystyleExpression).toParse();
|
||||
|
||||
var parse = parseTree(displaystyleExpression)[0];
|
||||
var parse = getParsed(displaystyleExpression)[0];
|
||||
expect(parse.type).toMatch("frac");
|
||||
expect(parse.value.numer.value[0].type).toMatch("styling");
|
||||
expect(parse.value.denom).toBeDefined();
|
||||
|
@ -545,9 +548,7 @@ describe("An over parser", function() {
|
|||
|
||||
it("should handle nested factions", function () {
|
||||
var nestedOverExpression = "{1 \\over 2} \\over 3";
|
||||
expect(nestedOverExpression).toParse();
|
||||
|
||||
var parse = parseTree(nestedOverExpression)[0];
|
||||
var parse = getParsed(nestedOverExpression)[0];
|
||||
expect(parse.type).toMatch("frac");
|
||||
expect(parse.value.numer.value[0].type).toMatch("frac");
|
||||
expect(parse.value.numer.value[0].value.numer.value[0].value).toMatch(1);
|
||||
|
@ -574,7 +575,7 @@ describe("A sizing parser", function() {
|
|||
});
|
||||
|
||||
it("should produce a sizing node", function() {
|
||||
var parse = parseTree(sizeExpression)[0];
|
||||
var parse = getParsed(sizeExpression)[0];
|
||||
|
||||
expect(parse.type).toMatch("sizing");
|
||||
expect(parse.value).toBeDefined();
|
||||
|
@ -596,14 +597,14 @@ describe("A text parser", function() {
|
|||
});
|
||||
|
||||
it("should produce a text", function() {
|
||||
var parse = parseTree(textExpression)[0];
|
||||
var parse = getParsed(textExpression)[0];
|
||||
|
||||
expect(parse.type).toMatch("text");
|
||||
expect(parse.value).toBeDefined();
|
||||
});
|
||||
|
||||
it("should produce textords instead of mathords", function() {
|
||||
var parse = parseTree(textExpression)[0];
|
||||
var parse = getParsed(textExpression)[0];
|
||||
var group = parse.value.body;
|
||||
|
||||
expect(group[0].type).toMatch("textord");
|
||||
|
@ -626,7 +627,7 @@ describe("A text parser", function() {
|
|||
});
|
||||
|
||||
it("should contract spaces", function() {
|
||||
var parse = parseTree(spaceTextExpression)[0];
|
||||
var parse = getParsed(spaceTextExpression)[0];
|
||||
var group = parse.value.body;
|
||||
|
||||
expect(group[0].type).toMatch("spacing");
|
||||
|
@ -636,7 +637,7 @@ describe("A text parser", function() {
|
|||
});
|
||||
|
||||
it("should ignore a space before the text group", function() {
|
||||
var parse = parseTree(leadingSpaceTextExpression)[0];
|
||||
var parse = getParsed(leadingSpaceTextExpression)[0];
|
||||
// [m, o, o]
|
||||
expect(parse.value.body.length).toBe(3);
|
||||
expect(
|
||||
|
@ -655,7 +656,7 @@ describe("A color parser", function() {
|
|||
});
|
||||
|
||||
it("should build a color node", function() {
|
||||
var parse = parseTree(colorExpression)[0];
|
||||
var parse = getParsed(colorExpression)[0];
|
||||
|
||||
expect(parse.type).toMatch("color");
|
||||
expect(parse.value.color).toBeDefined();
|
||||
|
@ -667,7 +668,7 @@ describe("A color parser", function() {
|
|||
});
|
||||
|
||||
it("should correctly extract the custom color", function() {
|
||||
var parse = parseTree(customColorExpression)[0];
|
||||
var parse = getParsed(customColorExpression)[0];
|
||||
|
||||
expect(parse.value.color).toMatch("#fA6");
|
||||
});
|
||||
|
@ -690,20 +691,20 @@ describe("A tie parser", function() {
|
|||
});
|
||||
|
||||
it("should produce spacing in math mode", function() {
|
||||
var parse = parseTree(mathTie);
|
||||
var parse = getParsed(mathTie);
|
||||
|
||||
expect(parse[1].type).toMatch("spacing");
|
||||
});
|
||||
|
||||
it("should produce spacing in text mode", function() {
|
||||
var text = parseTree(textTie)[0];
|
||||
var text = getParsed(textTie)[0];
|
||||
var parse = text.value.body;
|
||||
|
||||
expect(parse[1].type).toMatch("spacing");
|
||||
});
|
||||
|
||||
it("should not contract with spaces in text mode", function() {
|
||||
var text = parseTree(textTie)[0];
|
||||
var text = getParsed(textTie)[0];
|
||||
var parse = text.value.body;
|
||||
|
||||
expect(parse[2].type).toMatch("spacing");
|
||||
|
@ -725,22 +726,22 @@ describe("A delimiter sizing parser", function() {
|
|||
});
|
||||
|
||||
it("should produce a delimsizing", function() {
|
||||
var parse = parseTree(normalDelim)[0];
|
||||
var parse = getParsed(normalDelim)[0];
|
||||
|
||||
expect(parse.type).toMatch("delimsizing");
|
||||
});
|
||||
|
||||
it("should produce the correct direction delimiter", function() {
|
||||
var leftParse = parseTree(normalDelim)[0];
|
||||
var rightParse = parseTree(bigDelim)[0];
|
||||
var leftParse = getParsed(normalDelim)[0];
|
||||
var rightParse = getParsed(bigDelim)[0];
|
||||
|
||||
expect(leftParse.value.delimType).toMatch("open");
|
||||
expect(rightParse.value.delimType).toMatch("close");
|
||||
});
|
||||
|
||||
it("should parse the correct size delimiter", function() {
|
||||
var smallParse = parseTree(normalDelim)[0];
|
||||
var bigParse = parseTree(bigDelim)[0];
|
||||
var smallParse = getParsed(normalDelim)[0];
|
||||
var bigParse = getParsed(bigDelim)[0];
|
||||
|
||||
expect(smallParse.value.size).toEqual(1);
|
||||
expect(bigParse.value.size).toEqual(4);
|
||||
|
@ -755,7 +756,7 @@ describe("An overline parser", function() {
|
|||
});
|
||||
|
||||
it("should produce an overline", function() {
|
||||
var parse = parseTree(overline)[0];
|
||||
var parse = getParsed(overline)[0];
|
||||
|
||||
expect(parse.type).toMatch("overline");
|
||||
});
|
||||
|
@ -785,14 +786,14 @@ describe("A rule parser", function() {
|
|||
});
|
||||
|
||||
it("should produce a rule", function() {
|
||||
var parse = parseTree(emRule)[0];
|
||||
var parse = getParsed(emRule)[0];
|
||||
|
||||
expect(parse.type).toMatch("rule");
|
||||
});
|
||||
|
||||
it("should list the correct units", function() {
|
||||
var emParse = parseTree(emRule)[0];
|
||||
var exParse = parseTree(exRule)[0];
|
||||
var emParse = getParsed(emRule)[0];
|
||||
var exParse = getParsed(exRule)[0];
|
||||
|
||||
expect(emParse.value.width.unit).toMatch("em");
|
||||
expect(emParse.value.height.unit).toMatch("em");
|
||||
|
@ -802,16 +803,14 @@ describe("A rule parser", function() {
|
|||
});
|
||||
|
||||
it("should parse the number correctly", function() {
|
||||
var hardNumberParse = parseTree(hardNumberRule)[0];
|
||||
var hardNumberParse = getParsed(hardNumberRule)[0];
|
||||
|
||||
expect(hardNumberParse.value.width.number).toBeCloseTo(1.24);
|
||||
expect(hardNumberParse.value.height.number).toBeCloseTo(2.45);
|
||||
});
|
||||
|
||||
it("should parse negative sizes", function() {
|
||||
expect("\\rule{-1em}{- 0.2em}").toParse();
|
||||
|
||||
var parse = parseTree("\\rule{-1em}{- 0.2em}")[0];
|
||||
var parse = getParsed("\\rule{-1em}{- 0.2em}")[0];
|
||||
|
||||
expect(parse.value.width.number).toBeCloseTo(-1);
|
||||
expect(parse.value.height.number).toBeCloseTo(-0.2);
|
||||
|
@ -827,7 +826,7 @@ describe("A left/right parser", function() {
|
|||
});
|
||||
|
||||
it("should produce a leftright", function() {
|
||||
var parse = parseTree(normalLeftRight)[0];
|
||||
var parse = getParsed(normalLeftRight)[0];
|
||||
|
||||
expect(parse.type).toMatch("leftright");
|
||||
expect(parse.value.left).toMatch("\\(");
|
||||
|
@ -876,7 +875,7 @@ describe("A sqrt parser", function() {
|
|||
});
|
||||
|
||||
it("should produce sqrts", function() {
|
||||
var parse = parseTree(sqrt)[0];
|
||||
var parse = getParsed(sqrt)[0];
|
||||
|
||||
expect(parse.type).toMatch("sqrt");
|
||||
});
|
||||
|
@ -1036,18 +1035,16 @@ describe("A style change parser", function() {
|
|||
});
|
||||
|
||||
it("should produce the correct style", function() {
|
||||
var displayParse = parseTree("\\displaystyle x")[0];
|
||||
var displayParse = getParsed("\\displaystyle x")[0];
|
||||
expect(displayParse.value.style).toMatch("display");
|
||||
|
||||
var scriptscriptParse = parseTree("\\scriptscriptstyle x")[0];
|
||||
var scriptscriptParse = getParsed("\\scriptscriptstyle x")[0];
|
||||
expect(scriptscriptParse.value.style).toMatch("scriptscript");
|
||||
});
|
||||
|
||||
it("should only change the style within its group", function() {
|
||||
var text = "a b { c d \\displaystyle e f } g h";
|
||||
expect(text).toParse();
|
||||
|
||||
var parse = parseTree(text);
|
||||
var parse = getParsed(text);
|
||||
|
||||
var displayNode = parse[2].value[2];
|
||||
|
||||
|
@ -1108,13 +1105,13 @@ describe("An accent parser", function() {
|
|||
});
|
||||
|
||||
it("should produce accents", function() {
|
||||
var parse = parseTree("\\vec x")[0];
|
||||
var parse = getParsed("\\vec x")[0];
|
||||
|
||||
expect(parse.type).toMatch("accent");
|
||||
});
|
||||
|
||||
it("should be grouped more tightly than supsubs", function() {
|
||||
var parse = parseTree("\\vec x^2")[0];
|
||||
var parse = getParsed("\\vec x^2")[0];
|
||||
|
||||
expect(parse.type).toMatch("supsub");
|
||||
});
|
||||
|
@ -1144,7 +1141,7 @@ describe("An accent builder", function() {
|
|||
describe("A parser error", function () {
|
||||
it("should report the position of an error", function () {
|
||||
try {
|
||||
parseTree("\\sqrt}");
|
||||
parseTree("\\sqrt}", defaultSettings);
|
||||
} catch (e) {
|
||||
expect(e.position).toEqual(5);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user