commit f63af87f17fedfd0c4cab753a3d4f7a0a5290bc0
parent 79a5687057de6267ac71f507989d77a5e4a6812f
Author: Emily Eisenberg <emily@khanacademy.org>
Date: Sun, 14 Sep 2014 19:23:39 -0700
Add looots of comments
Summary:
Add comments everywhere! Also fix some small bugs like using Style.id
instead of Style.size, and rename some variables to be more descriptive.
Fixes #22
Test Plan:
- Make sure the huxley screenshots didn't change
- Make sure the tests still pass
Reviewers: alpert
Reviewed By: alpert
Differential Revision: http://phabricator.khanacademy.org/D13158
Diffstat:
| M | Lexer.js | | | 58 | +++++++++++++++++++++++++++++++++++++++++++++++----------- |
| M | Options.js | | | 37 | +++++++++++++++++++++++++++++++++++++ |
| M | ParseError.js | | | 9 | +++++++++ |
| M | Parser.js | | | 185 | +++++++++++++++++++++++++++++++++++++++++++++++-------------------------------- |
| M | Style.js | | | 47 | +++++++++++++++++++++++++++++++++++++++++++++-- |
| M | buildCommon.js | | | 43 | +++++++++++++++++++++++++++++++++++++++---- |
| M | buildTree.js | | | 538 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------ |
| M | delimiter.js | | | 167 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------- |
| M | domTree.js | | | 60 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++----- |
| M | fontMetrics.js | | | 38 | ++++++++++++++++++++++++++++++++++---- |
| M | katex.js | | | 15 | +++++++++++++++ |
| M | parseTree.js | | | 9 | ++++++++- |
| M | symbols.js | | | 28 | ++++++++++++++++++---------- |
| M | utils.js | | | 20 | +++++++++++++++++++- |
14 files changed, 956 insertions(+), 298 deletions(-)
diff --git a/Lexer.js b/Lexer.js
@@ -1,3 +1,16 @@
+/**
+ * The Lexer class handles tokenizing the input in various ways. Since our
+ * parser expects us to be able to backtrack, the lexer allows lexing from any
+ * given starting point.
+ *
+ * Its main exposed function is the `lex` function, which takes a position to
+ * lex from and a type of token to lex. It defers to the appropriate `_innerLex`
+ * function.
+ *
+ * The various `_innerLex` functions perform the actual lexing of different
+ * kinds.
+ */
+
var ParseError = require("./ParseError");
// The main lexer class
@@ -5,14 +18,15 @@ function Lexer(input) {
this._input = input;
};
-// The result of a single lex
+// The resulting token returned from `lex`.
function LexResult(type, text, position) {
this.type = type;
this.text = text;
this.position = position;
}
-// "normal" types of tokens
+// "normal" types of tokens. These are tokens which can be matched by a simple
+// regex, and have a type which is listed.
var mathNormals = [
[/^[/|@."`0-9]/, "textord"],
[/^[a-zA-Z]/, "mathord"],
@@ -29,6 +43,8 @@ var mathNormals = [
[/^~/, "spacing"]
];
+// These are "normal" tokens like above, but should instead be parsed in text
+// mode.
var textNormals = [
[/^[a-zA-Z0-9`!@*()-=+\[\]'";:?\/.,]/, "textord"],
[/^{/, "{"],
@@ -36,22 +52,29 @@ var textNormals = [
[/^~/, "spacing"]
];
+// Regexes for matching whitespace
var whitespaceRegex = /^\s*/;
var whitespaceConcatRegex = /^( +|\\ +)/;
-// Build a regex to easily parse the functions
+// This regex matches any other TeX function, which is a backslash followed by a
+// word or a single symbol
var anyFunc = /^\\(?:[a-zA-Z]+|.)/;
+/**
+ * This function lexes a single normal token. It takes a position, a list of
+ * "normal" tokens to try, and whether it should completely ignore whitespace or
+ * not.
+ */
Lexer.prototype._innerLex = function(pos, normals, ignoreWhitespace) {
var input = this._input.slice(pos);
- // Get rid of whitespace
if (ignoreWhitespace) {
+ // Get rid of whitespace.
var whitespace = input.match(whitespaceRegex)[0];
pos += whitespace.length;
input = input.slice(whitespace.length);
} else {
- // Do the funky concatenation of whitespace
+ // Do the funky concatenation of whitespace that happens in text mode.
var whitespace = input.match(whitespaceConcatRegex);
if (whitespace !== null) {
return new LexResult(" ", " ", pos + whitespace[0].length);
@@ -65,7 +88,7 @@ Lexer.prototype._innerLex = function(pos, normals, ignoreWhitespace) {
var match;
if ((match = input.match(anyFunc))) {
- // If we match one of the tokens, extract the type
+ // If we match a function token, return it
return new LexResult(match[0], match[0], pos + match[0].length);
} else {
// Otherwise, we look through the normal token regexes and see if it's
@@ -81,7 +104,6 @@ Lexer.prototype._innerLex = function(pos, normals, ignoreWhitespace) {
}
}
- // We didn't match any of the tokens, so throw an error.
throw new ParseError("Unexpected character: '" + input[0] +
"'", this, pos);
}
@@ -89,6 +111,9 @@ Lexer.prototype._innerLex = function(pos, normals, ignoreWhitespace) {
// A regex to match a CSS color (like #ffffff or BlueViolet)
var cssColor = /^(#[a-z0-9]+|[a-z]+)/i;
+/**
+ * This function lexes a CSS color.
+ */
Lexer.prototype._innerLexColor = function(pos) {
var input = this._input.slice(pos);
@@ -101,14 +126,18 @@ Lexer.prototype._innerLexColor = function(pos) {
if ((match = input.match(cssColor))) {
// If we look like a color, return a color
return new LexResult("color", match[0], pos + match[0].length);
+ } else {
+ throw new ParseError("Invalid color", this, pos);
}
-
- // We didn't match a color, so throw an error.
- throw new ParseError("Invalid color", this, pos);
};
+// A regex to match a dimension. Dimensions look like
+// "1.2em" or ".4pt" or "1 ex"
var sizeRegex = /^(\d+(?:\.\d*)?|\.\d+)\s*([a-z]{2})/;
+/**
+ * This function lexes a dimension.
+ */
Lexer.prototype._innerLexSize = function(pos) {
var input = this._input.slice(pos);
@@ -120,6 +149,7 @@ Lexer.prototype._innerLexSize = function(pos) {
var match;
if ((match = input.match(sizeRegex))) {
var unit = match[2];
+ // We only currently handle "em" and "ex" units
if (unit !== "em" && unit !== "ex") {
throw new ParseError("Invalid unit: '" + unit + "'", this, pos);
}
@@ -132,6 +162,9 @@ Lexer.prototype._innerLexSize = function(pos) {
throw new ParseError("Invalid size", this, pos);
};
+/**
+ * This function lexes a string of whitespace.
+ */
Lexer.prototype._innerLexWhitespace = function(pos) {
var input = this._input.slice(pos);
@@ -141,7 +174,10 @@ Lexer.prototype._innerLexWhitespace = function(pos) {
return new LexResult("whitespace", whitespace, pos);
};
-// Lex a single token
+/**
+ * This function lexes a single token starting at `pos` and of the given mode.
+ * Based on the mode, we defer to one of the `_innerLex` functions.
+ */
Lexer.prototype.lex = function(pos, mode) {
if (mode === "math") {
return this._innerLex(pos, mathNormals, true);
diff --git a/Options.js b/Options.js
@@ -1,3 +1,19 @@
+/**
+ * This file contains information about the options that the Parser carries
+ * around with it while parsing. Data is held in an `Options` object, and when
+ * recursing, a new `Options` object can be created with the `.with*` and
+ * `.reset` functions.
+ */
+
+/**
+ * This is the main options class. It contains the style, size, and color of the
+ * current parse level. It also contains the style and size of the parent parse
+ * level, so size changes can be handled efficiently.
+ *
+ * Each of the `.with*` and `.reset` functions passes its current style and size
+ * as the parentStyle and parentSize of the new options class, so parent
+ * handling is taken care of automatically.
+ */
function Options(style, size, color, parentStyle, parentSize) {
this.style = style;
this.color = color;
@@ -14,23 +30,40 @@ function Options(style, size, color, parentStyle, parentSize) {
this.parentSize = parentSize;
}
+/**
+ * Create a new options object with the given style.
+ */
Options.prototype.withStyle = function(style) {
return new Options(style, this.size, this.color, this.style, this.size);
};
+/**
+ * Create a new options object with the given size.
+ */
Options.prototype.withSize = function(size) {
return new Options(this.style, size, this.color, this.style, this.size);
};
+/**
+ * Create a new options object with the given color.
+ */
Options.prototype.withColor = function(color) {
return new Options(this.style, this.size, color, this.style, this.size);
};
+/**
+ * Create a new options object with the same style, size, and color. This is
+ * used so that parent style and size changes are handled correctly.
+ */
Options.prototype.reset = function() {
return new Options(
this.style, this.size, this.color, this.style, this.size);
};
+/**
+ * A map of color names to CSS colors.
+ * TODO(emily): Remove this when we have real macros
+ */
var colorMap = {
"katex-blue": "#6495ed",
"katex-orange": "#ffa500",
@@ -41,6 +74,10 @@ var colorMap = {
"katex-purple": "#9d38bd"
};
+/**
+ * Gets the CSS color of the current options object, accounting for the
+ * `colorMap`.
+ */
Options.prototype.getColor = function() {
return colorMap[this.color] || this.color;
};
diff --git a/ParseError.js b/ParseError.js
@@ -1,8 +1,14 @@
+/**
+ * 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.
+ */
function ParseError(message, lexer, position) {
var error = "KaTeX parse error: " + message;
if (lexer !== undefined && position !== undefined) {
// If we have the input and a position, make the error a bit fancier
+
// Prepend some information
error += " at position " + position + ": ";
@@ -18,12 +24,15 @@ function ParseError(message, lexer, position) {
error += input.slice(begin, end);
}
+ // 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;
return self;
}
+// More hackery
ParseError.prototype.__proto__ = Error.prototype;
module.exports = ParseError;
diff --git a/Parser.js b/Parser.js
@@ -5,60 +5,70 @@ var utils = require("./utils");
var ParseError = require("./ParseError");
-// This file contains the parser used to parse out a TeX expression from the
-// input. Since TeX isn't context-free, standard parsers don't work particularly
-// well.
-
-// The strategy of this parser is as such:
-//
-// The main functions (the `.parse...` ones) take a position in the current
-// parse string to parse tokens from. The lexer (found in Lexer.js, stored at
-// this.lexer) also supports pulling out tokens at arbitrary places. When
-// individual tokens are needed at a position, the lexer is called to pull out a
-// token, which is then used.
-//
-// The main functions also take a mode that the parser is currently in
-// (currently "math" or "text"), which denotes whether the current environment
-// is a math-y one or a text-y one (e.g. inside \text). Currently, this serves
-// to limit the functions which can be used in text mode.
-//
-// The main functions then return an object which contains the useful data that
-// was parsed at its given point, and a new position at the end of the parsed
-// data. The main functions can call each other and continue the parsing by
-// using the returned position as a new starting point.
-//
-// There are also extra `.handle...` functions, which pull out some reused
-// functionality into self-contained functions.
-//
-// The earlier functions return `ParseResult`s, which contain a ParseNode and a
-// new position.
-//
-// The later functions (which are called deeper in the parse) sometimes return
-// ParseFuncOrArgument, which contain a ParseResult as well as some data about
-// whether the parsed object is a function which is missing some arguments, or a
-// standalone object which can be used as an argument to another function.
-
-// Main Parser class
+/**
+ * This file contains the parser used to parse out a TeX expression from the
+ * input. Since TeX isn't context-free, standard parsers don't work particularly
+ * well.
+ *
+ * The strategy of this parser is as such:
+ *
+ * The main functions (the `.parse...` ones) take a position in the current
+ * parse string to parse tokens from. The lexer (found in Lexer.js, stored at
+ * this.lexer) also supports pulling out tokens at arbitrary places. When
+ * individual tokens are needed at a position, the lexer is called to pull out a
+ * token, which is then used.
+ *
+ * The main functions also take a mode that the parser is currently in
+ * (currently "math" or "text"), which denotes whether the current environment
+ * is a math-y one or a text-y one (e.g. inside \text). Currently, this serves
+ * to limit the functions which can be used in text mode.
+ *
+ * The main functions then return an object which contains the useful data that
+ * was parsed at its given point, and a new position at the end of the parsed
+ * data. The main functions can call each other and continue the parsing by
+ * using the returned position as a new starting point.
+ *
+ * There are also extra `.handle...` functions, which pull out some reused
+ * functionality into self-contained functions.
+ *
+ * The earlier functions return `ParseResult`s, which contain a ParseNode and a
+ * new position.
+ *
+ * The later functions (which are called deeper in the parse) sometimes return
+ * ParseFuncOrArgument, which contain a ParseResult as well as some data about
+ * whether the parsed object is a function which is missing some arguments, or a
+ * standalone object which can be used as an argument to another function.
+ */
+
+/**
+ * Main Parser class
+ */
function Parser(input) {
// Make a new lexer
this.lexer = new Lexer(input);
};
-// The resulting parse tree nodes of the parse tree.
+/**
+ * The resulting parse tree nodes of the parse tree.
+ */
function ParseNode(type, value, mode) {
this.type = type;
this.value = value;
this.mode = mode;
}
-// A result and final position returned by the `.parse...` functions.
+/**
+ * A result and final position returned by the `.parse...` functions.
+ */
function ParseResult(result, newPosition) {
this.result = result;
this.position = newPosition;
}
-// An initial function (without its arguments), or an argument to a function.
-// The `result` argument should be a ParseResult.
+/**
+ * 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, argTypes) {
this.result = result;
// Is this a function (i.e. is it something defined in functions.js)?
@@ -71,8 +81,10 @@ function ParseFuncOrArgument(result, isFunction, allowedInText, numArgs, argType
this.argTypes = argTypes;
}
-// Checks a result to make sure it has the right type, and throws an
-// appropriate error otherwise.
+/**
+ * Checks a result to make sure it has the right type, and throws an
+ * appropriate error otherwise.
+ */
Parser.prototype.expect = function(result, type) {
if (result.type !== type) {
throw new ParseError(
@@ -82,15 +94,20 @@ Parser.prototype.expect = function(result, type) {
}
};
-// Main parsing function, which parses an entire input. Returns either a list
-// of parseNodes or null if the parse fails.
+/**
+ * Main parsing function, which parses an entire input.
+ *
+ * @return {?Array.<ParseNode>}
+ */
Parser.prototype.parse = function(input) {
// Try to parse the input
var parse = this.parseInput(0, "math");
return parse.result;
};
-// Parses an entire input tree
+/**
+ * Parses an entire input tree.
+ */
Parser.prototype.parseInput = function(pos, mode) {
// Parse an expression
var expression = this.parseExpression(pos, mode);
@@ -100,7 +117,9 @@ Parser.prototype.parseInput = function(pos, mode) {
return expression;
};
-// Handles a body of an expression
+/**
+ * Handles a body of an expression.
+ */
Parser.prototype.handleExpressionBody = function(pos, mode) {
var body = [];
var atom;
@@ -116,9 +135,11 @@ Parser.prototype.handleExpressionBody = function(pos, mode) {
};
};
-// Parses an "expression", which is a list of atoms
-//
-// Returns ParseResult
+/**
+ * Parses an "expression", which is a list of atoms.
+ *
+ * @return {ParseResult}
+ */
Parser.prototype.parseExpression = function(pos, mode) {
var body = this.handleExpressionBody(pos, mode);
return new ParseResult(body.body, body.position);
@@ -127,7 +148,9 @@ Parser.prototype.parseExpression = function(pos, mode) {
// The greediness of a superscript or subscript
var SUPSUB_GREEDINESS = 1;
-// Handle a subscript or superscript with nice errors
+/**
+ * Handle a subscript or superscript with nice errors.
+ */
Parser.prototype.handleSupSubscript = function(pos, mode, symbol, name) {
var group = this.parseGroup(pos, mode);
@@ -151,9 +174,11 @@ Parser.prototype.handleSupSubscript = function(pos, mode, symbol, name) {
}
};
-// Parses a group with optional super/subscripts
-//
-// Returns ParseResult or null
+/**
+ * Parses a group with optional super/subscripts.
+ *
+ * @return {?ParseResult}
+ */
Parser.prototype.parseAtom = function(pos, mode) {
// The body of an atom is an implicit group, so that things like
// \left(x\right)^2 work correctly.
@@ -247,15 +272,17 @@ var styleFuncs = [
"\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle"
];
-// Parses an implicit group, which is a group that starts at the end of a
-// specified, and ends right before a higher explicit group ends, or at EOL. It
-// is used for functions that appear to affect the current style, like \Large or
-// \textrm, where instead of keeping a style we just pretend that there is an
-// implicit grouping after it until the end of the group. E.g.
-// small text {\Large large text} small text again
-// It is also used for \left and \right to get the correct grouping.
-//
-// Returns ParseResult or null
+/**
+ * Parses an implicit group, which is a group that starts at the end of a
+ * specified, and ends right before a higher explicit group ends, or at EOL. It
+ * is used for functions that appear to affect the current style, like \Large or
+ * \textrm, where instead of keeping a style we just pretend that there is an
+ * implicit grouping after it until the end of the group. E.g.
+ * small text {\Large large text} small text again
+ * It is also used for \left and \right to get the correct grouping.
+ *
+ * @return {?ParseResult}
+ */
Parser.prototype.parseImplicitGroup = function(pos, mode) {
var start = this.parseSymbol(pos, mode);
@@ -320,9 +347,11 @@ Parser.prototype.parseImplicitGroup = function(pos, mode) {
}
};
-// Parses an entire function, including its base and all of its arguments
-//
-// Returns ParseResult or null
+/**
+ * Parses an entire function, including its base and all of its arguments
+ *
+ * @return {?ParseResult}
+ */
Parser.prototype.parseFunction = function(pos, mode) {
var baseGroup = this.parseGroup(pos, mode);
@@ -392,10 +421,12 @@ Parser.prototype.parseFunction = function(pos, mode) {
}
};
-// Parses a group when the mode is changing. Takes a position, a new mode, and
-// an outer mode that is used to parse the outside.
-//
-// Returns a ParseFuncOrArgument or null
+/**
+ * Parses a group when the mode is changing. Takes a position, a new mode, and
+ * an outer mode that is used to parse the outside.
+ *
+ * @return {?ParseFuncOrArgument}
+ */
Parser.prototype.parseSpecialGroup = function(pos, mode, outerMode) {
if (mode === "color" || mode === "size") {
// color and size modes are special because they should have braces and
@@ -420,10 +451,12 @@ Parser.prototype.parseSpecialGroup = function(pos, mode, outerMode) {
}
};
-// Parses a group, which is either a single nucleus (like "x") or an expression
-// in braces (like "{x+y}")
-//
-// Returns a ParseFuncOrArgument or null
+/**
+ * Parses a group, which is either a single nucleus (like "x") or an expression
+ * in braces (like "{x+y}")
+ *
+ * @return {?ParseFuncOrArgument}
+ */
Parser.prototype.parseGroup = function(pos, mode) {
var start = this.lexer.lex(pos, mode);
// Try to parse an open brace
@@ -444,10 +477,12 @@ Parser.prototype.parseGroup = function(pos, mode) {
}
};
-// Parse a single symbol out of the string. Here, we handle both the functions
-// we have defined, as well as the single character symbols
-//
-// Returns a ParseFuncOrArgument or null
+/**
+ * Parse a single symbol out of the string. Here, we handle both the functions
+ * we have defined, as well as the single character symbols
+ *
+ * @return {?ParseFuncOrArgument}
+ */
Parser.prototype.parseSymbol = function(pos, mode) {
var nucleus = this.lexer.lex(pos, mode);
diff --git a/Style.js b/Style.js
@@ -1,3 +1,17 @@
+/**
+ * This file contains information and classes for the various kinds of styles
+ * used in TeX. It provides a generic `Style` class, which holds information
+ * about a specific style. It then provides instances of all the different kinds
+ * of styles possible, and provides functions to move between them and get
+ * information about them.
+ */
+
+/**
+ * The main style class. Contains a unique id for the style, a size (which is
+ * the same for cramped and uncramped version of a style), a cramped flag, and a
+ * size multiplier, which gives the size difference between a style and
+ * textstyle.
+ */
function Style(id, size, multiplier, cramped) {
this.id = id;
this.size = size;
@@ -5,36 +19,59 @@ function Style(id, size, multiplier, cramped) {
this.sizeMultiplier = multiplier;
}
+/**
+ * Get the style of a superscript given a base in the current style.
+ */
Style.prototype.sup = function() {
return styles[sup[this.id]];
};
+/**
+ * Get the style of a subscript given a base in the current style.
+ */
Style.prototype.sub = function() {
return styles[sub[this.id]];
};
+/**
+ * Get the style of a fraction numerator given the fraction in the current
+ * style.
+ */
Style.prototype.fracNum = function() {
return styles[fracNum[this.id]];
};
+/**
+ * Get the style of a fraction denominator given the fraction in the current
+ * style.
+ */
Style.prototype.fracDen = function() {
return styles[fracDen[this.id]];
};
+/**
+ * Get the cramped version of a style (in particular, cramping a cramped style
+ * doesn't change the style).
+ */
Style.prototype.cramp = function() {
return styles[cramp[this.id]];
};
-// HTML class name, like "displaystyle cramped"
+/**
+ * HTML class name, like "displaystyle cramped"
+ */
Style.prototype.cls = function() {
return sizeNames[this.size] + (this.cramped ? " cramped" : " uncramped");
};
-// HTML Reset class name, like "reset-textstyle"
+/**
+ * HTML Reset class name, like "reset-textstyle"
+ */
Style.prototype.reset = function() {
return resetNames[this.size];
};
+// IDs of the different styles
var D = 0;
var Dc = 1;
var T = 2;
@@ -44,6 +81,7 @@ var Sc = 5;
var SS = 6;
var SSc = 7;
+// String names for the different sizes
var sizeNames = [
"displaystyle textstyle",
"textstyle",
@@ -51,6 +89,7 @@ var sizeNames = [
"scriptscriptstyle"
];
+// Reset names for the different sizes
var resetNames = [
"reset-textstyle",
"reset-textstyle",
@@ -58,6 +97,7 @@ var resetNames = [
"reset-scriptscriptstyle",
];
+// Instances of the different styles
var styles = [
new Style(D, 0, 1.0, false),
new Style(Dc, 0, 1.0, true),
@@ -69,12 +109,15 @@ var styles = [
new Style(SSc, 3, 0.5, true)
];
+// Lookup tables for switching from one style to another
var sup = [S, Sc, S, Sc, SS, SSc, SS, SSc];
var sub = [Sc, Sc, Sc, Sc, SSc, SSc, SSc, SSc];
var fracNum = [T, Tc, S, Sc, SS, SSc, SS, SSc];
var fracDen = [Tc, Tc, Sc, Sc, SSc, SSc, SSc, SSc];
var cramp = [Dc, Dc, Tc, Tc, Sc, Sc, SSc, SSc];
+// We only export some of the styles. Also, we don't export the `Style` class so
+// no more styles can be generated.
module.exports = {
DISPLAY: styles[D],
TEXT: styles[T],
diff --git a/buildCommon.js b/buildCommon.js
@@ -1,8 +1,19 @@
+/**
+ * This module contains general functions that can be used for building
+ * different kinds of domTree nodes in a consistent manner.
+ */
+
var domTree = require("./domTree");
var fontMetrics = require("./fontMetrics");
var symbols = require("./symbols");
+/**
+ * Makes a symbolNode after translation via the list of symbols in symbols.js.
+ * Correctly pulls out metrics for the character, and optionally takes a list of
+ * classes to be attached to the node.
+ */
var makeSymbol = function(value, style, mode, color, classes) {
+ // Replace the value with its replaced value from symbol.js
if (symbols[mode][value] && symbols[mode][value].replace) {
value = symbols[mode][value].replace;
}
@@ -15,8 +26,10 @@ var makeSymbol = function(value, style, mode, color, classes) {
value, metrics.height, metrics.depth, metrics.italic, metrics.skew,
classes);
} else {
- console && console.warn("No character metrics for '" + value +
- "' in style '" + style + "'");
+ // TODO(emily): Figure out a good way to only print this in development
+ typeof console !== "undefined" && console.warn(
+ "No character metrics for '" + value + "' in style '" +
+ style + "'");
symbolNode = new domTree.symbolNode(value, 0, 0, 0, 0, classes);
}
@@ -27,12 +40,20 @@ var makeSymbol = function(value, style, mode, color, classes) {
return symbolNode;
};
+/**
+ * Makes a symbol in the italic math font.
+ */
var mathit = function(value, mode, color, classes) {
return makeSymbol(
value, "Math-Italic", mode, color, classes.concat(["mathit"]));
};
+/**
+ * Makes a symbol in the upright roman font.
+ */
var mathrm = function(value, mode, color, classes) {
+ // Decide what font to render the symbol in by its entry in the symbols
+ // table.
if (symbols[mode][value].font === "main") {
return makeSymbol(value, "Main-Regular", mode, color, classes);
} else {
@@ -41,6 +62,10 @@ var mathrm = function(value, mode, color, classes) {
}
};
+/**
+ * Calculate the height, depth, and maxFontSize of an element based on its
+ * children.
+ */
var sizeElementFromChildren = function(elem) {
var height = 0;
var depth = 0;
@@ -65,6 +90,9 @@ var sizeElementFromChildren = function(elem) {
elem.maxFontSize = maxFontSize;
};
+/**
+ * Makes a span with the given list of classes, list of children, and color.
+ */
var makeSpan = function(classes, children, color) {
var span = new domTree.span(classes, children);
@@ -77,6 +105,9 @@ var makeSpan = function(classes, children, color) {
return span;
};
+/**
+ * Makes a document fragment with the given list of children.
+ */
var makeFragment = function(children) {
var fragment = new domTree.documentFragment(children);
@@ -85,6 +116,11 @@ var makeFragment = function(children) {
return fragment;
};
+/**
+ * Makes an element placed in each of the vlist elements to ensure that each
+ * element has the same max font size. To do this, we create a zero-width space
+ * with the correct font size.
+ */
var makeFontSizer = function(options, fontSize) {
var fontSizeInner = makeSpan([], [new domTree.symbolNode("\u200b")]);
fontSizeInner.style.fontSize = (fontSize / options.style.sizeMultiplier) + "em";
@@ -96,7 +132,7 @@ var makeFontSizer = function(options, fontSize) {
return fontSizer;
};
-/*
+/**
* Makes a vertical list by stacking elements and kerns on top of each other.
* Allows for many different ways of specifying the positioning method.
*
@@ -229,6 +265,5 @@ module.exports = {
mathrm: mathrm,
makeSpan: makeSpan,
makeFragment: makeFragment,
- makeFontSizer: makeFontSizer,
makeVList: makeVList
};
diff --git a/buildTree.js b/buildTree.js
@@ -1,3 +1,10 @@
+/**
+ * This file does the main work of building a domTree sturcture from a parse
+ * tree. The entry point is the `buildTree` function, which takes a parse tree.
+ * Then, the buildExpression, buildGroup, and various groupTypes functions are
+ * called, to produce a final tree.
+ */
+
var Options = require("./Options");
var ParseError = require("./ParseError");
var Style = require("./Style");
@@ -12,6 +19,11 @@ var utils = require("./utils");
var makeSpan = buildCommon.makeSpan;
+/**
+ * Take a list of nodes, build them in order, and return a list of the built
+ * nodes. This function handles the `prev` node correctly, and passes the
+ * previous element from the list as the prev of the next element.
+ */
var buildExpression = function(expression, options, prev) {
var groups = [];
for (var i = 0; i < expression.length; i++) {
@@ -22,6 +34,7 @@ var buildExpression = function(expression, options, prev) {
return groups;
};
+// List of types used by getTypeOfGroup
var groupToType = {
mathord: "mord",
textord: "mord",
@@ -44,6 +57,20 @@ var groupToType = {
accent: "mord"
};
+/**
+ * Gets the final math type of an expression, given its group type. This type is
+ * used to determine spacing between elements, and affects bin elements by
+ * causing them to change depending on what types are around them. This type
+ * must be attached to the outermost node of an element as a CSS class so that
+ * spacing with its surrounding elements works correctly.
+ *
+ * Some elements can be mapped one-to-one from group type to math type, and
+ * those are listed in the `groupToType` table.
+ *
+ * Others (usually elements that wrap around other elements) often have
+ * recursive definitions, and thus call `getTypeOfGroup` on their inner
+ * elements.
+ */
var getTypeOfGroup = function(group) {
if (group == null) {
// Like when typesetting $^3$
@@ -65,11 +92,19 @@ var getTypeOfGroup = function(group) {
}
};
+/**
+ * Sometimes, groups perform special rules when they have superscripts or
+ * subscripts attached to them. This function lets the `supsub` group know that
+ * its inner element should handle the superscripts and subscripts instead of
+ * handling them itself.
+ */
var shouldHandleSupSub = function(group, options) {
if (group == null) {
return false;
} else if (group.type === "op") {
- return group.value.limits && options.style.id === Style.DISPLAY.id;
+ // Operators handle supsubs differently when they have limits
+ // (e.g. `\displaystyle\sum_2^3`)
+ return group.value.limits && options.style.size === Style.DISPLAY.size;
} else if (group.type === "accent") {
return isCharacterBox(group.value.base);
} else {
@@ -77,6 +112,11 @@ var shouldHandleSupSub = function(group, options) {
}
};
+/**
+ * Sometimes we want to pull out the innermost element of a group. In most
+ * cases, this will just be the group itself, but when ordgroups and colors have
+ * a single element, we want to pull that out.
+ */
var getBaseElem = function(group) {
if (group == null) {
return false;
@@ -97,18 +137,29 @@ var getBaseElem = function(group) {
}
};
+/**
+ * TeXbook algorithms often reference "character boxes", which are simply groups
+ * with a single character in them. To decide if something is a character box,
+ * we find its innermost group, and see if it is a single character.
+ */
var isCharacterBox = function(group) {
var baseElem = getBaseElem(group);
+ // These are all they types of groups which hold single characters
return baseElem.type === "mathord" ||
baseElem.type === "textord" ||
baseElem.type === "bin" ||
baseElem.type === "rel" ||
+ baseElem.type === "inner" ||
baseElem.type === "open" ||
baseElem.type === "close" ||
baseElem.type === "punct";
};
+/**
+ * This is a map of group types to the function used to handle that type.
+ * Simpler types come at the beginning, while complicated types come afterwards.
+ */
var groupTypes = {
mathord: function(group, options, prev) {
return buildCommon.mathit(
@@ -122,11 +173,17 @@ var groupTypes = {
bin: function(group, options, prev) {
var className = "mbin";
+ // Pull out the most recent element. Do some special handling to find
+ // things at the end of a \color group. Note that we don't use the same
+ // logic for ordgroups (which count as ords).
var prevAtom = prev;
while (prevAtom && prevAtom.type == "color") {
var atoms = prevAtom.value.value;
prevAtom = atoms[atoms.length - 1];
}
+ // See TeXbook pg. 442-446, Rules 5 and 6, and the text before Rule 19.
+ // Here, we determine whether the bin should turn into an ord. We
+ // currently only apply Rule 5.
if (!prev || utils.contains(["mbin", "mopen", "mrel", "mop", "mpunct"],
getTypeOfGroup(prevAtom))) {
group.type = "textord";
@@ -142,14 +199,59 @@ var groupTypes = {
group.value, group.mode, options.getColor(), ["mrel"]);
},
+ open: function(group, options, prev) {
+ return buildCommon.mathrm(
+ group.value, group.mode, options.getColor(), ["mopen"]);
+ },
+
+ close: function(group, options, prev) {
+ return buildCommon.mathrm(
+ group.value, group.mode, options.getColor(), ["mclose"]);
+ },
+
+ inner: function(group, options, prev) {
+ return buildCommon.mathrm(
+ group.value, group.mode, options.getColor(), ["minner"]);
+ },
+
+ punct: function(group, options, prev) {
+ return buildCommon.mathrm(
+ group.value, group.mode, options.getColor(), ["mpunct"]);
+ },
+
+ ordgroup: function(group, options, prev) {
+ return makeSpan(
+ ["mord", options.style.cls()],
+ buildExpression(group.value, options.reset())
+ );
+ },
+
text: function(group, options, prev) {
return makeSpan(["text", "mord", options.style.cls()],
buildExpression(group.value.body, options.reset()));
},
+ color: function(group, options, prev) {
+ var elements = buildExpression(
+ group.value.value,
+ options.withColor(group.value.color),
+ prev
+ );
+
+ // \color isn't supposed to affect the type of the elements it contains.
+ // To accomplish this, we wrap the results in a fragment, so the inner
+ // elements will be able to directly interact with their neighbors. For
+ // example, `\color{red}{2 +} 3` has the same spacing as `2 + 3`
+ return new buildCommon.makeFragment(elements);
+ },
+
supsub: function(group, options, prev) {
+ // Superscript and subscripts are handled in the TeXbook on page
+ // 445-446, rules 18(a-f).
var baseGroup = group.value.base;
+ // Here is where we defer to the inner group if it should handle
+ // superscripts and subscripts itself.
if (shouldHandleSupSub(group.value.base, options)) {
return groupTypes[group.value.base.type](group, options, prev);
}
@@ -170,77 +272,90 @@ var groupTypes = {
[options.style.reset(), options.style.sub().cls()], [sub]);
}
- var u, v;
+ // Rule 18a
+ var supShift, subShift;
if (isCharacterBox(group.value.base)) {
- u = 0;
- v = 0;
+ supShift = 0;
+ subShift = 0;
} else {
- u = base.height - fontMetrics.metrics.supDrop;
- v = base.depth + fontMetrics.metrics.subDrop;
+ supShift = base.height - fontMetrics.metrics.supDrop;
+ subShift = base.depth + fontMetrics.metrics.subDrop;
}
- var p;
+ // Rule 18c
+ var minSupShift;
if (options.style === Style.DISPLAY) {
- p = fontMetrics.metrics.sup1;
+ minSupShift = fontMetrics.metrics.sup1;
} else if (options.style.cramped) {
- p = fontMetrics.metrics.sup3;
+ minSupShift = fontMetrics.metrics.sup3;
} else {
- p = fontMetrics.metrics.sup2;
+ minSupShift = fontMetrics.metrics.sup2;
}
+ // scriptspace is a font-size-independent size, so scale it
+ // appropriately
var multiplier = Style.TEXT.sizeMultiplier *
options.style.sizeMultiplier;
var scriptspace =
(0.5 / fontMetrics.metrics.ptPerEm) / multiplier + "em";
var supsub;
-
if (!group.value.sup) {
- v = Math.max(v, fontMetrics.metrics.sub1,
+ // Rule 18b
+ subShift = Math.max(
+ subShift, fontMetrics.metrics.sub1,
sub.height - 0.8 * fontMetrics.metrics.xHeight);
supsub = buildCommon.makeVList([
{type: "elem", elem: submid}
- ], "shift", v, options);
+ ], "shift", subShift, options);
supsub.children[0].style.marginRight = scriptspace;
+ // Subscripts shouldn't be shifted by the base's italic correction.
+ // Account for that by shifting the subscript back the appropriate
+ // amount. Note we only do this when the base is a single symbol.
if (base instanceof domTree.symbolNode) {
supsub.children[0].style.marginLeft = -base.italic + "em";
}
} else if (!group.value.sub) {
- u = Math.max(u, p,
+ // Rule 18c, d
+ supShift = Math.max(supShift, minSupShift,
sup.depth + 0.25 * fontMetrics.metrics.xHeight);
supsub = buildCommon.makeVList([
{type: "elem", elem: supmid}
- ], "shift", -u, options);
+ ], "shift", -supShift, options);
supsub.children[0].style.marginRight = scriptspace;
} else {
- u = Math.max(u, p,
+ supShift = Math.max(
+ supShift, minSupShift,
sup.depth + 0.25 * fontMetrics.metrics.xHeight);
- v = Math.max(v, fontMetrics.metrics.sub2);
+ subShift = Math.max(subShift, fontMetrics.metrics.sub2);
- var theta = fontMetrics.metrics.defaultRuleThickness;
+ var ruleWidth = fontMetrics.metrics.defaultRuleThickness;
- if ((u - sup.depth) - (sub.height - v) < 4 * theta) {
- v = 4 * theta - (u - sup.depth) + sub.height;
- var psi = 0.8 * fontMetrics.metrics.xHeight - (u - sup.depth);
+ // Rule 18e
+ if ((supShift - sup.depth) - (sub.height - subShift) <
+ 4 * ruleWidth) {
+ subShift = 4 * ruleWidth - (supShift - sup.depth) + sub.height;
+ var psi = 0.8 * fontMetrics.metrics.xHeight -
+ (supShift - sup.depth);
if (psi > 0) {
- u += psi;
- v -= psi;
+ supShift += psi;
+ subShift -= psi;
}
}
supsub = buildCommon.makeVList([
- {type: "elem", elem: submid, shift: v},
- {type: "elem", elem: supmid, shift: -u}
+ {type: "elem", elem: submid, shift: subShift},
+ {type: "elem", elem: supmid, shift: -supShift}
], "individualShift", null, options);
+ // See comment above about subscripts not being shifted
if (base instanceof domTree.symbolNode) {
- supsub.children[1].style.marginLeft = base.italic + "em";
- base.italic = 0;
+ supsub.children[0].style.marginLeft = -base.italic + "em";
}
supsub.children[0].style.marginRight = scriptspace;
@@ -251,22 +366,10 @@ var groupTypes = {
[base, supsub]);
},
- open: function(group, options, prev) {
- return buildCommon.mathrm(
- group.value, group.mode, options.getColor(), ["mopen"]);
- },
-
- close: function(group, options, prev) {
- return buildCommon.mathrm(
- group.value, group.mode, options.getColor(), ["mclose"]);
- },
-
- inner: function(group, options, prev) {
- return buildCommon.mathrm(
- group.value, group.mode, options.getColor(), ["minner"]);
- },
-
frac: function(group, options, prev) {
+ // Fractions are handled in the TeXbook on pages 444-445, rules 15(a-e).
+ // Figure out what style this fraction should be in based on the
+ // function used
var fstyle = options.style;
if (group.value.size === "dfrac") {
fstyle = Style.DISPLAY;
@@ -283,40 +386,54 @@ var groupTypes = {
var denom = buildGroup(group.value.denom, options.withStyle(dstyle));
var denomreset = makeSpan([fstyle.reset(), dstyle.cls()], [denom])
- var theta = fontMetrics.metrics.defaultRuleThickness / options.style.sizeMultiplier;
+ var ruleWidth = fontMetrics.metrics.defaultRuleThickness /
+ options.style.sizeMultiplier;
- var mid = makeSpan([options.style.reset(), Style.TEXT.cls(), "frac-line"]);
- mid.height = theta;
+ var mid = makeSpan(
+ [options.style.reset(), Style.TEXT.cls(), "frac-line"]);
+ // Manually set the height of the line because its height is created in
+ // CSS
+ mid.height = ruleWidth;
- var u, v, phi;
+ // Rule 15b, 15d
+ var numShift, denomShift, clearance;
if (fstyle.size === Style.DISPLAY.size) {
- u = fontMetrics.metrics.num1;
- v = fontMetrics.metrics.denom1;
- phi = 3 * theta;
+ numShift = fontMetrics.metrics.num1;
+ denomShift = fontMetrics.metrics.denom1;
+ clearance = 3 * ruleWidth;
} else {
- u = fontMetrics.metrics.num2;
- v = fontMetrics.metrics.denom2;
- phi = theta;
+ numShift = fontMetrics.metrics.num2;
+ denomShift = fontMetrics.metrics.denom2;
+ clearance = ruleWidth;
}
- var a = fontMetrics.metrics.axisHeight;
+ var axisHeight = fontMetrics.metrics.axisHeight;
- if ((u - numer.depth) - (a + 0.5 * theta) < phi) {
- u += phi - ((u - numer.depth) - (a + 0.5 * theta));
+ // Rule 15d
+ if ((numShift - numer.depth) - (axisHeight + 0.5 * ruleWidth)
+ < clearance) {
+ numShift +=
+ clearance - ((numShift - numer.depth) -
+ (axisHeight + 0.5 * ruleWidth));
}
- if ((a - 0.5 * theta) - (denom.height - v) < phi) {
- v += phi - ((a - 0.5 * theta) - (denom.height - v));
+ if ((axisHeight - 0.5 * ruleWidth) - (denom.height - denomShift)
+ < clearance) {
+ denomShift +=
+ clearance - ((axisHeight - 0.5 * ruleWidth) -
+ (denom.height - denomShift));
}
- var midShift = -(a - 0.5 * theta);
+ var midShift = -(axisHeight - 0.5 * ruleWidth);
var frac = buildCommon.makeVList([
- {type: "elem", elem: denomreset, shift: v},
+ {type: "elem", elem: denomreset, shift: denomShift},
{type: "elem", elem: mid, shift: midShift},
- {type: "elem", elem: numerreset, shift: -u}
+ {type: "elem", elem: numerreset, shift: -numShift}
], "individualShift", null, options);
+ // Since we manually change the style sometimes (with \dfrac or \tfrac),
+ // account for the possible size change here.
frac.height *= fstyle.sizeMultiplier / options.style.sizeMultiplier;
frac.depth *= fstyle.sizeMultiplier / options.style.sizeMultiplier;
@@ -325,24 +442,19 @@ var groupTypes = {
[frac], options.getColor());
},
- color: function(group, options, prev) {
- var elements = buildExpression(
- group.value.value,
- options.withColor(group.value.color),
- prev
- );
-
- return new buildCommon.makeFragment(elements);
- },
-
spacing: function(group, options, prev) {
if (group.value === "\\ " || group.value === "\\space" ||
group.value === " " || group.value === "~") {
+ // Spaces are generated by adding an actual space. Each of these
+ // things has an entry in the symbols table, so these will be turned
+ // into appropriate outputs.
return makeSpan(
["mord", "mspace"],
[buildCommon.mathrm(group.value, group.mode)]
);
} else {
+ // Other kinds of spaces are of arbitrary width. We use CSS to
+ // generate these.
var spacingClassMap = {
"\\qquad": "qquad",
"\\quad": "quad",
@@ -374,23 +486,15 @@ var groupTypes = {
["rlap", options.style.cls()], [inner, fix]);
},
- punct: function(group, options, prev) {
- return buildCommon.mathrm(
- group.value, group.mode, options.getColor(), ["mpunct"]);
- },
-
- ordgroup: function(group, options, prev) {
- return makeSpan(
- ["mord", options.style.cls()],
- buildExpression(group.value, options.reset())
- );
- },
-
op: function(group, options, prev) {
+ // Operators are handled in the TeXbook pg. 443-444, rule 13(a).
var supGroup;
var subGroup;
var hasLimits = false;
if (group.type === "supsub" ) {
+ // If we have limits, supsub will pass us its group to handle. Pull
+ // out the superscript and subscript and set the group to the op in
+ // its base.
supGroup = group.value.sup;
subGroup = group.value.sub;
group = group.value.base;
@@ -403,29 +507,40 @@ var groupTypes = {
];
var large = false;
-
- if (options.style.id === Style.DISPLAY.id &&
+ if (options.style.size === Style.DISPLAY.size &&
group.value.symbol &&
!utils.contains(noSuccessor, group.value.body)) {
- // Make symbols larger in displaystyle, except for smallint
+ // Most symbol operators get larger in displaystyle (rule 13)
large = true;
}
var base;
var baseShift = 0;
- var delta = 0;
+ var slant = 0;
if (group.value.symbol) {
+ // If this is a symbol, create the symbol.
var style = large ? "Size2-Regular" : "Size1-Regular";
base = buildCommon.makeSymbol(
group.value.body, style, "math", options.getColor(),
["op-symbol", large ? "large-op" : "small-op", "mop"]);
+ // Shift the symbol so its center lies on the axis (rule 13). It
+ // appears that our fonts have the centers of the symbols already
+ // almost on the axis, so these numbers are very small. Note we
+ // don't actually apply this here, but instead it is used either in
+ // the vlist creation or separately when there are no limits.
baseShift = (base.height - base.depth) / 2 -
fontMetrics.metrics.axisHeight *
options.style.sizeMultiplier;
- delta = base.italic;
+
+ // The slant of the symbol is just its italic correction.
+ slant = base.italic;
} else {
+ // Otherwise, this is a text operator. Build the text from the
+ // operator's name.
+ // TODO(emily): Add a space in the middle of some of these
+ // operators, like \limsup
var output = [];
for (var i = 1; i < group.value.body.length; i++) {
output.push(buildCommon.mathrm(group.value.body[i], group.mode));
@@ -438,28 +553,34 @@ var groupTypes = {
// in a new span so it is an inline, and works.
var base = makeSpan([], [base]);
+ var supmid, supKern, submid, subKern;
+ // We manually have to handle the superscripts and subscripts. This,
+ // aside from the kern calculations, is copied from supsub.
if (supGroup) {
- var sup = buildGroup(supGroup,
- options.withStyle(options.style.sup()));
- var supmid = makeSpan(
+ var sup = buildGroup(
+ supGroup, options.withStyle(options.style.sup()));
+ supmid = makeSpan(
[options.style.reset(), options.style.sup().cls()], [sup]);
- var supKern = Math.max(
+ supKern = Math.max(
fontMetrics.metrics.bigOpSpacing1,
fontMetrics.metrics.bigOpSpacing3 - sup.depth);
}
if (subGroup) {
- var sub = buildGroup(subGroup,
- options.withStyle(options.style.sub()));
- var submid = makeSpan(
- [options.style.reset(), options.style.sub().cls()], [sub]);
+ var sub = buildGroup(
+ subGroup, options.withStyle(options.style.sub()));
+ submid = makeSpan(
+ [options.style.reset(), options.style.sub().cls()],
+ [sub]);
- var subKern = Math.max(
+ subKern = Math.max(
fontMetrics.metrics.bigOpSpacing2,
fontMetrics.metrics.bigOpSpacing4 - sub.height);
}
+ // Build the final group as a vlist of the possible subscript, base,
+ // and possible superscript.
var finalGroup;
if (!supGroup) {
var top = base.height - baseShift;
@@ -471,7 +592,11 @@ var groupTypes = {
{type: "elem", elem: base}
], "top", top, options);
- finalGroup.children[0].style.marginLeft = -delta + "em";
+ // Here, we shift the limits by the slant of the symbol. Note
+ // that we are supposed to shift the limits by 1/2 of the slant,
+ // but since we are centering the limits adding a full slant of
+ // margin will shift by 1/2 that.
+ finalGroup.children[0].style.marginLeft = -slant + "em";
} else if (!subGroup) {
var bottom = base.depth + baseShift;
@@ -482,8 +607,12 @@ var groupTypes = {
{type: "kern", size: fontMetrics.metrics.bigOpSpacing5}
], "bottom", bottom, options);
- finalGroup.children[1].style.marginLeft = delta + "em";
+ // See comment above about slants
+ finalGroup.children[1].style.marginLeft = slant + "em";
} else if (!supGroup && !subGroup) {
+ // This case probably shouldn't occur (this would mean the
+ // supsub was sending us a group with no superscript or
+ // subscript) but be safe.
return base;
} else {
var bottom = fontMetrics.metrics.bigOpSpacing5 +
@@ -501,8 +630,9 @@ var groupTypes = {
{type: "kern", size: fontMetrics.metrics.bigOpSpacing5}
], "bottom", bottom, options);
- finalGroup.children[0].style.marginLeft = -delta + "em";
- finalGroup.children[2].style.marginLeft = delta + "em";
+ // See comment above about slants
+ finalGroup.children[0].style.marginLeft = -slant + "em";
+ finalGroup.children[2].style.marginLeft = slant + "em";
}
return makeSpan(["mop", "op-limits"], [finalGroup]);
@@ -516,6 +646,9 @@ var groupTypes = {
},
katex: function(group, options, prev) {
+ // The KaTeX logo. The offsets for the K and a were chosen to look
+ // good, but the offsets for the T, E, and X were taken from the
+ // definition of \TeX in TeX (see TeXbook pg. 356)
var k = makeSpan(
["k"], [buildCommon.mathrm("K", group.mode)]);
var a = makeSpan(
@@ -539,42 +672,78 @@ var groupTypes = {
["katex-logo"], [k, a, t, e, x], options.getColor());
},
+ overline: function(group, options, prev) {
+ // Overlines are handled in the TeXbook pg 443, Rule 9.
+
+ // Build the inner group in the cramped style.
+ var innerGroup = buildGroup(group.value.body,
+ options.withStyle(options.style.cramp()));
+
+ var ruleWidth = fontMetrics.metrics.defaultRuleThickness /
+ options.style.sizeMultiplier;
+
+ // Create the line above the body
+ var line = makeSpan(
+ [options.style.reset(), Style.TEXT.cls(), "overline-line"]);
+ line.height = ruleWidth;
+ line.maxFontSize = 1.0;
+
+ // Generate the vlist, with the appropriate kerns
+ var vlist = buildCommon.makeVList([
+ {type: "elem", elem: innerGroup},
+ {type: "kern", size: 3 * ruleWidth},
+ {type: "elem", elem: line},
+ {type: "kern", size: ruleWidth}
+ ], "firstBaseline", null, options);
+
+ return makeSpan(["overline", "mord"], [vlist], options.getColor());
+ },
+
sqrt: function(group, options, prev) {
+ // Square roots are handled in the TeXbook pg. 443, Rule 11.
+
+ // First, we do the same steps as in overline to build the inner group
+ // and line
var inner = buildGroup(group.value.body,
options.withStyle(options.style.cramp()));
- var theta = fontMetrics.metrics.defaultRuleThickness /
+ var ruleWidth = fontMetrics.metrics.defaultRuleThickness /
options.style.sizeMultiplier;
var line = makeSpan(
[options.style.reset(), Style.TEXT.cls(), "sqrt-line"], [],
options.getColor());
- line.height = theta;
+ line.height = ruleWidth;
line.maxFontSize = 1.0;
- var phi = theta;
+ var phi = ruleWidth;
if (options.style.id < Style.TEXT.id) {
phi = fontMetrics.metrics.xHeight;
}
- var psi = theta + phi / 4;
+ // Calculate the clearance between the body and line
+ var lineClearance = ruleWidth + phi / 4;
var innerHeight =
(inner.height + inner.depth) * options.style.sizeMultiplier;
- var minDelimiterHeight = innerHeight + psi + theta;
+ var minDelimiterHeight = innerHeight + lineClearance + ruleWidth;
+ // Create a \surd delimiter of the required minimum size
var delim = makeSpan(["sqrt-sign"], [
delimiter.customSizedDelim("\\surd", minDelimiterHeight,
false, options, group.mode)],
options.getColor());
- var delimDepth = (delim.height + delim.depth) - theta;
+ var delimDepth = (delim.height + delim.depth) - ruleWidth;
- if (delimDepth > inner.height + inner.depth + psi) {
- psi = (psi + delimDepth - inner.height - inner.depth) / 2;
+ // Adjust the clearance based on the delimiter size
+ if (delimDepth > inner.height + inner.depth + lineClearance) {
+ lineClearance =
+ (lineClearance + delimDepth - inner.height - inner.depth) / 2;
}
- delimShift = -(inner.height + psi + theta) + delim.height;
+ // Shift the delimiter so that its top lines up with the top of the line
+ delimShift = -(inner.height + lineClearance + ruleWidth) + delim.height;
delim.style.top = delimShift + "em";
delim.height -= delimShift;
delim.depth += delimShift;
@@ -590,38 +759,19 @@ var groupTypes = {
} else {
body = buildCommon.makeVList([
{type: "elem", elem: inner},
- {type: "kern", size: psi},
+ {type: "kern", size: lineClearance},
{type: "elem", elem: line},
- {type: "kern", size: theta}
+ {type: "kern", size: ruleWidth}
], "firstBaseline", null, options);
}
return makeSpan(["sqrt", "mord"], [delim, body]);
},
- overline: function(group, options, prev) {
- var innerGroup = buildGroup(group.value.body,
- options.withStyle(options.style.cramp()));
-
- var theta = fontMetrics.metrics.defaultRuleThickness /
- options.style.sizeMultiplier;
-
- var line = makeSpan(
- [options.style.reset(), Style.TEXT.cls(), "overline-line"]);
- line.height = theta;
- line.maxFontSize = 1.0;
-
- var vlist = buildCommon.makeVList([
- {type: "elem", elem: innerGroup},
- {type: "kern", size: 3 * theta},
- {type: "elem", elem: line},
- {type: "kern", size: theta}
- ], "firstBaseline", null, options);
-
- return makeSpan(["overline", "mord"], [vlist], options.getColor());
- },
-
sizing: function(group, options, prev) {
+ // Handle sizing operators like \Huge. Real TeX doesn't actually allow
+ // these functions inside of math expressions, so we do some special
+ // handling.
var inner = buildExpression(group.value.value,
options.withSize(group.value.size), prev);
@@ -630,26 +780,17 @@ var groupTypes = {
options.style.cls()],
inner)]);
- var sizeToFontSize = {
- "size1": 0.5,
- "size2": 0.7,
- "size3": 0.8,
- "size4": 0.9,
- "size5": 1.0,
- "size6": 1.2,
- "size7": 1.44,
- "size8": 1.73,
- "size9": 2.07,
- "size10": 2.49
- };
-
- var fontSize = sizeToFontSize[group.value.size];
+ // Calculate the correct maxFontSize manually
+ var fontSize = sizingMultiplier[group.value.size];
span.maxFontSize = fontSize * options.style.sizeMultiplier;
return span;
},
styling: function(group, options, prev) {
+ // Style changes are handled in the TeXbook on pg. 442, Rule 3.
+
+ // Figure out what style we're changing to.
var style = {
"display": Style.DISPLAY,
"text": Style.TEXT,
@@ -659,6 +800,7 @@ var groupTypes = {
var newStyle = style[group.value.style];
+ // Build the inner expression in the new style.
var inner = buildExpression(
group.value.value, options.withStyle(newStyle), prev);
@@ -669,9 +811,12 @@ var groupTypes = {
var delim = group.value.value;
if (delim === ".") {
+ // Empty delimiters still count as elements, even though they don't
+ // show anything.
return makeSpan([groupToType[group.value.delimType]]);
}
+ // Use delimiter.sizedDelim to generate the delimiter.
return makeSpan(
[groupToType[group.value.delimType]],
[delimiter.sizedDelim(
@@ -679,30 +824,40 @@ var groupTypes = {
},
leftright: function(group, options, prev) {
+ // Build the inner expression
var inner = buildExpression(group.value.body, options.reset());
var innerHeight = 0;
var innerDepth = 0;
+ // Calculate its height and depth
for (var i = 0; i < inner.length; i++) {
innerHeight = Math.max(inner[i].height, innerHeight);
innerDepth = Math.max(inner[i].depth, innerDepth);
}
+ // The size of delimiters is the same, regardless of what style we are
+ // in. Thus, to correctly calculate the size of delimiter we need around
+ // a group, we scale down the inner size based on the size.
innerHeight *= options.style.sizeMultiplier;
innerDepth *= options.style.sizeMultiplier;
var leftDelim;
if (group.value.left === ".") {
+ // Empty delimiters in \left and \right make null delimiter spaces.
leftDelim = makeSpan(["nulldelimiter"]);
} else {
+ // Otherwise, use leftRightDelim to generate the correct sized
+ // delimiter.
leftDelim = delimiter.leftRightDelim(
group.value.left, innerHeight, innerDepth, options,
group.mode);
}
+ // Add it to the beginning of the expression
inner.unshift(leftDelim);
var rightDelim;
+ // Same for the right delimiter
if (group.value.right === ".") {
rightDelim = makeSpan(["nulldelimiter"]);
} else {
@@ -710,6 +865,7 @@ var groupTypes = {
group.value.right, innerHeight, innerDepth, options,
group.mode);
}
+ // Add it to the end of the expression.
inner.push(rightDelim);
return makeSpan(
@@ -720,6 +876,7 @@ var groupTypes = {
// Make an empty span for the rule
var rule = makeSpan(["mord", "rule"], [], options.getColor());
+ // Calculate the width and height of the rule, and account for units
var width = group.value.width.number;
if (group.value.width.unit === "ex") {
width *= fontMetrics.metrics.xHeight;
@@ -730,6 +887,8 @@ var groupTypes = {
height *= fontMetrics.metrics.xHeight;
}
+ // The sizes of rules are absolute, so make it larger if we are in a
+ // smaller style.
width /= options.style.sizeMultiplier;
height /= options.style.sizeMultiplier;
@@ -745,36 +904,69 @@ var groupTypes = {
},
accent: function(group, options, prev) {
+ // Accents are handled in the TeXbook pg. 443, rule 12.
var base = group.value.base;
var supsubGroup;
if (group.type === "supsub") {
+ // If our base is a character box, and we have superscripts and
+ // subscripts, the supsub will defer to us. In particular, we want
+ // to attach the superscripts and subscripts to the inner body (so
+ // that the position of the superscripts and subscripts won't be
+ // affected by the height of the accent). We accomplish this by
+ // sticking the base of the accent into the base of the supsub, and
+ // rendering that, while keeping track of where the accent is.
+
+ // The supsub group is the group that was passed in
var supsub = group;
- group = group.value.base;
+ // The real accent group is the base of the supsub group
+ group = supsub.value.base;
+ // The character box is the base of the accent group
base = group.value.base;
+ // Stick the character box into the base of the supsub group
supsub.value.base = base;
+ // Rerender the supsub group with its new base, and store that
+ // result.
supsubGroup = buildGroup(
- supsub, options.reset());
+ supsub, options.reset(), prev);
}
+ // Build the base group
var body = buildGroup(
base, options.withStyle(options.style.cramp()));
- var s;
- if (isCharacterBox(group.value.base)) {
- var baseChar = getBaseElem(group.value.base);
+ // Calculate the skew of the accent. This is based on the line "If the
+ // nucleus is not a single character, let s = 0; otherwise set s to the
+ // kern amount for the nucleus followed by the \skewchar of its font."
+ // Note that our skew metrics are just the kern between each character
+ // and the skewchar.
+ var skew;
+ if (isCharacterBox(base)) {
+ // If the base is a character box, then we want the skew of the
+ // innermost character. To do that, we find the innermost character:
+ var baseChar = getBaseElem(base);
+ // Then, we render its group to get the symbol inside it
var baseGroup = buildGroup(
baseChar, options.withStyle(options.style.cramp()));
- s = baseGroup.skew;
+ // Finally, we pull the skew off of the symbol.
+ skew = baseGroup.skew;
+ // Note that we now throw away baseGroup, because the layers we
+ // removed with getBaseElem might contain things like \color which
+ // we can't get rid of.
+ // TODO(emily): Find a better way to get the skew
} else {
- s = 0;
+ skew = 0;
}
- var delta = Math.min(body.height, fontMetrics.metrics.xHeight);
+ // calculate the amount of space between the body and the accent
+ var clearance = Math.min(body.height, fontMetrics.metrics.xHeight);
+ // Build the accent
var accent = buildCommon.makeSymbol(
group.value.accent, "Main-Regular", "math", options.getColor());
+ // Remove the italic correction of the accent, because it only serves to
+ // shift the accent over to a place we don't want.
accent.italic = 0;
// The \vec character that the fonts use is a combining character, and
@@ -788,11 +980,14 @@ var groupTypes = {
var accentBody = buildCommon.makeVList([
{type: "elem", elem: body},
- {type: "kern", size: -delta},
+ {type: "kern", size: -clearance},
{type: "elem", elem: accentBody}
], "firstBaseline", null, options);
- accentBody.children[1].style.marginLeft = 2 * s + "em";
+ // Shift the accent over by the skew. Note we shift by twice the skew
+ // because we are centering the accent, so by adding 2*skew to the left,
+ // we shift it to the right by 1*skew.
+ accentBody.children[1].style.marginLeft = 2 * skew + "em";
var accentWrap = makeSpan(["mord", "accent"], [accentBody]);
@@ -828,14 +1023,22 @@ var sizingMultiplier = {
size10: 2.49
};
+/**
+ * buildGroup is the function that takes a group and calls the correct groupType
+ * function for it. It also handles the interaction of size and style changes
+ * between parents and children.
+ */
var buildGroup = function(group, options, prev) {
if (!group) {
return makeSpan();
}
if (groupTypes[group.type]) {
+ // Call the groupTypes function
var groupNode = groupTypes[group.type](group, options, prev);
+ // If the style changed between the parent and the current group,
+ // account for the size difference
if (options.style !== options.parentStyle) {
var multiplier = options.style.sizeMultiplier /
options.parentStyle.sizeMultiplier;
@@ -844,6 +1047,8 @@ var buildGroup = function(group, options, prev) {
groupNode.depth *= multiplier;
}
+ // If the size changed between the parent and the current group, account
+ // for that size difference.
if (options.size !== options.parentSize) {
var multiplier = sizingMultiplier[options.size] /
sizingMultiplier[options.parentSize];
@@ -859,24 +1064,33 @@ var buildGroup = function(group, options, prev) {
}
};
+/**
+ * Take an entire parse tree, and build it into an appropriate set of nodes.
+ */
var buildTree = function(tree) {
// Setup the default options
var options = new Options(Style.TEXT, "size5", "");
+ // Build the expression contained in the tree
var expression = buildExpression(tree, options);
- var span = makeSpan(["base", options.style.cls()], expression);
+ var body = makeSpan(["base", options.style.cls()], expression);
+
+ // Add struts, which ensure that the top of the HTML element falls at the
+ // height of the expression, and the bottom of the HTML element falls at the
+ // depth of the expression.
var topStrut = makeSpan(["strut"]);
var bottomStrut = makeSpan(["strut", "bottom"]);
- topStrut.style.height = span.height + "em";
- bottomStrut.style.height = (span.height + span.depth) + "em";
+ topStrut.style.height = body.height + "em";
+ bottomStrut.style.height = (body.height + body.depth) + "em";
// We'd like to use `vertical-align: top` but in IE 9 this lowers the
// baseline of the box to the bottom of this strut (instead staying in the
// normal place) so we use an absolute value for vertical-align instead
- bottomStrut.style.verticalAlign = -span.depth + "em";
+ bottomStrut.style.verticalAlign = -body.depth + "em";
+ // Wrap the struts and body together
var katexNode = makeSpan(["katex"], [
- makeSpan(["katex-inner"], [topStrut, bottomStrut, span])
+ makeSpan(["katex-inner"], [topStrut, bottomStrut, body])
]);
return katexNode;
diff --git a/delimiter.js b/delimiter.js
@@ -1,17 +1,42 @@
+/**
+ * This file deals with creating delimiters of various sizes. The TeXbook
+ * discusses these routines on page 441-442, in the "Another subroutine sets box
+ * x to a specified variable delimiter" paragraph.
+ *
+ * There are three main routines here. `makeSmallDelim` makes a delimiter in the
+ * normal font, but in either text, script, or scriptscript style.
+ * `makeLargeDelim` makes a delimiter in textstyle, but in one of the Size1,
+ * Size2, Size3, or Size4 fonts. `makeStackedDelim` makes a delimiter out of
+ * smaller pieces that are stacked on top of one another.
+ *
+ * The functions take a parameter `center`, which determines if the delimiter
+ * should be centered around the axis.
+ *
+ * Then, there are three exposed functions. `sizedDelim` makes a delimiter in
+ * one of the given sizes. This is used for things like `\bigl`.
+ * `customSizedDelim` makes a delimiter with a given total height+depth. It is
+ * called in places like `\sqrt`. `leftRightDelim` makes an appropriate
+ * delimiter which surrounds an expression of a given height an depth. It is
+ * used in `\left` and `\right`.
+ */
+
var Options = require("./Options");
var ParseError = require("./ParseError");
var Style = require("./Style");
+var buildCommon = require("./buildCommon");
var domTree = require("./domTree");
var fontMetrics = require("./fontMetrics");
var parseTree = require("./parseTree");
-var utils = require("./utils");
var symbols = require("./symbols");
-var buildCommon = require("./buildCommon");
-var makeSpan = require("./buildCommon").makeSpan;
+var utils = require("./utils");
-// Get the metrics for a given symbol and font, after transformation (i.e.
-// after following replacement from symbols.js)
+var makeSpan = buildCommon.makeSpan;
+
+/**
+ * Get the metrics for a given symbol and font, after transformation (i.e.
+ * after following replacement from symbols.js)
+ */
var getMetrics = function(symbol, font) {
if (symbols["math"][symbol] && symbols["math"][symbol].replace) {
return fontMetrics.getCharacterMetrics(
@@ -22,12 +47,20 @@ var getMetrics = function(symbol, font) {
}
};
+/**
+ * Builds a symbol in the given font size (note size is an integer)
+ */
var mathrmSize = function(value, size, mode) {
return buildCommon.makeSymbol(value, "Size" + size + "-Regular", mode);
};
+/**
+ * Puts a delimiter span in a given style, and adds appropriate height, depth,
+ * and maxFontSizes.
+ */
var styleWrap = function(delim, toStyle, options) {
- var span = makeSpan(["style-wrap", options.style.reset(), toStyle.cls()], [delim]);
+ var span = makeSpan(
+ ["style-wrap", options.style.reset(), toStyle.cls()], [delim]);
var multiplier = toStyle.sizeMultiplier / options.style.sizeMultiplier;
@@ -38,6 +71,11 @@ var styleWrap = function(delim, toStyle, options) {
return span;
};
+/**
+ * Makes a small delimiter. This is a delimiter that comes in the Main-Regular
+ * font, but is restyled to either be in textstyle, scriptstyle, or
+ * scriptscriptstyle.
+ */
var makeSmallDelim = function(delim, style, center, options, mode) {
var text = buildCommon.makeSymbol(delim, "Main-Regular", mode);
@@ -56,6 +94,10 @@ var makeSmallDelim = function(delim, style, center, options, mode) {
return span;
};
+/**
+ * Makes a large delimiter. This is a delimiter that comes in the Size1, Size2,
+ * Size3, or Size4 fonts. It is always rendered in textstyle.
+ */
var makeLargeDelim = function(delim, size, center, options, mode) {
var inner = mathrmSize(delim, size, mode);
@@ -76,9 +118,13 @@ var makeLargeDelim = function(delim, size, center, options, mode) {
return span;
};
-// Make an inner span with the given offset and in the given font
+/**
+ * Make an inner span with the given offset and in the given font. This is used
+ * in `makeStackedDelim` to make the stacking pieces for the delimiter.
+ */
var makeInner = function(symbol, font, mode) {
var sizeClass;
+ // Apply the correct CSS class to choose the right font.
if (font === "Size1-Regular") {
sizeClass = "delim-size1";
} else if (font === "Size4-Regular") {
@@ -89,14 +135,22 @@ var makeInner = function(symbol, font, mode) {
["delimsizinginner", sizeClass],
[makeSpan([], [buildCommon.makeSymbol(symbol, font, mode)])]);
+ // Since this will be passed into `makeVList` in the end, wrap the element
+ // in the appropriate tag that VList uses.
return {type: "elem", elem: inner};
};
+/**
+ * Make a stacked delimiter out of a given delimiter, with the total height at
+ * least `heightTotal`. This routine is mentioned on page 442 of the TeXbook.
+ */
var makeStackedDelim = function(delim, heightTotal, center, options, mode) {
- // There are four parts, the top, a middle, a repeated part, and a bottom.
+ // There are four parts, the top, an optional middle, a repeated part, and a
+ // bottom.
var top, middle, repeat, bottom;
top = repeat = bottom = delim;
middle = null;
+ // Also keep track of what font the delimiters are in
var font = "Size1-Regular";
// We set the parts and font based on the symbol. Note that we use
@@ -175,7 +229,7 @@ var makeStackedDelim = function(delim, heightTotal, center, options, mode) {
font = "Size4-Regular";
}
- // Get the metrics of the three sections
+ // Get the metrics of the four sections
var topMetrics = getMetrics(top, font);
var topHeightTotal = topMetrics.height + topMetrics.depth;
var repeatMetrics = getMetrics(repeat, font);
@@ -188,36 +242,49 @@ var makeStackedDelim = function(delim, heightTotal, center, options, mode) {
middleHeightTotal = middleMetrics.height + middleMetrics.depth;
}
+ // Calcuate the real height that the delimiter will have. It is at least the
+ // size of the top, bottom, and optional middle combined.
var realHeightTotal = topHeightTotal + bottomHeightTotal;
if (middle !== null) {
realHeightTotal += middleHeightTotal;
}
+ // Then add repeated pieces until we reach the specified height.
while (realHeightTotal < heightTotal) {
realHeightTotal += repeatHeightTotal;
if (middle !== null) {
+ // If there is a middle section, we need an equal number of pieces
+ // on the top and bottom.
realHeightTotal += repeatHeightTotal;
}
}
+ // The center of the delimiter is placed at the center of the axis. Note
+ // that in this context, "center" means that the delimiter should be
+ // centered around the axis in the current style, while normally it is
+ // centered around the axis in textstyle.
var axisHeight = fontMetrics.metrics.axisHeight;
if (center) {
axisHeight *= options.style.sizeMultiplier;
}
+ // Calculate the height and depth
var height = realHeightTotal / 2 + axisHeight;
var depth = realHeightTotal / 2 - axisHeight;
- // Keep a list of the inner spans
+ // Now, we start building the pieces that will go into the vlist
+
+ // Keep a list of the inner pieces
var inners = [];
// Add the bottom symbol
inners.push(makeInner(bottom, font, mode));
if (middle === null) {
+ // Calculate the number of repeated symbols we need
var repeatHeight = realHeightTotal - topHeightTotal - bottomHeightTotal;
var symbolCount = Math.ceil(repeatHeight / repeatHeightTotal);
- // Add repeat symbols until there's only space for the bottom symbol
+ // Add that many symbols
for (var i = 0; i < symbolCount; i++) {
inners.push(makeInner(repeat, font, mode));
}
@@ -250,8 +317,10 @@ var makeStackedDelim = function(delim, heightTotal, center, options, mode) {
}
}
+ // Add the top symbol
inners.push(makeInner(top, font, mode));
+ // Finally, build the vlist
var inner = buildCommon.makeVList(inners, "bottom", depth, options);
return styleWrap(
@@ -259,29 +328,37 @@ var makeStackedDelim = function(delim, heightTotal, center, options, mode) {
Style.TEXT, options);
};
-var normalDelimiters = [
+// There are three kinds of delimiters, delimiters that stack when they become
+// too large
+var stackLargeDelimiters = [
"(", ")", "[", "\\lbrack", "]", "\\rbrack",
"\\{", "\\lbrace", "\\}", "\\rbrace",
"\\lfloor", "\\rfloor", "\\lceil", "\\rceil",
- "<", ">", "\\langle", "\\rangle", "/", "\\backslash",
"\\surd"
];
-var stackDelimiters = [
+// delimiters that always stack
+var stackAlwaysDelimiters = [
"\\uparrow", "\\downarrow", "\\updownarrow",
"\\Uparrow", "\\Downarrow", "\\Updownarrow",
"|", "\\|", "\\vert", "\\Vert"
];
-var onlyNormalDelimiters = [
+// and delimiters that never stack
+var stackNeverDelimiters = [
"<", ">", "\\langle", "\\rangle", "/", "\\backslash"
];
// Metrics of the different sizes. Found by looking at TeX's output of
-// $\bigl| \Bigl| \biggl| \Biggl| \showlists$
+// $\bigl| // \Bigl| \biggl| \Biggl| \showlists$
+// Used to create stacked delimiters of appropriate sizes in makeSizedDelim.
var sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0];
+/**
+ * Used to create a delimiter of a specific size, where `size` is 1, 2, 3, or 4.
+ */
var makeSizedDelim = function(delim, size, options, mode) {
+ // < and > turn into \langle and \rangle in delimiters
if (delim === "<") {
delim = "\\langle";
} else if (delim === ">") {
@@ -290,9 +367,11 @@ var makeSizedDelim = function(delim, size, options, mode) {
var retDelim;
- if (utils.contains(normalDelimiters, delim)) {
+ // Sized delimiters are never centered.
+ if (utils.contains(stackLargeDelimiters, delim) ||
+ utils.contains(stackNeverDelimiters, delim)) {
return makeLargeDelim(delim, size, false, options, mode);
- } else if (utils.contains(stackDelimiters, delim)) {
+ } else if (utils.contains(stackAlwaysDelimiters, delim)) {
return makeStackedDelim(
delim, sizeToMaxHeight[size], false, options, mode);
} else {
@@ -300,7 +379,20 @@ var makeSizedDelim = function(delim, size, options, mode) {
}
};
-var normalDelimiterSequence = [
+/**
+ * There are three different sequences of delimiter sizes that the delimiters
+ * follow depending on the kind of delimiter. This is used when creating custom
+ * sized delimiters to decide whether to create a small, large, or stacked
+ * delimiter.
+ *
+ * In real TeX, these sequences aren't explicitly defined, but are instead
+ * defined inside the font metrics. Since there are only three sequences that
+ * are possible for the delimiters that TeX defines, it is easier to just encode
+ * them explicitly here.
+ */
+
+// Delimiters that never stack try small delimiters and large delimiters only
+var stackNeverDelimiterSequence = [
{type: "small", style: Style.SCRIPTSCRIPT},
{type: "small", style: Style.SCRIPT},
{type: "small", style: Style.TEXT},
@@ -310,6 +402,7 @@ var normalDelimiterSequence = [
{type: "large", size: 4}
];
+// Delimiters that always stack try the small delimiters first, then stack
var stackAlwaysDelimiterSequence = [
{type: "small", style: Style.SCRIPTSCRIPT},
{type: "small", style: Style.SCRIPT},
@@ -317,6 +410,8 @@ var stackAlwaysDelimiterSequence = [
{type: "stack"}
];
+// Delimiters that stack when large try the small and then large delimiters, and
+// stack afterwards
var stackLargeDelimiterSequence = [
{type: "small", style: Style.SCRIPTSCRIPT},
{type: "small", style: Style.SCRIPT},
@@ -328,6 +423,9 @@ var stackLargeDelimiterSequence = [
{type: "stack"}
];
+/**
+ * Get the font used in a delimiter based on what kind of delimiter it is.
+ */
var delimTypeToFont = function(type) {
if (type.type === "small") {
return "Main-Regular";
@@ -338,6 +436,10 @@ var delimTypeToFont = function(type) {
}
};
+/**
+ * Traverse a sequence of types of delimiters to decide what kind of delimiter
+ * should be used to create a delimiter of the given height+depth.
+ */
var traverseSequence = function(delim, height, sequence, options) {
// Here, we choose the index we should start at in the sequences. In smaller
// sizes (which correspond to larger numbers in style.size) we start earlier
@@ -351,21 +453,29 @@ var traverseSequence = function(delim, height, sequence, options) {
}
var metrics = getMetrics(delim, delimTypeToFont(sequence[i]));
-
var heightDepth = metrics.height + metrics.depth;
+ // Small delimiters are scaled down versions of the same font, so we
+ // account for the style change size.
+
if (sequence[i].type === "small") {
heightDepth *= sequence[i].style.sizeMultiplier;
}
+ // Check if the delimiter at this size works for the given height.
if (heightDepth > height) {
return sequence[i];
}
}
+ // If we reached the end of the sequence, return the last sequence element.
return sequence[sequence.length - 1];
};
+/**
+ * Make a delimiter of a given height+depth, with optional centering. Here, we
+ * traverse the sequences, and create a delimiter that the sequence tells us to.
+ */
var makeCustomSizedDelim = function(delim, height, center, options, mode) {
if (delim === "<") {
delim = "\\langle";
@@ -373,17 +483,21 @@ var makeCustomSizedDelim = function(delim, height, center, options, mode) {
delim = "\\rangle";
}
+ // Decide what sequence to use
var sequence;
- if (utils.contains(onlyNormalDelimiters, delim)) {
- sequence = normalDelimiterSequence;
- } else if (utils.contains(normalDelimiters, delim)) {
+ if (utils.contains(stackNeverDelimiters, delim)) {
+ sequence = stackNeverDelimiterSequence;
+ } else if (utils.contains(stackLargeDelimiters, delim)) {
sequence = stackLargeDelimiterSequence;
} else {
sequence = stackAlwaysDelimiterSequence;
}
+ // Look through the sequence
var delimType = traverseSequence(delim, height, sequence, options);
+ // Depending on the sequence element we decided on, call the appropriate
+ // function.
if (delimType.type === "small") {
return makeSmallDelim(delim, delimType.style, center, options, mode);
} else if (delimType.type === "large") {
@@ -393,7 +507,12 @@ var makeCustomSizedDelim = function(delim, height, center, options, mode) {
}
};
+/**
+ * Make a delimiter for use with `\left` and `\right`, given a height and depth
+ * of an expression that the delimiters surround.
+ */
var makeLeftRightDelim = function(delim, height, depth, options, mode) {
+ // We always center \left/\right delimiters, so the axis is always shifted
var axisHeight =
fontMetrics.metrics.axisHeight * options.style.sizeMultiplier;
@@ -417,6 +536,8 @@ var makeLeftRightDelim = function(delim, height, depth, options, mode) {
maxDistFromAxis / 500 * delimiterFactor,
2 * maxDistFromAxis - delimiterExtend);
+ // Finally, we defer to `makeCustomSizedDelim` with our calculated total
+ // height
return makeCustomSizedDelim(delim, totalHeight, true, options, mode);
};
diff --git a/domTree.js b/domTree.js
@@ -1,11 +1,17 @@
-// These objects store the data about the DOM nodes we create, as well as some
-// extra data. They can then be transformed into real DOM nodes with the toNode
-// function or HTML markup using toMarkup. They are useful for both storing
-// extra properties on the nodes, as well as providing a way to easily work
-// with the DOM.
+/**
+ * These objects store the data about the DOM nodes we create, as well as some
+ * extra data. They can then be transformed into real DOM nodes with the toNode
+ * function or HTML markup using toMarkup. They are useful for both storing
+ * extra properties on the nodes, as well as providing a way to easily work
+ * with the DOM.
+ */
var utils = require("./utils");
+/**
+ * Create an HTML className based on a list of classes. In addition to joining
+ * with spaces, we also remove null or empty classes.
+ */
var createClass = function(classes) {
classes = classes.slice();
for (var i = classes.length - 1; i >= 0; i--) {
@@ -17,6 +23,11 @@ var createClass = function(classes) {
return classes.join(" ");
};
+/**
+ * This node represents a span node, with a className, a list of children, and
+ * an inline style. It also contains information about its height, depth, and
+ * maxFontSize.
+ */
function span(classes, children, height, depth, maxFontSize, style) {
this.classes = classes || [];
this.children = children || [];
@@ -26,17 +37,23 @@ function span(classes, children, height, depth, maxFontSize, style) {
this.style = style || {};
}
+/**
+ * Convert the span into an HTML node
+ */
span.prototype.toNode = function() {
var span = document.createElement("span");
+ // Apply the class
span.className = createClass(this.classes);
+ // Apply inline styles
for (var style in this.style) {
if (this.style.hasOwnProperty(style)) {
span.style[style] = this.style[style];
}
}
+ // Append the children, also as HTML nodes
for (var i = 0; i < this.children.length; i++) {
span.appendChild(this.children[i].toNode());
}
@@ -44,9 +61,13 @@ span.prototype.toNode = function() {
return span;
};
+/**
+ * Convert the span into an HTML markup string
+ */
span.prototype.toMarkup = function() {
var markup = "<span";
+ // Add the class
if (this.classes.length) {
markup += " class=\"";
markup += utils.escape(createClass(this.classes));
@@ -55,6 +76,7 @@ span.prototype.toMarkup = function() {
var styles = "";
+ // Add the styles, after hyphenation
for (var style in this.style) {
if (this.style.hasOwnProperty(style)) {
styles += utils.hyphenate(style) + ":" + this.style[style] + ";";
@@ -67,6 +89,7 @@ span.prototype.toMarkup = function() {
markup += ">";
+ // Add the markup of the children, also as markup
for (var i = 0; i < this.children.length; i++) {
markup += this.children[i].toMarkup();
}
@@ -76,6 +99,12 @@ span.prototype.toMarkup = function() {
return markup;
};
+/**
+ * This node represents a document fragment, which contains elements, but when
+ * placed into the DOM doesn't have any representation itself. Thus, it only
+ * contains children and doesn't have any HTML properties. It also keeps track
+ * of a height, depth, and maxFontSize.
+ */
function documentFragment(children, height, depth, maxFontSize) {
this.children = children || [];
this.height = height || 0;
@@ -83,9 +112,14 @@ function documentFragment(children, height, depth, maxFontSize) {
this.maxFontSize = maxFontSize || 0;
}
+/**
+ * Convert the fragment into a node
+ */
documentFragment.prototype.toNode = function() {
+ // Create a fragment
var frag = document.createDocumentFragment();
+ // Append the children
for (var i = 0; i < this.children.length; i++) {
frag.appendChild(this.children[i].toNode());
}
@@ -93,9 +127,13 @@ documentFragment.prototype.toNode = function() {
return frag;
};
+/**
+ * Convert the fragment into HTML markup
+ */
documentFragment.prototype.toMarkup = function() {
var markup = "";
+ // Simply concatenate the markup for the children together
for (var i = 0; i < this.children.length; i++) {
markup += this.children[i].toMarkup();
}
@@ -103,6 +141,11 @@ documentFragment.prototype.toMarkup = function() {
return markup;
};
+/**
+ * A symbol node contains information about a single symbol. It either renders
+ * to a single text node, or a span with a single text node in it, depending on
+ * whether it has CSS classes, styles, or needs italic correction.
+ */
function symbolNode(value, height, depth, italic, skew, classes, style) {
this.value = value || "";
this.height = height || 0;
@@ -114,6 +157,10 @@ function symbolNode(value, height, depth, italic, skew, classes, style) {
this.maxFontSize = 0;
}
+/**
+ * Creates a text node or span from a symbol node. Note that a span is only
+ * created if it is needed.
+ */
symbolNode.prototype.toNode = function() {
var node = document.createTextNode(this.value);
var span = null;
@@ -143,6 +190,9 @@ symbolNode.prototype.toNode = function() {
}
};
+/**
+ * Creates markup for a symbol node.
+ */
symbolNode.prototype.toMarkup = function() {
// TODO(alpert): More duplication than I'd like from
// span.prototype.toMarkup and symbolNode.prototype.toNode...
diff --git a/fontMetrics.js b/fontMetrics.js
@@ -1,4 +1,18 @@
-// These font metrics are extracted from TeX
+/**
+ * This file contains metrics regarding fonts and individual symbols. The sigma
+ * and xi variables, as well as the metricMap map contain data extracted from
+ * TeX, TeX font metrics, and the TTF files. These data are then exposed via the
+ * `metrics` variable and the getCharacterMetrics function.
+ */
+
+// These font metrics are extracted from TeX by using
+// \font\a=cmmi10
+// \showthe\fontdimenX\a
+// where X is the corresponding variable number. These correspond to the font
+// parameters of the symbol fonts. In TeX, there are actually three sets of
+// dimensions, one for each of textstyle, scriptstyle, and scriptscriptstyle,
+// but we only use the textstyle ones, and scale certain dimensions accordingly.
+// See the TeXbook, page 441.
var sigma1 = 0.025;
var sigma2 = 0;
var sigma3 = 0;
@@ -22,6 +36,11 @@ var sigma20 = 2.390;
var sigma21 = 0.101;
var sigma22 = 0.250;
+// These font metrics are extracted from TeX by using
+// \font\a=cmex10
+// \showthe\fontdimenX\a
+// where X is the corresponding variable number. These correspond to the font
+// parameters of the extension fonts (family 3). See the TeXbook, page 441.
var xi1 = 0;
var xi2 = 0;
var xi3 = 0;
@@ -36,11 +55,15 @@ var xi11 = .2;
var xi12 = .6;
var xi13 = .1;
-// This value is also used in katex.less, if you change it make sure the values
+// This value determines how large a pt is, for metrics which are defined in
+// terms of pts.
+// This value is also used in katex.less; if you change it make sure the values
// match.
var ptPerEm = 10.0;
-// This is just a mapping from common names to real metrics
+/**
+ * This is just a mapping from common names to real metrics
+ */
var metrics = {
xHeight: sigma5,
quad: sigma6,
@@ -68,9 +91,16 @@ var metrics = {
ptPerEm: ptPerEm
};
-// This map is generated by metric_parse.rb
+// This map contains a mapping from font name and character code to character
+// metrics, including height, depth, italic correction, and skew (kern from the
+// character to the corresponding \skewchar)
+// This map is generated via `make metrics`. It should not be changed manually.
var metricMap = {"AMS-Regular":{"10003":{"depth":0.0,"height":0.69224,"italic":0.0,"skew":0},"10016":{"depth":0.0,"height":0.69224,"italic":0.0,"skew":0},"1008":{"depth":0.0,"height":0.43056,"italic":0.04028,"skew":0},"107":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"10731":{"depth":0.11111,"height":0.69224,"italic":0.0,"skew":0},"10846":{"depth":0.19444,"height":0.75583,"italic":0.0,"skew":0},"10877":{"depth":0.13667,"height":0.63667,"italic":0.0,"skew":0},"10878":{"depth":0.13667,"height":0.63667,"italic":0.0,"skew":0},"10885":{"depth":0.25583,"height":0.75583,"italic":0.0,"skew":0},"10886":{"depth":0.25583,"height":0.75583,"italic":0.0,"skew":0},"10887":{"depth":0.13597,"height":0.63597,"italic":0.0,"skew":0},"10888":{"depth":0.13597,"height":0.63597,"italic":0.0,"skew":0},"10889":{"depth":0.26167,"height":0.75726,"italic":0.0,"skew":0},"10890":{"depth":0.26167,"height":0.75726,"italic":0.0,"skew":0},"10891":{"depth":0.48256,"height":0.98256,"italic":0.0,"skew":0},"10892":{"depth":0.48256,"height":0.98256,"italic":0.0,"skew":0},"10901":{"depth":0.13667,"height":0.63667,"italic":0.0,"skew":0},"10902":{"depth":0.13667,"height":0.63667,"italic":0.0,"skew":0},"10933":{"depth":0.25142,"height":0.75726,"italic":0.0,"skew":0},"10934":{"depth":0.25142,"height":0.75726,"italic":0.0,"skew":0},"10935":{"depth":0.26167,"height":0.75726,"italic":0.0,"skew":0},"10936":{"depth":0.26167,"height":0.75726,"italic":0.0,"skew":0},"10937":{"depth":0.26167,"height":0.75726,"italic":0.0,"skew":0},"10938":{"depth":0.26167,"height":0.75726,"italic":0.0,"skew":0},"10949":{"depth":0.25583,"height":0.75583,"italic":0.0,"skew":0},"10950":{"depth":0.25583,"height":0.75583,"italic":0.0,"skew":0},"10955":{"depth":0.28481,"height":0.79383,"italic":0.0,"skew":0},"10956":{"depth":0.28481,"height":0.79383,"italic":0.0,"skew":0},"165":{"depth":0.0,"height":0.675,"italic":0.025,"skew":0},"174":{"depth":0.15559,"height":0.69224,"italic":0.0,"skew":0},"240":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"295":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"57350":{"depth":0.08167,"height":0.58167,"italic":0.0,"skew":0},"57351":{"depth":0.08167,"height":0.58167,"italic":0.0,"skew":0},"57352":{"depth":0.08167,"height":0.58167,"italic":0.0,"skew":0},"57353":{"depth":0.0,"height":0.43056,"italic":0.04028,"skew":0},"57356":{"depth":0.25142,"height":0.75726,"italic":0.0,"skew":0},"57357":{"depth":0.25142,"height":0.75726,"italic":0.0,"skew":0},"57358":{"depth":0.41951,"height":0.91951,"italic":0.0,"skew":0},"57359":{"depth":0.30274,"height":0.79383,"italic":0.0,"skew":0},"57360":{"depth":0.30274,"height":0.79383,"italic":0.0,"skew":0},"57361":{"depth":0.41951,"height":0.91951,"italic":0.0,"skew":0},"57366":{"depth":0.25142,"height":0.75726,"italic":0.0,"skew":0},"57367":{"depth":0.25142,"height":0.75726,"italic":0.0,"skew":0},"57368":{"depth":0.25142,"height":0.75726,"italic":0.0,"skew":0},"57369":{"depth":0.25142,"height":0.75726,"italic":0.0,"skew":0},"57370":{"depth":0.13597,"height":0.63597,"italic":0.0,"skew":0},"57371":{"depth":0.13597,"height":0.63597,"italic":0.0,"skew":0},"65":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"66":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"67":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"68":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"69":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"70":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"71":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"710":{"depth":0.0,"height":0.825,"italic":0.0,"skew":0},"72":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"73":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"732":{"depth":0.0,"height":0.9,"italic":0.0,"skew":0},"74":{"depth":0.16667,"height":0.68889,"italic":0.0,"skew":0},"75":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"76":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"77":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"770":{"depth":0.0,"height":0.825,"italic":0.0,"skew":0},"771":{"depth":0.0,"height":0.9,"italic":0.0,"skew":0},"78":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"79":{"depth":0.16667,"height":0.68889,"italic":0.0,"skew":0},"80":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"81":{"depth":0.16667,"height":0.68889,"italic":0.0,"skew":0},"82":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"8245":{"depth":0.0,"height":0.54986,"italic":0.0,"skew":0},"83":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"84":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"8463":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"8487":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"8498":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"85":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"8502":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"8503":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"8504":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"8513":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"8592":{"depth":-0.03598,"height":0.46402,"italic":0.0,"skew":0},"8594":{"depth":-0.03598,"height":0.46402,"italic":0.0,"skew":0},"86":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"8602":{"depth":-0.13313,"height":0.36687,"italic":0.0,"skew":0},"8603":{"depth":-0.13313,"height":0.36687,"italic":0.0,"skew":0},"8606":{"depth":0.01354,"height":0.52239,"italic":0.0,"skew":0},"8608":{"depth":0.01354,"height":0.52239,"italic":0.0,"skew":0},"8610":{"depth":0.01354,"height":0.52239,"italic":0.0,"skew":0},"8611":{"depth":0.01354,"height":0.52239,"italic":0.0,"skew":0},"8619":{"depth":0.0,"height":0.54986,"italic":0.0,"skew":0},"8620":{"depth":0.0,"height":0.54986,"italic":0.0,"skew":0},"8621":{"depth":-0.13313,"height":0.37788,"italic":0.0,"skew":0},"8622":{"depth":-0.13313,"height":0.36687,"italic":0.0,"skew":0},"8624":{"depth":0.0,"height":0.69224,"italic":0.0,"skew":0},"8625":{"depth":0.0,"height":0.69224,"italic":0.0,"skew":0},"8630":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"8631":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"8634":{"depth":0.08198,"height":0.58198,"italic":0.0,"skew":0},"8635":{"depth":0.08198,"height":0.58198,"italic":0.0,"skew":0},"8638":{"depth":0.19444,"height":0.69224,"italic":0.0,"skew":0},"8639":{"depth":0.19444,"height":0.69224,"italic":0.0,"skew":0},"8642":{"depth":0.19444,"height":0.69224,"italic":0.0,"skew":0},"8643":{"depth":0.19444,"height":0.69224,"italic":0.0,"skew":0},"8644":{"depth":0.1808,"height":0.675,"italic":0.0,"skew":0},"8646":{"depth":0.1808,"height":0.675,"italic":0.0,"skew":0},"8647":{"depth":0.1808,"height":0.675,"italic":0.0,"skew":0},"8648":{"depth":0.19444,"height":0.69224,"italic":0.0,"skew":0},"8649":{"depth":0.1808,"height":0.675,"italic":0.0,"skew":0},"8650":{"depth":0.19444,"height":0.69224,"italic":0.0,"skew":0},"8651":{"depth":0.01354,"height":0.52239,"italic":0.0,"skew":0},"8652":{"depth":0.01354,"height":0.52239,"italic":0.0,"skew":0},"8653":{"depth":-0.13313,"height":0.36687,"italic":0.0,"skew":0},"8654":{"depth":-0.13313,"height":0.36687,"italic":0.0,"skew":0},"8655":{"depth":-0.13313,"height":0.36687,"italic":0.0,"skew":0},"8666":{"depth":0.13667,"height":0.63667,"italic":0.0,"skew":0},"8667":{"depth":0.13667,"height":0.63667,"italic":0.0,"skew":0},"8669":{"depth":-0.13313,"height":0.37788,"italic":0.0,"skew":0},"87":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"8705":{"depth":0.0,"height":0.825,"italic":0.0,"skew":0},"8708":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"8709":{"depth":0.08167,"height":0.58167,"italic":0.0,"skew":0},"8717":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"8722":{"depth":-0.03598,"height":0.46402,"italic":0.0,"skew":0},"8724":{"depth":0.08198,"height":0.69224,"italic":0.0,"skew":0},"8726":{"depth":0.08167,"height":0.58167,"italic":0.0,"skew":0},"8733":{"depth":0.0,"height":0.69224,"italic":0.0,"skew":0},"8736":{"depth":0.0,"height":0.69224,"italic":0.0,"skew":0},"8737":{"depth":0.0,"height":0.69224,"italic":0.0,"skew":0},"8738":{"depth":0.03517,"height":0.52239,"italic":0.0,"skew":0},"8739":{"depth":0.08167,"height":0.58167,"italic":0.0,"skew":0},"8740":{"depth":0.25142,"height":0.74111,"italic":0.0,"skew":0},"8741":{"depth":0.08167,"height":0.58167,"italic":0.0,"skew":0},"8742":{"depth":0.25142,"height":0.74111,"italic":0.0,"skew":0},"8756":{"depth":0.0,"height":0.69224,"italic":0.0,"skew":0},"8757":{"depth":0.0,"height":0.69224,"italic":0.0,"skew":0},"8764":{"depth":-0.13313,"height":0.36687,"italic":0.0,"skew":0},"8765":{"depth":-0.13313,"height":0.37788,"italic":0.0,"skew":0},"8769":{"depth":-0.13313,"height":0.36687,"italic":0.0,"skew":0},"8770":{"depth":-0.03625,"height":0.46375,"italic":0.0,"skew":0},"8774":{"depth":0.30274,"height":0.79383,"italic":0.0,"skew":0},"8776":{"depth":-0.01688,"height":0.48312,"italic":0.0,"skew":0},"8778":{"depth":0.08167,"height":0.58167,"italic":0.0,"skew":0},"8782":{"depth":0.06062,"height":0.54986,"italic":0.0,"skew":0},"8783":{"depth":0.06062,"height":0.54986,"italic":0.0,"skew":0},"8785":{"depth":0.08198,"height":0.58198,"italic":0.0,"skew":0},"8786":{"depth":0.08198,"height":0.58198,"italic":0.0,"skew":0},"8787":{"depth":0.08198,"height":0.58198,"italic":0.0,"skew":0},"8790":{"depth":0.0,"height":0.69224,"italic":0.0,"skew":0},"8791":{"depth":0.22958,"height":0.72958,"italic":0.0,"skew":0},"8796":{"depth":0.08198,"height":0.91667,"italic":0.0,"skew":0},"88":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"8806":{"depth":0.25583,"height":0.75583,"italic":0.0,"skew":0},"8807":{"depth":0.25583,"height":0.75583,"italic":0.0,"skew":0},"8808":{"depth":0.25142,"height":0.75726,"italic":0.0,"skew":0},"8809":{"depth":0.25142,"height":0.75726,"italic":0.0,"skew":0},"8812":{"depth":0.25583,"height":0.75583,"italic":0.0,"skew":0},"8814":{"depth":0.20576,"height":0.70576,"italic":0.0,"skew":0},"8815":{"depth":0.20576,"height":0.70576,"italic":0.0,"skew":0},"8816":{"depth":0.30274,"height":0.79383,"italic":0.0,"skew":0},"8817":{"depth":0.30274,"height":0.79383,"italic":0.0,"skew":0},"8818":{"depth":0.22958,"height":0.72958,"italic":0.0,"skew":0},"8819":{"depth":0.22958,"height":0.72958,"italic":0.0,"skew":0},"8822":{"depth":0.1808,"height":0.675,"italic":0.0,"skew":0},"8823":{"depth":0.1808,"height":0.675,"italic":0.0,"skew":0},"8828":{"depth":0.13667,"height":0.63667,"italic":0.0,"skew":0},"8829":{"depth":0.13667,"height":0.63667,"italic":0.0,"skew":0},"8830":{"depth":0.22958,"height":0.72958,"italic":0.0,"skew":0},"8831":{"depth":0.22958,"height":0.72958,"italic":0.0,"skew":0},"8832":{"depth":0.20576,"height":0.70576,"italic":0.0,"skew":0},"8833":{"depth":0.20576,"height":0.70576,"italic":0.0,"skew":0},"8840":{"depth":0.30274,"height":0.79383,"italic":0.0,"skew":0},"8841":{"depth":0.30274,"height":0.79383,"italic":0.0,"skew":0},"8842":{"depth":0.13597,"height":0.63597,"italic":0.0,"skew":0},"8843":{"depth":0.13597,"height":0.63597,"italic":0.0,"skew":0},"8847":{"depth":0.03517,"height":0.54986,"italic":0.0,"skew":0},"8848":{"depth":0.03517,"height":0.54986,"italic":0.0,"skew":0},"8858":{"depth":0.08198,"height":0.58198,"italic":0.0,"skew":0},"8859":{"depth":0.08198,"height":0.58198,"italic":0.0,"skew":0},"8861":{"depth":0.08198,"height":0.58198,"italic":0.0,"skew":0},"8862":{"depth":0.0,"height":0.675,"italic":0.0,"skew":0},"8863":{"depth":0.0,"height":0.675,"italic":0.0,"skew":0},"8864":{"depth":0.0,"height":0.675,"italic":0.0,"skew":0},"8865":{"depth":0.0,"height":0.675,"italic":0.0,"skew":0},"8872":{"depth":0.0,"height":0.69224,"italic":0.0,"skew":0},"8873":{"depth":0.0,"height":0.69224,"italic":0.0,"skew":0},"8874":{"depth":0.0,"height":0.69224,"italic":0.0,"skew":0},"8876":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"8877":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"8878":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"8879":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"8882":{"depth":0.03517,"height":0.54986,"italic":0.0,"skew":0},"8883":{"depth":0.03517,"height":0.54986,"italic":0.0,"skew":0},"8884":{"depth":0.13667,"height":0.63667,"italic":0.0,"skew":0},"8885":{"depth":0.13667,"height":0.63667,"italic":0.0,"skew":0},"8888":{"depth":0.0,"height":0.54986,"italic":0.0,"skew":0},"8890":{"depth":0.19444,"height":0.43056,"italic":0.0,"skew":0},"8891":{"depth":0.19444,"height":0.69224,"italic":0.0,"skew":0},"8892":{"depth":0.19444,"height":0.69224,"italic":0.0,"skew":0},"89":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"8901":{"depth":0.0,"height":0.54986,"italic":0.0,"skew":0},"8903":{"depth":0.08167,"height":0.58167,"italic":0.0,"skew":0},"8905":{"depth":0.08167,"height":0.58167,"italic":0.0,"skew":0},"8906":{"depth":0.08167,"height":0.58167,"italic":0.0,"skew":0},"8907":{"depth":0.0,"height":0.69224,"italic":0.0,"skew":0},"8908":{"depth":0.0,"height":0.69224,"italic":0.0,"skew":0},"8909":{"depth":-0.03598,"height":0.46402,"italic":0.0,"skew":0},"8910":{"depth":0.0,"height":0.54986,"italic":0.0,"skew":0},"8911":{"depth":0.0,"height":0.54986,"italic":0.0,"skew":0},"8912":{"depth":0.03517,"height":0.54986,"italic":0.0,"skew":0},"8913":{"depth":0.03517,"height":0.54986,"italic":0.0,"skew":0},"8914":{"depth":0.0,"height":0.54986,"italic":0.0,"skew":0},"8915":{"depth":0.0,"height":0.54986,"italic":0.0,"skew":0},"8916":{"depth":0.0,"height":0.69224,"italic":0.0,"skew":0},"8918":{"depth":0.0391,"height":0.5391,"italic":0.0,"skew":0},"8919":{"depth":0.0391,"height":0.5391,"italic":0.0,"skew":0},"8920":{"depth":0.03517,"height":0.54986,"italic":0.0,"skew":0},"8921":{"depth":0.03517,"height":0.54986,"italic":0.0,"skew":0},"8922":{"depth":0.38569,"height":0.88569,"italic":0.0,"skew":0},"8923":{"depth":0.38569,"height":0.88569,"italic":0.0,"skew":0},"8926":{"depth":0.13667,"height":0.63667,"italic":0.0,"skew":0},"8927":{"depth":0.13667,"height":0.63667,"italic":0.0,"skew":0},"8928":{"depth":0.30274,"height":0.79383,"italic":0.0,"skew":0},"8929":{"depth":0.30274,"height":0.79383,"italic":0.0,"skew":0},"8934":{"depth":0.23222,"height":0.74111,"italic":0.0,"skew":0},"8935":{"depth":0.23222,"height":0.74111,"italic":0.0,"skew":0},"8936":{"depth":0.23222,"height":0.74111,"italic":0.0,"skew":0},"8937":{"depth":0.23222,"height":0.74111,"italic":0.0,"skew":0},"8938":{"depth":0.20576,"height":0.70576,"italic":0.0,"skew":0},"8939":{"depth":0.20576,"height":0.70576,"italic":0.0,"skew":0},"8940":{"depth":0.30274,"height":0.79383,"italic":0.0,"skew":0},"8941":{"depth":0.30274,"height":0.79383,"italic":0.0,"skew":0},"8994":{"depth":0.19444,"height":0.69224,"italic":0.0,"skew":0},"8995":{"depth":0.19444,"height":0.69224,"italic":0.0,"skew":0},"90":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"9416":{"depth":0.15559,"height":0.69224,"italic":0.0,"skew":0},"9484":{"depth":0.0,"height":0.69224,"italic":0.0,"skew":0},"9488":{"depth":0.0,"height":0.69224,"italic":0.0,"skew":0},"9492":{"depth":0.0,"height":0.37788,"italic":0.0,"skew":0},"9496":{"depth":0.0,"height":0.37788,"italic":0.0,"skew":0},"9585":{"depth":0.19444,"height":0.68889,"italic":0.0,"skew":0},"9586":{"depth":0.19444,"height":0.74111,"italic":0.0,"skew":0},"9632":{"depth":0.0,"height":0.675,"italic":0.0,"skew":0},"9633":{"depth":0.0,"height":0.675,"italic":0.0,"skew":0},"9650":{"depth":0.0,"height":0.54986,"italic":0.0,"skew":0},"9651":{"depth":0.0,"height":0.54986,"italic":0.0,"skew":0},"9654":{"depth":0.03517,"height":0.54986,"italic":0.0,"skew":0},"9660":{"depth":0.0,"height":0.54986,"italic":0.0,"skew":0},"9661":{"depth":0.0,"height":0.54986,"italic":0.0,"skew":0},"9664":{"depth":0.03517,"height":0.54986,"italic":0.0,"skew":0},"9674":{"depth":0.11111,"height":0.69224,"italic":0.0,"skew":0},"9733":{"depth":0.19444,"height":0.69224,"italic":0.0,"skew":0},"989":{"depth":0.08167,"height":0.58167,"italic":0.0,"skew":0}},"Main-Bold":{"100":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"101":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"102":{"depth":0.0,"height":0.69444,"italic":0.10903,"skew":0},"10216":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"10217":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"103":{"depth":0.19444,"height":0.44444,"italic":0.01597,"skew":0},"104":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"105":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"106":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"107":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"108":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"10815":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"109":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"10927":{"depth":0.19667,"height":0.69667,"italic":0.0,"skew":0},"10928":{"depth":0.19667,"height":0.69667,"italic":0.0,"skew":0},"110":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"111":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"112":{"depth":0.19444,"height":0.44444,"italic":0.0,"skew":0},"113":{"depth":0.19444,"height":0.44444,"italic":0.0,"skew":0},"114":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"115":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"116":{"depth":0.0,"height":0.63492,"italic":0.0,"skew":0},"117":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"118":{"depth":0.0,"height":0.44444,"italic":0.01597,"skew":0},"119":{"depth":0.0,"height":0.44444,"italic":0.01597,"skew":0},"120":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"121":{"depth":0.19444,"height":0.44444,"italic":0.01597,"skew":0},"122":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"123":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"124":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"125":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"126":{"depth":0.35,"height":0.34444,"italic":0.0,"skew":0},"168":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"172":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"175":{"depth":0.0,"height":0.59611,"italic":0.0,"skew":0},"176":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"177":{"depth":0.13333,"height":0.63333,"italic":0.0,"skew":0},"180":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"215":{"depth":0.13333,"height":0.63333,"italic":0.0,"skew":0},"247":{"depth":0.13333,"height":0.63333,"italic":0.0,"skew":0},"305":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"33":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"34":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"35":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"36":{"depth":0.05556,"height":0.75,"italic":0.0,"skew":0},"37":{"depth":0.05556,"height":0.75,"italic":0.0,"skew":0},"38":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"39":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"40":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"41":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"42":{"depth":0.0,"height":0.75,"italic":0.0,"skew":0},"43":{"depth":0.13333,"height":0.63333,"italic":0.0,"skew":0},"44":{"depth":0.19444,"height":0.15556,"italic":0.0,"skew":0},"45":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"46":{"depth":0.0,"height":0.15556,"italic":0.0,"skew":0},"47":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"48":{"depth":0.0,"height":0.64444,"italic":0.0,"skew":0},"49":{"depth":0.0,"height":0.64444,"italic":0.0,"skew":0},"50":{"depth":0.0,"height":0.64444,"italic":0.0,"skew":0},"51":{"depth":0.0,"height":0.64444,"italic":0.0,"skew":0},"52":{"depth":0.0,"height":0.64444,"italic":0.0,"skew":0},"53":{"depth":0.0,"height":0.64444,"italic":0.0,"skew":0},"54":{"depth":0.0,"height":0.64444,"italic":0.0,"skew":0},"55":{"depth":0.0,"height":0.64444,"italic":0.0,"skew":0},"56":{"depth":0.0,"height":0.64444,"italic":0.0,"skew":0},"567":{"depth":0.19444,"height":0.44444,"italic":0.0,"skew":0},"57":{"depth":0.0,"height":0.64444,"italic":0.0,"skew":0},"58":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"59":{"depth":0.19444,"height":0.44444,"italic":0.0,"skew":0},"60":{"depth":0.08556,"height":0.58556,"italic":0.0,"skew":0},"61":{"depth":-0.10889,"height":0.39111,"italic":0.0,"skew":0},"62":{"depth":0.08556,"height":0.58556,"italic":0.0,"skew":0},"63":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"64":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"65":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"66":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"67":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"68":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"69":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"70":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"71":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"710":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"711":{"depth":0.0,"height":0.63194,"italic":0.0,"skew":0},"713":{"depth":0.0,"height":0.59611,"italic":0.0,"skew":0},"714":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"715":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"72":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"728":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"729":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"73":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"730":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"732":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"74":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"75":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"76":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"768":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"769":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"77":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"770":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"771":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"772":{"depth":0.0,"height":0.59611,"italic":0.0,"skew":0},"774":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"775":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"776":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"778":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"779":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"78":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"780":{"depth":0.0,"height":0.63194,"italic":0.0,"skew":0},"79":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"80":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"81":{"depth":0.19444,"height":0.68611,"italic":0.0,"skew":0},"82":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"8211":{"depth":0.0,"height":0.44444,"italic":0.03194,"skew":0},"8212":{"depth":0.0,"height":0.44444,"italic":0.03194,"skew":0},"8216":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8217":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8220":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8221":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8224":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"8225":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"824":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"8242":{"depth":0.0,"height":0.55556,"italic":0.0,"skew":0},"83":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"84":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"8407":{"depth":0.0,"height":0.72444,"italic":0.15486,"skew":0},"8463":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8465":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8467":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8472":{"depth":0.19444,"height":0.44444,"italic":0.0,"skew":0},"8476":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"85":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"8501":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8592":{"depth":-0.10889,"height":0.39111,"italic":0.0,"skew":0},"8593":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"8594":{"depth":-0.10889,"height":0.39111,"italic":0.0,"skew":0},"8595":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"8596":{"depth":-0.10889,"height":0.39111,"italic":0.0,"skew":0},"8597":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"8598":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"8599":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"86":{"depth":0.0,"height":0.68611,"italic":0.01597,"skew":0},"8600":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"8601":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"8636":{"depth":-0.10889,"height":0.39111,"italic":0.0,"skew":0},"8637":{"depth":-0.10889,"height":0.39111,"italic":0.0,"skew":0},"8640":{"depth":-0.10889,"height":0.39111,"italic":0.0,"skew":0},"8641":{"depth":-0.10889,"height":0.39111,"italic":0.0,"skew":0},"8656":{"depth":-0.10889,"height":0.39111,"italic":0.0,"skew":0},"8657":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"8658":{"depth":-0.10889,"height":0.39111,"italic":0.0,"skew":0},"8659":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"8660":{"depth":-0.10889,"height":0.39111,"italic":0.0,"skew":0},"8661":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"87":{"depth":0.0,"height":0.68611,"italic":0.01597,"skew":0},"8704":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8706":{"depth":0.0,"height":0.69444,"italic":0.06389,"skew":0},"8707":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8709":{"depth":0.05556,"height":0.75,"italic":0.0,"skew":0},"8711":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"8712":{"depth":0.08556,"height":0.58556,"italic":0.0,"skew":0},"8715":{"depth":0.08556,"height":0.58556,"italic":0.0,"skew":0},"8722":{"depth":0.13333,"height":0.63333,"italic":0.0,"skew":0},"8723":{"depth":0.13333,"height":0.63333,"italic":0.0,"skew":0},"8725":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"8726":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"8727":{"depth":-0.02778,"height":0.47222,"italic":0.0,"skew":0},"8728":{"depth":-0.02639,"height":0.47361,"italic":0.0,"skew":0},"8729":{"depth":-0.02639,"height":0.47361,"italic":0.0,"skew":0},"8730":{"depth":0.18,"height":0.82,"italic":0.0,"skew":0},"8733":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"8734":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"8736":{"depth":0.0,"height":0.69224,"italic":0.0,"skew":0},"8739":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"8741":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"8743":{"depth":0.0,"height":0.55556,"italic":0.0,"skew":0},"8744":{"depth":0.0,"height":0.55556,"italic":0.0,"skew":0},"8745":{"depth":0.0,"height":0.55556,"italic":0.0,"skew":0},"8746":{"depth":0.0,"height":0.55556,"italic":0.0,"skew":0},"8747":{"depth":0.19444,"height":0.69444,"italic":0.12778,"skew":0},"8764":{"depth":-0.10889,"height":0.39111,"italic":0.0,"skew":0},"8768":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"8771":{"depth":0.00222,"height":0.50222,"italic":0.0,"skew":0},"8776":{"depth":0.02444,"height":0.52444,"italic":0.0,"skew":0},"8781":{"depth":0.00222,"height":0.50222,"italic":0.0,"skew":0},"88":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"8801":{"depth":0.00222,"height":0.50222,"italic":0.0,"skew":0},"8804":{"depth":0.19667,"height":0.69667,"italic":0.0,"skew":0},"8805":{"depth":0.19667,"height":0.69667,"italic":0.0,"skew":0},"8810":{"depth":0.08556,"height":0.58556,"italic":0.0,"skew":0},"8811":{"depth":0.08556,"height":0.58556,"italic":0.0,"skew":0},"8826":{"depth":0.08556,"height":0.58556,"italic":0.0,"skew":0},"8827":{"depth":0.08556,"height":0.58556,"italic":0.0,"skew":0},"8834":{"depth":0.08556,"height":0.58556,"italic":0.0,"skew":0},"8835":{"depth":0.08556,"height":0.58556,"italic":0.0,"skew":0},"8838":{"depth":0.19667,"height":0.69667,"italic":0.0,"skew":0},"8839":{"depth":0.19667,"height":0.69667,"italic":0.0,"skew":0},"8846":{"depth":0.0,"height":0.55556,"italic":0.0,"skew":0},"8849":{"depth":0.19667,"height":0.69667,"italic":0.0,"skew":0},"8850":{"depth":0.19667,"height":0.69667,"italic":0.0,"skew":0},"8851":{"depth":0.0,"height":0.55556,"italic":0.0,"skew":0},"8852":{"depth":0.0,"height":0.55556,"italic":0.0,"skew":0},"8853":{"depth":0.13333,"height":0.63333,"italic":0.0,"skew":0},"8854":{"depth":0.13333,"height":0.63333,"italic":0.0,"skew":0},"8855":{"depth":0.13333,"height":0.63333,"italic":0.0,"skew":0},"8856":{"depth":0.13333,"height":0.63333,"italic":0.0,"skew":0},"8857":{"depth":0.13333,"height":0.63333,"italic":0.0,"skew":0},"8866":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8867":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8868":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8869":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"89":{"depth":0.0,"height":0.68611,"italic":0.02875,"skew":0},"8900":{"depth":-0.02639,"height":0.47361,"italic":0.0,"skew":0},"8901":{"depth":-0.02639,"height":0.47361,"italic":0.0,"skew":0},"8902":{"depth":-0.02778,"height":0.47222,"italic":0.0,"skew":0},"8968":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"8969":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"8970":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"8971":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"8994":{"depth":-0.13889,"height":0.36111,"italic":0.0,"skew":0},"8995":{"depth":-0.13889,"height":0.36111,"italic":0.0,"skew":0},"90":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"91":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"915":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"916":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"92":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"920":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"923":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"926":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"928":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"93":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"931":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"933":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"934":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"936":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"937":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"94":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"95":{"depth":0.31,"height":0.13444,"italic":0.03194,"skew":0},"96":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"9651":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"9657":{"depth":-0.02778,"height":0.47222,"italic":0.0,"skew":0},"9661":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"9667":{"depth":-0.02778,"height":0.47222,"italic":0.0,"skew":0},"97":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"9711":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"98":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"9824":{"depth":0.12963,"height":0.69444,"italic":0.0,"skew":0},"9825":{"depth":0.12963,"height":0.69444,"italic":0.0,"skew":0},"9826":{"depth":0.12963,"height":0.69444,"italic":0.0,"skew":0},"9827":{"depth":0.12963,"height":0.69444,"italic":0.0,"skew":0},"9837":{"depth":0.0,"height":0.75,"italic":0.0,"skew":0},"9838":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"9839":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"99":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0}},"Main-Italic":{"100":{"depth":0.0,"height":0.69444,"italic":0.10333,"skew":0},"101":{"depth":0.0,"height":0.43056,"italic":0.07514,"skew":0},"102":{"depth":0.19444,"height":0.69444,"italic":0.21194,"skew":0},"103":{"depth":0.19444,"height":0.43056,"italic":0.08847,"skew":0},"104":{"depth":0.0,"height":0.69444,"italic":0.07671,"skew":0},"105":{"depth":0.0,"height":0.65536,"italic":0.1019,"skew":0},"106":{"depth":0.19444,"height":0.65536,"italic":0.14467,"skew":0},"107":{"depth":0.0,"height":0.69444,"italic":0.10764,"skew":0},"108":{"depth":0.0,"height":0.69444,"italic":0.10333,"skew":0},"109":{"depth":0.0,"height":0.43056,"italic":0.07671,"skew":0},"110":{"depth":0.0,"height":0.43056,"italic":0.07671,"skew":0},"111":{"depth":0.0,"height":0.43056,"italic":0.06312,"skew":0},"112":{"depth":0.19444,"height":0.43056,"italic":0.06312,"skew":0},"113":{"depth":0.19444,"height":0.43056,"italic":0.08847,"skew":0},"114":{"depth":0.0,"height":0.43056,"italic":0.10764,"skew":0},"115":{"depth":0.0,"height":0.43056,"italic":0.08208,"skew":0},"116":{"depth":0.0,"height":0.61508,"italic":0.09486,"skew":0},"117":{"depth":0.0,"height":0.43056,"italic":0.07671,"skew":0},"118":{"depth":0.0,"height":0.43056,"italic":0.10764,"skew":0},"119":{"depth":0.0,"height":0.43056,"italic":0.10764,"skew":0},"120":{"depth":0.0,"height":0.43056,"italic":0.12042,"skew":0},"121":{"depth":0.19444,"height":0.43056,"italic":0.08847,"skew":0},"122":{"depth":0.0,"height":0.43056,"italic":0.12292,"skew":0},"126":{"depth":0.35,"height":0.31786,"italic":0.11585,"skew":0},"163":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"305":{"depth":0.0,"height":0.43056,"italic":0.07671,"skew":0},"33":{"depth":0.0,"height":0.69444,"italic":0.12417,"skew":0},"34":{"depth":0.0,"height":0.69444,"italic":0.06961,"skew":0},"35":{"depth":0.19444,"height":0.69444,"italic":0.06616,"skew":0},"37":{"depth":0.05556,"height":0.75,"italic":0.13639,"skew":0},"38":{"depth":0.0,"height":0.69444,"italic":0.09694,"skew":0},"39":{"depth":0.0,"height":0.69444,"italic":0.12417,"skew":0},"40":{"depth":0.25,"height":0.75,"italic":0.16194,"skew":0},"41":{"depth":0.25,"height":0.75,"italic":0.03694,"skew":0},"42":{"depth":0.0,"height":0.75,"italic":0.14917,"skew":0},"43":{"depth":0.05667,"height":0.56167,"italic":0.03694,"skew":0},"44":{"depth":0.19444,"height":0.10556,"italic":0.0,"skew":0},"45":{"depth":0.0,"height":0.43056,"italic":0.02826,"skew":0},"46":{"depth":0.0,"height":0.10556,"italic":0.0,"skew":0},"47":{"depth":0.25,"height":0.75,"italic":0.16194,"skew":0},"48":{"depth":0.0,"height":0.64444,"italic":0.13556,"skew":0},"49":{"depth":0.0,"height":0.64444,"italic":0.13556,"skew":0},"50":{"depth":0.0,"height":0.64444,"italic":0.13556,"skew":0},"51":{"depth":0.0,"height":0.64444,"italic":0.13556,"skew":0},"52":{"depth":0.19444,"height":0.64444,"italic":0.13556,"skew":0},"53":{"depth":0.0,"height":0.64444,"italic":0.13556,"skew":0},"54":{"depth":0.0,"height":0.64444,"italic":0.13556,"skew":0},"55":{"depth":0.19444,"height":0.64444,"italic":0.13556,"skew":0},"56":{"depth":0.0,"height":0.64444,"italic":0.13556,"skew":0},"567":{"depth":0.19444,"height":0.43056,"italic":0.03736,"skew":0},"57":{"depth":0.0,"height":0.64444,"italic":0.13556,"skew":0},"58":{"depth":0.0,"height":0.43056,"italic":0.0582,"skew":0},"59":{"depth":0.19444,"height":0.43056,"italic":0.0582,"skew":0},"61":{"depth":-0.13313,"height":0.36687,"italic":0.06616,"skew":0},"63":{"depth":0.0,"height":0.69444,"italic":0.1225,"skew":0},"64":{"depth":0.0,"height":0.69444,"italic":0.09597,"skew":0},"65":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"66":{"depth":0.0,"height":0.68333,"italic":0.10257,"skew":0},"67":{"depth":0.0,"height":0.68333,"italic":0.14528,"skew":0},"68":{"depth":0.0,"height":0.68333,"italic":0.09403,"skew":0},"69":{"depth":0.0,"height":0.68333,"italic":0.12028,"skew":0},"70":{"depth":0.0,"height":0.68333,"italic":0.13305,"skew":0},"71":{"depth":0.0,"height":0.68333,"italic":0.08722,"skew":0},"72":{"depth":0.0,"height":0.68333,"italic":0.16389,"skew":0},"73":{"depth":0.0,"height":0.68333,"italic":0.15806,"skew":0},"74":{"depth":0.0,"height":0.68333,"italic":0.14028,"skew":0},"75":{"depth":0.0,"height":0.68333,"italic":0.14528,"skew":0},"76":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"768":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"769":{"depth":0.0,"height":0.69444,"italic":0.09694,"skew":0},"77":{"depth":0.0,"height":0.68333,"italic":0.16389,"skew":0},"770":{"depth":0.0,"height":0.69444,"italic":0.06646,"skew":0},"771":{"depth":0.0,"height":0.66786,"italic":0.11585,"skew":0},"772":{"depth":0.0,"height":0.56167,"italic":0.10333,"skew":0},"774":{"depth":0.0,"height":0.69444,"italic":0.10806,"skew":0},"775":{"depth":0.0,"height":0.66786,"italic":0.11752,"skew":0},"776":{"depth":0.0,"height":0.66786,"italic":0.10474,"skew":0},"778":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"779":{"depth":0.0,"height":0.69444,"italic":0.1225,"skew":0},"78":{"depth":0.0,"height":0.68333,"italic":0.16389,"skew":0},"780":{"depth":0.0,"height":0.62847,"italic":0.08295,"skew":0},"79":{"depth":0.0,"height":0.68333,"italic":0.09403,"skew":0},"80":{"depth":0.0,"height":0.68333,"italic":0.10257,"skew":0},"81":{"depth":0.19444,"height":0.68333,"italic":0.09403,"skew":0},"82":{"depth":0.0,"height":0.68333,"italic":0.03868,"skew":0},"8211":{"depth":0.0,"height":0.43056,"italic":0.09208,"skew":0},"8212":{"depth":0.0,"height":0.43056,"italic":0.09208,"skew":0},"8216":{"depth":0.0,"height":0.69444,"italic":0.12417,"skew":0},"8217":{"depth":0.0,"height":0.69444,"italic":0.12417,"skew":0},"8220":{"depth":0.0,"height":0.69444,"italic":0.1685,"skew":0},"8221":{"depth":0.0,"height":0.69444,"italic":0.06961,"skew":0},"83":{"depth":0.0,"height":0.68333,"italic":0.11972,"skew":0},"84":{"depth":0.0,"height":0.68333,"italic":0.13305,"skew":0},"8463":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"85":{"depth":0.0,"height":0.68333,"italic":0.16389,"skew":0},"86":{"depth":0.0,"height":0.68333,"italic":0.18361,"skew":0},"87":{"depth":0.0,"height":0.68333,"italic":0.18361,"skew":0},"88":{"depth":0.0,"height":0.68333,"italic":0.15806,"skew":0},"89":{"depth":0.0,"height":0.68333,"italic":0.19383,"skew":0},"90":{"depth":0.0,"height":0.68333,"italic":0.14528,"skew":0},"91":{"depth":0.25,"height":0.75,"italic":0.1875,"skew":0},"915":{"depth":0.0,"height":0.68333,"italic":0.13305,"skew":0},"916":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"920":{"depth":0.0,"height":0.68333,"italic":0.09403,"skew":0},"923":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"926":{"depth":0.0,"height":0.68333,"italic":0.15294,"skew":0},"928":{"depth":0.0,"height":0.68333,"italic":0.16389,"skew":0},"93":{"depth":0.25,"height":0.75,"italic":0.10528,"skew":0},"931":{"depth":0.0,"height":0.68333,"italic":0.12028,"skew":0},"933":{"depth":0.0,"height":0.68333,"italic":0.11111,"skew":0},"934":{"depth":0.0,"height":0.68333,"italic":0.05986,"skew":0},"936":{"depth":0.0,"height":0.68333,"italic":0.11111,"skew":0},"937":{"depth":0.0,"height":0.68333,"italic":0.10257,"skew":0},"94":{"depth":0.0,"height":0.69444,"italic":0.06646,"skew":0},"95":{"depth":0.31,"height":0.12056,"italic":0.09208,"skew":0},"97":{"depth":0.0,"height":0.43056,"italic":0.07671,"skew":0},"98":{"depth":0.0,"height":0.69444,"italic":0.06312,"skew":0},"99":{"depth":0.0,"height":0.43056,"italic":0.05653,"skew":0}},"Main-Regular":{"32":{"0.0":0},"160":{"0.0":0},"8230":{"-0.0":0,"120.0":0.12},"8773":{"-22.0":-0.022,"0":0,"589.0":0.589},"8800":{"0":0,"215.0":0.215,"716.0":0.716},"8942":{"0":0,"30.0":0.03,"900.0":0.9},"8943":{"-190.0":-0.19,"0":0,"310.0":0.31},"8945":{"-100.0":-0.1,"0":0,"820.0":0.82},"100":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"101":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"102":{"depth":0.0,"height":0.69444,"italic":0.07778,"skew":0},"10216":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"10217":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"103":{"depth":0.19444,"height":0.43056,"italic":0.01389,"skew":0},"104":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"105":{"depth":0.0,"height":0.66786,"italic":0.0,"skew":0},"106":{"depth":0.19444,"height":0.66786,"italic":0.0,"skew":0},"107":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"108":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"10815":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"109":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"10927":{"depth":0.13597,"height":0.63597,"italic":0.0,"skew":0},"10928":{"depth":0.13597,"height":0.63597,"italic":0.0,"skew":0},"110":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"111":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"112":{"depth":0.19444,"height":0.43056,"italic":0.0,"skew":0},"113":{"depth":0.19444,"height":0.43056,"italic":0.0,"skew":0},"114":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"115":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"116":{"depth":0.0,"height":0.61508,"italic":0.0,"skew":0},"117":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"118":{"depth":0.0,"height":0.43056,"italic":0.01389,"skew":0},"119":{"depth":0.0,"height":0.43056,"italic":0.01389,"skew":0},"120":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"121":{"depth":0.19444,"height":0.43056,"italic":0.01389,"skew":0},"122":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"123":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"124":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"125":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"126":{"depth":0.35,"height":0.31786,"italic":0.0,"skew":0},"168":{"depth":0.0,"height":0.66786,"italic":0.0,"skew":0},"172":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"175":{"depth":0.0,"height":0.56778,"italic":0.0,"skew":0},"176":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"177":{"depth":0.08333,"height":0.58333,"italic":0.0,"skew":0},"180":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"215":{"depth":0.08333,"height":0.58333,"italic":0.0,"skew":0},"247":{"depth":0.08333,"height":0.58333,"italic":0.0,"skew":0},"305":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"33":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"34":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"35":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"36":{"depth":0.05556,"height":0.75,"italic":0.0,"skew":0},"37":{"depth":0.05556,"height":0.75,"italic":0.0,"skew":0},"38":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"39":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"40":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"41":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"42":{"depth":0.0,"height":0.75,"italic":0.0,"skew":0},"43":{"depth":0.08333,"height":0.58333,"italic":0.0,"skew":0},"44":{"depth":0.19444,"height":0.10556,"italic":0.0,"skew":0},"45":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"46":{"depth":0.0,"height":0.10556,"italic":0.0,"skew":0},"47":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"48":{"depth":0.0,"height":0.64444,"italic":0.0,"skew":0},"49":{"depth":0.0,"height":0.64444,"italic":0.0,"skew":0},"50":{"depth":0.0,"height":0.64444,"italic":0.0,"skew":0},"51":{"depth":0.0,"height":0.64444,"italic":0.0,"skew":0},"52":{"depth":0.0,"height":0.64444,"italic":0.0,"skew":0},"53":{"depth":0.0,"height":0.64444,"italic":0.0,"skew":0},"54":{"depth":0.0,"height":0.64444,"italic":0.0,"skew":0},"55":{"depth":0.0,"height":0.64444,"italic":0.0,"skew":0},"56":{"depth":0.0,"height":0.64444,"italic":0.0,"skew":0},"567":{"depth":0.19444,"height":0.43056,"italic":0.0,"skew":0},"57":{"depth":0.0,"height":0.64444,"italic":0.0,"skew":0},"58":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"59":{"depth":0.19444,"height":0.43056,"italic":0.0,"skew":0},"60":{"depth":0.0391,"height":0.5391,"italic":0.0,"skew":0},"61":{"depth":-0.13313,"height":0.36687,"italic":0.0,"skew":0},"62":{"depth":0.0391,"height":0.5391,"italic":0.0,"skew":0},"63":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"64":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"65":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"66":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"67":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"68":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"69":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"70":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"71":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"710":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"711":{"depth":0.0,"height":0.62847,"italic":0.0,"skew":0},"713":{"depth":0.0,"height":0.56778,"italic":0.0,"skew":0},"714":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"715":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"72":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"728":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"729":{"depth":0.0,"height":0.66786,"italic":0.0,"skew":0},"73":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"730":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"732":{"depth":0.0,"height":0.66786,"italic":0.0,"skew":0},"74":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"75":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"76":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"768":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"769":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"77":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"770":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"771":{"depth":0.0,"height":0.66786,"italic":0.0,"skew":0},"772":{"depth":0.0,"height":0.56778,"italic":0.0,"skew":0},"774":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"775":{"depth":0.0,"height":0.66786,"italic":0.0,"skew":0},"776":{"depth":0.0,"height":0.66786,"italic":0.0,"skew":0},"778":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"779":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"78":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"780":{"depth":0.0,"height":0.62847,"italic":0.0,"skew":0},"79":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"80":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"81":{"depth":0.19444,"height":0.68333,"italic":0.0,"skew":0},"82":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"8211":{"depth":0.0,"height":0.43056,"italic":0.02778,"skew":0},"8212":{"depth":0.0,"height":0.43056,"italic":0.02778,"skew":0},"8216":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8217":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8220":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8221":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8224":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"8225":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"824":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"8242":{"depth":0.0,"height":0.55556,"italic":0.0,"skew":0},"83":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"84":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"8407":{"depth":0.0,"height":0.71444,"italic":0.15382,"skew":0},"8463":{"depth":0.0,"height":0.68889,"italic":0.0,"skew":0},"8465":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8467":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0.11111},"8472":{"depth":0.19444,"height":0.43056,"italic":0.0,"skew":0.11111},"8476":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"85":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"8501":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8592":{"depth":-0.13313,"height":0.36687,"italic":0.0,"skew":0},"8593":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"8594":{"depth":-0.13313,"height":0.36687,"italic":0.0,"skew":0},"8595":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"8596":{"depth":-0.13313,"height":0.36687,"italic":0.0,"skew":0},"8597":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"8598":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"8599":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"86":{"depth":0.0,"height":0.68333,"italic":0.01389,"skew":0},"8600":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"8601":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"8636":{"depth":-0.13313,"height":0.36687,"italic":0.0,"skew":0},"8637":{"depth":-0.13313,"height":0.36687,"italic":0.0,"skew":0},"8640":{"depth":-0.13313,"height":0.36687,"italic":0.0,"skew":0},"8641":{"depth":-0.13313,"height":0.36687,"italic":0.0,"skew":0},"8656":{"depth":-0.13313,"height":0.36687,"italic":0.0,"skew":0},"8657":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"8658":{"depth":-0.13313,"height":0.36687,"italic":0.0,"skew":0},"8659":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"8660":{"depth":-0.13313,"height":0.36687,"italic":0.0,"skew":0},"8661":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"87":{"depth":0.0,"height":0.68333,"italic":0.01389,"skew":0},"8704":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8706":{"depth":0.0,"height":0.69444,"italic":0.05556,"skew":0.08334},"8707":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8709":{"depth":0.05556,"height":0.75,"italic":0.0,"skew":0},"8711":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"8712":{"depth":0.0391,"height":0.5391,"italic":0.0,"skew":0},"8715":{"depth":0.0391,"height":0.5391,"italic":0.0,"skew":0},"8722":{"depth":0.08333,"height":0.58333,"italic":0.0,"skew":0},"8723":{"depth":0.08333,"height":0.58333,"italic":0.0,"skew":0},"8725":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"8726":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"8727":{"depth":-0.03472,"height":0.46528,"italic":0.0,"skew":0},"8728":{"depth":-0.05555,"height":0.44445,"italic":0.0,"skew":0},"8729":{"depth":-0.05555,"height":0.44445,"italic":0.0,"skew":0},"8730":{"depth":0.2,"height":0.8,"italic":0.0,"skew":0},"8733":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"8734":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"8736":{"depth":0.0,"height":0.69224,"italic":0.0,"skew":0},"8739":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"8741":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"8743":{"depth":0.0,"height":0.55556,"italic":0.0,"skew":0},"8744":{"depth":0.0,"height":0.55556,"italic":0.0,"skew":0},"8745":{"depth":0.0,"height":0.55556,"italic":0.0,"skew":0},"8746":{"depth":0.0,"height":0.55556,"italic":0.0,"skew":0},"8747":{"depth":0.19444,"height":0.69444,"italic":0.11111,"skew":0},"8764":{"depth":-0.13313,"height":0.36687,"italic":0.0,"skew":0},"8768":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"8771":{"depth":-0.03625,"height":0.46375,"italic":0.0,"skew":0},"8776":{"depth":-0.01688,"height":0.48312,"italic":0.0,"skew":0},"8781":{"depth":-0.03625,"height":0.46375,"italic":0.0,"skew":0},"88":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"8801":{"depth":-0.03625,"height":0.46375,"italic":0.0,"skew":0},"8804":{"depth":0.13597,"height":0.63597,"italic":0.0,"skew":0},"8805":{"depth":0.13597,"height":0.63597,"italic":0.0,"skew":0},"8810":{"depth":0.0391,"height":0.5391,"italic":0.0,"skew":0},"8811":{"depth":0.0391,"height":0.5391,"italic":0.0,"skew":0},"8826":{"depth":0.0391,"height":0.5391,"italic":0.0,"skew":0},"8827":{"depth":0.0391,"height":0.5391,"italic":0.0,"skew":0},"8834":{"depth":0.0391,"height":0.5391,"italic":0.0,"skew":0},"8835":{"depth":0.0391,"height":0.5391,"italic":0.0,"skew":0},"8838":{"depth":0.13597,"height":0.63597,"italic":0.0,"skew":0},"8839":{"depth":0.13597,"height":0.63597,"italic":0.0,"skew":0},"8846":{"depth":0.0,"height":0.55556,"italic":0.0,"skew":0},"8849":{"depth":0.13597,"height":0.63597,"italic":0.0,"skew":0},"8850":{"depth":0.13597,"height":0.63597,"italic":0.0,"skew":0},"8851":{"depth":0.0,"height":0.55556,"italic":0.0,"skew":0},"8852":{"depth":0.0,"height":0.55556,"italic":0.0,"skew":0},"8853":{"depth":0.08333,"height":0.58333,"italic":0.0,"skew":0},"8854":{"depth":0.08333,"height":0.58333,"italic":0.0,"skew":0},"8855":{"depth":0.08333,"height":0.58333,"italic":0.0,"skew":0},"8856":{"depth":0.08333,"height":0.58333,"italic":0.0,"skew":0},"8857":{"depth":0.08333,"height":0.58333,"italic":0.0,"skew":0},"8866":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8867":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8868":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"8869":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"89":{"depth":0.0,"height":0.68333,"italic":0.025,"skew":0},"8900":{"depth":-0.05555,"height":0.44445,"italic":0.0,"skew":0},"8901":{"depth":-0.05555,"height":0.44445,"italic":0.0,"skew":0},"8902":{"depth":-0.03472,"height":0.46528,"italic":0.0,"skew":0},"8968":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"8969":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"8970":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"8971":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"8994":{"depth":-0.14236,"height":0.35764,"italic":0.0,"skew":0},"8995":{"depth":-0.14236,"height":0.35764,"italic":0.0,"skew":0},"90":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"91":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"915":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"916":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"92":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"920":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"923":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"926":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"928":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"93":{"depth":0.25,"height":0.75,"italic":0.0,"skew":0},"931":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"933":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"934":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"936":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"937":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0},"94":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"95":{"depth":0.31,"height":0.12056,"italic":0.02778,"skew":0},"96":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"9651":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"9657":{"depth":-0.03472,"height":0.46528,"italic":0.0,"skew":0},"9661":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"9667":{"depth":-0.03472,"height":0.46528,"italic":0.0,"skew":0},"97":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"9711":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"98":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"9824":{"depth":0.12963,"height":0.69444,"italic":0.0,"skew":0},"9825":{"depth":0.12963,"height":0.69444,"italic":0.0,"skew":0},"9826":{"depth":0.12963,"height":0.69444,"italic":0.0,"skew":0},"9827":{"depth":0.12963,"height":0.69444,"italic":0.0,"skew":0},"9837":{"depth":0.0,"height":0.75,"italic":0.0,"skew":0},"9838":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"9839":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"99":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0}},"Math-BoldItalic":{"100":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"1009":{"depth":0.19444,"height":0.44444,"italic":0.0,"skew":0},"101":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"1013":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"102":{"depth":0.19444,"height":0.69444,"italic":0.11042,"skew":0},"103":{"depth":0.19444,"height":0.44444,"italic":0.03704,"skew":0},"104":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"105":{"depth":0.0,"height":0.69326,"italic":0.0,"skew":0},"106":{"depth":0.19444,"height":0.69326,"italic":0.0622,"skew":0},"107":{"depth":0.0,"height":0.69444,"italic":0.01852,"skew":0},"108":{"depth":0.0,"height":0.69444,"italic":0.0088,"skew":0},"109":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"110":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"111":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"112":{"depth":0.19444,"height":0.44444,"italic":0.0,"skew":0},"113":{"depth":0.19444,"height":0.44444,"italic":0.03704,"skew":0},"114":{"depth":0.0,"height":0.44444,"italic":0.03194,"skew":0},"115":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"116":{"depth":0.0,"height":0.63492,"italic":0.0,"skew":0},"117":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"118":{"depth":0.0,"height":0.44444,"italic":0.03704,"skew":0},"119":{"depth":0.0,"height":0.44444,"italic":0.02778,"skew":0},"120":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"121":{"depth":0.19444,"height":0.44444,"italic":0.03704,"skew":0},"122":{"depth":0.0,"height":0.44444,"italic":0.04213,"skew":0},"47":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"65":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"66":{"depth":0.0,"height":0.68611,"italic":0.04835,"skew":0},"67":{"depth":0.0,"height":0.68611,"italic":0.06979,"skew":0},"68":{"depth":0.0,"height":0.68611,"italic":0.03194,"skew":0},"69":{"depth":0.0,"height":0.68611,"italic":0.05451,"skew":0},"70":{"depth":0.0,"height":0.68611,"italic":0.15972,"skew":0},"71":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"72":{"depth":0.0,"height":0.68611,"italic":0.08229,"skew":0},"73":{"depth":0.0,"height":0.68611,"italic":0.07778,"skew":0},"74":{"depth":0.0,"height":0.68611,"italic":0.10069,"skew":0},"75":{"depth":0.0,"height":0.68611,"italic":0.06979,"skew":0},"76":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"77":{"depth":0.0,"height":0.68611,"italic":0.11424,"skew":0},"78":{"depth":0.0,"height":0.68611,"italic":0.11424,"skew":0},"79":{"depth":0.0,"height":0.68611,"italic":0.03194,"skew":0},"80":{"depth":0.0,"height":0.68611,"italic":0.15972,"skew":0},"81":{"depth":0.19444,"height":0.68611,"italic":0.0,"skew":0},"82":{"depth":0.0,"height":0.68611,"italic":0.00421,"skew":0},"83":{"depth":0.0,"height":0.68611,"italic":0.05382,"skew":0},"84":{"depth":0.0,"height":0.68611,"italic":0.15972,"skew":0},"85":{"depth":0.0,"height":0.68611,"italic":0.11424,"skew":0},"86":{"depth":0.0,"height":0.68611,"italic":0.25555,"skew":0},"87":{"depth":0.0,"height":0.68611,"italic":0.15972,"skew":0},"88":{"depth":0.0,"height":0.68611,"italic":0.07778,"skew":0},"89":{"depth":0.0,"height":0.68611,"italic":0.25555,"skew":0},"90":{"depth":0.0,"height":0.68611,"italic":0.06979,"skew":0},"915":{"depth":0.0,"height":0.68611,"italic":0.15972,"skew":0},"916":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"920":{"depth":0.0,"height":0.68611,"italic":0.03194,"skew":0},"923":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"926":{"depth":0.0,"height":0.68611,"italic":0.07458,"skew":0},"928":{"depth":0.0,"height":0.68611,"italic":0.08229,"skew":0},"931":{"depth":0.0,"height":0.68611,"italic":0.05451,"skew":0},"933":{"depth":0.0,"height":0.68611,"italic":0.15972,"skew":0},"934":{"depth":0.0,"height":0.68611,"italic":0.0,"skew":0},"936":{"depth":0.0,"height":0.68611,"italic":0.11653,"skew":0},"937":{"depth":0.0,"height":0.68611,"italic":0.04835,"skew":0},"945":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"946":{"depth":0.19444,"height":0.69444,"italic":0.03403,"skew":0},"947":{"depth":0.19444,"height":0.44444,"italic":0.06389,"skew":0},"948":{"depth":0.0,"height":0.69444,"italic":0.03819,"skew":0},"949":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"950":{"depth":0.19444,"height":0.69444,"italic":0.06215,"skew":0},"951":{"depth":0.19444,"height":0.44444,"italic":0.03704,"skew":0},"952":{"depth":0.0,"height":0.69444,"italic":0.03194,"skew":0},"953":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"954":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"955":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"956":{"depth":0.19444,"height":0.44444,"italic":0.0,"skew":0},"957":{"depth":0.0,"height":0.44444,"italic":0.06898,"skew":0},"958":{"depth":0.19444,"height":0.69444,"italic":0.03021,"skew":0},"959":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"960":{"depth":0.0,"height":0.44444,"italic":0.03704,"skew":0},"961":{"depth":0.19444,"height":0.44444,"italic":0.0,"skew":0},"962":{"depth":0.09722,"height":0.44444,"italic":0.07917,"skew":0},"963":{"depth":0.0,"height":0.44444,"italic":0.03704,"skew":0},"964":{"depth":0.0,"height":0.44444,"italic":0.13472,"skew":0},"965":{"depth":0.0,"height":0.44444,"italic":0.03704,"skew":0},"966":{"depth":0.19444,"height":0.44444,"italic":0.0,"skew":0},"967":{"depth":0.19444,"height":0.44444,"italic":0.0,"skew":0},"968":{"depth":0.19444,"height":0.69444,"italic":0.03704,"skew":0},"969":{"depth":0.0,"height":0.44444,"italic":0.03704,"skew":0},"97":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0},"977":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"98":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"981":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"982":{"depth":0.0,"height":0.44444,"italic":0.03194,"skew":0},"99":{"depth":0.0,"height":0.44444,"italic":0.0,"skew":0}},"Math-Italic":{"100":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0.16667},"1009":{"depth":0.19444,"height":0.43056,"italic":0.0,"skew":0.08334},"101":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0.05556},"1013":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0.05556},"102":{"depth":0.19444,"height":0.69444,"italic":0.10764,"skew":0.16667},"103":{"depth":0.19444,"height":0.43056,"italic":0.03588,"skew":0.02778},"104":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"105":{"depth":0.0,"height":0.65952,"italic":0.0,"skew":0},"106":{"depth":0.19444,"height":0.65952,"italic":0.05724,"skew":0},"107":{"depth":0.0,"height":0.69444,"italic":0.03148,"skew":0},"108":{"depth":0.0,"height":0.69444,"italic":0.01968,"skew":0.08334},"109":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"110":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"111":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0.05556},"112":{"depth":0.19444,"height":0.43056,"italic":0.0,"skew":0.08334},"113":{"depth":0.19444,"height":0.43056,"italic":0.03588,"skew":0.08334},"114":{"depth":0.0,"height":0.43056,"italic":0.02778,"skew":0.05556},"115":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0.05556},"116":{"depth":0.0,"height":0.61508,"italic":0.0,"skew":0.08334},"117":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0.02778},"118":{"depth":0.0,"height":0.43056,"italic":0.03588,"skew":0.02778},"119":{"depth":0.0,"height":0.43056,"italic":0.02691,"skew":0.08334},"120":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0.02778},"121":{"depth":0.19444,"height":0.43056,"italic":0.03588,"skew":0.05556},"122":{"depth":0.0,"height":0.43056,"italic":0.04398,"skew":0.05556},"47":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0},"65":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0.13889},"66":{"depth":0.0,"height":0.68333,"italic":0.05017,"skew":0.08334},"67":{"depth":0.0,"height":0.68333,"italic":0.07153,"skew":0.08334},"68":{"depth":0.0,"height":0.68333,"italic":0.02778,"skew":0.05556},"69":{"depth":0.0,"height":0.68333,"italic":0.05764,"skew":0.08334},"70":{"depth":0.0,"height":0.68333,"italic":0.13889,"skew":0.08334},"71":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0.08334},"72":{"depth":0.0,"height":0.68333,"italic":0.08125,"skew":0.05556},"73":{"depth":0.0,"height":0.68333,"italic":0.07847,"skew":0.11111},"74":{"depth":0.0,"height":0.68333,"italic":0.09618,"skew":0.16667},"75":{"depth":0.0,"height":0.68333,"italic":0.07153,"skew":0.05556},"76":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0.02778},"77":{"depth":0.0,"height":0.68333,"italic":0.10903,"skew":0.08334},"78":{"depth":0.0,"height":0.68333,"italic":0.10903,"skew":0.08334},"79":{"depth":0.0,"height":0.68333,"italic":0.02778,"skew":0.08334},"80":{"depth":0.0,"height":0.68333,"italic":0.13889,"skew":0.08334},"81":{"depth":0.19444,"height":0.68333,"italic":0.0,"skew":0.08334},"82":{"depth":0.0,"height":0.68333,"italic":0.00773,"skew":0.08334},"83":{"depth":0.0,"height":0.68333,"italic":0.05764,"skew":0.08334},"84":{"depth":0.0,"height":0.68333,"italic":0.13889,"skew":0.08334},"85":{"depth":0.0,"height":0.68333,"italic":0.10903,"skew":0.02778},"86":{"depth":0.0,"height":0.68333,"italic":0.22222,"skew":0},"87":{"depth":0.0,"height":0.68333,"italic":0.13889,"skew":0},"88":{"depth":0.0,"height":0.68333,"italic":0.07847,"skew":0.08334},"89":{"depth":0.0,"height":0.68333,"italic":0.22222,"skew":0},"90":{"depth":0.0,"height":0.68333,"italic":0.07153,"skew":0.08334},"915":{"depth":0.0,"height":0.68333,"italic":0.13889,"skew":0.08334},"916":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0.16667},"920":{"depth":0.0,"height":0.68333,"italic":0.02778,"skew":0.08334},"923":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0.16667},"926":{"depth":0.0,"height":0.68333,"italic":0.07569,"skew":0.08334},"928":{"depth":0.0,"height":0.68333,"italic":0.08125,"skew":0.05556},"931":{"depth":0.0,"height":0.68333,"italic":0.05764,"skew":0.08334},"933":{"depth":0.0,"height":0.68333,"italic":0.13889,"skew":0.05556},"934":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0.08334},"936":{"depth":0.0,"height":0.68333,"italic":0.11,"skew":0.05556},"937":{"depth":0.0,"height":0.68333,"italic":0.05017,"skew":0.08334},"945":{"depth":0.0,"height":0.43056,"italic":0.0037,"skew":0.02778},"946":{"depth":0.19444,"height":0.69444,"italic":0.05278,"skew":0.08334},"947":{"depth":0.19444,"height":0.43056,"italic":0.05556,"skew":0},"948":{"depth":0.0,"height":0.69444,"italic":0.03785,"skew":0.05556},"949":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0.08334},"950":{"depth":0.19444,"height":0.69444,"italic":0.07378,"skew":0.08334},"951":{"depth":0.19444,"height":0.43056,"italic":0.03588,"skew":0.05556},"952":{"depth":0.0,"height":0.69444,"italic":0.02778,"skew":0.08334},"953":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0.05556},"954":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"955":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"956":{"depth":0.19444,"height":0.43056,"italic":0.0,"skew":0.02778},"957":{"depth":0.0,"height":0.43056,"italic":0.06366,"skew":0.02778},"958":{"depth":0.19444,"height":0.69444,"italic":0.04601,"skew":0.11111},"959":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0.05556},"960":{"depth":0.0,"height":0.43056,"italic":0.03588,"skew":0},"961":{"depth":0.19444,"height":0.43056,"italic":0.0,"skew":0.08334},"962":{"depth":0.09722,"height":0.43056,"italic":0.07986,"skew":0.08334},"963":{"depth":0.0,"height":0.43056,"italic":0.03588,"skew":0},"964":{"depth":0.0,"height":0.43056,"italic":0.1132,"skew":0.02778},"965":{"depth":0.0,"height":0.43056,"italic":0.03588,"skew":0.02778},"966":{"depth":0.19444,"height":0.43056,"italic":0.0,"skew":0.08334},"967":{"depth":0.19444,"height":0.43056,"italic":0.0,"skew":0.05556},"968":{"depth":0.19444,"height":0.69444,"italic":0.03588,"skew":0.11111},"969":{"depth":0.0,"height":0.43056,"italic":0.03588,"skew":0},"97":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"977":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0.08334},"98":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"981":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0.08334},"982":{"depth":0.0,"height":0.43056,"italic":0.02778,"skew":0},"99":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0.05556}},"Math-Regular":{"100":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0.16667},"1009":{"depth":0.19444,"height":0.43056,"italic":0.0,"skew":0.08334},"101":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0.05556},"1013":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0.05556},"102":{"depth":0.19444,"height":0.69444,"italic":0.10764,"skew":0.16667},"103":{"depth":0.19444,"height":0.43056,"italic":0.03588,"skew":0.02778},"104":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"105":{"depth":0.0,"height":0.65952,"italic":0.0,"skew":0},"106":{"depth":0.19444,"height":0.65952,"italic":0.05724,"skew":0},"107":{"depth":0.0,"height":0.69444,"italic":0.03148,"skew":0},"108":{"depth":0.0,"height":0.69444,"italic":0.01968,"skew":0.08334},"109":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"110":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"111":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0.05556},"112":{"depth":0.19444,"height":0.43056,"italic":0.0,"skew":0.08334},"113":{"depth":0.19444,"height":0.43056,"italic":0.03588,"skew":0.08334},"114":{"depth":0.0,"height":0.43056,"italic":0.02778,"skew":0.05556},"115":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0.05556},"116":{"depth":0.0,"height":0.61508,"italic":0.0,"skew":0.08334},"117":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0.02778},"118":{"depth":0.0,"height":0.43056,"italic":0.03588,"skew":0.02778},"119":{"depth":0.0,"height":0.43056,"italic":0.02691,"skew":0.08334},"120":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0.02778},"121":{"depth":0.19444,"height":0.43056,"italic":0.03588,"skew":0.05556},"122":{"depth":0.0,"height":0.43056,"italic":0.04398,"skew":0.05556},"65":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0.13889},"66":{"depth":0.0,"height":0.68333,"italic":0.05017,"skew":0.08334},"67":{"depth":0.0,"height":0.68333,"italic":0.07153,"skew":0.08334},"68":{"depth":0.0,"height":0.68333,"italic":0.02778,"skew":0.05556},"69":{"depth":0.0,"height":0.68333,"italic":0.05764,"skew":0.08334},"70":{"depth":0.0,"height":0.68333,"italic":0.13889,"skew":0.08334},"71":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0.08334},"72":{"depth":0.0,"height":0.68333,"italic":0.08125,"skew":0.05556},"73":{"depth":0.0,"height":0.68333,"italic":0.07847,"skew":0.11111},"74":{"depth":0.0,"height":0.68333,"italic":0.09618,"skew":0.16667},"75":{"depth":0.0,"height":0.68333,"italic":0.07153,"skew":0.05556},"76":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0.02778},"77":{"depth":0.0,"height":0.68333,"italic":0.10903,"skew":0.08334},"78":{"depth":0.0,"height":0.68333,"italic":0.10903,"skew":0.08334},"79":{"depth":0.0,"height":0.68333,"italic":0.02778,"skew":0.08334},"80":{"depth":0.0,"height":0.68333,"italic":0.13889,"skew":0.08334},"81":{"depth":0.19444,"height":0.68333,"italic":0.0,"skew":0.08334},"82":{"depth":0.0,"height":0.68333,"italic":0.00773,"skew":0.08334},"83":{"depth":0.0,"height":0.68333,"italic":0.05764,"skew":0.08334},"84":{"depth":0.0,"height":0.68333,"italic":0.13889,"skew":0.08334},"85":{"depth":0.0,"height":0.68333,"italic":0.10903,"skew":0.02778},"86":{"depth":0.0,"height":0.68333,"italic":0.22222,"skew":0},"87":{"depth":0.0,"height":0.68333,"italic":0.13889,"skew":0},"88":{"depth":0.0,"height":0.68333,"italic":0.07847,"skew":0.08334},"89":{"depth":0.0,"height":0.68333,"italic":0.22222,"skew":0},"90":{"depth":0.0,"height":0.68333,"italic":0.07153,"skew":0.08334},"915":{"depth":0.0,"height":0.68333,"italic":0.13889,"skew":0.08334},"916":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0.16667},"920":{"depth":0.0,"height":0.68333,"italic":0.02778,"skew":0.08334},"923":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0.16667},"926":{"depth":0.0,"height":0.68333,"italic":0.07569,"skew":0.08334},"928":{"depth":0.0,"height":0.68333,"italic":0.08125,"skew":0.05556},"931":{"depth":0.0,"height":0.68333,"italic":0.05764,"skew":0.08334},"933":{"depth":0.0,"height":0.68333,"italic":0.13889,"skew":0.05556},"934":{"depth":0.0,"height":0.68333,"italic":0.0,"skew":0.08334},"936":{"depth":0.0,"height":0.68333,"italic":0.11,"skew":0.05556},"937":{"depth":0.0,"height":0.68333,"italic":0.05017,"skew":0.08334},"945":{"depth":0.0,"height":0.43056,"italic":0.0037,"skew":0.02778},"946":{"depth":0.19444,"height":0.69444,"italic":0.05278,"skew":0.08334},"947":{"depth":0.19444,"height":0.43056,"italic":0.05556,"skew":0},"948":{"depth":0.0,"height":0.69444,"italic":0.03785,"skew":0.05556},"949":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0.08334},"950":{"depth":0.19444,"height":0.69444,"italic":0.07378,"skew":0.08334},"951":{"depth":0.19444,"height":0.43056,"italic":0.03588,"skew":0.05556},"952":{"depth":0.0,"height":0.69444,"italic":0.02778,"skew":0.08334},"953":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0.05556},"954":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"955":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"956":{"depth":0.19444,"height":0.43056,"italic":0.0,"skew":0.02778},"957":{"depth":0.0,"height":0.43056,"italic":0.06366,"skew":0.02778},"958":{"depth":0.19444,"height":0.69444,"italic":0.04601,"skew":0.11111},"959":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0.05556},"960":{"depth":0.0,"height":0.43056,"italic":0.03588,"skew":0},"961":{"depth":0.19444,"height":0.43056,"italic":0.0,"skew":0.08334},"962":{"depth":0.09722,"height":0.43056,"italic":0.07986,"skew":0.08334},"963":{"depth":0.0,"height":0.43056,"italic":0.03588,"skew":0},"964":{"depth":0.0,"height":0.43056,"italic":0.1132,"skew":0.02778},"965":{"depth":0.0,"height":0.43056,"italic":0.03588,"skew":0.02778},"966":{"depth":0.19444,"height":0.43056,"italic":0.0,"skew":0.08334},"967":{"depth":0.19444,"height":0.43056,"italic":0.0,"skew":0.05556},"968":{"depth":0.19444,"height":0.69444,"italic":0.03588,"skew":0.11111},"969":{"depth":0.0,"height":0.43056,"italic":0.03588,"skew":0},"97":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0},"977":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0.08334},"98":{"depth":0.0,"height":0.69444,"italic":0.0,"skew":0},"981":{"depth":0.19444,"height":0.69444,"italic":0.0,"skew":0.08334},"982":{"depth":0.0,"height":0.43056,"italic":0.02778,"skew":0},"99":{"depth":0.0,"height":0.43056,"italic":0.0,"skew":0.05556}},"Size1-Regular":{"10216":{"depth":0.35001,"height":0.85,"italic":0.0,"skew":0},"10217":{"depth":0.35001,"height":0.85,"italic":0.0,"skew":0},"10752":{"depth":0.25001,"height":0.75,"italic":0.0,"skew":0},"10753":{"depth":0.25001,"height":0.75,"italic":0.0,"skew":0},"10754":{"depth":0.25001,"height":0.75,"italic":0.0,"skew":0},"10756":{"depth":0.25001,"height":0.75,"italic":0.0,"skew":0},"10758":{"depth":0.25001,"height":0.75,"italic":0.0,"skew":0},"123":{"depth":0.35001,"height":0.85,"italic":0.0,"skew":0},"125":{"depth":0.35001,"height":0.85,"italic":0.0,"skew":0},"40":{"depth":0.35001,"height":0.85,"italic":0.0,"skew":0},"41":{"depth":0.35001,"height":0.85,"italic":0.0,"skew":0},"47":{"depth":0.35001,"height":0.85,"italic":0.0,"skew":0},"710":{"depth":0.0,"height":0.72222,"italic":0.0,"skew":0},"732":{"depth":0.0,"height":0.72222,"italic":0.0,"skew":0},"770":{"depth":0.0,"height":0.72222,"italic":0.0,"skew":0},"771":{"depth":0.0,"height":0.72222,"italic":0.0,"skew":0},"8214":{"depth":-0.00099,"height":0.601,"italic":0.0,"skew":0},"8593":{"depth":1e-05,"height":0.6,"italic":0.0,"skew":0},"8595":{"depth":1e-05,"height":0.6,"italic":0.0,"skew":0},"8657":{"depth":1e-05,"height":0.6,"italic":0.0,"skew":0},"8659":{"depth":1e-05,"height":0.6,"italic":0.0,"skew":0},"8719":{"depth":0.25001,"height":0.75,"italic":0.0,"skew":0},"8720":{"depth":0.25001,"height":0.75,"italic":0.0,"skew":0},"8721":{"depth":0.25001,"height":0.75,"italic":0.0,"skew":0},"8730":{"depth":0.35001,"height":0.85,"italic":0.0,"skew":0},"8739":{"depth":-0.00599,"height":0.606,"italic":0.0,"skew":0},"8741":{"depth":-0.00599,"height":0.606,"italic":0.0,"skew":0},"8747":{"depth":0.30612,"height":0.805,"italic":0.19445,"skew":0},"8750":{"depth":0.30612,"height":0.805,"italic":0.19445,"skew":0},"8896":{"depth":0.25001,"height":0.75,"italic":0.0,"skew":0},"8897":{"depth":0.25001,"height":0.75,"italic":0.0,"skew":0},"8898":{"depth":0.25001,"height":0.75,"italic":0.0,"skew":0},"8899":{"depth":0.25001,"height":0.75,"italic":0.0,"skew":0},"8968":{"depth":0.35001,"height":0.85,"italic":0.0,"skew":0},"8969":{"depth":0.35001,"height":0.85,"italic":0.0,"skew":0},"8970":{"depth":0.35001,"height":0.85,"italic":0.0,"skew":0},"8971":{"depth":0.35001,"height":0.85,"italic":0.0,"skew":0},"91":{"depth":0.35001,"height":0.85,"italic":0.0,"skew":0},"9168":{"depth":-0.00099,"height":0.601,"italic":0.0,"skew":0},"92":{"depth":0.35001,"height":0.85,"italic":0.0,"skew":0},"93":{"depth":0.35001,"height":0.85,"italic":0.0,"skew":0}},"Size2-Regular":{"10216":{"depth":0.65002,"height":1.15,"italic":0.0,"skew":0},"10217":{"depth":0.65002,"height":1.15,"italic":0.0,"skew":0},"10752":{"depth":0.55001,"height":1.05,"italic":0.0,"skew":0},"10753":{"depth":0.55001,"height":1.05,"italic":0.0,"skew":0},"10754":{"depth":0.55001,"height":1.05,"italic":0.0,"skew":0},"10756":{"depth":0.55001,"height":1.05,"italic":0.0,"skew":0},"10758":{"depth":0.55001,"height":1.05,"italic":0.0,"skew":0},"123":{"depth":0.65002,"height":1.15,"italic":0.0,"skew":0},"125":{"depth":0.65002,"height":1.15,"italic":0.0,"skew":0},"40":{"depth":0.65002,"height":1.15,"italic":0.0,"skew":0},"41":{"depth":0.65002,"height":1.15,"italic":0.0,"skew":0},"47":{"depth":0.65002,"height":1.15,"italic":0.0,"skew":0},"710":{"depth":0.0,"height":0.75,"italic":0.0,"skew":0},"732":{"depth":0.0,"height":0.75,"italic":0.0,"skew":0},"770":{"depth":0.0,"height":0.75,"italic":0.0,"skew":0},"771":{"depth":0.0,"height":0.75,"italic":0.0,"skew":0},"8719":{"depth":0.55001,"height":1.05,"italic":0.0,"skew":0},"8720":{"depth":0.55001,"height":1.05,"italic":0.0,"skew":0},"8721":{"depth":0.55001,"height":1.05,"italic":0.0,"skew":0},"8730":{"depth":0.65002,"height":1.15,"italic":0.0,"skew":0},"8747":{"depth":0.86225,"height":1.36,"italic":0.44445,"skew":0},"8750":{"depth":0.86225,"height":1.36,"italic":0.44445,"skew":0},"8896":{"depth":0.55001,"height":1.05,"italic":0.0,"skew":0},"8897":{"depth":0.55001,"height":1.05,"italic":0.0,"skew":0},"8898":{"depth":0.55001,"height":1.05,"italic":0.0,"skew":0},"8899":{"depth":0.55001,"height":1.05,"italic":0.0,"skew":0},"8968":{"depth":0.65002,"height":1.15,"italic":0.0,"skew":0},"8969":{"depth":0.65002,"height":1.15,"italic":0.0,"skew":0},"8970":{"depth":0.65002,"height":1.15,"italic":0.0,"skew":0},"8971":{"depth":0.65002,"height":1.15,"italic":0.0,"skew":0},"91":{"depth":0.65002,"height":1.15,"italic":0.0,"skew":0},"92":{"depth":0.65002,"height":1.15,"italic":0.0,"skew":0},"93":{"depth":0.65002,"height":1.15,"italic":0.0,"skew":0}},"Size3-Regular":{"10216":{"depth":0.95003,"height":1.45,"italic":0.0,"skew":0},"10217":{"depth":0.95003,"height":1.45,"italic":0.0,"skew":0},"123":{"depth":0.95003,"height":1.45,"italic":0.0,"skew":0},"125":{"depth":0.95003,"height":1.45,"italic":0.0,"skew":0},"40":{"depth":0.95003,"height":1.45,"italic":0.0,"skew":0},"41":{"depth":0.95003,"height":1.45,"italic":0.0,"skew":0},"47":{"depth":0.95003,"height":1.45,"italic":0.0,"skew":0},"710":{"depth":0.0,"height":0.75,"italic":0.0,"skew":0},"732":{"depth":0.0,"height":0.75,"italic":0.0,"skew":0},"770":{"depth":0.0,"height":0.75,"italic":0.0,"skew":0},"771":{"depth":0.0,"height":0.75,"italic":0.0,"skew":0},"8730":{"depth":0.95003,"height":1.45,"italic":0.0,"skew":0},"8968":{"depth":0.95003,"height":1.45,"italic":0.0,"skew":0},"8969":{"depth":0.95003,"height":1.45,"italic":0.0,"skew":0},"8970":{"depth":0.95003,"height":1.45,"italic":0.0,"skew":0},"8971":{"depth":0.95003,"height":1.45,"italic":0.0,"skew":0},"91":{"depth":0.95003,"height":1.45,"italic":0.0,"skew":0},"92":{"depth":0.95003,"height":1.45,"italic":0.0,"skew":0},"93":{"depth":0.95003,"height":1.45,"italic":0.0,"skew":0}},"Size4-Regular":{"10216":{"depth":1.25003,"height":1.75,"italic":0.0,"skew":0},"10217":{"depth":1.25003,"height":1.75,"italic":0.0,"skew":0},"123":{"depth":1.25003,"height":1.75,"italic":0.0,"skew":0},"125":{"depth":1.25003,"height":1.75,"italic":0.0,"skew":0},"40":{"depth":1.25003,"height":1.75,"italic":0.0,"skew":0},"41":{"depth":1.25003,"height":1.75,"italic":0.0,"skew":0},"47":{"depth":1.25003,"height":1.75,"italic":0.0,"skew":0},"57344":{"depth":-0.00499,"height":0.605,"italic":0.0,"skew":0},"57345":{"depth":-0.00499,"height":0.605,"italic":0.0,"skew":0},"57680":{"depth":0.0,"height":0.12,"italic":0.0,"skew":0},"57681":{"depth":0.0,"height":0.12,"italic":0.0,"skew":0},"57682":{"depth":0.0,"height":0.12,"italic":0.0,"skew":0},"57683":{"depth":0.0,"height":0.12,"italic":0.0,"skew":0},"710":{"depth":0.0,"height":0.825,"italic":0.0,"skew":0},"732":{"depth":0.0,"height":0.825,"italic":0.0,"skew":0},"770":{"depth":0.0,"height":0.825,"italic":0.0,"skew":0},"771":{"depth":0.0,"height":0.825,"italic":0.0,"skew":0},"8730":{"depth":1.25003,"height":1.75,"italic":0.0,"skew":0},"8968":{"depth":1.25003,"height":1.75,"italic":0.0,"skew":0},"8969":{"depth":1.25003,"height":1.75,"italic":0.0,"skew":0},"8970":{"depth":1.25003,"height":1.75,"italic":0.0,"skew":0},"8971":{"depth":1.25003,"height":1.75,"italic":0.0,"skew":0},"91":{"depth":1.25003,"height":1.75,"italic":0.0,"skew":0},"9115":{"depth":0.64502,"height":1.155,"italic":0.0,"skew":0},"9116":{"depth":1e-05,"height":0.6,"italic":0.0,"skew":0},"9117":{"depth":0.64502,"height":1.155,"italic":0.0,"skew":0},"9118":{"depth":0.64502,"height":1.155,"italic":0.0,"skew":0},"9119":{"depth":1e-05,"height":0.6,"italic":0.0,"skew":0},"9120":{"depth":0.64502,"height":1.155,"italic":0.0,"skew":0},"9121":{"depth":0.64502,"height":1.155,"italic":0.0,"skew":0},"9122":{"depth":-0.00099,"height":0.601,"italic":0.0,"skew":0},"9123":{"depth":0.64502,"height":1.155,"italic":0.0,"skew":0},"9124":{"depth":0.64502,"height":1.155,"italic":0.0,"skew":0},"9125":{"depth":-0.00099,"height":0.601,"italic":0.0,"skew":0},"9126":{"depth":0.64502,"height":1.155,"italic":0.0,"skew":0},"9127":{"depth":1e-05,"height":0.9,"italic":0.0,"skew":0},"9128":{"depth":0.65002,"height":1.15,"italic":0.0,"skew":0},"9129":{"depth":0.90001,"height":0.0,"italic":0.0,"skew":0},"9130":{"depth":0.0,"height":0.3,"italic":0.0,"skew":0},"9131":{"depth":1e-05,"height":0.9,"italic":0.0,"skew":0},"9132":{"depth":0.65002,"height":1.15,"italic":0.0,"skew":0},"9133":{"depth":0.90001,"height":0.0,"italic":0.0,"skew":0},"9143":{"depth":0.88502,"height":0.915,"italic":0.0,"skew":0},"92":{"depth":1.25003,"height":1.75,"italic":0.0,"skew":0},"93":{"depth":1.25003,"height":1.75,"italic":0.0,"skew":0}}};
+/**
+ * This function is a convience function for looking up information in the
+ * metricMap table. It takes a character as a string, and a style
+ */
var getCharacterMetrics = function(character, style) {
return metricMap[style][character.charCodeAt(0)];
};
diff --git a/katex.js b/katex.js
@@ -1,9 +1,21 @@
+/**
+ * This is the main entry point for KaTeX. Here, we expose functions for
+ * rendering expressions either to DOM nodes or to markup strings.
+ *
+ * We also expose the ParseError class to check if errors thrown from KaTeX are
+ * errors in the expression, or errors in javascript handling.
+ */
+
var ParseError = require("./ParseError");
var buildTree = require("./buildTree");
var parseTree = require("./parseTree");
var utils = require("./utils");
+/**
+ * Parse and build an expression, and place that expression in the DOM node
+ * given.
+ */
var process = function(toParse, baseNode) {
utils.clearNode(baseNode);
@@ -13,6 +25,9 @@ var process = function(toParse, baseNode) {
baseNode.appendChild(node);
};
+/**
+ * Parse and build an expression, and return the markup for that.
+ */
var renderToString = function(toParse) {
var tree = parseTree(toParse);
return buildTree(tree).toMarkup();
diff --git a/parseTree.js b/parseTree.js
@@ -1,6 +1,13 @@
+/**
+ * Provides a single function for parsing an expression using a Parser
+ * TODO(emily): Remove this
+ */
+
var Parser = require("./Parser");
-// Parses the expression using the parser
+/**
+ * Parses an expression using a Parser, then returns the parsed result.
+ */
var parseTree = function(toParse) {
var parser = new Parser(toParse);
diff --git a/symbols.js b/symbols.js
@@ -1,15 +1,18 @@
-/* This file holds a list of all no-argument functions and single-character
- * symbols (like 'a' or ';'). For each of the symbols, there are three
- * properties they can have:
- * - font (required): the font to be used for this * symbol. Either "main" (the
- normal font), or "ams" (the ams fonts)
+/**
+ * This file holds a list of all no-argument functions and single-character
+ * symbols (like 'a' or ';').
+ *
+ * For each of the symbols, there are three properties they can have:
+ * - font (required): the font to be used for this symbol. Either "main" (the
+ normal font), or "ams" (the ams fonts).
* - group (required): the ParseNode group type the symbol should have (i.e.
- "textord" or "mathord" or
- * - replace (optiona): the character that this symbol or function should be
+ "textord", "mathord", etc).
+ * - replace (optional): the character that this symbol or function should be
* replaced with (i.e. "\phi" has a replace value of "\u03d5", the phi
- * character in the main font)
- * There outermost map in the table indicates what mode the symbols should be
- * accepted in (e.g. "math" or "text")
+ * character in the main font).
+ *
+ * The outermost map in the table indicates what mode the symbols should be
+ * accepted in (e.g. "math" or "text").
*/
var symbols = {
@@ -854,6 +857,9 @@ var symbols = {
}
};
+// There are lots of symbols which are the same, so we add them in afterwards.
+
+// All of these are textords in math mode
var mathTextSymbols = "0123456789/@.\"";
for (var i = 0; i < mathTextSymbols.length; i++) {
var ch = mathTextSymbols.charAt(i);
@@ -863,6 +869,7 @@ for (var i = 0; i < mathTextSymbols.length; i++) {
};
}
+// All of these are textords in text mode
var textSymbols = "0123456789`!@*()-=+[]'\";:?/.,";
for (var i = 0; i < textSymbols.length; i++) {
var ch = textSymbols.charAt(i);
@@ -872,6 +879,7 @@ for (var i = 0; i < textSymbols.length; i++) {
};
}
+// All of these are textords in text mode, and mathords in math mode
var letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (var i = 0; i < letters.length; i++) {
var ch = letters.charAt(i);
diff --git a/utils.js b/utils.js
@@ -1,3 +1,12 @@
+/**
+ * This file contains a list of utility functions which are useful in other
+ * files.
+ */
+
+/**
+ * Provide an `indexOf` function which works in IE8, but defers to native if
+ * possible.
+ */
var nativeIndexOf = Array.prototype.indexOf;
var indexOf = function(list, elem) {
if (list == null) {
@@ -15,6 +24,9 @@ var indexOf = function(list, elem) {
return -1;
};
+/**
+ * Return whether an element is contained in a list
+ */
var contains = function(list, elem) {
return indexOf(list, elem) !== -1;
};
@@ -50,8 +62,11 @@ function escape(text) {
return ('' + text).replace(ESCAPE_REGEX, escaper);
}
+/**
+ * A function to set the text content of a DOM element in all supported
+ * browsers. Note that we don't define this if there is no document.
+ */
var setTextContent;
-
if (typeof document !== "undefined") {
var testNode = document.createElement("span");
if ("textContent" in testNode) {
@@ -65,6 +80,9 @@ if (typeof document !== "undefined") {
}
}
+/**
+ * A function to clear a node.
+ */
function clearNode(node) {
setTextContent(node, "");
}