• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.katex = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
2/* eslint no-console:0 */
3/**
4 * This is the main entry point for KaTeX. Here, we expose functions for
5 * rendering expressions either to DOM nodes or to markup strings.
6 *
7 * We also expose the ParseError class to check if errors thrown from KaTeX are
8 * errors in the expression, or errors in javascript handling.
9 */
10
11var ParseError = require("./src/ParseError");
12var Settings = require("./src/Settings");
13
14var buildTree = require("./src/buildTree");
15var parseTree = require("./src/parseTree");
16var utils = require("./src/utils");
17
18/**
19 * Parse and build an expression, and place that expression in the DOM node
20 * given.
21 */
22var render = function(expression, baseNode, options) {
23    utils.clearNode(baseNode);
24
25    var settings = new Settings(options);
26
27    var tree = parseTree(expression, settings);
28    var node = buildTree(tree, expression, settings).toNode();
29
30    baseNode.appendChild(node);
31};
32
33// KaTeX's styles don't work properly in quirks mode. Print out an error, and
34// disable rendering.
35if (typeof document !== "undefined") {
36    if (document.compatMode !== "CSS1Compat") {
37        typeof console !== "undefined" && console.warn(
38            "Warning: KaTeX doesn't work in quirks mode. Make sure your " +
39                "website has a suitable doctype.");
40
41        render = function() {
42            throw new ParseError("KaTeX doesn't work in quirks mode.");
43        };
44    }
45}
46
47/**
48 * Parse and build an expression, and return the markup for that.
49 */
50var renderToString = function(expression, options) {
51    var settings = new Settings(options);
52
53    var tree = parseTree(expression, settings);
54    return buildTree(tree, expression, settings).toMarkup();
55};
56
57/**
58 * Parse an expression and return the parse tree.
59 */
60var generateParseTree = function(expression, options) {
61    var settings = new Settings(options);
62    return parseTree(expression, settings);
63};
64
65module.exports = {
66    render: render,
67    renderToString: renderToString,
68    /**
69     * NOTE: This method is not currently recommended for public use.
70     * The internal tree representation is unstable and is very likely
71     * to change. Use at your own risk.
72     */
73    __parse: generateParseTree,
74    ParseError: ParseError
75};
76
77},{"./src/ParseError":6,"./src/Settings":8,"./src/buildTree":13,"./src/parseTree":22,"./src/utils":25}],2:[function(require,module,exports){
78/** @flow */
79
80"use strict";
81
82function getRelocatable(re) {
83  // In the future, this could use a WeakMap instead of an expando.
84  if (!re.__matchAtRelocatable) {
85    // Disjunctions are the lowest-precedence operator, so we can make any
86    // pattern match the empty string by appending `|()` to it:
87    // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-patterns
88    var source = re.source + "|()";
89
90    // We always make the new regex global.
91    var flags = "g" + (re.ignoreCase ? "i" : "") + (re.multiline ? "m" : "") + (re.unicode ? "u" : "")
92    // sticky (/.../y) doesn't make sense in conjunction with our relocation
93    // logic, so we ignore it here.
94    ;
95
96    re.__matchAtRelocatable = new RegExp(source, flags);
97  }
98  return re.__matchAtRelocatable;
99}
100
101function matchAt(re, str, pos) {
102  if (re.global || re.sticky) {
103    throw new Error("matchAt(...): Only non-global regexes are supported");
104  }
105  var reloc = getRelocatable(re);
106  reloc.lastIndex = pos;
107  var match = reloc.exec(str);
108  // Last capturing group is our sentinel that indicates whether the regex
109  // matched at the given location.
110  if (match[match.length - 1] == null) {
111    // Original regex matched.
112    match.length = match.length - 1;
113    return match;
114  } else {
115    return null;
116  }
117}
118
119module.exports = matchAt;
120},{}],3:[function(require,module,exports){
121/**
122 * The Lexer class handles tokenizing the input in various ways. Since our
123 * parser expects us to be able to backtrack, the lexer allows lexing from any
124 * given starting point.
125 *
126 * Its main exposed function is the `lex` function, which takes a position to
127 * lex from and a type of token to lex. It defers to the appropriate `_innerLex`
128 * function.
129 *
130 * The various `_innerLex` functions perform the actual lexing of different
131 * kinds.
132 */
133
134var matchAt = require("match-at");
135
136var ParseError = require("./ParseError");
137
138// The main lexer class
139function Lexer(input) {
140    this.input = input;
141    this.pos = 0;
142}
143
144/**
145 * The resulting token returned from `lex`.
146 *
147 * It consists of the token text plus some position information.
148 * The position information is essentially a range in an input string,
149 * but instead of referencing the bare input string, we refer to the lexer.
150 * That way it is possible to attach extra metadata to the input string,
151 * like for example a file name or similar.
152 *
153 * The position information (all three parameters) is optional,
154 * so it is OK to construct synthetic tokens if appropriate.
155 * Not providing available position information may lead to
156 * degraded error reporting, though.
157 *
158 * @param {string}  text   the text of this token
159 * @param {number=} start  the start offset, zero-based inclusive
160 * @param {number=} end    the end offset, zero-based exclusive
161 * @param {Lexer=}  lexer  the lexer which in turn holds the input string
162 */
163function Token(text, start, end, lexer) {
164    this.text = text;
165    this.start = start;
166    this.end = end;
167    this.lexer = lexer;
168}
169
170/**
171 * Given a pair of tokens (this and endToken), compute a “Token” encompassing
172 * the whole input range enclosed by these two.
173 *
174 * @param {Token}  endToken  last token of the range, inclusive
175 * @param {string} text      the text of the newly constructed token
176 */
177Token.prototype.range = function(endToken, text) {
178    if (endToken.lexer !== this.lexer) {
179        return new Token(text); // sorry, no position information available
180    }
181    return new Token(text, this.start, endToken.end, this.lexer);
182};
183
184/* The following tokenRegex
185 * - matches typical whitespace (but not NBSP etc.) using its first group
186 * - does not match any control character \x00-\x1f except whitespace
187 * - does not match a bare backslash
188 * - matches any ASCII character except those just mentioned
189 * - does not match the BMP private use area \uE000-\uF8FF
190 * - does not match bare surrogate code units
191 * - matches any BMP character except for those just described
192 * - matches any valid Unicode surrogate pair
193 * - matches a backslash followed by one or more letters
194 * - matches a backslash followed by any BMP character, including newline
195 * Just because the Lexer matches something doesn't mean it's valid input:
196 * If there is no matching function or symbol definition, the Parser will
197 * still reject the input.
198 */
199var tokenRegex = new RegExp(
200    "([ \r\n\t]+)|" +                                 // whitespace
201    "([!-\\[\\]-\u2027\u202A-\uD7FF\uF900-\uFFFF]" +  // single codepoint
202    "|[\uD800-\uDBFF][\uDC00-\uDFFF]" +               // surrogate pair
203    "|\\\\(?:[a-zA-Z]+|[^\uD800-\uDFFF])" +           // function name
204    ")"
205);
206
207/**
208 * This function lexes a single token.
209 */
210Lexer.prototype.lex = function() {
211    var input = this.input;
212    var pos = this.pos;
213    if (pos === input.length) {
214        return new Token("EOF", pos, pos, this);
215    }
216    var match = matchAt(tokenRegex, input, pos);
217    if (match === null) {
218        throw new ParseError(
219            "Unexpected character: '" + input[pos] + "'",
220            new Token(input[pos], pos, pos + 1, this));
221    }
222    var text = match[2] || " ";
223    var start = this.pos;
224    this.pos += match[0].length;
225    var end = this.pos;
226    return new Token(text, start, end, this);
227};
228
229module.exports = Lexer;
230
231},{"./ParseError":6,"match-at":2}],4:[function(require,module,exports){
232/**
233 * This file contains the “gullet” where macros are expanded
234 * until only non-macro tokens remain.
235 */
236
237var Lexer = require("./Lexer");
238
239function MacroExpander(input, macros) {
240    this.lexer = new Lexer(input);
241    this.macros = macros;
242    this.stack = []; // contains tokens in REVERSE order
243    this.discardedWhiteSpace = [];
244}
245
246/**
247 * Recursively expand first token, then return first non-expandable token.
248 */
249MacroExpander.prototype.nextToken = function() {
250    for (;;) {
251        if (this.stack.length === 0) {
252            this.stack.push(this.lexer.lex());
253        }
254        var topToken = this.stack.pop();
255        var name = topToken.text;
256        if (!(name.charAt(0) === "\\" && this.macros.hasOwnProperty(name))) {
257            return topToken;
258        }
259        var expansion = this.macros[name];
260        if (typeof expansion === "string") {
261            var bodyLexer = new Lexer(expansion);
262            expansion = [];
263            var tok = bodyLexer.lex();
264            while (tok.text !== "EOF") {
265                expansion.push(tok);
266                tok = bodyLexer.lex();
267            }
268            expansion.reverse(); // to fit in with stack using push and pop
269            this.macros[name] = expansion;
270        }
271        this.stack = this.stack.concat(expansion);
272    }
273};
274
275MacroExpander.prototype.get = function(ignoreSpace) {
276    this.discardedWhiteSpace = [];
277    var token = this.nextToken();
278    if (ignoreSpace) {
279        while (token.text === " ") {
280            this.discardedWhiteSpace.push(token);
281            token = this.nextToken();
282        }
283    }
284    return token;
285};
286
287/**
288 * Undo the effect of the preceding call to the get method.
289 * A call to this method MUST be immediately preceded and immediately followed
290 * by a call to get.  Only used during mode switching, i.e. after one token
291 * was got in the old mode but should get got again in a new mode
292 * with possibly different whitespace handling.
293 */
294MacroExpander.prototype.unget = function(token) {
295    this.stack.push(token);
296    while (this.discardedWhiteSpace.length !== 0) {
297        this.stack.push(this.discardedWhiteSpace.pop());
298    }
299};
300
301module.exports = MacroExpander;
302
303},{"./Lexer":3}],5:[function(require,module,exports){
304/**
305 * This file contains information about the options that the Parser carries
306 * around with it while parsing. Data is held in an `Options` object, and when
307 * recursing, a new `Options` object can be created with the `.with*` and
308 * `.reset` functions.
309 */
310
311/**
312 * This is the main options class. It contains the style, size, color, and font
313 * of the current parse level. It also contains the style and size of the parent
314 * parse level, so size changes can be handled efficiently.
315 *
316 * Each of the `.with*` and `.reset` functions passes its current style and size
317 * as the parentStyle and parentSize of the new options class, so parent
318 * handling is taken care of automatically.
319 */
320function Options(data) {
321    this.style = data.style;
322    this.color = data.color;
323    this.size = data.size;
324    this.phantom = data.phantom;
325    this.font = data.font;
326
327    if (data.parentStyle === undefined) {
328        this.parentStyle = data.style;
329    } else {
330        this.parentStyle = data.parentStyle;
331    }
332
333    if (data.parentSize === undefined) {
334        this.parentSize = data.size;
335    } else {
336        this.parentSize = data.parentSize;
337    }
338}
339
340/**
341 * Returns a new options object with the same properties as "this".  Properties
342 * from "extension" will be copied to the new options object.
343 */
344Options.prototype.extend = function(extension) {
345    var data = {
346        style: this.style,
347        size: this.size,
348        color: this.color,
349        parentStyle: this.style,
350        parentSize: this.size,
351        phantom: this.phantom,
352        font: this.font
353    };
354
355    for (var key in extension) {
356        if (extension.hasOwnProperty(key)) {
357            data[key] = extension[key];
358        }
359    }
360
361    return new Options(data);
362};
363
364/**
365 * Create a new options object with the given style.
366 */
367Options.prototype.withStyle = function(style) {
368    return this.extend({
369        style: style
370    });
371};
372
373/**
374 * Create a new options object with the given size.
375 */
376Options.prototype.withSize = function(size) {
377    return this.extend({
378        size: size
379    });
380};
381
382/**
383 * Create a new options object with the given color.
384 */
385Options.prototype.withColor = function(color) {
386    return this.extend({
387        color: color
388    });
389};
390
391/**
392 * Create a new options object with "phantom" set to true.
393 */
394Options.prototype.withPhantom = function() {
395    return this.extend({
396        phantom: true
397    });
398};
399
400/**
401 * Create a new options objects with the give font.
402 */
403Options.prototype.withFont = function(font) {
404    return this.extend({
405        font: font || this.font
406    });
407};
408
409/**
410 * Create a new options object with the same style, size, and color. This is
411 * used so that parent style and size changes are handled correctly.
412 */
413Options.prototype.reset = function() {
414    return this.extend({});
415};
416
417/**
418 * A map of color names to CSS colors.
419 * TODO(emily): Remove this when we have real macros
420 */
421var colorMap = {
422    "katex-blue": "#6495ed",
423    "katex-orange": "#ffa500",
424    "katex-pink": "#ff00af",
425    "katex-red": "#df0030",
426    "katex-green": "#28ae7b",
427    "katex-gray": "gray",
428    "katex-purple": "#9d38bd",
429    "katex-blueA": "#ccfaff",
430    "katex-blueB": "#80f6ff",
431    "katex-blueC": "#63d9ea",
432    "katex-blueD": "#11accd",
433    "katex-blueE": "#0c7f99",
434    "katex-tealA": "#94fff5",
435    "katex-tealB": "#26edd5",
436    "katex-tealC": "#01d1c1",
437    "katex-tealD": "#01a995",
438    "katex-tealE": "#208170",
439    "katex-greenA": "#b6ffb0",
440    "katex-greenB": "#8af281",
441    "katex-greenC": "#74cf70",
442    "katex-greenD": "#1fab54",
443    "katex-greenE": "#0d923f",
444    "katex-goldA": "#ffd0a9",
445    "katex-goldB": "#ffbb71",
446    "katex-goldC": "#ff9c39",
447    "katex-goldD": "#e07d10",
448    "katex-goldE": "#a75a05",
449    "katex-redA": "#fca9a9",
450    "katex-redB": "#ff8482",
451    "katex-redC": "#f9685d",
452    "katex-redD": "#e84d39",
453    "katex-redE": "#bc2612",
454    "katex-maroonA": "#ffbde0",
455    "katex-maroonB": "#ff92c6",
456    "katex-maroonC": "#ed5fa6",
457    "katex-maroonD": "#ca337c",
458    "katex-maroonE": "#9e034e",
459    "katex-purpleA": "#ddd7ff",
460    "katex-purpleB": "#c6b9fc",
461    "katex-purpleC": "#aa87ff",
462    "katex-purpleD": "#7854ab",
463    "katex-purpleE": "#543b78",
464    "katex-mintA": "#f5f9e8",
465    "katex-mintB": "#edf2df",
466    "katex-mintC": "#e0e5cc",
467    "katex-grayA": "#f6f7f7",
468    "katex-grayB": "#f0f1f2",
469    "katex-grayC": "#e3e5e6",
470    "katex-grayD": "#d6d8da",
471    "katex-grayE": "#babec2",
472    "katex-grayF": "#888d93",
473    "katex-grayG": "#626569",
474    "katex-grayH": "#3b3e40",
475    "katex-grayI": "#21242c",
476    "katex-kaBlue": "#314453",
477    "katex-kaGreen": "#71B307"
478};
479
480/**
481 * Gets the CSS color of the current options object, accounting for the
482 * `colorMap`.
483 */
484Options.prototype.getColor = function() {
485    if (this.phantom) {
486        return "transparent";
487    } else {
488        return colorMap[this.color] || this.color;
489    }
490};
491
492module.exports = Options;
493
494},{}],6:[function(require,module,exports){
495/**
496 * This is the ParseError class, which is the main error thrown by KaTeX
497 * functions when something has gone wrong. This is used to distinguish internal
498 * errors from errors in the expression that the user provided.
499 *
500 * If possible, a caller should provide a Token or ParseNode with information
501 * about where in the source string the problem occurred.
502 *
503 * @param {string} message  The error message
504 * @param {(Token|ParseNode)=} token  An object providing position information
505 */
506function ParseError(message, token) {
507    var error = "KaTeX parse error: " + message;
508    var start;
509    var end;
510
511    if (token && token.lexer && token.start <= token.end) {
512        // If we have the input and a position, make the error a bit fancier
513
514        // Get the input
515        var input = token.lexer.input;
516
517        // Prepend some information
518        start = token.start;
519        end = token.end;
520        if (start === input.length) {
521            error += " at end of input: ";
522        } else {
523            error += " at position " + (start + 1) + ": ";
524        }
525
526        // Underline token in question using combining underscores
527        var underlined = input.slice(start, end).replace(/[^]/g, "$&\u0332");
528
529        // Extract some context from the input and add it to the error
530        var left;
531        if (start > 15) {
532            left = "…" + input.slice(start - 15, start);
533        } else {
534            left = input.slice(0, start);
535        }
536        var right;
537        if (end + 15 < input.length) {
538            right = input.slice(end, end + 15) + "…";
539        } else {
540            right = input.slice(end);
541        }
542        error += left + underlined + right;
543    }
544
545    // Some hackery to make ParseError a prototype of Error
546    // See http://stackoverflow.com/a/8460753
547    var self = new Error(error);
548    self.name = "ParseError";
549    self.__proto__ = ParseError.prototype;
550
551    self.position = start;
552    return self;
553}
554
555// More hackery
556ParseError.prototype.__proto__ = Error.prototype;
557
558module.exports = ParseError;
559
560},{}],7:[function(require,module,exports){
561/* eslint no-constant-condition:0 */
562var functions = require("./functions");
563var environments = require("./environments");
564var MacroExpander = require("./MacroExpander");
565var symbols = require("./symbols");
566var utils = require("./utils");
567var cjkRegex = require("./unicodeRegexes").cjkRegex;
568
569var parseData = require("./parseData");
570var ParseError = require("./ParseError");
571
572/**
573 * This file contains the parser used to parse out a TeX expression from the
574 * input. Since TeX isn't context-free, standard parsers don't work particularly
575 * well.
576 *
577 * The strategy of this parser is as such:
578 *
579 * The main functions (the `.parse...` ones) take a position in the current
580 * parse string to parse tokens from. The lexer (found in Lexer.js, stored at
581 * this.lexer) also supports pulling out tokens at arbitrary places. When
582 * individual tokens are needed at a position, the lexer is called to pull out a
583 * token, which is then used.
584 *
585 * The parser has a property called "mode" indicating the mode that
586 * the parser is currently in. Currently it has to be one of "math" or
587 * "text", which denotes whether the current environment is a math-y
588 * one or a text-y one (e.g. inside \text). Currently, this serves to
589 * limit the functions which can be used in text mode.
590 *
591 * The main functions then return an object which contains the useful data that
592 * was parsed at its given point, and a new position at the end of the parsed
593 * data. The main functions can call each other and continue the parsing by
594 * using the returned position as a new starting point.
595 *
596 * There are also extra `.handle...` functions, which pull out some reused
597 * functionality into self-contained functions.
598 *
599 * The earlier functions return ParseNodes.
600 * The later functions (which are called deeper in the parse) sometimes return
601 * ParseFuncOrArgument, which contain a ParseNode as well as some data about
602 * whether the parsed object is a function which is missing some arguments, or a
603 * standalone object which can be used as an argument to another function.
604 */
605
606/**
607 * Main Parser class
608 */
609function Parser(input, settings) {
610    // Create a new macro expander (gullet) and (indirectly via that) also a
611    // new lexer (mouth) for this parser (stomach, in the language of TeX)
612    this.gullet = new MacroExpander(input, settings.macros);
613    // Store the settings for use in parsing
614    this.settings = settings;
615    // Count leftright depth (for \middle errors)
616    this.leftrightDepth = 0;
617}
618
619var ParseNode = parseData.ParseNode;
620
621/**
622 * An initial function (without its arguments), or an argument to a function.
623 * The `result` argument should be a ParseNode.
624 */
625function ParseFuncOrArgument(result, isFunction, token) {
626    this.result = result;
627    // Is this a function (i.e. is it something defined in functions.js)?
628    this.isFunction = isFunction;
629    this.token = token;
630}
631
632/**
633 * Checks a result to make sure it has the right type, and throws an
634 * appropriate error otherwise.
635 *
636 * @param {boolean=} consume whether to consume the expected token,
637 *                           defaults to true
638 */
639Parser.prototype.expect = function(text, consume) {
640    if (this.nextToken.text !== text) {
641        throw new ParseError(
642            "Expected '" + text + "', got '" + this.nextToken.text + "'",
643            this.nextToken
644        );
645    }
646    if (consume !== false) {
647        this.consume();
648    }
649};
650
651/**
652 * Considers the current look ahead token as consumed,
653 * and fetches the one after that as the new look ahead.
654 */
655Parser.prototype.consume = function() {
656    this.nextToken = this.gullet.get(this.mode === "math");
657};
658
659Parser.prototype.switchMode = function(newMode) {
660    this.gullet.unget(this.nextToken);
661    this.mode = newMode;
662    this.consume();
663};
664
665/**
666 * Main parsing function, which parses an entire input.
667 *
668 * @return {?Array.<ParseNode>}
669 */
670Parser.prototype.parse = function() {
671    // Try to parse the input
672    this.mode = "math";
673    this.consume();
674    var parse = this.parseInput();
675    return parse;
676};
677
678/**
679 * Parses an entire input tree.
680 */
681Parser.prototype.parseInput = function() {
682    // Parse an expression
683    var expression = this.parseExpression(false);
684    // If we succeeded, make sure there's an EOF at the end
685    this.expect("EOF", false);
686    return expression;
687};
688
689var endOfExpression = ["}", "\\end", "\\right", "&", "\\\\", "\\cr"];
690
691/**
692 * Parses an "expression", which is a list of atoms.
693 *
694 * @param {boolean} breakOnInfix  Should the parsing stop when we hit infix
695 *                  nodes? This happens when functions have higher precendence
696 *                  than infix nodes in implicit parses.
697 *
698 * @param {?string} breakOnTokenText  The text of the token that the expression
699 *                  should end with, or `null` if something else should end the
700 *                  expression.
701 *
702 * @return {ParseNode}
703 */
704Parser.prototype.parseExpression = function(breakOnInfix, breakOnTokenText) {
705    var body = [];
706    // Keep adding atoms to the body until we can't parse any more atoms (either
707    // we reached the end, a }, or a \right)
708    while (true) {
709        var lex = this.nextToken;
710        if (endOfExpression.indexOf(lex.text) !== -1) {
711            break;
712        }
713        if (breakOnTokenText && lex.text === breakOnTokenText) {
714            break;
715        }
716        if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) {
717            break;
718        }
719        var atom = this.parseAtom();
720        if (!atom) {
721            if (!this.settings.throwOnError && lex.text[0] === "\\") {
722                var errorNode = this.handleUnsupportedCmd();
723                body.push(errorNode);
724                continue;
725            }
726
727            break;
728        }
729        body.push(atom);
730    }
731    return this.handleInfixNodes(body);
732};
733
734/**
735 * Rewrites infix operators such as \over with corresponding commands such
736 * as \frac.
737 *
738 * There can only be one infix operator per group.  If there's more than one
739 * then the expression is ambiguous.  This can be resolved by adding {}.
740 *
741 * @returns {Array}
742 */
743Parser.prototype.handleInfixNodes = function(body) {
744    var overIndex = -1;
745    var funcName;
746
747    for (var i = 0; i < body.length; i++) {
748        var node = body[i];
749        if (node.type === "infix") {
750            if (overIndex !== -1) {
751                throw new ParseError(
752                    "only one infix operator per group",
753                    node.value.token);
754            }
755            overIndex = i;
756            funcName = node.value.replaceWith;
757        }
758    }
759
760    if (overIndex !== -1) {
761        var numerNode;
762        var denomNode;
763
764        var numerBody = body.slice(0, overIndex);
765        var denomBody = body.slice(overIndex + 1);
766
767        if (numerBody.length === 1 && numerBody[0].type === "ordgroup") {
768            numerNode = numerBody[0];
769        } else {
770            numerNode = new ParseNode("ordgroup", numerBody, this.mode);
771        }
772
773        if (denomBody.length === 1 && denomBody[0].type === "ordgroup") {
774            denomNode = denomBody[0];
775        } else {
776            denomNode = new ParseNode("ordgroup", denomBody, this.mode);
777        }
778
779        var value = this.callFunction(
780            funcName, [numerNode, denomNode], null);
781        return [new ParseNode(value.type, value, this.mode)];
782    } else {
783        return body;
784    }
785};
786
787// The greediness of a superscript or subscript
788var SUPSUB_GREEDINESS = 1;
789
790/**
791 * Handle a subscript or superscript with nice errors.
792 */
793Parser.prototype.handleSupSubscript = function(name) {
794    var symbolToken = this.nextToken;
795    var symbol = symbolToken.text;
796    this.consume();
797    var group = this.parseGroup();
798
799    if (!group) {
800        if (!this.settings.throwOnError && this.nextToken.text[0] === "\\") {
801            return this.handleUnsupportedCmd();
802        } else {
803            throw new ParseError(
804                "Expected group after '" + symbol + "'",
805                symbolToken
806            );
807        }
808    } else if (group.isFunction) {
809        // ^ and _ have a greediness, so handle interactions with functions'
810        // greediness
811        var funcGreediness = functions[group.result].greediness;
812        if (funcGreediness > SUPSUB_GREEDINESS) {
813            return this.parseFunction(group);
814        } else {
815            throw new ParseError(
816                "Got function '" + group.result + "' with no arguments " +
817                    "as " + name, symbolToken);
818        }
819    } else {
820        return group.result;
821    }
822};
823
824/**
825 * Converts the textual input of an unsupported command into a text node
826 * contained within a color node whose color is determined by errorColor
827 */
828Parser.prototype.handleUnsupportedCmd = function() {
829    var text = this.nextToken.text;
830    var textordArray = [];
831
832    for (var i = 0; i < text.length; i++) {
833        textordArray.push(new ParseNode("textord", text[i], "text"));
834    }
835
836    var textNode = new ParseNode(
837        "text",
838        {
839            body: textordArray,
840            type: "text"
841        },
842        this.mode);
843
844    var colorNode = new ParseNode(
845        "color",
846        {
847            color: this.settings.errorColor,
848            value: [textNode],
849            type: "color"
850        },
851        this.mode);
852
853    this.consume();
854    return colorNode;
855};
856
857/**
858 * Parses a group with optional super/subscripts.
859 *
860 * @return {?ParseNode}
861 */
862Parser.prototype.parseAtom = function() {
863    // The body of an atom is an implicit group, so that things like
864    // \left(x\right)^2 work correctly.
865    var base = this.parseImplicitGroup();
866
867    // In text mode, we don't have superscripts or subscripts
868    if (this.mode === "text") {
869        return base;
870    }
871
872    // Note that base may be empty (i.e. null) at this point.
873
874    var superscript;
875    var subscript;
876    while (true) {
877        // Lex the first token
878        var lex = this.nextToken;
879
880        if (lex.text === "\\limits" || lex.text === "\\nolimits") {
881            // We got a limit control
882            if (!base || base.type !== "op") {
883                throw new ParseError(
884                    "Limit controls must follow a math operator",
885                    lex);
886            } else {
887                var limits = lex.text === "\\limits";
888                base.value.limits = limits;
889                base.value.alwaysHandleSupSub = true;
890            }
891            this.consume();
892        } else if (lex.text === "^") {
893            // We got a superscript start
894            if (superscript) {
895                throw new ParseError("Double superscript", lex);
896            }
897            superscript = this.handleSupSubscript("superscript");
898        } else if (lex.text === "_") {
899            // We got a subscript start
900            if (subscript) {
901                throw new ParseError("Double subscript", lex);
902            }
903            subscript = this.handleSupSubscript("subscript");
904        } else if (lex.text === "'") {
905            // We got a prime
906            var prime = new ParseNode("textord", "\\prime", this.mode);
907
908            // Many primes can be grouped together, so we handle this here
909            var primes = [prime];
910            this.consume();
911            // Keep lexing tokens until we get something that's not a prime
912            while (this.nextToken.text === "'") {
913                // For each one, add another prime to the list
914                primes.push(prime);
915                this.consume();
916            }
917            // Put them into an ordgroup as the superscript
918            superscript = new ParseNode("ordgroup", primes, this.mode);
919        } else {
920            // If it wasn't ^, _, or ', stop parsing super/subscripts
921            break;
922        }
923    }
924
925    if (superscript || subscript) {
926        // If we got either a superscript or subscript, create a supsub
927        return new ParseNode("supsub", {
928            base: base,
929            sup: superscript,
930            sub: subscript
931        }, this.mode);
932    } else {
933        // Otherwise return the original body
934        return base;
935    }
936};
937
938// A list of the size-changing functions, for use in parseImplicitGroup
939var sizeFuncs = [
940    "\\tiny", "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize",
941    "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge"
942];
943
944// A list of the style-changing functions, for use in parseImplicitGroup
945var styleFuncs = [
946    "\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle"
947];
948
949/**
950 * Parses an implicit group, which is a group that starts at the end of a
951 * specified, and ends right before a higher explicit group ends, or at EOL. It
952 * is used for functions that appear to affect the current style, like \Large or
953 * \textrm, where instead of keeping a style we just pretend that there is an
954 * implicit grouping after it until the end of the group. E.g.
955 *   small text {\Large large text} small text again
956 * It is also used for \left and \right to get the correct grouping.
957 *
958 * @return {?ParseNode}
959 */
960Parser.prototype.parseImplicitGroup = function() {
961    var start = this.parseSymbol();
962
963    if (start == null) {
964        // If we didn't get anything we handle, fall back to parseFunction
965        return this.parseFunction();
966    }
967
968    var func = start.result;
969    var body;
970
971    if (func === "\\left") {
972        // If we see a left:
973        // Parse the entire left function (including the delimiter)
974        var left = this.parseFunction(start);
975        // Parse out the implicit body
976        ++this.leftrightDepth;
977        body = this.parseExpression(false);
978        --this.leftrightDepth;
979        // Check the next token
980        this.expect("\\right", false);
981        var right = this.parseFunction();
982        return new ParseNode("leftright", {
983            body: body,
984            left: left.value.value,
985            right: right.value.value
986        }, this.mode);
987    } else if (func === "\\begin") {
988        // begin...end is similar to left...right
989        var begin = this.parseFunction(start);
990        var envName = begin.value.name;
991        if (!environments.hasOwnProperty(envName)) {
992            throw new ParseError(
993                "No such environment: " + envName, begin.value.nameGroup);
994        }
995        // Build the environment object. Arguments and other information will
996        // be made available to the begin and end methods using properties.
997        var env = environments[envName];
998        var args = this.parseArguments("\\begin{" + envName + "}", env);
999        var context = {
1000            mode: this.mode,
1001            envName: envName,
1002            parser: this,
1003            positions: args.pop()
1004        };
1005        var result = env.handler(context, args);
1006        this.expect("\\end", false);
1007        var endNameToken = this.nextToken;
1008        var end = this.parseFunction();
1009        if (end.value.name !== envName) {
1010            throw new ParseError(
1011                "Mismatch: \\begin{" + envName + "} matched " +
1012                "by \\end{" + end.value.name + "}",
1013                endNameToken);
1014        }
1015        result.position = end.position;
1016        return result;
1017    } else if (utils.contains(sizeFuncs, func)) {
1018        // If we see a sizing function, parse out the implict body
1019        body = this.parseExpression(false);
1020        return new ParseNode("sizing", {
1021            // Figure out what size to use based on the list of functions above
1022            size: "size" + (utils.indexOf(sizeFuncs, func) + 1),
1023            value: body
1024        }, this.mode);
1025    } else if (utils.contains(styleFuncs, func)) {
1026        // If we see a styling function, parse out the implict body
1027        body = this.parseExpression(true);
1028        return new ParseNode("styling", {
1029            // Figure out what style to use by pulling out the style from
1030            // the function name
1031            style: func.slice(1, func.length - 5),
1032            value: body
1033        }, this.mode);
1034    } else {
1035        // Defer to parseFunction if it's not a function we handle
1036        return this.parseFunction(start);
1037    }
1038};
1039
1040/**
1041 * Parses an entire function, including its base and all of its arguments.
1042 * The base might either have been parsed already, in which case
1043 * it is provided as an argument, or it's the next group in the input.
1044 *
1045 * @param {ParseFuncOrArgument=} baseGroup optional as described above
1046 * @return {?ParseNode}
1047 */
1048Parser.prototype.parseFunction = function(baseGroup) {
1049    if (!baseGroup) {
1050        baseGroup = this.parseGroup();
1051    }
1052
1053    if (baseGroup) {
1054        if (baseGroup.isFunction) {
1055            var func = baseGroup.result;
1056            var funcData = functions[func];
1057            if (this.mode === "text" && !funcData.allowedInText) {
1058                throw new ParseError(
1059                    "Can't use function '" + func + "' in text mode",
1060                    baseGroup.token);
1061            }
1062
1063            var args = this.parseArguments(func, funcData);
1064            var token = baseGroup.token;
1065            var result = this.callFunction(func, args, args.pop(), token);
1066            return new ParseNode(result.type, result, this.mode);
1067        } else {
1068            return baseGroup.result;
1069        }
1070    } else {
1071        return null;
1072    }
1073};
1074
1075/**
1076 * Call a function handler with a suitable context and arguments.
1077 */
1078Parser.prototype.callFunction = function(name, args, positions, token) {
1079    var context = {
1080        funcName: name,
1081        parser: this,
1082        positions: positions,
1083        token: token
1084    };
1085    return functions[name].handler(context, args);
1086};
1087
1088/**
1089 * Parses the arguments of a function or environment
1090 *
1091 * @param {string} func  "\name" or "\begin{name}"
1092 * @param {{numArgs:number,numOptionalArgs:number|undefined}} funcData
1093 * @return the array of arguments, with the list of positions as last element
1094 */
1095Parser.prototype.parseArguments = function(func, funcData) {
1096    var totalArgs = funcData.numArgs + funcData.numOptionalArgs;
1097    if (totalArgs === 0) {
1098        return [[this.pos]];
1099    }
1100
1101    var baseGreediness = funcData.greediness;
1102    var positions = [this.pos];
1103    var args = [];
1104
1105    for (var i = 0; i < totalArgs; i++) {
1106        var nextToken = this.nextToken;
1107        var argType = funcData.argTypes && funcData.argTypes[i];
1108        var arg;
1109        if (i < funcData.numOptionalArgs) {
1110            if (argType) {
1111                arg = this.parseGroupOfType(argType, true);
1112            } else {
1113                arg = this.parseGroup(true);
1114            }
1115            if (!arg) {
1116                args.push(null);
1117                positions.push(this.pos);
1118                continue;
1119            }
1120        } else {
1121            if (argType) {
1122                arg = this.parseGroupOfType(argType);
1123            } else {
1124                arg = this.parseGroup();
1125            }
1126            if (!arg) {
1127                if (!this.settings.throwOnError &&
1128                    this.nextToken.text[0] === "\\") {
1129                    arg = new ParseFuncOrArgument(
1130                        this.handleUnsupportedCmd(this.nextToken.text),
1131                        false);
1132                } else {
1133                    throw new ParseError(
1134                        "Expected group after '" + func + "'", nextToken);
1135                }
1136            }
1137        }
1138        var argNode;
1139        if (arg.isFunction) {
1140            var argGreediness =
1141                functions[arg.result].greediness;
1142            if (argGreediness > baseGreediness) {
1143                argNode = this.parseFunction(arg);
1144            } else {
1145                throw new ParseError(
1146                    "Got function '" + arg.result + "' as " +
1147                    "argument to '" + func + "'", nextToken);
1148            }
1149        } else {
1150            argNode = arg.result;
1151        }
1152        args.push(argNode);
1153        positions.push(this.pos);
1154    }
1155
1156    args.push(positions);
1157
1158    return args;
1159};
1160
1161
1162/**
1163 * Parses a group when the mode is changing.
1164 *
1165 * @return {?ParseFuncOrArgument}
1166 */
1167Parser.prototype.parseGroupOfType = function(innerMode, optional) {
1168    var outerMode = this.mode;
1169    // Handle `original` argTypes
1170    if (innerMode === "original") {
1171        innerMode = outerMode;
1172    }
1173
1174    if (innerMode === "color") {
1175        return this.parseColorGroup(optional);
1176    }
1177    if (innerMode === "size") {
1178        return this.parseSizeGroup(optional);
1179    }
1180
1181    this.switchMode(innerMode);
1182    if (innerMode === "text") {
1183        // text mode is special because it should ignore the whitespace before
1184        // it
1185        while (this.nextToken.text === " ") {
1186            this.consume();
1187        }
1188    }
1189    // By the time we get here, innerMode is one of "text" or "math".
1190    // We switch the mode of the parser, recurse, then restore the old mode.
1191    var res = this.parseGroup(optional);
1192    this.switchMode(outerMode);
1193    return res;
1194};
1195
1196/**
1197 * Parses a group, essentially returning the string formed by the
1198 * brace-enclosed tokens plus some position information.
1199 *
1200 * @param {string} modeName  Used to describe the mode in error messages
1201 * @param {boolean=} optional  Whether the group is optional or required
1202 */
1203Parser.prototype.parseStringGroup = function(modeName, optional) {
1204    if (optional && this.nextToken.text !== "[") {
1205        return null;
1206    }
1207    var outerMode = this.mode;
1208    this.mode = "text";
1209    this.expect(optional ? "[" : "{");
1210    var str = "";
1211    var firstToken = this.nextToken;
1212    var lastToken = firstToken;
1213    while (this.nextToken.text !== (optional ? "]" : "}")) {
1214        if (this.nextToken.text === "EOF") {
1215            throw new ParseError(
1216                "Unexpected end of input in " + modeName,
1217                firstToken.range(this.nextToken, str));
1218        }
1219        lastToken = this.nextToken;
1220        str += lastToken.text;
1221        this.consume();
1222    }
1223    this.mode = outerMode;
1224    this.expect(optional ? "]" : "}");
1225    return firstToken.range(lastToken, str);
1226};
1227
1228/**
1229 * Parses a regex-delimited group: the largest sequence of tokens
1230 * whose concatenated strings match `regex`. Returns the string
1231 * formed by the tokens plus some position information.
1232 *
1233 * @param {RegExp} regex
1234 * @param {string} modeName  Used to describe the mode in error messages
1235 */
1236Parser.prototype.parseRegexGroup = function(regex, modeName) {
1237    var outerMode = this.mode;
1238    this.mode = "text";
1239    var firstToken = this.nextToken;
1240    var lastToken = firstToken;
1241    var str = "";
1242    while (this.nextToken.text !== "EOF"
1243           && regex.test(str + this.nextToken.text)) {
1244        lastToken = this.nextToken;
1245        str += lastToken.text;
1246        this.consume();
1247    }
1248    if (str === "") {
1249        throw new ParseError(
1250            "Invalid " + modeName + ": '" + firstToken.text + "'",
1251            firstToken);
1252    }
1253    this.mode = outerMode;
1254    return firstToken.range(lastToken, str);
1255};
1256
1257/**
1258 * Parses a color description.
1259 */
1260Parser.prototype.parseColorGroup = function(optional) {
1261    var res = this.parseStringGroup("color", optional);
1262    if (!res) {
1263        return null;
1264    }
1265    var match = (/^(#[a-z0-9]+|[a-z]+)$/i).exec(res.text);
1266    if (!match) {
1267        throw new ParseError("Invalid color: '" + res.text + "'", res);
1268    }
1269    return new ParseFuncOrArgument(
1270        new ParseNode("color", match[0], this.mode),
1271        false);
1272};
1273
1274/**
1275 * Parses a size specification, consisting of magnitude and unit.
1276 */
1277Parser.prototype.parseSizeGroup = function(optional) {
1278    var res;
1279    if (!optional && this.nextToken.text !== "{") {
1280        res = this.parseRegexGroup(
1281            /^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2}$/, "size");
1282    } else {
1283        res = this.parseStringGroup("size", optional);
1284    }
1285    if (!res) {
1286        return null;
1287    }
1288    var match = (/([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/).exec(res.text);
1289    if (!match) {
1290        throw new ParseError("Invalid size: '" + res.text + "'", res);
1291    }
1292    var data = {
1293        number: +(match[1] + match[2]), // sign + magnitude, cast to number
1294        unit: match[3]
1295    };
1296    if (data.unit !== "em" && data.unit !== "ex" && data.unit !== "mu") {
1297        throw new ParseError("Invalid unit: '" + data.unit + "'", res);
1298    }
1299    return new ParseFuncOrArgument(
1300        new ParseNode("color", data, this.mode),
1301        false);
1302};
1303
1304/**
1305 * If the argument is false or absent, this parses an ordinary group,
1306 * which is either a single nucleus (like "x") or an expression
1307 * in braces (like "{x+y}").
1308 * If the argument is true, it parses either a bracket-delimited expression
1309 * (like "[x+y]") or returns null to indicate the absence of a
1310 * bracket-enclosed group.
1311 *
1312 * @param {boolean=} optional  Whether the group is optional or required
1313 * @return {?ParseFuncOrArgument}
1314 */
1315Parser.prototype.parseGroup = function(optional) {
1316    var firstToken = this.nextToken;
1317    // Try to parse an open brace
1318    if (this.nextToken.text === (optional ? "[" : "{")) {
1319        // If we get a brace, parse an expression
1320        this.consume();
1321        var expression = this.parseExpression(false, optional ? "]" : null);
1322        var lastToken = this.nextToken;
1323        // Make sure we get a close brace
1324        this.expect(optional ? "]" : "}");
1325        if (this.mode === "text") {
1326            this.formLigatures(expression);
1327        }
1328        return new ParseFuncOrArgument(
1329            new ParseNode("ordgroup", expression, this.mode,
1330                          firstToken, lastToken),
1331            false);
1332    } else {
1333        // Otherwise, just return a nucleus, or nothing for an optional group
1334        return optional ? null : this.parseSymbol();
1335    }
1336};
1337
1338/**
1339 * Form ligature-like combinations of characters for text mode.
1340 * This includes inputs like "--", "---", "``" and "''".
1341 * The result will simply replace multiple textord nodes with a single
1342 * character in each value by a single textord node having multiple
1343 * characters in its value.  The representation is still ASCII source.
1344 *
1345 * @param {Array.<ParseNode>} group  the nodes of this group,
1346 *                                   list will be moified in place
1347 */
1348Parser.prototype.formLigatures = function(group) {
1349    var i;
1350    var n = group.length - 1;
1351    for (i = 0; i < n; ++i) {
1352        var a = group[i];
1353        var v = a.value;
1354        if (v === "-" && group[i + 1].value === "-") {
1355            if (i + 1 < n && group[i + 2].value === "-") {
1356                group.splice(i, 3, new ParseNode(
1357                    "textord", "---", "text", a, group[i + 2]));
1358                n -= 2;
1359            } else {
1360                group.splice(i, 2, new ParseNode(
1361                    "textord", "--", "text", a, group[i + 1]));
1362                n -= 1;
1363            }
1364        }
1365        if ((v === "'" || v === "`") && group[i + 1].value === v) {
1366            group.splice(i, 2, new ParseNode(
1367                "textord", v + v, "text", a, group[i + 1]));
1368            n -= 1;
1369        }
1370    }
1371};
1372
1373/**
1374 * Parse a single symbol out of the string. Here, we handle both the functions
1375 * we have defined, as well as the single character symbols
1376 *
1377 * @return {?ParseFuncOrArgument}
1378 */
1379Parser.prototype.parseSymbol = function() {
1380    var nucleus = this.nextToken;
1381
1382    if (functions[nucleus.text]) {
1383        this.consume();
1384        // If there exists a function with this name, we return the function and
1385        // say that it is a function.
1386        return new ParseFuncOrArgument(
1387            nucleus.text,
1388            true, nucleus);
1389    } else if (symbols[this.mode][nucleus.text]) {
1390        this.consume();
1391        // Otherwise if this is a no-argument function, find the type it
1392        // corresponds to in the symbols map
1393        return new ParseFuncOrArgument(
1394            new ParseNode(symbols[this.mode][nucleus.text].group,
1395                          nucleus.text, this.mode, nucleus),
1396            false, nucleus);
1397    } else if (this.mode === "text" && cjkRegex.test(nucleus.text)) {
1398        this.consume();
1399        return new ParseFuncOrArgument(
1400            new ParseNode("textord", nucleus.text, this.mode, nucleus),
1401            false, nucleus);
1402    } else {
1403        return null;
1404    }
1405};
1406
1407Parser.prototype.ParseNode = ParseNode;
1408
1409module.exports = Parser;
1410
1411},{"./MacroExpander":4,"./ParseError":6,"./environments":16,"./functions":19,"./parseData":21,"./symbols":23,"./unicodeRegexes":24,"./utils":25}],8:[function(require,module,exports){
1412/**
1413 * This is a module for storing settings passed into KaTeX. It correctly handles
1414 * default settings.
1415 */
1416
1417/**
1418 * Helper function for getting a default value if the value is undefined
1419 */
1420function get(option, defaultValue) {
1421    return option === undefined ? defaultValue : option;
1422}
1423
1424/**
1425 * The main Settings object
1426 *
1427 * The current options stored are:
1428 *  - displayMode: Whether the expression should be typeset by default in
1429 *                 textstyle or displaystyle (default false)
1430 */
1431function Settings(options) {
1432    // allow null options
1433    options = options || {};
1434    this.displayMode = get(options.displayMode, false);
1435    this.throwOnError = get(options.throwOnError, true);
1436    this.errorColor = get(options.errorColor, "#cc0000");
1437    this.macros = options.macros || {};
1438}
1439
1440module.exports = Settings;
1441
1442},{}],9:[function(require,module,exports){
1443/**
1444 * This file contains information and classes for the various kinds of styles
1445 * used in TeX. It provides a generic `Style` class, which holds information
1446 * about a specific style. It then provides instances of all the different kinds
1447 * of styles possible, and provides functions to move between them and get
1448 * information about them.
1449 */
1450
1451var sigmas = require("./fontMetrics.js").sigmas;
1452
1453var metrics = [{}, {}, {}];
1454var i;
1455for (var key in sigmas) {
1456    if (sigmas.hasOwnProperty(key)) {
1457        for (i = 0; i < 3; i++) {
1458            metrics[i][key] = sigmas[key][i];
1459        }
1460    }
1461}
1462for (i = 0; i < 3; i++) {
1463    metrics[i].emPerEx = sigmas.xHeight[i] / sigmas.quad[i];
1464}
1465
1466/**
1467 * The main style class. Contains a unique id for the style, a size (which is
1468 * the same for cramped and uncramped version of a style), a cramped flag, and a
1469 * size multiplier, which gives the size difference between a style and
1470 * textstyle.
1471 */
1472function Style(id, size, multiplier, cramped) {
1473    this.id = id;
1474    this.size = size;
1475    this.cramped = cramped;
1476    this.sizeMultiplier = multiplier;
1477    this.metrics = metrics[size > 0 ? size - 1 : 0];
1478}
1479
1480/**
1481 * Get the style of a superscript given a base in the current style.
1482 */
1483Style.prototype.sup = function() {
1484    return styles[sup[this.id]];
1485};
1486
1487/**
1488 * Get the style of a subscript given a base in the current style.
1489 */
1490Style.prototype.sub = function() {
1491    return styles[sub[this.id]];
1492};
1493
1494/**
1495 * Get the style of a fraction numerator given the fraction in the current
1496 * style.
1497 */
1498Style.prototype.fracNum = function() {
1499    return styles[fracNum[this.id]];
1500};
1501
1502/**
1503 * Get the style of a fraction denominator given the fraction in the current
1504 * style.
1505 */
1506Style.prototype.fracDen = function() {
1507    return styles[fracDen[this.id]];
1508};
1509
1510/**
1511 * Get the cramped version of a style (in particular, cramping a cramped style
1512 * doesn't change the style).
1513 */
1514Style.prototype.cramp = function() {
1515    return styles[cramp[this.id]];
1516};
1517
1518/**
1519 * HTML class name, like "displaystyle cramped"
1520 */
1521Style.prototype.cls = function() {
1522    return sizeNames[this.size] + (this.cramped ? " cramped" : " uncramped");
1523};
1524
1525/**
1526 * HTML Reset class name, like "reset-textstyle"
1527 */
1528Style.prototype.reset = function() {
1529    return resetNames[this.size];
1530};
1531
1532/**
1533 * Return if this style is tightly spaced (scriptstyle/scriptscriptstyle)
1534 */
1535Style.prototype.isTight = function() {
1536    return this.size >= 2;
1537};
1538
1539// IDs of the different styles
1540var D = 0;
1541var Dc = 1;
1542var T = 2;
1543var Tc = 3;
1544var S = 4;
1545var Sc = 5;
1546var SS = 6;
1547var SSc = 7;
1548
1549// String names for the different sizes
1550var sizeNames = [
1551    "displaystyle textstyle",
1552    "textstyle",
1553    "scriptstyle",
1554    "scriptscriptstyle"
1555];
1556
1557// Reset names for the different sizes
1558var resetNames = [
1559    "reset-textstyle",
1560    "reset-textstyle",
1561    "reset-scriptstyle",
1562    "reset-scriptscriptstyle"
1563];
1564
1565// Instances of the different styles
1566var styles = [
1567    new Style(D, 0, 1.0, false),
1568    new Style(Dc, 0, 1.0, true),
1569    new Style(T, 1, 1.0, false),
1570    new Style(Tc, 1, 1.0, true),
1571    new Style(S, 2, 0.7, false),
1572    new Style(Sc, 2, 0.7, true),
1573    new Style(SS, 3, 0.5, false),
1574    new Style(SSc, 3, 0.5, true)
1575];
1576
1577// Lookup tables for switching from one style to another
1578var sup = [S, Sc, S, Sc, SS, SSc, SS, SSc];
1579var sub = [Sc, Sc, Sc, Sc, SSc, SSc, SSc, SSc];
1580var fracNum = [T, Tc, S, Sc, SS, SSc, SS, SSc];
1581var fracDen = [Tc, Tc, Sc, Sc, SSc, SSc, SSc, SSc];
1582var cramp = [Dc, Dc, Tc, Tc, Sc, Sc, SSc, SSc];
1583
1584// We only export some of the styles. Also, we don't export the `Style` class so
1585// no more styles can be generated.
1586module.exports = {
1587    DISPLAY: styles[D],
1588    TEXT: styles[T],
1589    SCRIPT: styles[S],
1590    SCRIPTSCRIPT: styles[SS]
1591};
1592
1593},{"./fontMetrics.js":17}],10:[function(require,module,exports){
1594/* eslint no-console:0 */
1595/**
1596 * This module contains general functions that can be used for building
1597 * different kinds of domTree nodes in a consistent manner.
1598 */
1599
1600var domTree = require("./domTree");
1601var fontMetrics = require("./fontMetrics");
1602var symbols = require("./symbols");
1603var utils = require("./utils");
1604
1605var greekCapitals = [
1606    "\\Gamma",
1607    "\\Delta",
1608    "\\Theta",
1609    "\\Lambda",
1610    "\\Xi",
1611    "\\Pi",
1612    "\\Sigma",
1613    "\\Upsilon",
1614    "\\Phi",
1615    "\\Psi",
1616    "\\Omega"
1617];
1618
1619// The following have to be loaded from Main-Italic font, using class mainit
1620var mainitLetters = [
1621    "\u0131",   // dotless i, \imath
1622    "\u0237",   // dotless j, \jmath
1623    "\u00a3"   // \pounds
1624];
1625
1626/**
1627 * Makes a symbolNode after translation via the list of symbols in symbols.js.
1628 * Correctly pulls out metrics for the character, and optionally takes a list of
1629 * classes to be attached to the node.
1630 *
1631 * TODO: make argument order closer to makeSpan
1632 * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which
1633 * should if present come first in `classes`.
1634 */
1635var makeSymbol = function(value, fontFamily, mode, options, classes) {
1636    // Replace the value with its replaced value from symbol.js
1637    if (symbols[mode][value] && symbols[mode][value].replace) {
1638        value = symbols[mode][value].replace;
1639    }
1640
1641    var metrics = fontMetrics.getCharacterMetrics(value, fontFamily);
1642
1643    var symbolNode;
1644    if (metrics) {
1645        var italic = metrics.italic;
1646        if (mode === "text") {
1647            italic = 0;
1648        }
1649        symbolNode = new domTree.symbolNode(
1650            value, metrics.height, metrics.depth, italic, metrics.skew,
1651            classes);
1652    } else {
1653        // TODO(emily): Figure out a good way to only print this in development
1654        typeof console !== "undefined" && console.warn(
1655            "No character metrics for '" + value + "' in style '" +
1656                fontFamily + "'");
1657        symbolNode = new domTree.symbolNode(value, 0, 0, 0, 0, classes);
1658    }
1659
1660    if (options) {
1661        if (options.style.isTight()) {
1662            symbolNode.classes.push("mtight");
1663        }
1664        if (options.getColor()) {
1665            symbolNode.style.color = options.getColor();
1666        }
1667    }
1668
1669    return symbolNode;
1670};
1671
1672/**
1673 * Makes a symbol in Main-Regular or AMS-Regular.
1674 * Used for rel, bin, open, close, inner, and punct.
1675 */
1676var mathsym = function(value, mode, options, classes) {
1677    // Decide what font to render the symbol in by its entry in the symbols
1678    // table.
1679    // Have a special case for when the value = \ because the \ is used as a
1680    // textord in unsupported command errors but cannot be parsed as a regular
1681    // text ordinal and is therefore not present as a symbol in the symbols
1682    // table for text
1683    if (value === "\\" || symbols[mode][value].font === "main") {
1684        return makeSymbol(value, "Main-Regular", mode, options, classes);
1685    } else {
1686        return makeSymbol(
1687            value, "AMS-Regular", mode, options, classes.concat(["amsrm"]));
1688    }
1689};
1690
1691/**
1692 * Makes a symbol in the default font for mathords and textords.
1693 */
1694var mathDefault = function(value, mode, options, classes, type) {
1695    if (type === "mathord") {
1696        return mathit(value, mode, options, classes);
1697    } else if (type === "textord") {
1698        return makeSymbol(
1699            value, "Main-Regular", mode, options, classes.concat(["mathrm"]));
1700    } else {
1701        throw new Error("unexpected type: " + type + " in mathDefault");
1702    }
1703};
1704
1705/**
1706 * Makes a symbol in the italic math font.
1707 */
1708var mathit = function(value, mode, options, classes) {
1709    if (/[0-9]/.test(value.charAt(0)) ||
1710            // glyphs for \imath and \jmath do not exist in Math-Italic so we
1711            // need to use Main-Italic instead
1712            utils.contains(mainitLetters, value) ||
1713            utils.contains(greekCapitals, value)) {
1714        return makeSymbol(
1715            value, "Main-Italic", mode, options, classes.concat(["mainit"]));
1716    } else {
1717        return makeSymbol(
1718            value, "Math-Italic", mode, options, classes.concat(["mathit"]));
1719    }
1720};
1721
1722/**
1723 * Makes either a mathord or textord in the correct font and color.
1724 */
1725var makeOrd = function(group, options, type) {
1726    var mode = group.mode;
1727    var value = group.value;
1728    if (symbols[mode][value] && symbols[mode][value].replace) {
1729        value = symbols[mode][value].replace;
1730    }
1731
1732    var classes = ["mord"];
1733
1734    var font = options.font;
1735    if (font) {
1736        if (font === "mathit" || utils.contains(mainitLetters, value)) {
1737            return mathit(value, mode, options, classes);
1738        } else {
1739            var fontName = fontMap[font].fontName;
1740            if (fontMetrics.getCharacterMetrics(value, fontName)) {
1741                return makeSymbol(
1742                    value, fontName, mode, options, classes.concat([font]));
1743            } else {
1744                return mathDefault(value, mode, options, classes, type);
1745            }
1746        }
1747    } else {
1748        return mathDefault(value, mode, options, classes, type);
1749    }
1750};
1751
1752/**
1753 * Calculate the height, depth, and maxFontSize of an element based on its
1754 * children.
1755 */
1756var sizeElementFromChildren = function(elem) {
1757    var height = 0;
1758    var depth = 0;
1759    var maxFontSize = 0;
1760
1761    if (elem.children) {
1762        for (var i = 0; i < elem.children.length; i++) {
1763            if (elem.children[i].height > height) {
1764                height = elem.children[i].height;
1765            }
1766            if (elem.children[i].depth > depth) {
1767                depth = elem.children[i].depth;
1768            }
1769            if (elem.children[i].maxFontSize > maxFontSize) {
1770                maxFontSize = elem.children[i].maxFontSize;
1771            }
1772        }
1773    }
1774
1775    elem.height = height;
1776    elem.depth = depth;
1777    elem.maxFontSize = maxFontSize;
1778};
1779
1780/**
1781 * Makes a span with the given list of classes, list of children, and options.
1782 *
1783 * TODO: Ensure that `options` is always provided (currently some call sites
1784 * don't pass it).
1785 * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which
1786 * should if present come first in `classes`.
1787 */
1788var makeSpan = function(classes, children, options) {
1789    var span = new domTree.span(classes, children, options);
1790
1791    sizeElementFromChildren(span);
1792
1793    return span;
1794};
1795
1796/**
1797 * Prepends the given children to the given span, updating height, depth, and
1798 * maxFontSize.
1799 */
1800var prependChildren = function(span, children) {
1801    span.children = children.concat(span.children);
1802
1803    sizeElementFromChildren(span);
1804};
1805
1806/**
1807 * Makes a document fragment with the given list of children.
1808 */
1809var makeFragment = function(children) {
1810    var fragment = new domTree.documentFragment(children);
1811
1812    sizeElementFromChildren(fragment);
1813
1814    return fragment;
1815};
1816
1817/**
1818 * Makes an element placed in each of the vlist elements to ensure that each
1819 * element has the same max font size. To do this, we create a zero-width space
1820 * with the correct font size.
1821 */
1822var makeFontSizer = function(options, fontSize) {
1823    var fontSizeInner = makeSpan([], [new domTree.symbolNode("\u200b")]);
1824    fontSizeInner.style.fontSize =
1825        (fontSize / options.style.sizeMultiplier) + "em";
1826
1827    var fontSizer = makeSpan(
1828        ["fontsize-ensurer", "reset-" + options.size, "size5"],
1829        [fontSizeInner]);
1830
1831    return fontSizer;
1832};
1833
1834/**
1835 * Makes a vertical list by stacking elements and kerns on top of each other.
1836 * Allows for many different ways of specifying the positioning method.
1837 *
1838 * Arguments:
1839 *  - children: A list of child or kern nodes to be stacked on top of each other
1840 *              (i.e. the first element will be at the bottom, and the last at
1841 *              the top). Element nodes are specified as
1842 *                {type: "elem", elem: node}
1843 *              while kern nodes are specified as
1844 *                {type: "kern", size: size}
1845 *  - positionType: The method by which the vlist should be positioned. Valid
1846 *                  values are:
1847 *                   - "individualShift": The children list only contains elem
1848 *                                        nodes, and each node contains an extra
1849 *                                        "shift" value of how much it should be
1850 *                                        shifted (note that shifting is always
1851 *                                        moving downwards). positionData is
1852 *                                        ignored.
1853 *                   - "top": The positionData specifies the topmost point of
1854 *                            the vlist (note this is expected to be a height,
1855 *                            so positive values move up)
1856 *                   - "bottom": The positionData specifies the bottommost point
1857 *                               of the vlist (note this is expected to be a
1858 *                               depth, so positive values move down
1859 *                   - "shift": The vlist will be positioned such that its
1860 *                              baseline is positionData away from the baseline
1861 *                              of the first child. Positive values move
1862 *                              downwards.
1863 *                   - "firstBaseline": The vlist will be positioned such that
1864 *                                      its baseline is aligned with the
1865 *                                      baseline of the first child.
1866 *                                      positionData is ignored. (this is
1867 *                                      equivalent to "shift" with
1868 *                                      positionData=0)
1869 *  - positionData: Data used in different ways depending on positionType
1870 *  - options: An Options object
1871 *
1872 */
1873var makeVList = function(children, positionType, positionData, options) {
1874    var depth;
1875    var currPos;
1876    var i;
1877    if (positionType === "individualShift") {
1878        var oldChildren = children;
1879        children = [oldChildren[0]];
1880
1881        // Add in kerns to the list of children to get each element to be
1882        // shifted to the correct specified shift
1883        depth = -oldChildren[0].shift - oldChildren[0].elem.depth;
1884        currPos = depth;
1885        for (i = 1; i < oldChildren.length; i++) {
1886            var diff = -oldChildren[i].shift - currPos -
1887                oldChildren[i].elem.depth;
1888            var size = diff -
1889                (oldChildren[i - 1].elem.height +
1890                 oldChildren[i - 1].elem.depth);
1891
1892            currPos = currPos + diff;
1893
1894            children.push({type: "kern", size: size});
1895            children.push(oldChildren[i]);
1896        }
1897    } else if (positionType === "top") {
1898        // We always start at the bottom, so calculate the bottom by adding up
1899        // all the sizes
1900        var bottom = positionData;
1901        for (i = 0; i < children.length; i++) {
1902            if (children[i].type === "kern") {
1903                bottom -= children[i].size;
1904            } else {
1905                bottom -= children[i].elem.height + children[i].elem.depth;
1906            }
1907        }
1908        depth = bottom;
1909    } else if (positionType === "bottom") {
1910        depth = -positionData;
1911    } else if (positionType === "shift") {
1912        depth = -children[0].elem.depth - positionData;
1913    } else if (positionType === "firstBaseline") {
1914        depth = -children[0].elem.depth;
1915    } else {
1916        depth = 0;
1917    }
1918
1919    // Make the fontSizer
1920    var maxFontSize = 0;
1921    for (i = 0; i < children.length; i++) {
1922        if (children[i].type === "elem") {
1923            maxFontSize = Math.max(maxFontSize, children[i].elem.maxFontSize);
1924        }
1925    }
1926    var fontSizer = makeFontSizer(options, maxFontSize);
1927
1928    // Create a new list of actual children at the correct offsets
1929    var realChildren = [];
1930    currPos = depth;
1931    for (i = 0; i < children.length; i++) {
1932        if (children[i].type === "kern") {
1933            currPos += children[i].size;
1934        } else {
1935            var child = children[i].elem;
1936
1937            var shift = -child.depth - currPos;
1938            currPos += child.height + child.depth;
1939
1940            var childWrap = makeSpan([], [fontSizer, child]);
1941            childWrap.height -= shift;
1942            childWrap.depth += shift;
1943            childWrap.style.top = shift + "em";
1944
1945            realChildren.push(childWrap);
1946        }
1947    }
1948
1949    // Add in an element at the end with no offset to fix the calculation of
1950    // baselines in some browsers (namely IE, sometimes safari)
1951    var baselineFix = makeSpan(
1952        ["baseline-fix"], [fontSizer, new domTree.symbolNode("\u200b")]);
1953    realChildren.push(baselineFix);
1954
1955    var vlist = makeSpan(["vlist"], realChildren);
1956    // Fix the final height and depth, in case there were kerns at the ends
1957    // since the makeSpan calculation won't take that in to account.
1958    vlist.height = Math.max(currPos, vlist.height);
1959    vlist.depth = Math.max(-depth, vlist.depth);
1960    return vlist;
1961};
1962
1963// A table of size -> font size for the different sizing functions
1964var sizingMultiplier = {
1965    size1: 0.5,
1966    size2: 0.7,
1967    size3: 0.8,
1968    size4: 0.9,
1969    size5: 1.0,
1970    size6: 1.2,
1971    size7: 1.44,
1972    size8: 1.73,
1973    size9: 2.07,
1974    size10: 2.49
1975};
1976
1977// A map of spacing functions to their attributes, like size and corresponding
1978// CSS class
1979var spacingFunctions = {
1980    "\\qquad": {
1981        size: "2em",
1982        className: "qquad"
1983    },
1984    "\\quad": {
1985        size: "1em",
1986        className: "quad"
1987    },
1988    "\\enspace": {
1989        size: "0.5em",
1990        className: "enspace"
1991    },
1992    "\\;": {
1993        size: "0.277778em",
1994        className: "thickspace"
1995    },
1996    "\\:": {
1997        size: "0.22222em",
1998        className: "mediumspace"
1999    },
2000    "\\,": {
2001        size: "0.16667em",
2002        className: "thinspace"
2003    },
2004    "\\!": {
2005        size: "-0.16667em",
2006        className: "negativethinspace"
2007    }
2008};
2009
2010/**
2011 * Maps TeX font commands to objects containing:
2012 * - variant: string used for "mathvariant" attribute in buildMathML.js
2013 * - fontName: the "style" parameter to fontMetrics.getCharacterMetrics
2014 */
2015// A map between tex font commands an MathML mathvariant attribute values
2016var fontMap = {
2017    // styles
2018    "mathbf": {
2019        variant: "bold",
2020        fontName: "Main-Bold"
2021    },
2022    "mathrm": {
2023        variant: "normal",
2024        fontName: "Main-Regular"
2025    },
2026    "textit": {
2027        variant: "italic",
2028        fontName: "Main-Italic"
2029    },
2030
2031    // "mathit" is missing because it requires the use of two fonts: Main-Italic
2032    // and Math-Italic.  This is handled by a special case in makeOrd which ends
2033    // up calling mathit.
2034
2035    // families
2036    "mathbb": {
2037        variant: "double-struck",
2038        fontName: "AMS-Regular"
2039    },
2040    "mathcal": {
2041        variant: "script",
2042        fontName: "Caligraphic-Regular"
2043    },
2044    "mathfrak": {
2045        variant: "fraktur",
2046        fontName: "Fraktur-Regular"
2047    },
2048    "mathscr": {
2049        variant: "script",
2050        fontName: "Script-Regular"
2051    },
2052    "mathsf": {
2053        variant: "sans-serif",
2054        fontName: "SansSerif-Regular"
2055    },
2056    "mathtt": {
2057        variant: "monospace",
2058        fontName: "Typewriter-Regular"
2059    }
2060};
2061
2062module.exports = {
2063    fontMap: fontMap,
2064    makeSymbol: makeSymbol,
2065    mathsym: mathsym,
2066    makeSpan: makeSpan,
2067    makeFragment: makeFragment,
2068    makeVList: makeVList,
2069    makeOrd: makeOrd,
2070    prependChildren: prependChildren,
2071    sizingMultiplier: sizingMultiplier,
2072    spacingFunctions: spacingFunctions
2073};
2074
2075},{"./domTree":15,"./fontMetrics":17,"./symbols":23,"./utils":25}],11:[function(require,module,exports){
2076/* eslint no-console:0 */
2077/**
2078 * This file does the main work of building a domTree structure from a parse
2079 * tree. The entry point is the `buildHTML` function, which takes a parse tree.
2080 * Then, the buildExpression, buildGroup, and various groupTypes functions are
2081 * called, to produce a final HTML tree.
2082 */
2083
2084var ParseError = require("./ParseError");
2085var Style = require("./Style");
2086
2087var buildCommon = require("./buildCommon");
2088var delimiter = require("./delimiter");
2089var domTree = require("./domTree");
2090var fontMetrics = require("./fontMetrics");
2091var utils = require("./utils");
2092
2093var makeSpan = buildCommon.makeSpan;
2094
2095var isSpace = function(node) {
2096    return node instanceof domTree.span && node.classes[0] === "mspace";
2097};
2098
2099// Binary atoms (first class `mbin`) change into ordinary atoms (`mord`)
2100// depending on their surroundings. See TeXbook pg. 442-446, Rules 5 and 6,
2101// and the text before Rule 19.
2102
2103var isBin = function(node) {
2104    return node && node.classes[0] === "mbin";
2105};
2106
2107var isBinLeftCanceller = function(node, isRealGroup) {
2108    // TODO: This code assumes that a node's math class is the first element
2109    // of its `classes` array. A later cleanup should ensure this, for
2110    // instance by changing the signature of `makeSpan`.
2111    if (node) {
2112        return utils.contains(["mbin", "mopen", "mrel", "mop", "mpunct"],
2113                              node.classes[0]);
2114    } else {
2115        return isRealGroup;
2116    }
2117};
2118
2119var isBinRightCanceller = function(node, isRealGroup) {
2120    if (node) {
2121        return utils.contains(["mrel", "mclose", "mpunct"], node.classes[0]);
2122    } else {
2123        return isRealGroup;
2124    }
2125};
2126
2127/**
2128 * Take a list of nodes, build them in order, and return a list of the built
2129 * nodes. documentFragments are flattened into their contents, so the
2130 * returned list contains no fragments. `isRealGroup` is true if `expression`
2131 * is a real group (no atoms will be added on either side), as opposed to
2132 * a partial group (e.g. one created by \color).
2133 */
2134var buildExpression = function(expression, options, isRealGroup) {
2135    // Parse expressions into `groups`.
2136    var groups = [];
2137    for (var i = 0; i < expression.length; i++) {
2138        var group = expression[i];
2139        var output = buildGroup(group, options);
2140        if (output instanceof domTree.documentFragment) {
2141            Array.prototype.push.apply(groups, output.children);
2142        } else {
2143            groups.push(output);
2144        }
2145    }
2146    // At this point `groups` consists entirely of `symbolNode`s and `span`s.
2147
2148    // Explicit spaces (e.g., \;, \,) should be ignored with respect to atom
2149    // spacing (e.g., "add thick space between mord and mrel"). Since CSS
2150    // adjacency rules implement atom spacing, spaces should be invisible to
2151    // CSS. So we splice them out of `groups` and into the atoms themselves.
2152    var spaces = null;
2153    for (i = 0; i < groups.length; i++) {
2154        if (isSpace(groups[i])) {
2155            spaces = spaces || [];
2156            spaces.push(groups[i]);
2157            groups.splice(i, 1);
2158            i--;
2159        } else if (spaces) {
2160            if (groups[i] instanceof domTree.symbolNode) {
2161                groups[i] = makeSpan([].concat(groups[i].classes), [groups[i]]);
2162            }
2163            buildCommon.prependChildren(groups[i], spaces);
2164            spaces = null;
2165        }
2166    }
2167    if (spaces) {
2168        Array.prototype.push.apply(groups, spaces);
2169    }
2170
2171    // Binary operators change to ordinary symbols in some contexts.
2172    for (i = 0; i < groups.length; i++) {
2173        if (isBin(groups[i])
2174            && (isBinLeftCanceller(groups[i - 1], isRealGroup)
2175                || isBinRightCanceller(groups[i + 1], isRealGroup))) {
2176            groups[i].classes[0] = "mord";
2177        }
2178    }
2179
2180    return groups;
2181};
2182
2183// Return math atom class (mclass) of a domTree.
2184var getTypeOfDomTree = function(node) {
2185    if (node instanceof domTree.documentFragment) {
2186        if (node.children.length) {
2187            return getTypeOfDomTree(
2188                node.children[node.children.length - 1]);
2189        }
2190    } else {
2191        if (utils.contains(["mord", "mop", "mbin", "mrel", "mopen", "mclose",
2192            "mpunct", "minner"], node.classes[0])) {
2193            return node.classes[0];
2194        }
2195    }
2196    return null;
2197};
2198
2199/**
2200 * Sometimes, groups perform special rules when they have superscripts or
2201 * subscripts attached to them. This function lets the `supsub` group know that
2202 * its inner element should handle the superscripts and subscripts instead of
2203 * handling them itself.
2204 */
2205var shouldHandleSupSub = function(group, options) {
2206    if (!group) {
2207        return false;
2208    } else if (group.type === "op") {
2209        // Operators handle supsubs differently when they have limits
2210        // (e.g. `\displaystyle\sum_2^3`)
2211        return group.value.limits &&
2212            (options.style.size === Style.DISPLAY.size ||
2213            group.value.alwaysHandleSupSub);
2214    } else if (group.type === "accent") {
2215        return isCharacterBox(group.value.base);
2216    } else {
2217        return null;
2218    }
2219};
2220
2221/**
2222 * Sometimes we want to pull out the innermost element of a group. In most
2223 * cases, this will just be the group itself, but when ordgroups and colors have
2224 * a single element, we want to pull that out.
2225 */
2226var getBaseElem = function(group) {
2227    if (!group) {
2228        return false;
2229    } else if (group.type === "ordgroup") {
2230        if (group.value.length === 1) {
2231            return getBaseElem(group.value[0]);
2232        } else {
2233            return group;
2234        }
2235    } else if (group.type === "color") {
2236        if (group.value.value.length === 1) {
2237            return getBaseElem(group.value.value[0]);
2238        } else {
2239            return group;
2240        }
2241    } else if (group.type === "font") {
2242        return getBaseElem(group.value.body);
2243    } else {
2244        return group;
2245    }
2246};
2247
2248/**
2249 * TeXbook algorithms often reference "character boxes", which are simply groups
2250 * with a single character in them. To decide if something is a character box,
2251 * we find its innermost group, and see if it is a single character.
2252 */
2253var isCharacterBox = function(group) {
2254    var baseElem = getBaseElem(group);
2255
2256    // These are all they types of groups which hold single characters
2257    return baseElem.type === "mathord" ||
2258        baseElem.type === "textord" ||
2259        baseElem.type === "bin" ||
2260        baseElem.type === "rel" ||
2261        baseElem.type === "inner" ||
2262        baseElem.type === "open" ||
2263        baseElem.type === "close" ||
2264        baseElem.type === "punct";
2265};
2266
2267var makeNullDelimiter = function(options, classes) {
2268    return makeSpan(classes.concat([
2269        "sizing", "reset-" + options.size, "size5",
2270        options.style.reset(), Style.TEXT.cls(),
2271        "nulldelimiter"]));
2272};
2273
2274/**
2275 * This is a map of group types to the function used to handle that type.
2276 * Simpler types come at the beginning, while complicated types come afterwards.
2277 */
2278var groupTypes = {};
2279
2280groupTypes.mathord = function(group, options) {
2281    return buildCommon.makeOrd(group, options, "mathord");
2282};
2283
2284groupTypes.textord = function(group, options) {
2285    return buildCommon.makeOrd(group, options, "textord");
2286};
2287
2288groupTypes.bin = function(group, options) {
2289    return buildCommon.mathsym(
2290        group.value, group.mode, options, ["mbin"]);
2291};
2292
2293groupTypes.rel = function(group, options) {
2294    return buildCommon.mathsym(
2295        group.value, group.mode, options, ["mrel"]);
2296};
2297
2298groupTypes.open = function(group, options) {
2299    return buildCommon.mathsym(
2300        group.value, group.mode, options, ["mopen"]);
2301};
2302
2303groupTypes.close = function(group, options) {
2304    return buildCommon.mathsym(
2305        group.value, group.mode, options, ["mclose"]);
2306};
2307
2308groupTypes.inner = function(group, options) {
2309    return buildCommon.mathsym(
2310        group.value, group.mode, options, ["minner"]);
2311};
2312
2313groupTypes.punct = function(group, options) {
2314    return buildCommon.mathsym(
2315        group.value, group.mode, options, ["mpunct"]);
2316};
2317
2318groupTypes.ordgroup = function(group, options) {
2319    return makeSpan(
2320        ["mord", options.style.cls()],
2321        buildExpression(group.value, options.reset(), true),
2322        options
2323    );
2324};
2325
2326groupTypes.text = function(group, options) {
2327    var newOptions = options.withFont(group.value.style);
2328    var inner = buildExpression(group.value.body, newOptions, true);
2329    for (var i = 0; i < inner.length - 1; i++) {
2330        if (inner[i].tryCombine(inner[i + 1])) {
2331            inner.splice(i + 1, 1);
2332            i--;
2333        }
2334    }
2335    return makeSpan(["mord", "text", newOptions.style.cls()],
2336        inner, newOptions);
2337};
2338
2339groupTypes.color = function(group, options) {
2340    var elements = buildExpression(
2341        group.value.value,
2342        options.withColor(group.value.color),
2343        false
2344    );
2345
2346    // \color isn't supposed to affect the type of the elements it contains.
2347    // To accomplish this, we wrap the results in a fragment, so the inner
2348    // elements will be able to directly interact with their neighbors. For
2349    // example, `\color{red}{2 +} 3` has the same spacing as `2 + 3`
2350    return new buildCommon.makeFragment(elements);
2351};
2352
2353groupTypes.supsub = function(group, options) {
2354    // Superscript and subscripts are handled in the TeXbook on page
2355    // 445-446, rules 18(a-f).
2356
2357    // Here is where we defer to the inner group if it should handle
2358    // superscripts and subscripts itself.
2359    if (shouldHandleSupSub(group.value.base, options)) {
2360        return groupTypes[group.value.base.type](group, options);
2361    }
2362
2363    var base = buildGroup(group.value.base, options.reset());
2364    var supmid;
2365    var submid;
2366    var sup;
2367    var sub;
2368
2369    var style = options.style;
2370    var newOptions;
2371
2372    if (group.value.sup) {
2373        newOptions = options.withStyle(style.sup());
2374        sup = buildGroup(group.value.sup, newOptions);
2375        supmid = makeSpan([style.reset(), style.sup().cls()],
2376            [sup], newOptions);
2377    }
2378
2379    if (group.value.sub) {
2380        newOptions = options.withStyle(style.sub());
2381        sub = buildGroup(group.value.sub, newOptions);
2382        submid = makeSpan([style.reset(), style.sub().cls()],
2383            [sub], newOptions);
2384    }
2385
2386    // Rule 18a
2387    var supShift;
2388    var subShift;
2389    if (isCharacterBox(group.value.base)) {
2390        supShift = 0;
2391        subShift = 0;
2392    } else {
2393        supShift = base.height - style.metrics.supDrop;
2394        subShift = base.depth + style.metrics.subDrop;
2395    }
2396
2397    // Rule 18c
2398    var minSupShift;
2399    if (style === Style.DISPLAY) {
2400        minSupShift = style.metrics.sup1;
2401    } else if (style.cramped) {
2402        minSupShift = style.metrics.sup3;
2403    } else {
2404        minSupShift = style.metrics.sup2;
2405    }
2406
2407    // scriptspace is a font-size-independent size, so scale it
2408    // appropriately
2409    var multiplier = Style.TEXT.sizeMultiplier *
2410            style.sizeMultiplier;
2411    var scriptspace =
2412        (0.5 / fontMetrics.metrics.ptPerEm) / multiplier + "em";
2413
2414    var supsub;
2415    if (!group.value.sup) {
2416        // Rule 18b
2417        subShift = Math.max(
2418            subShift, style.metrics.sub1,
2419            sub.height - 0.8 * style.metrics.xHeight);
2420
2421        supsub = buildCommon.makeVList([
2422            {type: "elem", elem: submid}
2423        ], "shift", subShift, options);
2424
2425        supsub.children[0].style.marginRight = scriptspace;
2426
2427        // Subscripts shouldn't be shifted by the base's italic correction.
2428        // Account for that by shifting the subscript back the appropriate
2429        // amount. Note we only do this when the base is a single symbol.
2430        if (base instanceof domTree.symbolNode) {
2431            supsub.children[0].style.marginLeft = -base.italic + "em";
2432        }
2433    } else if (!group.value.sub) {
2434        // Rule 18c, d
2435        supShift = Math.max(supShift, minSupShift,
2436            sup.depth + 0.25 * style.metrics.xHeight);
2437
2438        supsub = buildCommon.makeVList([
2439            {type: "elem", elem: supmid}
2440        ], "shift", -supShift, options);
2441
2442        supsub.children[0].style.marginRight = scriptspace;
2443    } else {
2444        supShift = Math.max(
2445            supShift, minSupShift, sup.depth + 0.25 * style.metrics.xHeight);
2446        subShift = Math.max(subShift, style.metrics.sub2);
2447
2448        var ruleWidth = fontMetrics.metrics.defaultRuleThickness;
2449
2450        // Rule 18e
2451        if ((supShift - sup.depth) - (sub.height - subShift) <
2452                4 * ruleWidth) {
2453            subShift = 4 * ruleWidth - (supShift - sup.depth) + sub.height;
2454            var psi = 0.8 * style.metrics.xHeight - (supShift - sup.depth);
2455            if (psi > 0) {
2456                supShift += psi;
2457                subShift -= psi;
2458            }
2459        }
2460
2461        supsub = buildCommon.makeVList([
2462            {type: "elem", elem: submid, shift: subShift},
2463            {type: "elem", elem: supmid, shift: -supShift}
2464        ], "individualShift", null, options);
2465
2466        // See comment above about subscripts not being shifted
2467        if (base instanceof domTree.symbolNode) {
2468            supsub.children[0].style.marginLeft = -base.italic + "em";
2469        }
2470
2471        supsub.children[0].style.marginRight = scriptspace;
2472        supsub.children[1].style.marginRight = scriptspace;
2473    }
2474
2475    // We ensure to wrap the supsub vlist in a span.msupsub to reset text-align
2476    var mclass = getTypeOfDomTree(base) || "mord";
2477    return makeSpan([mclass],
2478        [base, makeSpan(["msupsub"], [supsub])],
2479        options);
2480};
2481
2482groupTypes.genfrac = function(group, options) {
2483    // Fractions are handled in the TeXbook on pages 444-445, rules 15(a-e).
2484    // Figure out what style this fraction should be in based on the
2485    // function used
2486    var style = options.style;
2487    if (group.value.size === "display") {
2488        style = Style.DISPLAY;
2489    } else if (group.value.size === "text") {
2490        style = Style.TEXT;
2491    }
2492
2493    var nstyle = style.fracNum();
2494    var dstyle = style.fracDen();
2495    var newOptions;
2496
2497    newOptions = options.withStyle(nstyle);
2498    var numer = buildGroup(group.value.numer, newOptions);
2499    var numerreset = makeSpan([style.reset(), nstyle.cls()],
2500        [numer], newOptions);
2501
2502    newOptions = options.withStyle(dstyle);
2503    var denom = buildGroup(group.value.denom, newOptions);
2504    var denomreset = makeSpan([style.reset(), dstyle.cls()],
2505        [denom], newOptions);
2506
2507    var ruleWidth;
2508    if (group.value.hasBarLine) {
2509        ruleWidth = fontMetrics.metrics.defaultRuleThickness /
2510            options.style.sizeMultiplier;
2511    } else {
2512        ruleWidth = 0;
2513    }
2514
2515    // Rule 15b
2516    var numShift;
2517    var clearance;
2518    var denomShift;
2519    if (style.size === Style.DISPLAY.size) {
2520        numShift = style.metrics.num1;
2521        if (ruleWidth > 0) {
2522            clearance = 3 * ruleWidth;
2523        } else {
2524            clearance = 7 * fontMetrics.metrics.defaultRuleThickness;
2525        }
2526        denomShift = style.metrics.denom1;
2527    } else {
2528        if (ruleWidth > 0) {
2529            numShift = style.metrics.num2;
2530            clearance = ruleWidth;
2531        } else {
2532            numShift = style.metrics.num3;
2533            clearance = 3 * fontMetrics.metrics.defaultRuleThickness;
2534        }
2535        denomShift = style.metrics.denom2;
2536    }
2537
2538    var frac;
2539    if (ruleWidth === 0) {
2540        // Rule 15c
2541        var candidateClearance =
2542            (numShift - numer.depth) - (denom.height - denomShift);
2543        if (candidateClearance < clearance) {
2544            numShift += 0.5 * (clearance - candidateClearance);
2545            denomShift += 0.5 * (clearance - candidateClearance);
2546        }
2547
2548        frac = buildCommon.makeVList([
2549            {type: "elem", elem: denomreset, shift: denomShift},
2550            {type: "elem", elem: numerreset, shift: -numShift}
2551        ], "individualShift", null, options);
2552    } else {
2553        // Rule 15d
2554        var axisHeight = style.metrics.axisHeight;
2555
2556        if ((numShift - numer.depth) - (axisHeight + 0.5 * ruleWidth) <
2557                clearance) {
2558            numShift +=
2559                clearance - ((numShift - numer.depth) -
2560                             (axisHeight + 0.5 * ruleWidth));
2561        }
2562
2563        if ((axisHeight - 0.5 * ruleWidth) - (denom.height - denomShift) <
2564                clearance) {
2565            denomShift +=
2566                clearance - ((axisHeight - 0.5 * ruleWidth) -
2567                             (denom.height - denomShift));
2568        }
2569
2570        var mid = makeSpan(
2571            [options.style.reset(), Style.TEXT.cls(), "frac-line"]);
2572        // Manually set the height of the line because its height is
2573        // created in CSS
2574        mid.height = ruleWidth;
2575
2576        var midShift = -(axisHeight - 0.5 * ruleWidth);
2577
2578        frac = buildCommon.makeVList([
2579            {type: "elem", elem: denomreset, shift: denomShift},
2580            {type: "elem", elem: mid,        shift: midShift},
2581            {type: "elem", elem: numerreset, shift: -numShift}
2582        ], "individualShift", null, options);
2583    }
2584
2585    // Since we manually change the style sometimes (with \dfrac or \tfrac),
2586    // account for the possible size change here.
2587    frac.height *= style.sizeMultiplier / options.style.sizeMultiplier;
2588    frac.depth *= style.sizeMultiplier / options.style.sizeMultiplier;
2589
2590    // Rule 15e
2591    var delimSize;
2592    if (style.size === Style.DISPLAY.size) {
2593        delimSize = style.metrics.delim1;
2594    } else {
2595        delimSize = style.metrics.delim2;
2596    }
2597
2598    var leftDelim;
2599    var rightDelim;
2600    if (group.value.leftDelim == null) {
2601        leftDelim = makeNullDelimiter(options, ["mopen"]);
2602    } else {
2603        leftDelim = delimiter.customSizedDelim(
2604            group.value.leftDelim, delimSize, true,
2605            options.withStyle(style), group.mode, ["mopen"]);
2606    }
2607    if (group.value.rightDelim == null) {
2608        rightDelim = makeNullDelimiter(options, ["mclose"]);
2609    } else {
2610        rightDelim = delimiter.customSizedDelim(
2611            group.value.rightDelim, delimSize, true,
2612            options.withStyle(style), group.mode, ["mclose"]);
2613    }
2614
2615    return makeSpan(
2616        ["mord", options.style.reset(), style.cls()],
2617        [leftDelim, makeSpan(["mfrac"], [frac]), rightDelim],
2618        options);
2619};
2620
2621var calculateSize = function(sizeValue, style) {
2622    var x = sizeValue.number;
2623    if (sizeValue.unit === "ex") {
2624        x *= style.metrics.emPerEx;
2625    } else if (sizeValue.unit === "mu") {
2626        x /= 18;
2627    }
2628    return x;
2629};
2630
2631groupTypes.array = function(group, options) {
2632    var r;
2633    var c;
2634    var nr = group.value.body.length;
2635    var nc = 0;
2636    var body = new Array(nr);
2637
2638    var style = options.style;
2639
2640    // Horizontal spacing
2641    var pt = 1 / fontMetrics.metrics.ptPerEm;
2642    var arraycolsep = 5 * pt; // \arraycolsep in article.cls
2643
2644    // Vertical spacing
2645    var baselineskip = 12 * pt; // see size10.clo
2646    // Default \arraystretch from lttab.dtx
2647    // TODO(gagern): may get redefined once we have user-defined macros
2648    var arraystretch = utils.deflt(group.value.arraystretch, 1);
2649    var arrayskip = arraystretch * baselineskip;
2650    var arstrutHeight = 0.7 * arrayskip; // \strutbox in ltfsstrc.dtx and
2651    var arstrutDepth = 0.3 * arrayskip;  // \@arstrutbox in lttab.dtx
2652
2653    var totalHeight = 0;
2654    for (r = 0; r < group.value.body.length; ++r) {
2655        var inrow = group.value.body[r];
2656        var height = arstrutHeight; // \@array adds an \@arstrut
2657        var depth = arstrutDepth;   // to each tow (via the template)
2658
2659        if (nc < inrow.length) {
2660            nc = inrow.length;
2661        }
2662
2663        var outrow = new Array(inrow.length);
2664        for (c = 0; c < inrow.length; ++c) {
2665            var elt = buildGroup(inrow[c], options);
2666            if (depth < elt.depth) {
2667                depth = elt.depth;
2668            }
2669            if (height < elt.height) {
2670                height = elt.height;
2671            }
2672            outrow[c] = elt;
2673        }
2674
2675        var gap = 0;
2676        if (group.value.rowGaps[r]) {
2677            gap = calculateSize(group.value.rowGaps[r].value, style);
2678            if (gap > 0) { // \@argarraycr
2679                gap += arstrutDepth;
2680                if (depth < gap) {
2681                    depth = gap; // \@xargarraycr
2682                }
2683                gap = 0;
2684            }
2685        }
2686
2687        outrow.height = height;
2688        outrow.depth = depth;
2689        totalHeight += height;
2690        outrow.pos = totalHeight;
2691        totalHeight += depth + gap; // \@yargarraycr
2692        body[r] = outrow;
2693    }
2694
2695    var offset = totalHeight / 2 + style.metrics.axisHeight;
2696    var colDescriptions = group.value.cols || [];
2697    var cols = [];
2698    var colSep;
2699    var colDescrNum;
2700    for (c = 0, colDescrNum = 0;
2701         // Continue while either there are more columns or more column
2702         // descriptions, so trailing separators don't get lost.
2703         c < nc || colDescrNum < colDescriptions.length;
2704         ++c, ++colDescrNum) {
2705
2706        var colDescr = colDescriptions[colDescrNum] || {};
2707
2708        var firstSeparator = true;
2709        while (colDescr.type === "separator") {
2710            // If there is more than one separator in a row, add a space
2711            // between them.
2712            if (!firstSeparator) {
2713                colSep = makeSpan(["arraycolsep"], []);
2714                colSep.style.width =
2715                    fontMetrics.metrics.doubleRuleSep + "em";
2716                cols.push(colSep);
2717            }
2718
2719            if (colDescr.separator === "|") {
2720                var separator = makeSpan(
2721                    ["vertical-separator"],
2722                    []);
2723                separator.style.height = totalHeight + "em";
2724                separator.style.verticalAlign =
2725                    -(totalHeight - offset) + "em";
2726
2727                cols.push(separator);
2728            } else {
2729                throw new ParseError(
2730                    "Invalid separator type: " + colDescr.separator);
2731            }
2732
2733            colDescrNum++;
2734            colDescr = colDescriptions[colDescrNum] || {};
2735            firstSeparator = false;
2736        }
2737
2738        if (c >= nc) {
2739            continue;
2740        }
2741
2742        var sepwidth;
2743        if (c > 0 || group.value.hskipBeforeAndAfter) {
2744            sepwidth = utils.deflt(colDescr.pregap, arraycolsep);
2745            if (sepwidth !== 0) {
2746                colSep = makeSpan(["arraycolsep"], []);
2747                colSep.style.width = sepwidth + "em";
2748                cols.push(colSep);
2749            }
2750        }
2751
2752        var col = [];
2753        for (r = 0; r < nr; ++r) {
2754            var row = body[r];
2755            var elem = row[c];
2756            if (!elem) {
2757                continue;
2758            }
2759            var shift = row.pos - offset;
2760            elem.depth = row.depth;
2761            elem.height = row.height;
2762            col.push({type: "elem", elem: elem, shift: shift});
2763        }
2764
2765        col = buildCommon.makeVList(col, "individualShift", null, options);
2766        col = makeSpan(
2767            ["col-align-" + (colDescr.align || "c")],
2768            [col]);
2769        cols.push(col);
2770
2771        if (c < nc - 1 || group.value.hskipBeforeAndAfter) {
2772            sepwidth = utils.deflt(colDescr.postgap, arraycolsep);
2773            if (sepwidth !== 0) {
2774                colSep = makeSpan(["arraycolsep"], []);
2775                colSep.style.width = sepwidth + "em";
2776                cols.push(colSep);
2777            }
2778        }
2779    }
2780    body = makeSpan(["mtable"], cols);
2781    return makeSpan(["mord"], [body], options);
2782};
2783
2784groupTypes.spacing = function(group, options) {
2785    if (group.value === "\\ " || group.value === "\\space" ||
2786        group.value === " " || group.value === "~") {
2787        // Spaces are generated by adding an actual space. Each of these
2788        // things has an entry in the symbols table, so these will be turned
2789        // into appropriate outputs.
2790        if (group.mode === "text") {
2791            return buildCommon.makeOrd(group, options, "textord");
2792        } else {
2793            return makeSpan(["mspace"],
2794                [buildCommon.mathsym(group.value, group.mode, options)],
2795                options);
2796        }
2797    } else {
2798        // Other kinds of spaces are of arbitrary width. We use CSS to
2799        // generate these.
2800        return makeSpan(
2801            ["mspace",
2802                buildCommon.spacingFunctions[group.value].className],
2803            [], options);
2804    }
2805};
2806
2807groupTypes.llap = function(group, options) {
2808    var inner = makeSpan(
2809        ["inner"], [buildGroup(group.value.body, options.reset())]);
2810    var fix = makeSpan(["fix"], []);
2811    return makeSpan(
2812        ["mord", "llap", options.style.cls()], [inner, fix], options);
2813};
2814
2815groupTypes.rlap = function(group, options) {
2816    var inner = makeSpan(
2817        ["inner"], [buildGroup(group.value.body, options.reset())]);
2818    var fix = makeSpan(["fix"], []);
2819    return makeSpan(
2820        ["mord", "rlap", options.style.cls()], [inner, fix], options);
2821};
2822
2823groupTypes.op = function(group, options) {
2824    // Operators are handled in the TeXbook pg. 443-444, rule 13(a).
2825    var supGroup;
2826    var subGroup;
2827    var hasLimits = false;
2828    if (group.type === "supsub") {
2829        // If we have limits, supsub will pass us its group to handle. Pull
2830        // out the superscript and subscript and set the group to the op in
2831        // its base.
2832        supGroup = group.value.sup;
2833        subGroup = group.value.sub;
2834        group = group.value.base;
2835        hasLimits = true;
2836    }
2837
2838    var style = options.style;
2839
2840    // Most operators have a large successor symbol, but these don't.
2841    var noSuccessor = [
2842        "\\smallint"
2843    ];
2844
2845    var large = false;
2846    if (style.size === Style.DISPLAY.size &&
2847        group.value.symbol &&
2848        !utils.contains(noSuccessor, group.value.body)) {
2849
2850        // Most symbol operators get larger in displaystyle (rule 13)
2851        large = true;
2852    }
2853
2854    var base;
2855    var baseShift = 0;
2856    var slant = 0;
2857    if (group.value.symbol) {
2858        // If this is a symbol, create the symbol.
2859        var fontName = large ? "Size2-Regular" : "Size1-Regular";
2860        base = buildCommon.makeSymbol(
2861            group.value.body, fontName, "math", options,
2862            ["mop", "op-symbol", large ? "large-op" : "small-op"]);
2863
2864        // Shift the symbol so its center lies on the axis (rule 13). It
2865        // appears that our fonts have the centers of the symbols already
2866        // almost on the axis, so these numbers are very small. Note we
2867        // don't actually apply this here, but instead it is used either in
2868        // the vlist creation or separately when there are no limits.
2869        baseShift = (base.height - base.depth) / 2 -
2870            style.metrics.axisHeight * style.sizeMultiplier;
2871
2872        // The slant of the symbol is just its italic correction.
2873        slant = base.italic;
2874    } else if (group.value.value) {
2875        // If this is a list, compose that list.
2876        var inner = buildExpression(group.value.value, options, true);
2877
2878        base = makeSpan(["mop"], inner, options);
2879    } else {
2880        // Otherwise, this is a text operator. Build the text from the
2881        // operator's name.
2882        // TODO(emily): Add a space in the middle of some of these
2883        // operators, like \limsup
2884        var output = [];
2885        for (var i = 1; i < group.value.body.length; i++) {
2886            output.push(buildCommon.mathsym(group.value.body[i], group.mode));
2887        }
2888        base = makeSpan(["mop"], output, options);
2889    }
2890
2891    if (hasLimits) {
2892        // IE 8 clips \int if it is in a display: inline-block. We wrap it
2893        // in a new span so it is an inline, and works.
2894        base = makeSpan([], [base]);
2895
2896        var supmid;
2897        var supKern;
2898        var submid;
2899        var subKern;
2900        var newOptions;
2901        // We manually have to handle the superscripts and subscripts. This,
2902        // aside from the kern calculations, is copied from supsub.
2903        if (supGroup) {
2904            newOptions = options.withStyle(style.sup());
2905            var sup = buildGroup(supGroup, newOptions);
2906            supmid = makeSpan([style.reset(), style.sup().cls()],
2907                [sup], newOptions);
2908
2909            supKern = Math.max(
2910                fontMetrics.metrics.bigOpSpacing1,
2911                fontMetrics.metrics.bigOpSpacing3 - sup.depth);
2912        }
2913
2914        if (subGroup) {
2915            newOptions = options.withStyle(style.sub());
2916            var sub = buildGroup(subGroup, newOptions);
2917            submid = makeSpan([style.reset(), style.sub().cls()],
2918                [sub], newOptions);
2919
2920            subKern = Math.max(
2921                fontMetrics.metrics.bigOpSpacing2,
2922                fontMetrics.metrics.bigOpSpacing4 - sub.height);
2923        }
2924
2925        // Build the final group as a vlist of the possible subscript, base,
2926        // and possible superscript.
2927        var finalGroup;
2928        var top;
2929        var bottom;
2930        if (!supGroup) {
2931            top = base.height - baseShift;
2932
2933            finalGroup = buildCommon.makeVList([
2934                {type: "kern", size: fontMetrics.metrics.bigOpSpacing5},
2935                {type: "elem", elem: submid},
2936                {type: "kern", size: subKern},
2937                {type: "elem", elem: base}
2938            ], "top", top, options);
2939
2940            // Here, we shift the limits by the slant of the symbol. Note
2941            // that we are supposed to shift the limits by 1/2 of the slant,
2942            // but since we are centering the limits adding a full slant of
2943            // margin will shift by 1/2 that.
2944            finalGroup.children[0].style.marginLeft = -slant + "em";
2945        } else if (!subGroup) {
2946            bottom = base.depth + baseShift;
2947
2948            finalGroup = buildCommon.makeVList([
2949                {type: "elem", elem: base},
2950                {type: "kern", size: supKern},
2951                {type: "elem", elem: supmid},
2952                {type: "kern", size: fontMetrics.metrics.bigOpSpacing5}
2953            ], "bottom", bottom, options);
2954
2955            // See comment above about slants
2956            finalGroup.children[1].style.marginLeft = slant + "em";
2957        } else if (!supGroup && !subGroup) {
2958            // This case probably shouldn't occur (this would mean the
2959            // supsub was sending us a group with no superscript or
2960            // subscript) but be safe.
2961            return base;
2962        } else {
2963            bottom = fontMetrics.metrics.bigOpSpacing5 +
2964                submid.height + submid.depth +
2965                subKern +
2966                base.depth + baseShift;
2967
2968            finalGroup = buildCommon.makeVList([
2969                {type: "kern", size: fontMetrics.metrics.bigOpSpacing5},
2970                {type: "elem", elem: submid},
2971                {type: "kern", size: subKern},
2972                {type: "elem", elem: base},
2973                {type: "kern", size: supKern},
2974                {type: "elem", elem: supmid},
2975                {type: "kern", size: fontMetrics.metrics.bigOpSpacing5}
2976            ], "bottom", bottom, options);
2977
2978            // See comment above about slants
2979            finalGroup.children[0].style.marginLeft = -slant + "em";
2980            finalGroup.children[2].style.marginLeft = slant + "em";
2981        }
2982
2983        return makeSpan(["mop", "op-limits"], [finalGroup], options);
2984    } else {
2985        if (group.value.symbol) {
2986            base.style.top = baseShift + "em";
2987        }
2988
2989        return base;
2990    }
2991};
2992
2993groupTypes.mod = function(group, options) {
2994    var inner = [];
2995
2996    if (group.value.modType === "bmod") {
2997        // “\nonscript\mskip-\medmuskip\mkern5mu”
2998        if (!options.style.isTight()) {
2999            inner.push(makeSpan(
3000                ["mspace", "negativemediumspace"], [], options));
3001        }
3002        inner.push(makeSpan(["mspace", "thickspace"], [], options));
3003    } else if (options.style.size === Style.DISPLAY.size) {
3004        inner.push(makeSpan(["mspace", "quad"], [], options));
3005    } else if (group.value.modType === "mod") {
3006        inner.push(makeSpan(["mspace", "twelvemuspace"], [], options));
3007    } else {
3008        inner.push(makeSpan(["mspace", "eightmuspace"], [], options));
3009    }
3010
3011    if (group.value.modType === "pod" || group.value.modType === "pmod") {
3012        inner.push(buildCommon.mathsym("(", group.mode));
3013    }
3014
3015    if (group.value.modType !== "pod") {
3016        var modInner = [
3017            buildCommon.mathsym("m", group.mode),
3018            buildCommon.mathsym("o", group.mode),
3019            buildCommon.mathsym("d", group.mode)];
3020        if (group.value.modType === "bmod") {
3021            inner.push(makeSpan(["mbin"], modInner, options));
3022            // “\mkern5mu\nonscript\mskip-\medmuskip”
3023            inner.push(makeSpan(["mspace", "thickspace"], [], options));
3024            if (!options.style.isTight()) {
3025                inner.push(makeSpan(
3026                    ["mspace", "negativemediumspace"], [], options));
3027            }
3028        } else {
3029            Array.prototype.push.apply(inner, modInner);
3030            inner.push(makeSpan(["mspace", "sixmuspace"], [], options));
3031        }
3032    }
3033
3034    if (group.value.value) {
3035        Array.prototype.push.apply(inner,
3036            buildExpression(group.value.value, options, false));
3037    }
3038
3039    if (group.value.modType === "pod" || group.value.modType === "pmod") {
3040        inner.push(buildCommon.mathsym(")", group.mode));
3041    }
3042
3043    return buildCommon.makeFragment(inner);
3044};
3045
3046groupTypes.katex = function(group, options) {
3047    // The KaTeX logo. The offsets for the K and a were chosen to look
3048    // good, but the offsets for the T, E, and X were taken from the
3049    // definition of \TeX in TeX (see TeXbook pg. 356)
3050    var k = makeSpan(
3051        ["k"], [buildCommon.mathsym("K", group.mode)], options);
3052    var a = makeSpan(
3053        ["a"], [buildCommon.mathsym("A", group.mode)], options);
3054
3055    a.height = (a.height + 0.2) * 0.75;
3056    a.depth = (a.height - 0.2) * 0.75;
3057
3058    var t = makeSpan(
3059        ["t"], [buildCommon.mathsym("T", group.mode)], options);
3060    var e = makeSpan(
3061        ["e"], [buildCommon.mathsym("E", group.mode)], options);
3062
3063    e.height = (e.height - 0.2155);
3064    e.depth = (e.depth + 0.2155);
3065
3066    var x = makeSpan(
3067        ["x"], [buildCommon.mathsym("X", group.mode)], options);
3068
3069    return makeSpan(
3070        ["mord", "katex-logo"], [k, a, t, e, x], options);
3071};
3072
3073groupTypes.overline = function(group, options) {
3074    // Overlines are handled in the TeXbook pg 443, Rule 9.
3075    var style = options.style;
3076
3077    // Build the inner group in the cramped style.
3078    var innerGroup = buildGroup(group.value.body,
3079            options.withStyle(style.cramp()));
3080
3081    var ruleWidth = fontMetrics.metrics.defaultRuleThickness /
3082        style.sizeMultiplier;
3083
3084    // Create the line above the body
3085    var line = makeSpan(
3086        [style.reset(), Style.TEXT.cls(), "overline-line"]);
3087    line.height = ruleWidth;
3088    line.maxFontSize = 1.0;
3089
3090    // Generate the vlist, with the appropriate kerns
3091    var vlist = buildCommon.makeVList([
3092        {type: "elem", elem: innerGroup},
3093        {type: "kern", size: 3 * ruleWidth},
3094        {type: "elem", elem: line},
3095        {type: "kern", size: ruleWidth}
3096    ], "firstBaseline", null, options);
3097
3098    return makeSpan(["mord", "overline"], [vlist], options);
3099};
3100
3101groupTypes.underline = function(group, options) {
3102    // Underlines are handled in the TeXbook pg 443, Rule 10.
3103    var style = options.style;
3104
3105    // Build the inner group.
3106    var innerGroup = buildGroup(group.value.body, options);
3107
3108    var ruleWidth = fontMetrics.metrics.defaultRuleThickness /
3109        style.sizeMultiplier;
3110
3111    // Create the line above the body
3112    var line = makeSpan([style.reset(), Style.TEXT.cls(), "underline-line"]);
3113    line.height = ruleWidth;
3114    line.maxFontSize = 1.0;
3115
3116    // Generate the vlist, with the appropriate kerns
3117    var vlist = buildCommon.makeVList([
3118        {type: "kern", size: ruleWidth},
3119        {type: "elem", elem: line},
3120        {type: "kern", size: 3 * ruleWidth},
3121        {type: "elem", elem: innerGroup}
3122    ], "top", innerGroup.height, options);
3123
3124    return makeSpan(["mord", "underline"], [vlist], options);
3125};
3126
3127groupTypes.sqrt = function(group, options) {
3128    // Square roots are handled in the TeXbook pg. 443, Rule 11.
3129    var style = options.style;
3130
3131    // First, we do the same steps as in overline to build the inner group
3132    // and line
3133    var inner = buildGroup(group.value.body, options.withStyle(style.cramp()));
3134
3135    var ruleWidth = fontMetrics.metrics.defaultRuleThickness /
3136        style.sizeMultiplier;
3137
3138    var line = makeSpan(
3139        [style.reset(), Style.TEXT.cls(), "sqrt-line"], [],
3140        options);
3141    line.height = ruleWidth;
3142    line.maxFontSize = 1.0;
3143
3144    var phi = ruleWidth;
3145    if (style.id < Style.TEXT.id) {
3146        phi = style.metrics.xHeight;
3147    }
3148
3149    // Calculate the clearance between the body and line
3150    var lineClearance = ruleWidth + phi / 4;
3151
3152    var innerHeight = (inner.height + inner.depth) * style.sizeMultiplier;
3153    var minDelimiterHeight = innerHeight + lineClearance + ruleWidth;
3154
3155    // Create a \surd delimiter of the required minimum size
3156    var delim = makeSpan(["sqrt-sign"], [
3157        delimiter.customSizedDelim("\\surd", minDelimiterHeight,
3158                                   false, options, group.mode)],
3159                         options);
3160
3161    var delimDepth = (delim.height + delim.depth) - ruleWidth;
3162
3163    // Adjust the clearance based on the delimiter size
3164    if (delimDepth > inner.height + inner.depth + lineClearance) {
3165        lineClearance =
3166            (lineClearance + delimDepth - inner.height - inner.depth) / 2;
3167    }
3168
3169    // Shift the delimiter so that its top lines up with the top of the line
3170    var delimShift = -(inner.height + lineClearance + ruleWidth) + delim.height;
3171    delim.style.top = delimShift + "em";
3172    delim.height -= delimShift;
3173    delim.depth += delimShift;
3174
3175    // We add a special case here, because even when `inner` is empty, we
3176    // still get a line. So, we use a simple heuristic to decide if we
3177    // should omit the body entirely. (note this doesn't work for something
3178    // like `\sqrt{\rlap{x}}`, but if someone is doing that they deserve for
3179    // it not to work.
3180    var body;
3181    if (inner.height === 0 && inner.depth === 0) {
3182        body = makeSpan();
3183    } else {
3184        body = buildCommon.makeVList([
3185            {type: "elem", elem: inner},
3186            {type: "kern", size: lineClearance},
3187            {type: "elem", elem: line},
3188            {type: "kern", size: ruleWidth}
3189        ], "firstBaseline", null, options);
3190    }
3191
3192    if (!group.value.index) {
3193        return makeSpan(["mord", "sqrt"], [delim, body], options);
3194    } else {
3195        // Handle the optional root index
3196
3197        // The index is always in scriptscript style
3198        var newOptions = options.withStyle(Style.SCRIPTSCRIPT);
3199        var root = buildGroup(group.value.index, newOptions);
3200        var rootWrap = makeSpan(
3201            [style.reset(), Style.SCRIPTSCRIPT.cls()],
3202            [root],
3203            newOptions);
3204
3205        // Figure out the height and depth of the inner part
3206        var innerRootHeight = Math.max(delim.height, body.height);
3207        var innerRootDepth = Math.max(delim.depth, body.depth);
3208
3209        // The amount the index is shifted by. This is taken from the TeX
3210        // source, in the definition of `\r@@t`.
3211        var toShift = 0.6 * (innerRootHeight - innerRootDepth);
3212
3213        // Build a VList with the superscript shifted up correctly
3214        var rootVList = buildCommon.makeVList(
3215            [{type: "elem", elem: rootWrap}],
3216            "shift", -toShift, options);
3217        // Add a class surrounding it so we can add on the appropriate
3218        // kerning
3219        var rootVListWrap = makeSpan(["root"], [rootVList]);
3220
3221        return makeSpan(["mord", "sqrt"],
3222            [rootVListWrap, delim, body], options);
3223    }
3224};
3225
3226groupTypes.sizing = function(group, options) {
3227    // Handle sizing operators like \Huge. Real TeX doesn't actually allow
3228    // these functions inside of math expressions, so we do some special
3229    // handling.
3230    var inner = buildExpression(group.value.value,
3231            options.withSize(group.value.size), false);
3232
3233    // Compute the correct maxFontSize.
3234    var style = options.style;
3235    var fontSize = buildCommon.sizingMultiplier[group.value.size];
3236    fontSize = fontSize * style.sizeMultiplier;
3237
3238    // Add size-resetting classes to the inner list and set maxFontSize
3239    // manually. Handle nested size changes.
3240    for (var i = 0; i < inner.length; i++) {
3241        var pos = utils.indexOf(inner[i].classes, "sizing");
3242        if (pos < 0) {
3243            inner[i].classes.push("sizing", "reset-" + options.size,
3244                                  group.value.size, style.cls());
3245            inner[i].maxFontSize = fontSize;
3246        } else if (inner[i].classes[pos + 1] === "reset-" + group.value.size) {
3247            // This is a nested size change: e.g., inner[i] is the "b" in
3248            // `\Huge a \small b`. Override the old size (the `reset-` class)
3249            // but not the new size.
3250            inner[i].classes[pos + 1] = "reset-" + options.size;
3251        }
3252    }
3253
3254    return buildCommon.makeFragment(inner);
3255};
3256
3257groupTypes.styling = function(group, options) {
3258    // Style changes are handled in the TeXbook on pg. 442, Rule 3.
3259
3260    // Figure out what style we're changing to.
3261    var styleMap = {
3262        "display": Style.DISPLAY,
3263        "text": Style.TEXT,
3264        "script": Style.SCRIPT,
3265        "scriptscript": Style.SCRIPTSCRIPT
3266    };
3267
3268    var newStyle = styleMap[group.value.style];
3269    var newOptions = options.withStyle(newStyle);
3270
3271    // Build the inner expression in the new style.
3272    var inner = buildExpression(
3273        group.value.value, newOptions, false);
3274
3275    // Add style-resetting classes to the inner list. Handle nested changes.
3276    for (var i = 0; i < inner.length; i++) {
3277        var pos = utils.indexOf(inner[i].classes, newStyle.reset());
3278        if (pos < 0) {
3279            inner[i].classes.push(options.style.reset(), newStyle.cls());
3280        } else {
3281            // This is a nested style change, as `\textstyle a\scriptstyle b`.
3282            // Only override the old style (the reset class).
3283            inner[i].classes[pos] = options.style.reset();
3284        }
3285    }
3286
3287    return new buildCommon.makeFragment(inner);
3288};
3289
3290groupTypes.font = function(group, options) {
3291    var font = group.value.font;
3292    return buildGroup(group.value.body, options.withFont(font));
3293};
3294
3295groupTypes.delimsizing = function(group, options) {
3296    var delim = group.value.value;
3297
3298    if (delim === ".") {
3299        // Empty delimiters still count as elements, even though they don't
3300        // show anything.
3301        return makeSpan([group.value.mclass]);
3302    }
3303
3304    // Use delimiter.sizedDelim to generate the delimiter.
3305    return delimiter.sizedDelim(
3306            delim, group.value.size, options, group.mode,
3307            [group.value.mclass]);
3308};
3309
3310groupTypes.leftright = function(group, options) {
3311    // Build the inner expression
3312    var inner = buildExpression(group.value.body, options.reset(), true);
3313
3314    var innerHeight = 0;
3315    var innerDepth = 0;
3316    var hadMiddle = false;
3317
3318    // Calculate its height and depth
3319    for (var i = 0; i < inner.length; i++) {
3320        if (inner[i].isMiddle) {
3321            hadMiddle = true;
3322        } else {
3323            innerHeight = Math.max(inner[i].height, innerHeight);
3324            innerDepth = Math.max(inner[i].depth, innerDepth);
3325        }
3326    }
3327
3328    var style = options.style;
3329
3330    // The size of delimiters is the same, regardless of what style we are
3331    // in. Thus, to correctly calculate the size of delimiter we need around
3332    // a group, we scale down the inner size based on the size.
3333    innerHeight *= style.sizeMultiplier;
3334    innerDepth *= style.sizeMultiplier;
3335
3336    var leftDelim;
3337    if (group.value.left === ".") {
3338        // Empty delimiters in \left and \right make null delimiter spaces.
3339        leftDelim = makeNullDelimiter(options, ["mopen"]);
3340    } else {
3341        // Otherwise, use leftRightDelim to generate the correct sized
3342        // delimiter.
3343        leftDelim = delimiter.leftRightDelim(
3344            group.value.left, innerHeight, innerDepth, options,
3345            group.mode, ["mopen"]);
3346    }
3347    // Add it to the beginning of the expression
3348    inner.unshift(leftDelim);
3349
3350    // Handle middle delimiters
3351    if (hadMiddle) {
3352        for (i = 1; i < inner.length; i++) {
3353            if (inner[i].isMiddle) {
3354                // Apply the options that were active when \middle was called
3355                inner[i] = delimiter.leftRightDelim(
3356                    inner[i].isMiddle.value, innerHeight, innerDepth,
3357                    inner[i].isMiddle.options, group.mode, []);
3358            }
3359        }
3360    }
3361
3362    var rightDelim;
3363    // Same for the right delimiter
3364    if (group.value.right === ".") {
3365        rightDelim = makeNullDelimiter(options, ["mclose"]);
3366    } else {
3367        rightDelim = delimiter.leftRightDelim(
3368            group.value.right, innerHeight, innerDepth, options,
3369            group.mode, ["mclose"]);
3370    }
3371    // Add it to the end of the expression.
3372    inner.push(rightDelim);
3373
3374    return makeSpan(
3375        ["minner", style.cls()], inner, options);
3376};
3377
3378groupTypes.middle = function(group, options) {
3379    var middleDelim;
3380    if (group.value.value === ".") {
3381        middleDelim = makeNullDelimiter(options, []);
3382    } else {
3383        middleDelim = delimiter.sizedDelim(
3384            group.value.value, 1, options,
3385            group.mode, []);
3386        middleDelim.isMiddle = {value: group.value.value, options: options};
3387    }
3388    return middleDelim;
3389};
3390
3391groupTypes.rule = function(group, options) {
3392    // Make an empty span for the rule
3393    var rule = makeSpan(["mord", "rule"], [], options);
3394    var style = options.style;
3395
3396    // Calculate the shift, width, and height of the rule, and account for units
3397    var shift = 0;
3398    if (group.value.shift) {
3399        shift = calculateSize(group.value.shift, style);
3400    }
3401
3402    var width = calculateSize(group.value.width, style);
3403    var height = calculateSize(group.value.height, style);
3404
3405    // The sizes of rules are absolute, so make it larger if we are in a
3406    // smaller style.
3407    shift /= style.sizeMultiplier;
3408    width /= style.sizeMultiplier;
3409    height /= style.sizeMultiplier;
3410
3411    // Style the rule to the right size
3412    rule.style.borderRightWidth = width + "em";
3413    rule.style.borderTopWidth = height + "em";
3414    rule.style.bottom = shift + "em";
3415
3416    // Record the height and width
3417    rule.width = width;
3418    rule.height = height + shift;
3419    rule.depth = -shift;
3420
3421    return rule;
3422};
3423
3424groupTypes.kern = function(group, options) {
3425    // Make an empty span for the rule
3426    var rule = makeSpan(["mord", "rule"], [], options);
3427    var style = options.style;
3428
3429    var dimension = 0;
3430    if (group.value.dimension) {
3431        dimension = calculateSize(group.value.dimension, style);
3432    }
3433
3434    dimension /= style.sizeMultiplier;
3435
3436    rule.style.marginLeft = dimension + "em";
3437
3438    return rule;
3439};
3440
3441groupTypes.accent = function(group, options) {
3442    // Accents are handled in the TeXbook pg. 443, rule 12.
3443    var base = group.value.base;
3444    var style = options.style;
3445
3446    var supsubGroup;
3447    if (group.type === "supsub") {
3448        // If our base is a character box, and we have superscripts and
3449        // subscripts, the supsub will defer to us. In particular, we want
3450        // to attach the superscripts and subscripts to the inner body (so
3451        // that the position of the superscripts and subscripts won't be
3452        // affected by the height of the accent). We accomplish this by
3453        // sticking the base of the accent into the base of the supsub, and
3454        // rendering that, while keeping track of where the accent is.
3455
3456        // The supsub group is the group that was passed in
3457        var supsub = group;
3458        // The real accent group is the base of the supsub group
3459        group = supsub.value.base;
3460        // The character box is the base of the accent group
3461        base = group.value.base;
3462        // Stick the character box into the base of the supsub group
3463        supsub.value.base = base;
3464
3465        // Rerender the supsub group with its new base, and store that
3466        // result.
3467        supsubGroup = buildGroup(
3468            supsub, options.reset());
3469    }
3470
3471    // Build the base group
3472    var body = buildGroup(
3473        base, options.withStyle(style.cramp()));
3474
3475    // Calculate the skew of the accent. This is based on the line "If the
3476    // nucleus is not a single character, let s = 0; otherwise set s to the
3477    // kern amount for the nucleus followed by the \skewchar of its font."
3478    // Note that our skew metrics are just the kern between each character
3479    // and the skewchar.
3480    var skew;
3481    if (isCharacterBox(base)) {
3482        // If the base is a character box, then we want the skew of the
3483        // innermost character. To do that, we find the innermost character:
3484        var baseChar = getBaseElem(base);
3485        // Then, we render its group to get the symbol inside it
3486        var baseGroup = buildGroup(
3487            baseChar, options.withStyle(style.cramp()));
3488        // Finally, we pull the skew off of the symbol.
3489        skew = baseGroup.skew;
3490        // Note that we now throw away baseGroup, because the layers we
3491        // removed with getBaseElem might contain things like \color which
3492        // we can't get rid of.
3493        // TODO(emily): Find a better way to get the skew
3494    } else {
3495        skew = 0;
3496    }
3497
3498    // calculate the amount of space between the body and the accent
3499    var clearance = Math.min(
3500        body.height,
3501        style.metrics.xHeight);
3502
3503    // Build the accent
3504    var accent = buildCommon.makeSymbol(
3505        group.value.accent, "Main-Regular", "math", options);
3506    // Remove the italic correction of the accent, because it only serves to
3507    // shift the accent over to a place we don't want.
3508    accent.italic = 0;
3509
3510    // The \vec character that the fonts use is a combining character, and
3511    // thus shows up much too far to the left. To account for this, we add a
3512    // specific class which shifts the accent over to where we want it.
3513    // TODO(emily): Fix this in a better way, like by changing the font
3514    var vecClass = group.value.accent === "\\vec" ? "accent-vec" : null;
3515
3516    var accentBody = makeSpan(["accent-body", vecClass], [
3517        makeSpan([], [accent])]);
3518
3519    accentBody = buildCommon.makeVList([
3520        {type: "elem", elem: body},
3521        {type: "kern", size: -clearance},
3522        {type: "elem", elem: accentBody}
3523    ], "firstBaseline", null, options);
3524
3525    // Shift the accent over by the skew. Note we shift by twice the skew
3526    // because we are centering the accent, so by adding 2*skew to the left,
3527    // we shift it to the right by 1*skew.
3528    accentBody.children[1].style.marginLeft = 2 * skew + "em";
3529
3530    var accentWrap = makeSpan(["mord", "accent"], [accentBody], options);
3531
3532    if (supsubGroup) {
3533        // Here, we replace the "base" child of the supsub with our newly
3534        // generated accent.
3535        supsubGroup.children[0] = accentWrap;
3536
3537        // Since we don't rerun the height calculation after replacing the
3538        // accent, we manually recalculate height.
3539        supsubGroup.height = Math.max(accentWrap.height, supsubGroup.height);
3540
3541        // Accents should always be ords, even when their innards are not.
3542        supsubGroup.classes[0] = "mord";
3543
3544        return supsubGroup;
3545    } else {
3546        return accentWrap;
3547    }
3548};
3549
3550groupTypes.phantom = function(group, options) {
3551    var elements = buildExpression(
3552        group.value.value,
3553        options.withPhantom(),
3554        false
3555    );
3556
3557    // \phantom isn't supposed to affect the elements it contains.
3558    // See "color" for more details.
3559    return new buildCommon.makeFragment(elements);
3560};
3561
3562groupTypes.mclass = function(group, options) {
3563    var elements = buildExpression(group.value.value, options, true);
3564
3565    return makeSpan([group.value.mclass], elements, options);
3566};
3567
3568/**
3569 * buildGroup is the function that takes a group and calls the correct groupType
3570 * function for it. It also handles the interaction of size and style changes
3571 * between parents and children.
3572 */
3573var buildGroup = function(group, options) {
3574    if (!group) {
3575        return makeSpan();
3576    }
3577
3578    if (groupTypes[group.type]) {
3579        // Call the groupTypes function
3580        var groupNode = groupTypes[group.type](group, options);
3581        var multiplier;
3582
3583        // If the style changed between the parent and the current group,
3584        // account for the size difference
3585        if (options.style !== options.parentStyle) {
3586            multiplier = options.style.sizeMultiplier /
3587                    options.parentStyle.sizeMultiplier;
3588
3589            groupNode.height *= multiplier;
3590            groupNode.depth *= multiplier;
3591        }
3592
3593        // If the size changed between the parent and the current group, account
3594        // for that size difference.
3595        if (options.size !== options.parentSize) {
3596            multiplier = buildCommon.sizingMultiplier[options.size] /
3597                    buildCommon.sizingMultiplier[options.parentSize];
3598
3599            groupNode.height *= multiplier;
3600            groupNode.depth *= multiplier;
3601        }
3602
3603        return groupNode;
3604    } else {
3605        throw new ParseError(
3606            "Got group of unknown type: '" + group.type + "'");
3607    }
3608};
3609
3610/**
3611 * Take an entire parse tree, and build it into an appropriate set of HTML
3612 * nodes.
3613 */
3614var buildHTML = function(tree, options) {
3615    // buildExpression is destructive, so we need to make a clone
3616    // of the incoming tree so that it isn't accidentally changed
3617    tree = JSON.parse(JSON.stringify(tree));
3618
3619    // Build the expression contained in the tree
3620    var expression = buildExpression(tree, options, true);
3621    var body = makeSpan(["base", options.style.cls()], expression, options);
3622
3623    // Add struts, which ensure that the top of the HTML element falls at the
3624    // height of the expression, and the bottom of the HTML element falls at the
3625    // depth of the expression.
3626    var topStrut = makeSpan(["strut"]);
3627    var bottomStrut = makeSpan(["strut", "bottom"]);
3628
3629    topStrut.style.height = body.height + "em";
3630    bottomStrut.style.height = (body.height + body.depth) + "em";
3631    // We'd like to use `vertical-align: top` but in IE 9 this lowers the
3632    // baseline of the box to the bottom of this strut (instead staying in the
3633    // normal place) so we use an absolute value for vertical-align instead
3634    bottomStrut.style.verticalAlign = -body.depth + "em";
3635
3636    // Wrap the struts and body together
3637    var htmlNode = makeSpan(["katex-html"], [topStrut, bottomStrut, body]);
3638
3639    htmlNode.setAttribute("aria-hidden", "true");
3640
3641    return htmlNode;
3642};
3643
3644module.exports = buildHTML;
3645
3646},{"./ParseError":6,"./Style":9,"./buildCommon":10,"./delimiter":14,"./domTree":15,"./fontMetrics":17,"./utils":25}],12:[function(require,module,exports){
3647/**
3648 * This file converts a parse tree into a cooresponding MathML tree. The main
3649 * entry point is the `buildMathML` function, which takes a parse tree from the
3650 * parser.
3651 */
3652
3653var buildCommon = require("./buildCommon");
3654var fontMetrics = require("./fontMetrics");
3655var mathMLTree = require("./mathMLTree");
3656var ParseError = require("./ParseError");
3657var symbols = require("./symbols");
3658var utils = require("./utils");
3659
3660var makeSpan = buildCommon.makeSpan;
3661var fontMap = buildCommon.fontMap;
3662
3663/**
3664 * Takes a symbol and converts it into a MathML text node after performing
3665 * optional replacement from symbols.js.
3666 */
3667var makeText = function(text, mode) {
3668    if (symbols[mode][text] && symbols[mode][text].replace) {
3669        text = symbols[mode][text].replace;
3670    }
3671
3672    return new mathMLTree.TextNode(text);
3673};
3674
3675/**
3676 * Returns the math variant as a string or null if none is required.
3677 */
3678var getVariant = function(group, options) {
3679    var font = options.font;
3680    if (!font) {
3681        return null;
3682    }
3683
3684    var mode = group.mode;
3685    if (font === "mathit") {
3686        return "italic";
3687    }
3688
3689    var value = group.value;
3690    if (utils.contains(["\\imath", "\\jmath"], value)) {
3691        return null;
3692    }
3693
3694    if (symbols[mode][value] && symbols[mode][value].replace) {
3695        value = symbols[mode][value].replace;
3696    }
3697
3698    var fontName = fontMap[font].fontName;
3699    if (fontMetrics.getCharacterMetrics(value, fontName)) {
3700        return fontMap[options.font].variant;
3701    }
3702
3703    return null;
3704};
3705
3706/**
3707 * Functions for handling the different types of groups found in the parse
3708 * tree. Each function should take a parse group and return a MathML node.
3709 */
3710var groupTypes = {};
3711
3712groupTypes.mathord = function(group, options) {
3713    var node = new mathMLTree.MathNode(
3714        "mi",
3715        [makeText(group.value, group.mode)]);
3716
3717    var variant = getVariant(group, options);
3718    if (variant) {
3719        node.setAttribute("mathvariant", variant);
3720    }
3721    return node;
3722};
3723
3724groupTypes.textord = function(group, options) {
3725    var text = makeText(group.value, group.mode);
3726
3727    var variant = getVariant(group, options) || "normal";
3728
3729    var node;
3730    if (/[0-9]/.test(group.value)) {
3731        // TODO(kevinb) merge adjacent <mn> nodes
3732        // do it as a post processing step
3733        node = new mathMLTree.MathNode("mn", [text]);
3734        if (options.font) {
3735            node.setAttribute("mathvariant", variant);
3736        }
3737    } else {
3738        node = new mathMLTree.MathNode("mi", [text]);
3739        node.setAttribute("mathvariant", variant);
3740    }
3741
3742    return node;
3743};
3744
3745groupTypes.bin = function(group) {
3746    var node = new mathMLTree.MathNode(
3747        "mo", [makeText(group.value, group.mode)]);
3748
3749    return node;
3750};
3751
3752groupTypes.rel = function(group) {
3753    var node = new mathMLTree.MathNode(
3754        "mo", [makeText(group.value, group.mode)]);
3755
3756    return node;
3757};
3758
3759groupTypes.open = function(group) {
3760    var node = new mathMLTree.MathNode(
3761        "mo", [makeText(group.value, group.mode)]);
3762
3763    return node;
3764};
3765
3766groupTypes.close = function(group) {
3767    var node = new mathMLTree.MathNode(
3768        "mo", [makeText(group.value, group.mode)]);
3769
3770    return node;
3771};
3772
3773groupTypes.inner = function(group) {
3774    var node = new mathMLTree.MathNode(
3775        "mo", [makeText(group.value, group.mode)]);
3776
3777    return node;
3778};
3779
3780groupTypes.punct = function(group) {
3781    var node = new mathMLTree.MathNode(
3782        "mo", [makeText(group.value, group.mode)]);
3783
3784    node.setAttribute("separator", "true");
3785
3786    return node;
3787};
3788
3789groupTypes.ordgroup = function(group, options) {
3790    var inner = buildExpression(group.value, options);
3791
3792    var node = new mathMLTree.MathNode("mrow", inner);
3793
3794    return node;
3795};
3796
3797groupTypes.text = function(group, options) {
3798    var inner = buildExpression(group.value.body, options);
3799
3800    var node = new mathMLTree.MathNode("mtext", inner);
3801
3802    return node;
3803};
3804
3805groupTypes.color = function(group, options) {
3806    var inner = buildExpression(group.value.value, options);
3807
3808    var node = new mathMLTree.MathNode("mstyle", inner);
3809
3810    node.setAttribute("mathcolor", group.value.color);
3811
3812    return node;
3813};
3814
3815groupTypes.supsub = function(group, options) {
3816    var children = [buildGroup(group.value.base, options)];
3817
3818    if (group.value.sub) {
3819        children.push(buildGroup(group.value.sub, options));
3820    }
3821
3822    if (group.value.sup) {
3823        children.push(buildGroup(group.value.sup, options));
3824    }
3825
3826    var nodeType;
3827    if (!group.value.sub) {
3828        nodeType = "msup";
3829    } else if (!group.value.sup) {
3830        nodeType = "msub";
3831    } else {
3832        nodeType = "msubsup";
3833    }
3834
3835    var node = new mathMLTree.MathNode(nodeType, children);
3836
3837    return node;
3838};
3839
3840groupTypes.genfrac = function(group, options) {
3841    var node = new mathMLTree.MathNode(
3842        "mfrac",
3843        [buildGroup(group.value.numer, options),
3844            buildGroup(group.value.denom, options)]);
3845
3846    if (!group.value.hasBarLine) {
3847        node.setAttribute("linethickness", "0px");
3848    }
3849
3850    if (group.value.leftDelim != null || group.value.rightDelim != null) {
3851        var withDelims = [];
3852
3853        if (group.value.leftDelim != null) {
3854            var leftOp = new mathMLTree.MathNode(
3855                "mo", [new mathMLTree.TextNode(group.value.leftDelim)]);
3856
3857            leftOp.setAttribute("fence", "true");
3858
3859            withDelims.push(leftOp);
3860        }
3861
3862        withDelims.push(node);
3863
3864        if (group.value.rightDelim != null) {
3865            var rightOp = new mathMLTree.MathNode(
3866                "mo", [new mathMLTree.TextNode(group.value.rightDelim)]);
3867
3868            rightOp.setAttribute("fence", "true");
3869
3870            withDelims.push(rightOp);
3871        }
3872
3873        var outerNode = new mathMLTree.MathNode("mrow", withDelims);
3874
3875        return outerNode;
3876    }
3877
3878    return node;
3879};
3880
3881groupTypes.array = function(group, options) {
3882    return new mathMLTree.MathNode(
3883        "mtable", group.value.body.map(function(row) {
3884            return new mathMLTree.MathNode(
3885                "mtr", row.map(function(cell) {
3886                    return new mathMLTree.MathNode(
3887                        "mtd", [buildGroup(cell, options)]);
3888                }));
3889        }));
3890};
3891
3892groupTypes.sqrt = function(group, options) {
3893    var node;
3894    if (group.value.index) {
3895        node = new mathMLTree.MathNode(
3896            "mroot", [
3897                buildGroup(group.value.body, options),
3898                buildGroup(group.value.index, options)
3899            ]);
3900    } else {
3901        node = new mathMLTree.MathNode(
3902            "msqrt", [buildGroup(group.value.body, options)]);
3903    }
3904
3905    return node;
3906};
3907
3908groupTypes.leftright = function(group, options) {
3909    var inner = buildExpression(group.value.body, options);
3910
3911    if (group.value.left !== ".") {
3912        var leftNode = new mathMLTree.MathNode(
3913            "mo", [makeText(group.value.left, group.mode)]);
3914
3915        leftNode.setAttribute("fence", "true");
3916
3917        inner.unshift(leftNode);
3918    }
3919
3920    if (group.value.right !== ".") {
3921        var rightNode = new mathMLTree.MathNode(
3922            "mo", [makeText(group.value.right, group.mode)]);
3923
3924        rightNode.setAttribute("fence", "true");
3925
3926        inner.push(rightNode);
3927    }
3928
3929    var outerNode = new mathMLTree.MathNode("mrow", inner);
3930
3931    return outerNode;
3932};
3933
3934groupTypes.middle = function(group, options) {
3935    var middleNode = new mathMLTree.MathNode(
3936        "mo", [makeText(group.value.middle, group.mode)]);
3937    middleNode.setAttribute("fence", "true");
3938    return middleNode;
3939};
3940
3941groupTypes.accent = function(group, options) {
3942    var accentNode = new mathMLTree.MathNode(
3943        "mo", [makeText(group.value.accent, group.mode)]);
3944
3945    var node = new mathMLTree.MathNode(
3946        "mover",
3947        [buildGroup(group.value.base, options),
3948            accentNode]);
3949
3950    node.setAttribute("accent", "true");
3951
3952    return node;
3953};
3954
3955groupTypes.spacing = function(group) {
3956    var node;
3957
3958    if (group.value === "\\ " || group.value === "\\space" ||
3959        group.value === " " || group.value === "~") {
3960        node = new mathMLTree.MathNode(
3961            "mtext", [new mathMLTree.TextNode("\u00a0")]);
3962    } else {
3963        node = new mathMLTree.MathNode("mspace");
3964
3965        node.setAttribute(
3966            "width", buildCommon.spacingFunctions[group.value].size);
3967    }
3968
3969    return node;
3970};
3971
3972groupTypes.op = function(group, options) {
3973    var node;
3974
3975    // TODO(emily): handle big operators using the `largeop` attribute
3976
3977    if (group.value.symbol) {
3978        // This is a symbol. Just add the symbol.
3979        node = new mathMLTree.MathNode(
3980            "mo", [makeText(group.value.body, group.mode)]);
3981    } else if (group.value.value) {
3982        // This is an operator with children. Add them.
3983        node = new mathMLTree.MathNode(
3984            "mo", buildExpression(group.value.value, options));
3985    } else {
3986        // This is a text operator. Add all of the characters from the
3987        // operator's name.
3988        // TODO(emily): Add a space in the middle of some of these
3989        // operators, like \limsup.
3990        node = new mathMLTree.MathNode(
3991            "mi", [new mathMLTree.TextNode(group.value.body.slice(1))]);
3992    }
3993
3994    return node;
3995};
3996
3997groupTypes.mod = function(group, options) {
3998    var inner = [];
3999
4000    if (group.value.modType === "pod" || group.value.modType === "pmod") {
4001        inner.push(new mathMLTree.MathNode(
4002            "mo", [makeText("(", group.mode)]));
4003    }
4004    if (group.value.modType !== "pod") {
4005        inner.push(new mathMLTree.MathNode(
4006            "mo", [makeText("mod", group.mode)]));
4007    }
4008    if (group.value.value) {
4009        var space = new mathMLTree.MathNode("mspace");
4010        space.setAttribute("width", "0.333333em");
4011        inner.push(space);
4012        inner = inner.concat(buildExpression(group.value.value, options));
4013    }
4014    if (group.value.modType === "pod" || group.value.modType === "pmod") {
4015        inner.push(new mathMLTree.MathNode(
4016            "mo", [makeText(")", group.mode)]));
4017    }
4018
4019    return new mathMLTree.MathNode("mo", inner);
4020};
4021
4022groupTypes.katex = function(group) {
4023    var node = new mathMLTree.MathNode(
4024        "mtext", [new mathMLTree.TextNode("KaTeX")]);
4025
4026    return node;
4027};
4028
4029groupTypes.font = function(group, options) {
4030    var font = group.value.font;
4031    return buildGroup(group.value.body, options.withFont(font));
4032};
4033
4034groupTypes.delimsizing = function(group) {
4035    var children = [];
4036
4037    if (group.value.value !== ".") {
4038        children.push(makeText(group.value.value, group.mode));
4039    }
4040
4041    var node = new mathMLTree.MathNode("mo", children);
4042
4043    if (group.value.mclass === "mopen" ||
4044        group.value.mclass === "mclose") {
4045        // Only some of the delimsizing functions act as fences, and they
4046        // return "mopen" or "mclose" mclass.
4047        node.setAttribute("fence", "true");
4048    } else {
4049        // Explicitly disable fencing if it's not a fence, to override the
4050        // defaults.
4051        node.setAttribute("fence", "false");
4052    }
4053
4054    return node;
4055};
4056
4057groupTypes.styling = function(group, options) {
4058    var inner = buildExpression(group.value.value, options);
4059
4060    var node = new mathMLTree.MathNode("mstyle", inner);
4061
4062    var styleAttributes = {
4063        "display": ["0", "true"],
4064        "text": ["0", "false"],
4065        "script": ["1", "false"],
4066        "scriptscript": ["2", "false"]
4067    };
4068
4069    var attr = styleAttributes[group.value.style];
4070
4071    node.setAttribute("scriptlevel", attr[0]);
4072    node.setAttribute("displaystyle", attr[1]);
4073
4074    return node;
4075};
4076
4077groupTypes.sizing = function(group, options) {
4078    var inner = buildExpression(group.value.value, options);
4079
4080    var node = new mathMLTree.MathNode("mstyle", inner);
4081
4082    // TODO(emily): This doesn't produce the correct size for nested size
4083    // changes, because we don't keep state of what style we're currently
4084    // in, so we can't reset the size to normal before changing it.  Now
4085    // that we're passing an options parameter we should be able to fix
4086    // this.
4087    node.setAttribute(
4088        "mathsize", buildCommon.sizingMultiplier[group.value.size] + "em");
4089
4090    return node;
4091};
4092
4093groupTypes.overline = function(group, options) {
4094    var operator = new mathMLTree.MathNode(
4095        "mo", [new mathMLTree.TextNode("\u203e")]);
4096    operator.setAttribute("stretchy", "true");
4097
4098    var node = new mathMLTree.MathNode(
4099        "mover",
4100        [buildGroup(group.value.body, options),
4101            operator]);
4102    node.setAttribute("accent", "true");
4103
4104    return node;
4105};
4106
4107groupTypes.underline = function(group, options) {
4108    var operator = new mathMLTree.MathNode(
4109        "mo", [new mathMLTree.TextNode("\u203e")]);
4110    operator.setAttribute("stretchy", "true");
4111
4112    var node = new mathMLTree.MathNode(
4113        "munder",
4114        [buildGroup(group.value.body, options),
4115            operator]);
4116    node.setAttribute("accentunder", "true");
4117
4118    return node;
4119};
4120
4121groupTypes.rule = function(group) {
4122    // TODO(emily): Figure out if there's an actual way to draw black boxes
4123    // in MathML.
4124    var node = new mathMLTree.MathNode("mrow");
4125
4126    return node;
4127};
4128
4129groupTypes.kern = function(group) {
4130    // TODO(kevin): Figure out if there's a way to add space in MathML
4131    var node = new mathMLTree.MathNode("mrow");
4132
4133    return node;
4134};
4135
4136groupTypes.llap = function(group, options) {
4137    var node = new mathMLTree.MathNode(
4138        "mpadded", [buildGroup(group.value.body, options)]);
4139
4140    node.setAttribute("lspace", "-1width");
4141    node.setAttribute("width", "0px");
4142
4143    return node;
4144};
4145
4146groupTypes.rlap = function(group, options) {
4147    var node = new mathMLTree.MathNode(
4148        "mpadded", [buildGroup(group.value.body, options)]);
4149
4150    node.setAttribute("width", "0px");
4151
4152    return node;
4153};
4154
4155groupTypes.phantom = function(group, options) {
4156    var inner = buildExpression(group.value.value, options);
4157    return new mathMLTree.MathNode("mphantom", inner);
4158};
4159
4160groupTypes.mclass = function(group, options) {
4161    var inner = buildExpression(group.value.value, options);
4162    return new mathMLTree.MathNode("mstyle", inner);
4163};
4164
4165/**
4166 * Takes a list of nodes, builds them, and returns a list of the generated
4167 * MathML nodes. A little simpler than the HTML version because we don't do any
4168 * previous-node handling.
4169 */
4170var buildExpression = function(expression, options) {
4171    var groups = [];
4172    for (var i = 0; i < expression.length; i++) {
4173        var group = expression[i];
4174        groups.push(buildGroup(group, options));
4175    }
4176    return groups;
4177};
4178
4179/**
4180 * Takes a group from the parser and calls the appropriate groupTypes function
4181 * on it to produce a MathML node.
4182 */
4183var buildGroup = function(group, options) {
4184    if (!group) {
4185        return new mathMLTree.MathNode("mrow");
4186    }
4187
4188    if (groupTypes[group.type]) {
4189        // Call the groupTypes function
4190        return groupTypes[group.type](group, options);
4191    } else {
4192        throw new ParseError(
4193            "Got group of unknown type: '" + group.type + "'");
4194    }
4195};
4196
4197/**
4198 * Takes a full parse tree and settings and builds a MathML representation of
4199 * it. In particular, we put the elements from building the parse tree into a
4200 * <semantics> tag so we can also include that TeX source as an annotation.
4201 *
4202 * Note that we actually return a domTree element with a `<math>` inside it so
4203 * we can do appropriate styling.
4204 */
4205var buildMathML = function(tree, texExpression, options) {
4206    var expression = buildExpression(tree, options);
4207
4208    // Wrap up the expression in an mrow so it is presented in the semantics
4209    // tag correctly.
4210    var wrapper = new mathMLTree.MathNode("mrow", expression);
4211
4212    // Build a TeX annotation of the source
4213    var annotation = new mathMLTree.MathNode(
4214        "annotation", [new mathMLTree.TextNode(texExpression)]);
4215
4216    annotation.setAttribute("encoding", "application/x-tex");
4217
4218    var semantics = new mathMLTree.MathNode(
4219        "semantics", [wrapper, annotation]);
4220
4221    var math = new mathMLTree.MathNode("math", [semantics]);
4222
4223    // You can't style <math> nodes, so we wrap the node in a span.
4224    return makeSpan(["katex-mathml"], [math]);
4225};
4226
4227module.exports = buildMathML;
4228
4229},{"./ParseError":6,"./buildCommon":10,"./fontMetrics":17,"./mathMLTree":20,"./symbols":23,"./utils":25}],13:[function(require,module,exports){
4230var buildHTML = require("./buildHTML");
4231var buildMathML = require("./buildMathML");
4232var buildCommon = require("./buildCommon");
4233var Options = require("./Options");
4234var Settings = require("./Settings");
4235var Style = require("./Style");
4236
4237var makeSpan = buildCommon.makeSpan;
4238
4239var buildTree = function(tree, expression, settings) {
4240    settings = settings || new Settings({});
4241
4242    var startStyle = Style.TEXT;
4243    if (settings.displayMode) {
4244        startStyle = Style.DISPLAY;
4245    }
4246
4247    // Setup the default options
4248    var options = new Options({
4249        style: startStyle,
4250        size: "size5"
4251    });
4252
4253    // `buildHTML` sometimes messes with the parse tree (like turning bins ->
4254    // ords), so we build the MathML version first.
4255    var mathMLNode = buildMathML(tree, expression, options);
4256    var htmlNode = buildHTML(tree, options);
4257
4258    var katexNode = makeSpan(["katex"], [
4259        mathMLNode, htmlNode
4260    ]);
4261
4262    if (settings.displayMode) {
4263        return makeSpan(["katex-display"], [katexNode]);
4264    } else {
4265        return katexNode;
4266    }
4267};
4268
4269module.exports = buildTree;
4270
4271},{"./Options":5,"./Settings":8,"./Style":9,"./buildCommon":10,"./buildHTML":11,"./buildMathML":12}],14:[function(require,module,exports){
4272/**
4273 * This file deals with creating delimiters of various sizes. The TeXbook
4274 * discusses these routines on page 441-442, in the "Another subroutine sets box
4275 * x to a specified variable delimiter" paragraph.
4276 *
4277 * There are three main routines here. `makeSmallDelim` makes a delimiter in the
4278 * normal font, but in either text, script, or scriptscript style.
4279 * `makeLargeDelim` makes a delimiter in textstyle, but in one of the Size1,
4280 * Size2, Size3, or Size4 fonts. `makeStackedDelim` makes a delimiter out of
4281 * smaller pieces that are stacked on top of one another.
4282 *
4283 * The functions take a parameter `center`, which determines if the delimiter
4284 * should be centered around the axis.
4285 *
4286 * Then, there are three exposed functions. `sizedDelim` makes a delimiter in
4287 * one of the given sizes. This is used for things like `\bigl`.
4288 * `customSizedDelim` makes a delimiter with a given total height+depth. It is
4289 * called in places like `\sqrt`. `leftRightDelim` makes an appropriate
4290 * delimiter which surrounds an expression of a given height an depth. It is
4291 * used in `\left` and `\right`.
4292 */
4293
4294var ParseError = require("./ParseError");
4295var Style = require("./Style");
4296
4297var buildCommon = require("./buildCommon");
4298var fontMetrics = require("./fontMetrics");
4299var symbols = require("./symbols");
4300var utils = require("./utils");
4301
4302var makeSpan = buildCommon.makeSpan;
4303
4304/**
4305 * Get the metrics for a given symbol and font, after transformation (i.e.
4306 * after following replacement from symbols.js)
4307 */
4308var getMetrics = function(symbol, font) {
4309    if (symbols.math[symbol] && symbols.math[symbol].replace) {
4310        return fontMetrics.getCharacterMetrics(
4311            symbols.math[symbol].replace, font);
4312    } else {
4313        return fontMetrics.getCharacterMetrics(
4314            symbol, font);
4315    }
4316};
4317
4318/**
4319 * Builds a symbol in the given font size (note size is an integer)
4320 */
4321var mathrmSize = function(value, size, mode, options) {
4322    return buildCommon.makeSymbol(value, "Size" + size + "-Regular",
4323        mode, options);
4324};
4325
4326/**
4327 * Puts a delimiter span in a given style, and adds appropriate height, depth,
4328 * and maxFontSizes.
4329 */
4330var styleWrap = function(delim, toStyle, options, classes) {
4331    classes = classes || [];
4332    var span = makeSpan(
4333        classes.concat(["style-wrap", options.style.reset(), toStyle.cls()]),
4334        [delim], options);
4335
4336    var multiplier = toStyle.sizeMultiplier / options.style.sizeMultiplier;
4337
4338    span.height *= multiplier;
4339    span.depth *= multiplier;
4340    span.maxFontSize = toStyle.sizeMultiplier;
4341
4342    return span;
4343};
4344
4345/**
4346 * Makes a small delimiter. This is a delimiter that comes in the Main-Regular
4347 * font, but is restyled to either be in textstyle, scriptstyle, or
4348 * scriptscriptstyle.
4349 */
4350var makeSmallDelim = function(delim, style, center, options, mode, classes) {
4351    var text = buildCommon.makeSymbol(delim, "Main-Regular", mode, options);
4352
4353    var span = styleWrap(text, style, options, classes);
4354
4355    if (center) {
4356        var shift =
4357            (1 - options.style.sizeMultiplier / style.sizeMultiplier) *
4358            options.style.metrics.axisHeight;
4359
4360        span.style.top = shift + "em";
4361        span.height -= shift;
4362        span.depth += shift;
4363    }
4364
4365    return span;
4366};
4367
4368/**
4369 * Makes a large delimiter. This is a delimiter that comes in the Size1, Size2,
4370 * Size3, or Size4 fonts. It is always rendered in textstyle.
4371 */
4372var makeLargeDelim = function(delim, size, center, options, mode, classes) {
4373    var inner = mathrmSize(delim, size, mode, options);
4374
4375    var span = styleWrap(
4376        makeSpan(["delimsizing", "size" + size], [inner], options),
4377        Style.TEXT, options, classes);
4378
4379    if (center) {
4380        var shift = (1 - options.style.sizeMultiplier) *
4381            options.style.metrics.axisHeight;
4382
4383        span.style.top = shift + "em";
4384        span.height -= shift;
4385        span.depth += shift;
4386    }
4387
4388    return span;
4389};
4390
4391/**
4392 * Make an inner span with the given offset and in the given font. This is used
4393 * in `makeStackedDelim` to make the stacking pieces for the delimiter.
4394 */
4395var makeInner = function(symbol, font, mode) {
4396    var sizeClass;
4397    // Apply the correct CSS class to choose the right font.
4398    if (font === "Size1-Regular") {
4399        sizeClass = "delim-size1";
4400    } else if (font === "Size4-Regular") {
4401        sizeClass = "delim-size4";
4402    }
4403
4404    var inner = makeSpan(
4405        ["delimsizinginner", sizeClass],
4406        [makeSpan([], [buildCommon.makeSymbol(symbol, font, mode)])]);
4407
4408    // Since this will be passed into `makeVList` in the end, wrap the element
4409    // in the appropriate tag that VList uses.
4410    return {type: "elem", elem: inner};
4411};
4412
4413/**
4414 * Make a stacked delimiter out of a given delimiter, with the total height at
4415 * least `heightTotal`. This routine is mentioned on page 442 of the TeXbook.
4416 */
4417var makeStackedDelim = function(delim, heightTotal, center, options, mode,
4418                                classes) {
4419    // There are four parts, the top, an optional middle, a repeated part, and a
4420    // bottom.
4421    var top;
4422    var middle;
4423    var repeat;
4424    var bottom;
4425    top = repeat = bottom = delim;
4426    middle = null;
4427    // Also keep track of what font the delimiters are in
4428    var font = "Size1-Regular";
4429
4430    // We set the parts and font based on the symbol. Note that we use
4431    // '\u23d0' instead of '|' and '\u2016' instead of '\\|' for the
4432    // repeats of the arrows
4433    if (delim === "\\uparrow") {
4434        repeat = bottom = "\u23d0";
4435    } else if (delim === "\\Uparrow") {
4436        repeat = bottom = "\u2016";
4437    } else if (delim === "\\downarrow") {
4438        top = repeat = "\u23d0";
4439    } else if (delim === "\\Downarrow") {
4440        top = repeat = "\u2016";
4441    } else if (delim === "\\updownarrow") {
4442        top = "\\uparrow";
4443        repeat = "\u23d0";
4444        bottom = "\\downarrow";
4445    } else if (delim === "\\Updownarrow") {
4446        top = "\\Uparrow";
4447        repeat = "\u2016";
4448        bottom = "\\Downarrow";
4449    } else if (delim === "[" || delim === "\\lbrack") {
4450        top = "\u23a1";
4451        repeat = "\u23a2";
4452        bottom = "\u23a3";
4453        font = "Size4-Regular";
4454    } else if (delim === "]" || delim === "\\rbrack") {
4455        top = "\u23a4";
4456        repeat = "\u23a5";
4457        bottom = "\u23a6";
4458        font = "Size4-Regular";
4459    } else if (delim === "\\lfloor") {
4460        repeat = top = "\u23a2";
4461        bottom = "\u23a3";
4462        font = "Size4-Regular";
4463    } else if (delim === "\\lceil") {
4464        top = "\u23a1";
4465        repeat = bottom = "\u23a2";
4466        font = "Size4-Regular";
4467    } else if (delim === "\\rfloor") {
4468        repeat = top = "\u23a5";
4469        bottom = "\u23a6";
4470        font = "Size4-Regular";
4471    } else if (delim === "\\rceil") {
4472        top = "\u23a4";
4473        repeat = bottom = "\u23a5";
4474        font = "Size4-Regular";
4475    } else if (delim === "(") {
4476        top = "\u239b";
4477        repeat = "\u239c";
4478        bottom = "\u239d";
4479        font = "Size4-Regular";
4480    } else if (delim === ")") {
4481        top = "\u239e";
4482        repeat = "\u239f";
4483        bottom = "\u23a0";
4484        font = "Size4-Regular";
4485    } else if (delim === "\\{" || delim === "\\lbrace") {
4486        top = "\u23a7";
4487        middle = "\u23a8";
4488        bottom = "\u23a9";
4489        repeat = "\u23aa";
4490        font = "Size4-Regular";
4491    } else if (delim === "\\}" || delim === "\\rbrace") {
4492        top = "\u23ab";
4493        middle = "\u23ac";
4494        bottom = "\u23ad";
4495        repeat = "\u23aa";
4496        font = "Size4-Regular";
4497    } else if (delim === "\\lgroup") {
4498        top = "\u23a7";
4499        bottom = "\u23a9";
4500        repeat = "\u23aa";
4501        font = "Size4-Regular";
4502    } else if (delim === "\\rgroup") {
4503        top = "\u23ab";
4504        bottom = "\u23ad";
4505        repeat = "\u23aa";
4506        font = "Size4-Regular";
4507    } else if (delim === "\\lmoustache") {
4508        top = "\u23a7";
4509        bottom = "\u23ad";
4510        repeat = "\u23aa";
4511        font = "Size4-Regular";
4512    } else if (delim === "\\rmoustache") {
4513        top = "\u23ab";
4514        bottom = "\u23a9";
4515        repeat = "\u23aa";
4516        font = "Size4-Regular";
4517    } else if (delim === "\\surd") {
4518        top = "\ue001";
4519        bottom = "\u23b7";
4520        repeat = "\ue000";
4521        font = "Size4-Regular";
4522    }
4523
4524    // Get the metrics of the four sections
4525    var topMetrics = getMetrics(top, font);
4526    var topHeightTotal = topMetrics.height + topMetrics.depth;
4527    var repeatMetrics = getMetrics(repeat, font);
4528    var repeatHeightTotal = repeatMetrics.height + repeatMetrics.depth;
4529    var bottomMetrics = getMetrics(bottom, font);
4530    var bottomHeightTotal = bottomMetrics.height + bottomMetrics.depth;
4531    var middleHeightTotal = 0;
4532    var middleFactor = 1;
4533    if (middle !== null) {
4534        var middleMetrics = getMetrics(middle, font);
4535        middleHeightTotal = middleMetrics.height + middleMetrics.depth;
4536        middleFactor = 2; // repeat symmetrically above and below middle
4537    }
4538
4539    // Calcuate the minimal height that the delimiter can have.
4540    // It is at least the size of the top, bottom, and optional middle combined.
4541    var minHeight = topHeightTotal + bottomHeightTotal + middleHeightTotal;
4542
4543    // Compute the number of copies of the repeat symbol we will need
4544    var repeatCount = Math.ceil(
4545        (heightTotal - minHeight) / (middleFactor * repeatHeightTotal));
4546
4547    // Compute the total height of the delimiter including all the symbols
4548    var realHeightTotal =
4549        minHeight + repeatCount * middleFactor * repeatHeightTotal;
4550
4551    // The center of the delimiter is placed at the center of the axis. Note
4552    // that in this context, "center" means that the delimiter should be
4553    // centered around the axis in the current style, while normally it is
4554    // centered around the axis in textstyle.
4555    var axisHeight = options.style.metrics.axisHeight;
4556    if (center) {
4557        axisHeight *= options.style.sizeMultiplier;
4558    }
4559    // Calculate the depth
4560    var depth = realHeightTotal / 2 - axisHeight;
4561
4562    // Now, we start building the pieces that will go into the vlist
4563
4564    // Keep a list of the inner pieces
4565    var inners = [];
4566
4567    // Add the bottom symbol
4568    inners.push(makeInner(bottom, font, mode));
4569
4570    var i;
4571    if (middle === null) {
4572        // Add that many symbols
4573        for (i = 0; i < repeatCount; i++) {
4574            inners.push(makeInner(repeat, font, mode));
4575        }
4576    } else {
4577        // When there is a middle bit, we need the middle part and two repeated
4578        // sections
4579        for (i = 0; i < repeatCount; i++) {
4580            inners.push(makeInner(repeat, font, mode));
4581        }
4582        inners.push(makeInner(middle, font, mode));
4583        for (i = 0; i < repeatCount; i++) {
4584            inners.push(makeInner(repeat, font, mode));
4585        }
4586    }
4587
4588    // Add the top symbol
4589    inners.push(makeInner(top, font, mode));
4590
4591    // Finally, build the vlist
4592    var inner = buildCommon.makeVList(inners, "bottom", depth, options);
4593
4594    return styleWrap(
4595        makeSpan(["delimsizing", "mult"], [inner], options),
4596        Style.TEXT, options, classes);
4597};
4598
4599// There are three kinds of delimiters, delimiters that stack when they become
4600// too large
4601var stackLargeDelimiters = [
4602    "(", ")", "[", "\\lbrack", "]", "\\rbrack",
4603    "\\{", "\\lbrace", "\\}", "\\rbrace",
4604    "\\lfloor", "\\rfloor", "\\lceil", "\\rceil",
4605    "\\surd"
4606];
4607
4608// delimiters that always stack
4609var stackAlwaysDelimiters = [
4610    "\\uparrow", "\\downarrow", "\\updownarrow",
4611    "\\Uparrow", "\\Downarrow", "\\Updownarrow",
4612    "|", "\\|", "\\vert", "\\Vert",
4613    "\\lvert", "\\rvert", "\\lVert", "\\rVert",
4614    "\\lgroup", "\\rgroup", "\\lmoustache", "\\rmoustache"
4615];
4616
4617// and delimiters that never stack
4618var stackNeverDelimiters = [
4619    "<", ">", "\\langle", "\\rangle", "/", "\\backslash", "\\lt", "\\gt"
4620];
4621
4622// Metrics of the different sizes. Found by looking at TeX's output of
4623// $\bigl| // \Bigl| \biggl| \Biggl| \showlists$
4624// Used to create stacked delimiters of appropriate sizes in makeSizedDelim.
4625var sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0];
4626
4627/**
4628 * Used to create a delimiter of a specific size, where `size` is 1, 2, 3, or 4.
4629 */
4630var makeSizedDelim = function(delim, size, options, mode, classes) {
4631    // < and > turn into \langle and \rangle in delimiters
4632    if (delim === "<" || delim === "\\lt") {
4633        delim = "\\langle";
4634    } else if (delim === ">" || delim === "\\gt") {
4635        delim = "\\rangle";
4636    }
4637
4638    // Sized delimiters are never centered.
4639    if (utils.contains(stackLargeDelimiters, delim) ||
4640        utils.contains(stackNeverDelimiters, delim)) {
4641        return makeLargeDelim(delim, size, false, options, mode, classes);
4642    } else if (utils.contains(stackAlwaysDelimiters, delim)) {
4643        return makeStackedDelim(
4644            delim, sizeToMaxHeight[size], false, options, mode, classes);
4645    } else {
4646        throw new ParseError("Illegal delimiter: '" + delim + "'");
4647    }
4648};
4649
4650/**
4651 * There are three different sequences of delimiter sizes that the delimiters
4652 * follow depending on the kind of delimiter. This is used when creating custom
4653 * sized delimiters to decide whether to create a small, large, or stacked
4654 * delimiter.
4655 *
4656 * In real TeX, these sequences aren't explicitly defined, but are instead
4657 * defined inside the font metrics. Since there are only three sequences that
4658 * are possible for the delimiters that TeX defines, it is easier to just encode
4659 * them explicitly here.
4660 */
4661
4662// Delimiters that never stack try small delimiters and large delimiters only
4663var stackNeverDelimiterSequence = [
4664    {type: "small", style: Style.SCRIPTSCRIPT},
4665    {type: "small", style: Style.SCRIPT},
4666    {type: "small", style: Style.TEXT},
4667    {type: "large", size: 1},
4668    {type: "large", size: 2},
4669    {type: "large", size: 3},
4670    {type: "large", size: 4}
4671];
4672
4673// Delimiters that always stack try the small delimiters first, then stack
4674var stackAlwaysDelimiterSequence = [
4675    {type: "small", style: Style.SCRIPTSCRIPT},
4676    {type: "small", style: Style.SCRIPT},
4677    {type: "small", style: Style.TEXT},
4678    {type: "stack"}
4679];
4680
4681// Delimiters that stack when large try the small and then large delimiters, and
4682// stack afterwards
4683var stackLargeDelimiterSequence = [
4684    {type: "small", style: Style.SCRIPTSCRIPT},
4685    {type: "small", style: Style.SCRIPT},
4686    {type: "small", style: Style.TEXT},
4687    {type: "large", size: 1},
4688    {type: "large", size: 2},
4689    {type: "large", size: 3},
4690    {type: "large", size: 4},
4691    {type: "stack"}
4692];
4693
4694/**
4695 * Get the font used in a delimiter based on what kind of delimiter it is.
4696 */
4697var delimTypeToFont = function(type) {
4698    if (type.type === "small") {
4699        return "Main-Regular";
4700    } else if (type.type === "large") {
4701        return "Size" + type.size + "-Regular";
4702    } else if (type.type === "stack") {
4703        return "Size4-Regular";
4704    }
4705};
4706
4707/**
4708 * Traverse a sequence of types of delimiters to decide what kind of delimiter
4709 * should be used to create a delimiter of the given height+depth.
4710 */
4711var traverseSequence = function(delim, height, sequence, options) {
4712    // Here, we choose the index we should start at in the sequences. In smaller
4713    // sizes (which correspond to larger numbers in style.size) we start earlier
4714    // in the sequence. Thus, scriptscript starts at index 3-3=0, script starts
4715    // at index 3-2=1, text starts at 3-1=2, and display starts at min(2,3-0)=2
4716    var start = Math.min(2, 3 - options.style.size);
4717    for (var i = start; i < sequence.length; i++) {
4718        if (sequence[i].type === "stack") {
4719            // This is always the last delimiter, so we just break the loop now.
4720            break;
4721        }
4722
4723        var metrics = getMetrics(delim, delimTypeToFont(sequence[i]));
4724        var heightDepth = metrics.height + metrics.depth;
4725
4726        // Small delimiters are scaled down versions of the same font, so we
4727        // account for the style change size.
4728
4729        if (sequence[i].type === "small") {
4730            heightDepth *= sequence[i].style.sizeMultiplier;
4731        }
4732
4733        // Check if the delimiter at this size works for the given height.
4734        if (heightDepth > height) {
4735            return sequence[i];
4736        }
4737    }
4738
4739    // If we reached the end of the sequence, return the last sequence element.
4740    return sequence[sequence.length - 1];
4741};
4742
4743/**
4744 * Make a delimiter of a given height+depth, with optional centering. Here, we
4745 * traverse the sequences, and create a delimiter that the sequence tells us to.
4746 */
4747var makeCustomSizedDelim = function(delim, height, center, options, mode,
4748                                    classes) {
4749    if (delim === "<" || delim === "\\lt") {
4750        delim = "\\langle";
4751    } else if (delim === ">" || delim === "\\gt") {
4752        delim = "\\rangle";
4753    }
4754
4755    // Decide what sequence to use
4756    var sequence;
4757    if (utils.contains(stackNeverDelimiters, delim)) {
4758        sequence = stackNeverDelimiterSequence;
4759    } else if (utils.contains(stackLargeDelimiters, delim)) {
4760        sequence = stackLargeDelimiterSequence;
4761    } else {
4762        sequence = stackAlwaysDelimiterSequence;
4763    }
4764
4765    // Look through the sequence
4766    var delimType = traverseSequence(delim, height, sequence, options);
4767
4768    // Depending on the sequence element we decided on, call the appropriate
4769    // function.
4770    if (delimType.type === "small") {
4771        return makeSmallDelim(delim, delimType.style, center, options, mode,
4772                              classes);
4773    } else if (delimType.type === "large") {
4774        return makeLargeDelim(delim, delimType.size, center, options, mode,
4775                              classes);
4776    } else if (delimType.type === "stack") {
4777        return makeStackedDelim(delim, height, center, options, mode, classes);
4778    }
4779};
4780
4781/**
4782 * Make a delimiter for use with `\left` and `\right`, given a height and depth
4783 * of an expression that the delimiters surround.
4784 */
4785var makeLeftRightDelim = function(delim, height, depth, options, mode,
4786                                  classes) {
4787    // We always center \left/\right delimiters, so the axis is always shifted
4788    var axisHeight =
4789        options.style.metrics.axisHeight * options.style.sizeMultiplier;
4790
4791    // Taken from TeX source, tex.web, function make_left_right
4792    var delimiterFactor = 901;
4793    var delimiterExtend = 5.0 / fontMetrics.metrics.ptPerEm;
4794
4795    var maxDistFromAxis = Math.max(
4796        height - axisHeight, depth + axisHeight);
4797
4798    var totalHeight = Math.max(
4799        // In real TeX, calculations are done using integral values which are
4800        // 65536 per pt, or 655360 per em. So, the division here truncates in
4801        // TeX but doesn't here, producing different results. If we wanted to
4802        // exactly match TeX's calculation, we could do
4803        //   Math.floor(655360 * maxDistFromAxis / 500) *
4804        //    delimiterFactor / 655360
4805        // (To see the difference, compare
4806        //    x^{x^{\left(\rule{0.1em}{0.68em}\right)}}
4807        // in TeX and KaTeX)
4808        maxDistFromAxis / 500 * delimiterFactor,
4809        2 * maxDistFromAxis - delimiterExtend);
4810
4811    // Finally, we defer to `makeCustomSizedDelim` with our calculated total
4812    // height
4813    return makeCustomSizedDelim(delim, totalHeight, true, options, mode,
4814                                classes);
4815};
4816
4817module.exports = {
4818    sizedDelim: makeSizedDelim,
4819    customSizedDelim: makeCustomSizedDelim,
4820    leftRightDelim: makeLeftRightDelim
4821};
4822
4823},{"./ParseError":6,"./Style":9,"./buildCommon":10,"./fontMetrics":17,"./symbols":23,"./utils":25}],15:[function(require,module,exports){
4824/**
4825 * These objects store the data about the DOM nodes we create, as well as some
4826 * extra data. They can then be transformed into real DOM nodes with the
4827 * `toNode` function or HTML markup using `toMarkup`. They are useful for both
4828 * storing extra properties on the nodes, as well as providing a way to easily
4829 * work with the DOM.
4830 *
4831 * Similar functions for working with MathML nodes exist in mathMLTree.js.
4832 */
4833var unicodeRegexes = require("./unicodeRegexes");
4834var utils = require("./utils");
4835
4836/**
4837 * Create an HTML className based on a list of classes. In addition to joining
4838 * with spaces, we also remove null or empty classes.
4839 */
4840var createClass = function(classes) {
4841    classes = classes.slice();
4842    for (var i = classes.length - 1; i >= 0; i--) {
4843        if (!classes[i]) {
4844            classes.splice(i, 1);
4845        }
4846    }
4847
4848    return classes.join(" ");
4849};
4850
4851/**
4852 * This node represents a span node, with a className, a list of children, and
4853 * an inline style. It also contains information about its height, depth, and
4854 * maxFontSize.
4855 */
4856function span(classes, children, options) {
4857    this.classes = classes || [];
4858    this.children = children || [];
4859    this.height = 0;
4860    this.depth = 0;
4861    this.maxFontSize = 0;
4862    this.style = {};
4863    this.attributes = {};
4864    if (options) {
4865        if (options.style.isTight()) {
4866            this.classes.push("mtight");
4867        }
4868        if (options.getColor()) {
4869            this.style.color = options.getColor();
4870        }
4871    }
4872}
4873
4874/**
4875 * Sets an arbitrary attribute on the span. Warning: use this wisely. Not all
4876 * browsers support attributes the same, and having too many custom attributes
4877 * is probably bad.
4878 */
4879span.prototype.setAttribute = function(attribute, value) {
4880    this.attributes[attribute] = value;
4881};
4882
4883span.prototype.tryCombine = function(sibling) {
4884    return false;
4885};
4886
4887/**
4888 * Convert the span into an HTML node
4889 */
4890span.prototype.toNode = function() {
4891    var span = document.createElement("span");
4892
4893    // Apply the class
4894    span.className = createClass(this.classes);
4895
4896    // Apply inline styles
4897    for (var style in this.style) {
4898        if (Object.prototype.hasOwnProperty.call(this.style, style)) {
4899            span.style[style] = this.style[style];
4900        }
4901    }
4902
4903    // Apply attributes
4904    for (var attr in this.attributes) {
4905        if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
4906            span.setAttribute(attr, this.attributes[attr]);
4907        }
4908    }
4909
4910    // Append the children, also as HTML nodes
4911    for (var i = 0; i < this.children.length; i++) {
4912        span.appendChild(this.children[i].toNode());
4913    }
4914
4915    return span;
4916};
4917
4918/**
4919 * Convert the span into an HTML markup string
4920 */
4921span.prototype.toMarkup = function() {
4922    var markup = "<span";
4923
4924    // Add the class
4925    if (this.classes.length) {
4926        markup += " class=\"";
4927        markup += utils.escape(createClass(this.classes));
4928        markup += "\"";
4929    }
4930
4931    var styles = "";
4932
4933    // Add the styles, after hyphenation
4934    for (var style in this.style) {
4935        if (this.style.hasOwnProperty(style)) {
4936            styles += utils.hyphenate(style) + ":" + this.style[style] + ";";
4937        }
4938    }
4939
4940    if (styles) {
4941        markup += " style=\"" + utils.escape(styles) + "\"";
4942    }
4943
4944    // Add the attributes
4945    for (var attr in this.attributes) {
4946        if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
4947            markup += " " + attr + "=\"";
4948            markup += utils.escape(this.attributes[attr]);
4949            markup += "\"";
4950        }
4951    }
4952
4953    markup += ">";
4954
4955    // Add the markup of the children, also as markup
4956    for (var i = 0; i < this.children.length; i++) {
4957        markup += this.children[i].toMarkup();
4958    }
4959
4960    markup += "</span>";
4961
4962    return markup;
4963};
4964
4965/**
4966 * This node represents a document fragment, which contains elements, but when
4967 * placed into the DOM doesn't have any representation itself. Thus, it only
4968 * contains children and doesn't have any HTML properties. It also keeps track
4969 * of a height, depth, and maxFontSize.
4970 */
4971function documentFragment(children) {
4972    this.children = children || [];
4973    this.height = 0;
4974    this.depth = 0;
4975    this.maxFontSize = 0;
4976}
4977
4978/**
4979 * Convert the fragment into a node
4980 */
4981documentFragment.prototype.toNode = function() {
4982    // Create a fragment
4983    var frag = document.createDocumentFragment();
4984
4985    // Append the children
4986    for (var i = 0; i < this.children.length; i++) {
4987        frag.appendChild(this.children[i].toNode());
4988    }
4989
4990    return frag;
4991};
4992
4993/**
4994 * Convert the fragment into HTML markup
4995 */
4996documentFragment.prototype.toMarkup = function() {
4997    var markup = "";
4998
4999    // Simply concatenate the markup for the children together
5000    for (var i = 0; i < this.children.length; i++) {
5001        markup += this.children[i].toMarkup();
5002    }
5003
5004    return markup;
5005};
5006
5007var iCombinations = {
5008    'î': '\u0131\u0302',
5009    'ï': '\u0131\u0308',
5010    'í': '\u0131\u0301',
5011    // 'ī': '\u0131\u0304', // enable when we add Extended Latin
5012    'ì': '\u0131\u0300'
5013};
5014
5015/**
5016 * A symbol node contains information about a single symbol. It either renders
5017 * to a single text node, or a span with a single text node in it, depending on
5018 * whether it has CSS classes, styles, or needs italic correction.
5019 */
5020function symbolNode(value, height, depth, italic, skew, classes, style) {
5021    this.value = value || "";
5022    this.height = height || 0;
5023    this.depth = depth || 0;
5024    this.italic = italic || 0;
5025    this.skew = skew || 0;
5026    this.classes = classes || [];
5027    this.style = style || {};
5028    this.maxFontSize = 0;
5029
5030    // Mark CJK characters with specific classes so that we can specify which
5031    // fonts to use.  This allows us to render these characters with a serif
5032    // font in situations where the browser would either default to a sans serif
5033    // or render a placeholder character.
5034    if (unicodeRegexes.cjkRegex.test(value)) {
5035        // I couldn't find any fonts that contained Hangul as well as all of
5036        // the other characters we wanted to test there for it gets its own
5037        // CSS class.
5038        if (unicodeRegexes.hangulRegex.test(value)) {
5039            this.classes.push('hangul_fallback');
5040        } else {
5041            this.classes.push('cjk_fallback');
5042        }
5043    }
5044
5045    if (/[îïíì]/.test(this.value)) {    // add ī when we add Extended Latin
5046        this.value = iCombinations[this.value];
5047    }
5048}
5049
5050symbolNode.prototype.tryCombine = function(sibling) {
5051    if (!sibling
5052        || !(sibling instanceof symbolNode)
5053        || this.italic > 0
5054        || createClass(this.classes) !== createClass(sibling.classes)
5055        || this.skew !== sibling.skew
5056        || this.maxFontSize !== sibling.maxFontSize) {
5057        return false;
5058    }
5059    for (var style in this.style) {
5060        if (this.style.hasOwnProperty(style)
5061            && this.style[style] !== sibling.style[style]) {
5062            return false;
5063        }
5064    }
5065    for (style in sibling.style) {
5066        if (sibling.style.hasOwnProperty(style)
5067            && this.style[style] !== sibling.style[style]) {
5068            return false;
5069        }
5070    }
5071    this.value += sibling.value;
5072    this.height = Math.max(this.height, sibling.height);
5073    this.depth = Math.max(this.depth, sibling.depth);
5074    this.italic = sibling.italic;
5075    return true;
5076};
5077
5078/**
5079 * Creates a text node or span from a symbol node. Note that a span is only
5080 * created if it is needed.
5081 */
5082symbolNode.prototype.toNode = function() {
5083    var node = document.createTextNode(this.value);
5084    var span = null;
5085
5086    if (this.italic > 0) {
5087        span = document.createElement("span");
5088        span.style.marginRight = this.italic + "em";
5089    }
5090
5091    if (this.classes.length > 0) {
5092        span = span || document.createElement("span");
5093        span.className = createClass(this.classes);
5094    }
5095
5096    for (var style in this.style) {
5097        if (this.style.hasOwnProperty(style)) {
5098            span = span || document.createElement("span");
5099            span.style[style] = this.style[style];
5100        }
5101    }
5102
5103    if (span) {
5104        span.appendChild(node);
5105        return span;
5106    } else {
5107        return node;
5108    }
5109};
5110
5111/**
5112 * Creates markup for a symbol node.
5113 */
5114symbolNode.prototype.toMarkup = function() {
5115    // TODO(alpert): More duplication than I'd like from
5116    // span.prototype.toMarkup and symbolNode.prototype.toNode...
5117    var needsSpan = false;
5118
5119    var markup = "<span";
5120
5121    if (this.classes.length) {
5122        needsSpan = true;
5123        markup += " class=\"";
5124        markup += utils.escape(createClass(this.classes));
5125        markup += "\"";
5126    }
5127
5128    var styles = "";
5129
5130    if (this.italic > 0) {
5131        styles += "margin-right:" + this.italic + "em;";
5132    }
5133    for (var style in this.style) {
5134        if (this.style.hasOwnProperty(style)) {
5135            styles += utils.hyphenate(style) + ":" + this.style[style] + ";";
5136        }
5137    }
5138
5139    if (styles) {
5140        needsSpan = true;
5141        markup += " style=\"" + utils.escape(styles) + "\"";
5142    }
5143
5144    var escaped = utils.escape(this.value);
5145    if (needsSpan) {
5146        markup += ">";
5147        markup += escaped;
5148        markup += "</span>";
5149        return markup;
5150    } else {
5151        return escaped;
5152    }
5153};
5154
5155module.exports = {
5156    span: span,
5157    documentFragment: documentFragment,
5158    symbolNode: symbolNode
5159};
5160
5161},{"./unicodeRegexes":24,"./utils":25}],16:[function(require,module,exports){
5162/* eslint no-constant-condition:0 */
5163var parseData = require("./parseData");
5164var ParseError = require("./ParseError");
5165var Style = require("./Style");
5166
5167var ParseNode = parseData.ParseNode;
5168
5169/**
5170 * Parse the body of the environment, with rows delimited by \\ and
5171 * columns delimited by &, and create a nested list in row-major order
5172 * with one group per cell.
5173 */
5174function parseArray(parser, result) {
5175    var row = [];
5176    var body = [row];
5177    var rowGaps = [];
5178    while (true) {
5179        var cell = parser.parseExpression(false, null);
5180        row.push(new ParseNode("ordgroup", cell, parser.mode));
5181        var next = parser.nextToken.text;
5182        if (next === "&") {
5183            parser.consume();
5184        } else if (next === "\\end") {
5185            break;
5186        } else if (next === "\\\\" || next === "\\cr") {
5187            var cr = parser.parseFunction();
5188            rowGaps.push(cr.value.size);
5189            row = [];
5190            body.push(row);
5191        } else {
5192            throw new ParseError("Expected & or \\\\ or \\end",
5193                                 parser.nextToken);
5194        }
5195    }
5196    result.body = body;
5197    result.rowGaps = rowGaps;
5198    return new ParseNode(result.type, result, parser.mode);
5199}
5200
5201/*
5202 * An environment definition is very similar to a function definition:
5203 * it is declared with a name or a list of names, a set of properties
5204 * and a handler containing the actual implementation.
5205 *
5206 * The properties include:
5207 *  - numArgs: The number of arguments after the \begin{name} function.
5208 *  - argTypes: (optional) Just like for a function
5209 *  - allowedInText: (optional) Whether or not the environment is allowed inside
5210 *                   text mode (default false) (not enforced yet)
5211 *  - numOptionalArgs: (optional) Just like for a function
5212 * A bare number instead of that object indicates the numArgs value.
5213 *
5214 * The handler function will receive two arguments
5215 *  - context: information and references provided by the parser
5216 *  - args: an array of arguments passed to \begin{name}
5217 * The context contains the following properties:
5218 *  - envName: the name of the environment, one of the listed names.
5219 *  - parser: the parser object
5220 *  - lexer: the lexer object
5221 *  - positions: the positions associated with these arguments from args.
5222 * The handler must return a ParseResult.
5223 */
5224
5225function defineEnvironment(names, props, handler) {
5226    if (typeof names === "string") {
5227        names = [names];
5228    }
5229    if (typeof props === "number") {
5230        props = { numArgs: props };
5231    }
5232    // Set default values of environments
5233    var data = {
5234        numArgs: props.numArgs || 0,
5235        argTypes: props.argTypes,
5236        greediness: 1,
5237        allowedInText: !!props.allowedInText,
5238        numOptionalArgs: props.numOptionalArgs || 0,
5239        handler: handler
5240    };
5241    for (var i = 0; i < names.length; ++i) {
5242        module.exports[names[i]] = data;
5243    }
5244}
5245
5246// Arrays are part of LaTeX, defined in lttab.dtx so its documentation
5247// is part of the source2e.pdf file of LaTeX2e source documentation.
5248defineEnvironment("array", {
5249    numArgs: 1
5250}, function(context, args) {
5251    var colalign = args[0];
5252    colalign = colalign.value.map ? colalign.value : [colalign];
5253    var cols = colalign.map(function(node) {
5254        var ca = node.value;
5255        if ("lcr".indexOf(ca) !== -1) {
5256            return {
5257                type: "align",
5258                align: ca
5259            };
5260        } else if (ca === "|") {
5261            return {
5262                type: "separator",
5263                separator: "|"
5264            };
5265        }
5266        throw new ParseError(
5267            "Unknown column alignment: " + node.value,
5268            node);
5269    });
5270    var res = {
5271        type: "array",
5272        cols: cols,
5273        hskipBeforeAndAfter: true // \@preamble in lttab.dtx
5274    };
5275    res = parseArray(context.parser, res);
5276    return res;
5277});
5278
5279// The matrix environments of amsmath builds on the array environment
5280// of LaTeX, which is discussed above.
5281defineEnvironment([
5282    "matrix",
5283    "pmatrix",
5284    "bmatrix",
5285    "Bmatrix",
5286    "vmatrix",
5287    "Vmatrix"
5288], {
5289}, function(context) {
5290    var delimiters = {
5291        "matrix": null,
5292        "pmatrix": ["(", ")"],
5293        "bmatrix": ["[", "]"],
5294        "Bmatrix": ["\\{", "\\}"],
5295        "vmatrix": ["|", "|"],
5296        "Vmatrix": ["\\Vert", "\\Vert"]
5297    }[context.envName];
5298    var res = {
5299        type: "array",
5300        hskipBeforeAndAfter: false // \hskip -\arraycolsep in amsmath
5301    };
5302    res = parseArray(context.parser, res);
5303    if (delimiters) {
5304        res = new ParseNode("leftright", {
5305            body: [res],
5306            left: delimiters[0],
5307            right: delimiters[1]
5308        }, context.mode);
5309    }
5310    return res;
5311});
5312
5313// A cases environment (in amsmath.sty) is almost equivalent to
5314// \def\arraystretch{1.2}%
5315// \left\{\begin{array}{@{}l@{\quad}l@{}} … \end{array}\right.
5316defineEnvironment("cases", {
5317}, function(context) {
5318    var res = {
5319        type: "array",
5320        arraystretch: 1.2,
5321        cols: [{
5322            type: "align",
5323            align: "l",
5324            pregap: 0,
5325            // TODO(kevinb) get the current style.
5326            // For now we use the metrics for TEXT style which is what we were
5327            // doing before.  Before attempting to get the current style we
5328            // should look at TeX's behavior especially for \over and matrices.
5329            postgap: Style.TEXT.metrics.quad
5330        }, {
5331            type: "align",
5332            align: "l",
5333            pregap: 0,
5334            postgap: 0
5335        }]
5336    };
5337    res = parseArray(context.parser, res);
5338    res = new ParseNode("leftright", {
5339        body: [res],
5340        left: "\\{",
5341        right: "."
5342    }, context.mode);
5343    return res;
5344});
5345
5346// An aligned environment is like the align* environment
5347// except it operates within math mode.
5348// Note that we assume \nomallineskiplimit to be zero,
5349// so that \strut@ is the same as \strut.
5350defineEnvironment("aligned", {
5351}, function(context) {
5352    var res = {
5353        type: "array",
5354        cols: []
5355    };
5356    res = parseArray(context.parser, res);
5357    var emptyGroup = new ParseNode("ordgroup", [], context.mode);
5358    var numCols = 0;
5359    res.value.body.forEach(function(row) {
5360        var i;
5361        for (i = 1; i < row.length; i += 2) {
5362            row[i].value.unshift(emptyGroup);
5363        }
5364        if (numCols < row.length) {
5365            numCols = row.length;
5366        }
5367    });
5368    for (var i = 0; i < numCols; ++i) {
5369        var align = "r";
5370        var pregap = 0;
5371        if (i % 2 === 1) {
5372            align = "l";
5373        } else if (i > 0) {
5374            pregap = 2; // one \qquad between columns
5375        }
5376        res.value.cols[i] = {
5377            type: "align",
5378            align: align,
5379            pregap: pregap,
5380            postgap: 0
5381        };
5382    }
5383    return res;
5384});
5385
5386},{"./ParseError":6,"./Style":9,"./parseData":21}],17:[function(require,module,exports){
5387/* eslint no-unused-vars:0 */
5388
5389var Style = require("./Style");
5390var cjkRegex = require("./unicodeRegexes").cjkRegex;
5391
5392/**
5393 * This file contains metrics regarding fonts and individual symbols. The sigma
5394 * and xi variables, as well as the metricMap map contain data extracted from
5395 * TeX, TeX font metrics, and the TTF files. These data are then exposed via the
5396 * `metrics` variable and the getCharacterMetrics function.
5397 */
5398
5399// In TeX, there are actually three sets of dimensions, one for each of
5400// textstyle, scriptstyle, and scriptscriptstyle.  These are provided in the
5401// the arrays below, in that order.
5402//
5403// The font metrics are stored in fonts cmsy10, cmsy7, and cmsy5 respsectively.
5404// This was determined by running the folllowing script:
5405//
5406//     latex -interaction=nonstopmode \
5407//     '\documentclass{article}\usepackage{amsmath}\begin{document}' \
5408//     '$a$ \expandafter\show\the\textfont2' \
5409//     '\expandafter\show\the\scriptfont2' \
5410//     '\expandafter\show\the\scriptscriptfont2' \
5411//     '\stop'
5412//
5413// The metrics themselves were retreived using the following commands:
5414//
5415//     tftopl cmsy10
5416//     tftopl cmsy7
5417//     tftopl cmsy5
5418//
5419// The output of each of these commands is quite lengthy.  The only part we
5420// care about is the FONTDIMEN section. Each value is measured in EMs.
5421var sigmas = {
5422    slant: [0.250, 0.250, 0.250],       // sigma1
5423    space: [0.000, 0.000, 0.000],       // sigma2
5424    stretch: [0.000, 0.000, 0.000],     // sigma3
5425    shrink: [0.000, 0.000, 0.000],      // sigma4
5426    xHeight: [0.431, 0.431, 0.431],     // sigma5
5427    quad: [1.000, 1.171, 1.472],        // sigma6
5428    extraSpace: [0.000, 0.000, 0.000],  // sigma7
5429    num1: [0.677, 0.732, 0.925],        // sigma8
5430    num2: [0.394, 0.384, 0.387],        // sigma9
5431    num3: [0.444, 0.471, 0.504],        // sigma10
5432    denom1: [0.686, 0.752, 1.025],      // sigma11
5433    denom2: [0.345, 0.344, 0.532],      // sigma12
5434    sup1: [0.413, 0.503, 0.504],        // sigma13
5435    sup2: [0.363, 0.431, 0.404],        // sigma14
5436    sup3: [0.289, 0.286, 0.294],        // sigma15
5437    sub1: [0.150, 0.143, 0.200],        // sigma16
5438    sub2: [0.247, 0.286, 0.400],        // sigma17
5439    supDrop: [0.386, 0.353, 0.494],     // sigma18
5440    subDrop: [0.050, 0.071, 0.100],     // sigma19
5441    delim1: [2.390, 1.700, 1.980],      // sigma20
5442    delim2: [1.010, 1.157, 1.420],      // sigma21
5443    axisHeight: [0.250, 0.250, 0.250]  // sigma22
5444};
5445
5446// These font metrics are extracted from TeX by using
5447// \font\a=cmex10
5448// \showthe\fontdimenX\a
5449// where X is the corresponding variable number. These correspond to the font
5450// parameters of the extension fonts (family 3). See the TeXbook, page 441.
5451var xi1 = 0;
5452var xi2 = 0;
5453var xi3 = 0;
5454var xi4 = 0;
5455var xi5 = 0.431;
5456var xi6 = 1;
5457var xi7 = 0;
5458var xi8 = 0.04;
5459var xi9 = 0.111;
5460var xi10 = 0.166;
5461var xi11 = 0.2;
5462var xi12 = 0.6;
5463var xi13 = 0.1;
5464
5465// This value determines how large a pt is, for metrics which are defined in
5466// terms of pts.
5467// This value is also used in katex.less; if you change it make sure the values
5468// match.
5469var ptPerEm = 10.0;
5470
5471// The space between adjacent `|` columns in an array definition. From
5472// `\showthe\doublerulesep` in LaTeX.
5473var doubleRuleSep = 2.0 / ptPerEm;
5474
5475/**
5476 * This is just a mapping from common names to real metrics
5477 */
5478var metrics = {
5479    defaultRuleThickness: xi8,
5480    bigOpSpacing1: xi9,
5481    bigOpSpacing2: xi10,
5482    bigOpSpacing3: xi11,
5483    bigOpSpacing4: xi12,
5484    bigOpSpacing5: xi13,
5485    ptPerEm: ptPerEm,
5486    doubleRuleSep: doubleRuleSep
5487};
5488
5489// This map contains a mapping from font name and character code to character
5490// metrics, including height, depth, italic correction, and skew (kern from the
5491// character to the corresponding \skewchar)
5492// This map is generated via `make metrics`. It should not be changed manually.
5493var metricMap = require("./fontMetricsData");
5494
5495// These are very rough approximations.  We default to Times New Roman which
5496// should have Latin-1 and Cyrillic characters, but may not depending on the
5497// operating system.  The metrics do not account for extra height from the
5498// accents.  In the case of Cyrillic characters which have both ascenders and
5499// descenders we prefer approximations with ascenders, primarily to prevent
5500// the fraction bar or root line from intersecting the glyph.
5501// TODO(kevinb) allow union of multiple glyph metrics for better accuracy.
5502var extraCharacterMap = {
5503    // Latin-1
5504    'À': 'A',
5505    'Á': 'A',
5506    'Â': 'A',
5507    'Ã': 'A',
5508    'Ä': 'A',
5509    'Å': 'A',
5510    'Æ': 'A',
5511    'Ç': 'C',
5512    'È': 'E',
5513    'É': 'E',
5514    'Ê': 'E',
5515    'Ë': 'E',
5516    'Ì': 'I',
5517    'Í': 'I',
5518    'Î': 'I',
5519    'Ï': 'I',
5520    'Ð': 'D',
5521    'Ñ': 'N',
5522    'Ò': 'O',
5523    'Ó': 'O',
5524    'Ô': 'O',
5525    'Õ': 'O',
5526    'Ö': 'O',
5527    'Ø': 'O',
5528    'Ù': 'U',
5529    'Ú': 'U',
5530    'Û': 'U',
5531    'Ü': 'U',
5532    'Ý': 'Y',
5533    'Þ': 'o',
5534    'ß': 'B',
5535    'à': 'a',
5536    'á': 'a',
5537    'â': 'a',
5538    'ã': 'a',
5539    'ä': 'a',
5540    'å': 'a',
5541    'æ': 'a',
5542    'ç': 'c',
5543    'è': 'e',
5544    'é': 'e',
5545    'ê': 'e',
5546    'ë': 'e',
5547    'ì': 'i',
5548    'í': 'i',
5549    'î': 'i',
5550    'ï': 'i',
5551    'ð': 'd',
5552    'ñ': 'n',
5553    'ò': 'o',
5554    'ó': 'o',
5555    'ô': 'o',
5556    'õ': 'o',
5557    'ö': 'o',
5558    'ø': 'o',
5559    'ù': 'u',
5560    'ú': 'u',
5561    'û': 'u',
5562    'ü': 'u',
5563    'ý': 'y',
5564    'þ': 'o',
5565    'ÿ': 'y',
5566
5567    // Cyrillic
5568    'А': 'A',
5569    'Б': 'B',
5570    'В': 'B',
5571    'Г': 'F',
5572    'Д': 'A',
5573    'Е': 'E',
5574    'Ж': 'K',
5575    'З': '3',
5576    'И': 'N',
5577    'Й': 'N',
5578    'К': 'K',
5579    'Л': 'N',
5580    'М': 'M',
5581    'Н': 'H',
5582    'О': 'O',
5583    'П': 'N',
5584    'Р': 'P',
5585    'С': 'C',
5586    'Т': 'T',
5587    'У': 'y',
5588    'Ф': 'O',
5589    'Х': 'X',
5590    'Ц': 'U',
5591    'Ч': 'h',
5592    'Ш': 'W',
5593    'Щ': 'W',
5594    'Ъ': 'B',
5595    'Ы': 'X',
5596    'Ь': 'B',
5597    'Э': '3',
5598    'Ю': 'X',
5599    'Я': 'R',
5600    'а': 'a',
5601    'б': 'b',
5602    'в': 'a',
5603    'г': 'r',
5604    'д': 'y',
5605    'е': 'e',
5606    'ж': 'm',
5607    'з': 'e',
5608    'и': 'n',
5609    'й': 'n',
5610    'к': 'n',
5611    'л': 'n',
5612    'м': 'm',
5613    'н': 'n',
5614    'о': 'o',
5615    'п': 'n',
5616    'р': 'p',
5617    'с': 'c',
5618    'т': 'o',
5619    'у': 'y',
5620    'ф': 'b',
5621    'х': 'x',
5622    'ц': 'n',
5623    'ч': 'n',
5624    'ш': 'w',
5625    'щ': 'w',
5626    'ъ': 'a',
5627    'ы': 'm',
5628    'ь': 'a',
5629    'э': 'e',
5630    'ю': 'm',
5631    'я': 'r'
5632};
5633
5634/**
5635 * This function is a convenience function for looking up information in the
5636 * metricMap table. It takes a character as a string, and a style.
5637 *
5638 * Note: the `width` property may be undefined if fontMetricsData.js wasn't
5639 * built using `Make extended_metrics`.
5640 */
5641var getCharacterMetrics = function(character, style) {
5642    var ch = character.charCodeAt(0);
5643    if (character[0] in extraCharacterMap) {
5644        ch = extraCharacterMap[character[0]].charCodeAt(0);
5645    } else if (cjkRegex.test(character[0])) {
5646        ch = 'M'.charCodeAt(0);
5647    }
5648    var metrics = metricMap[style][ch];
5649    if (metrics) {
5650        return {
5651            depth: metrics[0],
5652            height: metrics[1],
5653            italic: metrics[2],
5654            skew: metrics[3],
5655            width: metrics[4]
5656        };
5657    }
5658};
5659
5660module.exports = {
5661    metrics: metrics,
5662    sigmas: sigmas,
5663    getCharacterMetrics: getCharacterMetrics
5664};
5665
5666},{"./Style":9,"./fontMetricsData":18,"./unicodeRegexes":24}],18:[function(require,module,exports){
5667module.exports = {
5668    "AMS-Regular": {
5669        "65": [0, 0.68889, 0, 0],
5670        "66": [0, 0.68889, 0, 0],
5671        "67": [0, 0.68889, 0, 0],
5672        "68": [0, 0.68889, 0, 0],
5673        "69": [0, 0.68889, 0, 0],
5674        "70": [0, 0.68889, 0, 0],
5675        "71": [0, 0.68889, 0, 0],
5676        "72": [0, 0.68889, 0, 0],
5677        "73": [0, 0.68889, 0, 0],
5678        "74": [0.16667, 0.68889, 0, 0],
5679        "75": [0, 0.68889, 0, 0],
5680        "76": [0, 0.68889, 0, 0],
5681        "77": [0, 0.68889, 0, 0],
5682        "78": [0, 0.68889, 0, 0],
5683        "79": [0.16667, 0.68889, 0, 0],
5684        "80": [0, 0.68889, 0, 0],
5685        "81": [0.16667, 0.68889, 0, 0],
5686        "82": [0, 0.68889, 0, 0],
5687        "83": [0, 0.68889, 0, 0],
5688        "84": [0, 0.68889, 0, 0],
5689        "85": [0, 0.68889, 0, 0],
5690        "86": [0, 0.68889, 0, 0],
5691        "87": [0, 0.68889, 0, 0],
5692        "88": [0, 0.68889, 0, 0],
5693        "89": [0, 0.68889, 0, 0],
5694        "90": [0, 0.68889, 0, 0],
5695        "107": [0, 0.68889, 0, 0],
5696        "165": [0, 0.675, 0.025, 0],
5697        "174": [0.15559, 0.69224, 0, 0],
5698        "240": [0, 0.68889, 0, 0],
5699        "295": [0, 0.68889, 0, 0],
5700        "710": [0, 0.825, 0, 0],
5701        "732": [0, 0.9, 0, 0],
5702        "770": [0, 0.825, 0, 0],
5703        "771": [0, 0.9, 0, 0],
5704        "989": [0.08167, 0.58167, 0, 0],
5705        "1008": [0, 0.43056, 0.04028, 0],
5706        "8245": [0, 0.54986, 0, 0],
5707        "8463": [0, 0.68889, 0, 0],
5708        "8487": [0, 0.68889, 0, 0],
5709        "8498": [0, 0.68889, 0, 0],
5710        "8502": [0, 0.68889, 0, 0],
5711        "8503": [0, 0.68889, 0, 0],
5712        "8504": [0, 0.68889, 0, 0],
5713        "8513": [0, 0.68889, 0, 0],
5714        "8592": [-0.03598, 0.46402, 0, 0],
5715        "8594": [-0.03598, 0.46402, 0, 0],
5716        "8602": [-0.13313, 0.36687, 0, 0],
5717        "8603": [-0.13313, 0.36687, 0, 0],
5718        "8606": [0.01354, 0.52239, 0, 0],
5719        "8608": [0.01354, 0.52239, 0, 0],
5720        "8610": [0.01354, 0.52239, 0, 0],
5721        "8611": [0.01354, 0.52239, 0, 0],
5722        "8619": [0, 0.54986, 0, 0],
5723        "8620": [0, 0.54986, 0, 0],
5724        "8621": [-0.13313, 0.37788, 0, 0],
5725        "8622": [-0.13313, 0.36687, 0, 0],
5726        "8624": [0, 0.69224, 0, 0],
5727        "8625": [0, 0.69224, 0, 0],
5728        "8630": [0, 0.43056, 0, 0],
5729        "8631": [0, 0.43056, 0, 0],
5730        "8634": [0.08198, 0.58198, 0, 0],
5731        "8635": [0.08198, 0.58198, 0, 0],
5732        "8638": [0.19444, 0.69224, 0, 0],
5733        "8639": [0.19444, 0.69224, 0, 0],
5734        "8642": [0.19444, 0.69224, 0, 0],
5735        "8643": [0.19444, 0.69224, 0, 0],
5736        "8644": [0.1808, 0.675, 0, 0],
5737        "8646": [0.1808, 0.675, 0, 0],
5738        "8647": [0.1808, 0.675, 0, 0],
5739        "8648": [0.19444, 0.69224, 0, 0],
5740        "8649": [0.1808, 0.675, 0, 0],
5741        "8650": [0.19444, 0.69224, 0, 0],
5742        "8651": [0.01354, 0.52239, 0, 0],
5743        "8652": [0.01354, 0.52239, 0, 0],
5744        "8653": [-0.13313, 0.36687, 0, 0],
5745        "8654": [-0.13313, 0.36687, 0, 0],
5746        "8655": [-0.13313, 0.36687, 0, 0],
5747        "8666": [0.13667, 0.63667, 0, 0],
5748        "8667": [0.13667, 0.63667, 0, 0],
5749        "8669": [-0.13313, 0.37788, 0, 0],
5750        "8672": [-0.064, 0.437, 0, 0],
5751        "8674": [-0.064, 0.437, 0, 0],
5752        "8705": [0, 0.825, 0, 0],
5753        "8708": [0, 0.68889, 0, 0],
5754        "8709": [0.08167, 0.58167, 0, 0],
5755        "8717": [0, 0.43056, 0, 0],
5756        "8722": [-0.03598, 0.46402, 0, 0],
5757        "8724": [0.08198, 0.69224, 0, 0],
5758        "8726": [0.08167, 0.58167, 0, 0],
5759        "8733": [0, 0.69224, 0, 0],
5760        "8736": [0, 0.69224, 0, 0],
5761        "8737": [0, 0.69224, 0, 0],
5762        "8738": [0.03517, 0.52239, 0, 0],
5763        "8739": [0.08167, 0.58167, 0, 0],
5764        "8740": [0.25142, 0.74111, 0, 0],
5765        "8741": [0.08167, 0.58167, 0, 0],
5766        "8742": [0.25142, 0.74111, 0, 0],
5767        "8756": [0, 0.69224, 0, 0],
5768        "8757": [0, 0.69224, 0, 0],
5769        "8764": [-0.13313, 0.36687, 0, 0],
5770        "8765": [-0.13313, 0.37788, 0, 0],
5771        "8769": [-0.13313, 0.36687, 0, 0],
5772        "8770": [-0.03625, 0.46375, 0, 0],
5773        "8774": [0.30274, 0.79383, 0, 0],
5774        "8776": [-0.01688, 0.48312, 0, 0],
5775        "8778": [0.08167, 0.58167, 0, 0],
5776        "8782": [0.06062, 0.54986, 0, 0],
5777        "8783": [0.06062, 0.54986, 0, 0],
5778        "8785": [0.08198, 0.58198, 0, 0],
5779        "8786": [0.08198, 0.58198, 0, 0],
5780        "8787": [0.08198, 0.58198, 0, 0],
5781        "8790": [0, 0.69224, 0, 0],
5782        "8791": [0.22958, 0.72958, 0, 0],
5783        "8796": [0.08198, 0.91667, 0, 0],
5784        "8806": [0.25583, 0.75583, 0, 0],
5785        "8807": [0.25583, 0.75583, 0, 0],
5786        "8808": [0.25142, 0.75726, 0, 0],
5787        "8809": [0.25142, 0.75726, 0, 0],
5788        "8812": [0.25583, 0.75583, 0, 0],
5789        "8814": [0.20576, 0.70576, 0, 0],
5790        "8815": [0.20576, 0.70576, 0, 0],
5791        "8816": [0.30274, 0.79383, 0, 0],
5792        "8817": [0.30274, 0.79383, 0, 0],
5793        "8818": [0.22958, 0.72958, 0, 0],
5794        "8819": [0.22958, 0.72958, 0, 0],
5795        "8822": [0.1808, 0.675, 0, 0],
5796        "8823": [0.1808, 0.675, 0, 0],
5797        "8828": [0.13667, 0.63667, 0, 0],
5798        "8829": [0.13667, 0.63667, 0, 0],
5799        "8830": [0.22958, 0.72958, 0, 0],
5800        "8831": [0.22958, 0.72958, 0, 0],
5801        "8832": [0.20576, 0.70576, 0, 0],
5802        "8833": [0.20576, 0.70576, 0, 0],
5803        "8840": [0.30274, 0.79383, 0, 0],
5804        "8841": [0.30274, 0.79383, 0, 0],
5805        "8842": [0.13597, 0.63597, 0, 0],
5806        "8843": [0.13597, 0.63597, 0, 0],
5807        "8847": [0.03517, 0.54986, 0, 0],
5808        "8848": [0.03517, 0.54986, 0, 0],
5809        "8858": [0.08198, 0.58198, 0, 0],
5810        "8859": [0.08198, 0.58198, 0, 0],
5811        "8861": [0.08198, 0.58198, 0, 0],
5812        "8862": [0, 0.675, 0, 0],
5813        "8863": [0, 0.675, 0, 0],
5814        "8864": [0, 0.675, 0, 0],
5815        "8865": [0, 0.675, 0, 0],
5816        "8872": [0, 0.69224, 0, 0],
5817        "8873": [0, 0.69224, 0, 0],
5818        "8874": [0, 0.69224, 0, 0],
5819        "8876": [0, 0.68889, 0, 0],
5820        "8877": [0, 0.68889, 0, 0],
5821        "8878": [0, 0.68889, 0, 0],
5822        "8879": [0, 0.68889, 0, 0],
5823        "8882": [0.03517, 0.54986, 0, 0],
5824        "8883": [0.03517, 0.54986, 0, 0],
5825        "8884": [0.13667, 0.63667, 0, 0],
5826        "8885": [0.13667, 0.63667, 0, 0],
5827        "8888": [0, 0.54986, 0, 0],
5828        "8890": [0.19444, 0.43056, 0, 0],
5829        "8891": [0.19444, 0.69224, 0, 0],
5830        "8892": [0.19444, 0.69224, 0, 0],
5831        "8901": [0, 0.54986, 0, 0],
5832        "8903": [0.08167, 0.58167, 0, 0],
5833        "8905": [0.08167, 0.58167, 0, 0],
5834        "8906": [0.08167, 0.58167, 0, 0],
5835        "8907": [0, 0.69224, 0, 0],
5836        "8908": [0, 0.69224, 0, 0],
5837        "8909": [-0.03598, 0.46402, 0, 0],
5838        "8910": [0, 0.54986, 0, 0],
5839        "8911": [0, 0.54986, 0, 0],
5840        "8912": [0.03517, 0.54986, 0, 0],
5841        "8913": [0.03517, 0.54986, 0, 0],
5842        "8914": [0, 0.54986, 0, 0],
5843        "8915": [0, 0.54986, 0, 0],
5844        "8916": [0, 0.69224, 0, 0],
5845        "8918": [0.0391, 0.5391, 0, 0],
5846        "8919": [0.0391, 0.5391, 0, 0],
5847        "8920": [0.03517, 0.54986, 0, 0],
5848        "8921": [0.03517, 0.54986, 0, 0],
5849        "8922": [0.38569, 0.88569, 0, 0],
5850        "8923": [0.38569, 0.88569, 0, 0],
5851        "8926": [0.13667, 0.63667, 0, 0],
5852        "8927": [0.13667, 0.63667, 0, 0],
5853        "8928": [0.30274, 0.79383, 0, 0],
5854        "8929": [0.30274, 0.79383, 0, 0],
5855        "8934": [0.23222, 0.74111, 0, 0],
5856        "8935": [0.23222, 0.74111, 0, 0],
5857        "8936": [0.23222, 0.74111, 0, 0],
5858        "8937": [0.23222, 0.74111, 0, 0],
5859        "8938": [0.20576, 0.70576, 0, 0],
5860        "8939": [0.20576, 0.70576, 0, 0],
5861        "8940": [0.30274, 0.79383, 0, 0],
5862        "8941": [0.30274, 0.79383, 0, 0],
5863        "8994": [0.19444, 0.69224, 0, 0],
5864        "8995": [0.19444, 0.69224, 0, 0],
5865        "9416": [0.15559, 0.69224, 0, 0],
5866        "9484": [0, 0.69224, 0, 0],
5867        "9488": [0, 0.69224, 0, 0],
5868        "9492": [0, 0.37788, 0, 0],
5869        "9496": [0, 0.37788, 0, 0],
5870        "9585": [0.19444, 0.68889, 0, 0],
5871        "9586": [0.19444, 0.74111, 0, 0],
5872        "9632": [0, 0.675, 0, 0],
5873        "9633": [0, 0.675, 0, 0],
5874        "9650": [0, 0.54986, 0, 0],
5875        "9651": [0, 0.54986, 0, 0],
5876        "9654": [0.03517, 0.54986, 0, 0],
5877        "9660": [0, 0.54986, 0, 0],
5878        "9661": [0, 0.54986, 0, 0],
5879        "9664": [0.03517, 0.54986, 0, 0],
5880        "9674": [0.11111, 0.69224, 0, 0],
5881        "9733": [0.19444, 0.69224, 0, 0],
5882        "10003": [0, 0.69224, 0, 0],
5883        "10016": [0, 0.69224, 0, 0],
5884        "10731": [0.11111, 0.69224, 0, 0],
5885        "10846": [0.19444, 0.75583, 0, 0],
5886        "10877": [0.13667, 0.63667, 0, 0],
5887        "10878": [0.13667, 0.63667, 0, 0],
5888        "10885": [0.25583, 0.75583, 0, 0],
5889        "10886": [0.25583, 0.75583, 0, 0],
5890        "10887": [0.13597, 0.63597, 0, 0],
5891        "10888": [0.13597, 0.63597, 0, 0],
5892        "10889": [0.26167, 0.75726, 0, 0],
5893        "10890": [0.26167, 0.75726, 0, 0],
5894        "10891": [0.48256, 0.98256, 0, 0],
5895        "10892": [0.48256, 0.98256, 0, 0],
5896        "10901": [0.13667, 0.63667, 0, 0],
5897        "10902": [0.13667, 0.63667, 0, 0],
5898        "10933": [0.25142, 0.75726, 0, 0],
5899        "10934": [0.25142, 0.75726, 0, 0],
5900        "10935": [0.26167, 0.75726, 0, 0],
5901        "10936": [0.26167, 0.75726, 0, 0],
5902        "10937": [0.26167, 0.75726, 0, 0],
5903        "10938": [0.26167, 0.75726, 0, 0],
5904        "10949": [0.25583, 0.75583, 0, 0],
5905        "10950": [0.25583, 0.75583, 0, 0],
5906        "10955": [0.28481, 0.79383, 0, 0],
5907        "10956": [0.28481, 0.79383, 0, 0],
5908        "57350": [0.08167, 0.58167, 0, 0],
5909        "57351": [0.08167, 0.58167, 0, 0],
5910        "57352": [0.08167, 0.58167, 0, 0],
5911        "57353": [0, 0.43056, 0.04028, 0],
5912        "57356": [0.25142, 0.75726, 0, 0],
5913        "57357": [0.25142, 0.75726, 0, 0],
5914        "57358": [0.41951, 0.91951, 0, 0],
5915        "57359": [0.30274, 0.79383, 0, 0],
5916        "57360": [0.30274, 0.79383, 0, 0],
5917        "57361": [0.41951, 0.91951, 0, 0],
5918        "57366": [0.25142, 0.75726, 0, 0],
5919        "57367": [0.25142, 0.75726, 0, 0],
5920        "57368": [0.25142, 0.75726, 0, 0],
5921        "57369": [0.25142, 0.75726, 0, 0],
5922        "57370": [0.13597, 0.63597, 0, 0],
5923        "57371": [0.13597, 0.63597, 0, 0]
5924    },
5925    "Caligraphic-Regular": {
5926        "48": [0, 0.43056, 0, 0],
5927        "49": [0, 0.43056, 0, 0],
5928        "50": [0, 0.43056, 0, 0],
5929        "51": [0.19444, 0.43056, 0, 0],
5930        "52": [0.19444, 0.43056, 0, 0],
5931        "53": [0.19444, 0.43056, 0, 0],
5932        "54": [0, 0.64444, 0, 0],
5933        "55": [0.19444, 0.43056, 0, 0],
5934        "56": [0, 0.64444, 0, 0],
5935        "57": [0.19444, 0.43056, 0, 0],
5936        "65": [0, 0.68333, 0, 0.19445],
5937        "66": [0, 0.68333, 0.03041, 0.13889],
5938        "67": [0, 0.68333, 0.05834, 0.13889],
5939        "68": [0, 0.68333, 0.02778, 0.08334],
5940        "69": [0, 0.68333, 0.08944, 0.11111],
5941        "70": [0, 0.68333, 0.09931, 0.11111],
5942        "71": [0.09722, 0.68333, 0.0593, 0.11111],
5943        "72": [0, 0.68333, 0.00965, 0.11111],
5944        "73": [0, 0.68333, 0.07382, 0],
5945        "74": [0.09722, 0.68333, 0.18472, 0.16667],
5946        "75": [0, 0.68333, 0.01445, 0.05556],
5947        "76": [0, 0.68333, 0, 0.13889],
5948        "77": [0, 0.68333, 0, 0.13889],
5949        "78": [0, 0.68333, 0.14736, 0.08334],
5950        "79": [0, 0.68333, 0.02778, 0.11111],
5951        "80": [0, 0.68333, 0.08222, 0.08334],
5952        "81": [0.09722, 0.68333, 0, 0.11111],
5953        "82": [0, 0.68333, 0, 0.08334],
5954        "83": [0, 0.68333, 0.075, 0.13889],
5955        "84": [0, 0.68333, 0.25417, 0],
5956        "85": [0, 0.68333, 0.09931, 0.08334],
5957        "86": [0, 0.68333, 0.08222, 0],
5958        "87": [0, 0.68333, 0.08222, 0.08334],
5959        "88": [0, 0.68333, 0.14643, 0.13889],
5960        "89": [0.09722, 0.68333, 0.08222, 0.08334],
5961        "90": [0, 0.68333, 0.07944, 0.13889]
5962    },
5963    "Fraktur-Regular": {
5964        "33": [0, 0.69141, 0, 0],
5965        "34": [0, 0.69141, 0, 0],
5966        "38": [0, 0.69141, 0, 0],
5967        "39": [0, 0.69141, 0, 0],
5968        "40": [0.24982, 0.74947, 0, 0],
5969        "41": [0.24982, 0.74947, 0, 0],
5970        "42": [0, 0.62119, 0, 0],
5971        "43": [0.08319, 0.58283, 0, 0],
5972        "44": [0, 0.10803, 0, 0],
5973        "45": [0.08319, 0.58283, 0, 0],
5974        "46": [0, 0.10803, 0, 0],
5975        "47": [0.24982, 0.74947, 0, 0],
5976        "48": [0, 0.47534, 0, 0],
5977        "49": [0, 0.47534, 0, 0],
5978        "50": [0, 0.47534, 0, 0],
5979        "51": [0.18906, 0.47534, 0, 0],
5980        "52": [0.18906, 0.47534, 0, 0],
5981        "53": [0.18906, 0.47534, 0, 0],
5982        "54": [0, 0.69141, 0, 0],
5983        "55": [0.18906, 0.47534, 0, 0],
5984        "56": [0, 0.69141, 0, 0],
5985        "57": [0.18906, 0.47534, 0, 0],
5986        "58": [0, 0.47534, 0, 0],
5987        "59": [0.12604, 0.47534, 0, 0],
5988        "61": [-0.13099, 0.36866, 0, 0],
5989        "63": [0, 0.69141, 0, 0],
5990        "65": [0, 0.69141, 0, 0],
5991        "66": [0, 0.69141, 0, 0],
5992        "67": [0, 0.69141, 0, 0],
5993        "68": [0, 0.69141, 0, 0],
5994        "69": [0, 0.69141, 0, 0],
5995        "70": [0.12604, 0.69141, 0, 0],
5996        "71": [0, 0.69141, 0, 0],
5997        "72": [0.06302, 0.69141, 0, 0],
5998        "73": [0, 0.69141, 0, 0],
5999        "74": [0.12604, 0.69141, 0, 0],
6000        "75": [0, 0.69141, 0, 0],
6001        "76": [0, 0.69141, 0, 0],
6002        "77": [0, 0.69141, 0, 0],
6003        "78": [0, 0.69141, 0, 0],
6004        "79": [0, 0.69141, 0, 0],
6005        "80": [0.18906, 0.69141, 0, 0],
6006        "81": [0.03781, 0.69141, 0, 0],
6007        "82": [0, 0.69141, 0, 0],
6008        "83": [0, 0.69141, 0, 0],
6009        "84": [0, 0.69141, 0, 0],
6010        "85": [0, 0.69141, 0, 0],
6011        "86": [0, 0.69141, 0, 0],
6012        "87": [0, 0.69141, 0, 0],
6013        "88": [0, 0.69141, 0, 0],
6014        "89": [0.18906, 0.69141, 0, 0],
6015        "90": [0.12604, 0.69141, 0, 0],
6016        "91": [0.24982, 0.74947, 0, 0],
6017        "93": [0.24982, 0.74947, 0, 0],
6018        "94": [0, 0.69141, 0, 0],
6019        "97": [0, 0.47534, 0, 0],
6020        "98": [0, 0.69141, 0, 0],
6021        "99": [0, 0.47534, 0, 0],
6022        "100": [0, 0.62119, 0, 0],
6023        "101": [0, 0.47534, 0, 0],
6024        "102": [0.18906, 0.69141, 0, 0],
6025        "103": [0.18906, 0.47534, 0, 0],
6026        "104": [0.18906, 0.69141, 0, 0],
6027        "105": [0, 0.69141, 0, 0],
6028        "106": [0, 0.69141, 0, 0],
6029        "107": [0, 0.69141, 0, 0],
6030        "108": [0, 0.69141, 0, 0],
6031        "109": [0, 0.47534, 0, 0],
6032        "110": [0, 0.47534, 0, 0],
6033        "111": [0, 0.47534, 0, 0],
6034        "112": [0.18906, 0.52396, 0, 0],
6035        "113": [0.18906, 0.47534, 0, 0],
6036        "114": [0, 0.47534, 0, 0],
6037        "115": [0, 0.47534, 0, 0],
6038        "116": [0, 0.62119, 0, 0],
6039        "117": [0, 0.47534, 0, 0],
6040        "118": [0, 0.52396, 0, 0],
6041        "119": [0, 0.52396, 0, 0],
6042        "120": [0.18906, 0.47534, 0, 0],
6043        "121": [0.18906, 0.47534, 0, 0],
6044        "122": [0.18906, 0.47534, 0, 0],
6045        "8216": [0, 0.69141, 0, 0],
6046        "8217": [0, 0.69141, 0, 0],
6047        "58112": [0, 0.62119, 0, 0],
6048        "58113": [0, 0.62119, 0, 0],
6049        "58114": [0.18906, 0.69141, 0, 0],
6050        "58115": [0.18906, 0.69141, 0, 0],
6051        "58116": [0.18906, 0.47534, 0, 0],
6052        "58117": [0, 0.69141, 0, 0],
6053        "58118": [0, 0.62119, 0, 0],
6054        "58119": [0, 0.47534, 0, 0]
6055    },
6056    "Main-Bold": {
6057        "33": [0, 0.69444, 0, 0],
6058        "34": [0, 0.69444, 0, 0],
6059        "35": [0.19444, 0.69444, 0, 0],
6060        "36": [0.05556, 0.75, 0, 0],
6061        "37": [0.05556, 0.75, 0, 0],
6062        "38": [0, 0.69444, 0, 0],
6063        "39": [0, 0.69444, 0, 0],
6064        "40": [0.25, 0.75, 0, 0],
6065        "41": [0.25, 0.75, 0, 0],
6066        "42": [0, 0.75, 0, 0],
6067        "43": [0.13333, 0.63333, 0, 0],
6068        "44": [0.19444, 0.15556, 0, 0],
6069        "45": [0, 0.44444, 0, 0],
6070        "46": [0, 0.15556, 0, 0],
6071        "47": [0.25, 0.75, 0, 0],
6072        "48": [0, 0.64444, 0, 0],
6073        "49": [0, 0.64444, 0, 0],
6074        "50": [0, 0.64444, 0, 0],
6075        "51": [0, 0.64444, 0, 0],
6076        "52": [0, 0.64444, 0, 0],
6077        "53": [0, 0.64444, 0, 0],
6078        "54": [0, 0.64444, 0, 0],
6079        "55": [0, 0.64444, 0, 0],
6080        "56": [0, 0.64444, 0, 0],
6081        "57": [0, 0.64444, 0, 0],
6082        "58": [0, 0.44444, 0, 0],
6083        "59": [0.19444, 0.44444, 0, 0],
6084        "60": [0.08556, 0.58556, 0, 0],
6085        "61": [-0.10889, 0.39111, 0, 0],
6086        "62": [0.08556, 0.58556, 0, 0],
6087        "63": [0, 0.69444, 0, 0],
6088        "64": [0, 0.69444, 0, 0],
6089        "65": [0, 0.68611, 0, 0],
6090        "66": [0, 0.68611, 0, 0],
6091        "67": [0, 0.68611, 0, 0],
6092        "68": [0, 0.68611, 0, 0],
6093        "69": [0, 0.68611, 0, 0],
6094        "70": [0, 0.68611, 0, 0],
6095        "71": [0, 0.68611, 0, 0],
6096        "72": [0, 0.68611, 0, 0],
6097        "73": [0, 0.68611, 0, 0],
6098        "74": [0, 0.68611, 0, 0],
6099        "75": [0, 0.68611, 0, 0],
6100        "76": [0, 0.68611, 0, 0],
6101        "77": [0, 0.68611, 0, 0],
6102        "78": [0, 0.68611, 0, 0],
6103        "79": [0, 0.68611, 0, 0],
6104        "80": [0, 0.68611, 0, 0],
6105        "81": [0.19444, 0.68611, 0, 0],
6106        "82": [0, 0.68611, 0, 0],
6107        "83": [0, 0.68611, 0, 0],
6108        "84": [0, 0.68611, 0, 0],
6109        "85": [0, 0.68611, 0, 0],
6110        "86": [0, 0.68611, 0.01597, 0],
6111        "87": [0, 0.68611, 0.01597, 0],
6112        "88": [0, 0.68611, 0, 0],
6113        "89": [0, 0.68611, 0.02875, 0],
6114        "90": [0, 0.68611, 0, 0],
6115        "91": [0.25, 0.75, 0, 0],
6116        "92": [0.25, 0.75, 0, 0],
6117        "93": [0.25, 0.75, 0, 0],
6118        "94": [0, 0.69444, 0, 0],
6119        "95": [0.31, 0.13444, 0.03194, 0],
6120        "96": [0, 0.69444, 0, 0],
6121        "97": [0, 0.44444, 0, 0],
6122        "98": [0, 0.69444, 0, 0],
6123        "99": [0, 0.44444, 0, 0],
6124        "100": [0, 0.69444, 0, 0],
6125        "101": [0, 0.44444, 0, 0],
6126        "102": [0, 0.69444, 0.10903, 0],
6127        "103": [0.19444, 0.44444, 0.01597, 0],
6128        "104": [0, 0.69444, 0, 0],
6129        "105": [0, 0.69444, 0, 0],
6130        "106": [0.19444, 0.69444, 0, 0],
6131        "107": [0, 0.69444, 0, 0],
6132        "108": [0, 0.69444, 0, 0],
6133        "109": [0, 0.44444, 0, 0],
6134        "110": [0, 0.44444, 0, 0],
6135        "111": [0, 0.44444, 0, 0],
6136        "112": [0.19444, 0.44444, 0, 0],
6137        "113": [0.19444, 0.44444, 0, 0],
6138        "114": [0, 0.44444, 0, 0],
6139        "115": [0, 0.44444, 0, 0],
6140        "116": [0, 0.63492, 0, 0],
6141        "117": [0, 0.44444, 0, 0],
6142        "118": [0, 0.44444, 0.01597, 0],
6143        "119": [0, 0.44444, 0.01597, 0],
6144        "120": [0, 0.44444, 0, 0],
6145        "121": [0.19444, 0.44444, 0.01597, 0],
6146        "122": [0, 0.44444, 0, 0],
6147        "123": [0.25, 0.75, 0, 0],
6148        "124": [0.25, 0.75, 0, 0],
6149        "125": [0.25, 0.75, 0, 0],
6150        "126": [0.35, 0.34444, 0, 0],
6151        "168": [0, 0.69444, 0, 0],
6152        "172": [0, 0.44444, 0, 0],
6153        "175": [0, 0.59611, 0, 0],
6154        "176": [0, 0.69444, 0, 0],
6155        "177": [0.13333, 0.63333, 0, 0],
6156        "180": [0, 0.69444, 0, 0],
6157        "215": [0.13333, 0.63333, 0, 0],
6158        "247": [0.13333, 0.63333, 0, 0],
6159        "305": [0, 0.44444, 0, 0],
6160        "567": [0.19444, 0.44444, 0, 0],
6161        "710": [0, 0.69444, 0, 0],
6162        "711": [0, 0.63194, 0, 0],
6163        "713": [0, 0.59611, 0, 0],
6164        "714": [0, 0.69444, 0, 0],
6165        "715": [0, 0.69444, 0, 0],
6166        "728": [0, 0.69444, 0, 0],
6167        "729": [0, 0.69444, 0, 0],
6168        "730": [0, 0.69444, 0, 0],
6169        "732": [0, 0.69444, 0, 0],
6170        "768": [0, 0.69444, 0, 0],
6171        "769": [0, 0.69444, 0, 0],
6172        "770": [0, 0.69444, 0, 0],
6173        "771": [0, 0.69444, 0, 0],
6174        "772": [0, 0.59611, 0, 0],
6175        "774": [0, 0.69444, 0, 0],
6176        "775": [0, 0.69444, 0, 0],
6177        "776": [0, 0.69444, 0, 0],
6178        "778": [0, 0.69444, 0, 0],
6179        "779": [0, 0.69444, 0, 0],
6180        "780": [0, 0.63194, 0, 0],
6181        "824": [0.19444, 0.69444, 0, 0],
6182        "915": [0, 0.68611, 0, 0],
6183        "916": [0, 0.68611, 0, 0],
6184        "920": [0, 0.68611, 0, 0],
6185        "923": [0, 0.68611, 0, 0],
6186        "926": [0, 0.68611, 0, 0],
6187        "928": [0, 0.68611, 0, 0],
6188        "931": [0, 0.68611, 0, 0],
6189        "933": [0, 0.68611, 0, 0],
6190        "934": [0, 0.68611, 0, 0],
6191        "936": [0, 0.68611, 0, 0],
6192        "937": [0, 0.68611, 0, 0],
6193        "8211": [0, 0.44444, 0.03194, 0],
6194        "8212": [0, 0.44444, 0.03194, 0],
6195        "8216": [0, 0.69444, 0, 0],
6196        "8217": [0, 0.69444, 0, 0],
6197        "8220": [0, 0.69444, 0, 0],
6198        "8221": [0, 0.69444, 0, 0],
6199        "8224": [0.19444, 0.69444, 0, 0],
6200        "8225": [0.19444, 0.69444, 0, 0],
6201        "8242": [0, 0.55556, 0, 0],
6202        "8407": [0, 0.72444, 0.15486, 0],
6203        "8463": [0, 0.69444, 0, 0],
6204        "8465": [0, 0.69444, 0, 0],
6205        "8467": [0, 0.69444, 0, 0],
6206        "8472": [0.19444, 0.44444, 0, 0],
6207        "8476": [0, 0.69444, 0, 0],
6208        "8501": [0, 0.69444, 0, 0],
6209        "8592": [-0.10889, 0.39111, 0, 0],
6210        "8593": [0.19444, 0.69444, 0, 0],
6211        "8594": [-0.10889, 0.39111, 0, 0],
6212        "8595": [0.19444, 0.69444, 0, 0],
6213        "8596": [-0.10889, 0.39111, 0, 0],
6214        "8597": [0.25, 0.75, 0, 0],
6215        "8598": [0.19444, 0.69444, 0, 0],
6216        "8599": [0.19444, 0.69444, 0, 0],
6217        "8600": [0.19444, 0.69444, 0, 0],
6218        "8601": [0.19444, 0.69444, 0, 0],
6219        "8636": [-0.10889, 0.39111, 0, 0],
6220        "8637": [-0.10889, 0.39111, 0, 0],
6221        "8640": [-0.10889, 0.39111, 0, 0],
6222        "8641": [-0.10889, 0.39111, 0, 0],
6223        "8656": [-0.10889, 0.39111, 0, 0],
6224        "8657": [0.19444, 0.69444, 0, 0],
6225        "8658": [-0.10889, 0.39111, 0, 0],
6226        "8659": [0.19444, 0.69444, 0, 0],
6227        "8660": [-0.10889, 0.39111, 0, 0],
6228        "8661": [0.25, 0.75, 0, 0],
6229        "8704": [0, 0.69444, 0, 0],
6230        "8706": [0, 0.69444, 0.06389, 0],
6231        "8707": [0, 0.69444, 0, 0],
6232        "8709": [0.05556, 0.75, 0, 0],
6233        "8711": [0, 0.68611, 0, 0],
6234        "8712": [0.08556, 0.58556, 0, 0],
6235        "8715": [0.08556, 0.58556, 0, 0],
6236        "8722": [0.13333, 0.63333, 0, 0],
6237        "8723": [0.13333, 0.63333, 0, 0],
6238        "8725": [0.25, 0.75, 0, 0],
6239        "8726": [0.25, 0.75, 0, 0],
6240        "8727": [-0.02778, 0.47222, 0, 0],
6241        "8728": [-0.02639, 0.47361, 0, 0],
6242        "8729": [-0.02639, 0.47361, 0, 0],
6243        "8730": [0.18, 0.82, 0, 0],
6244        "8733": [0, 0.44444, 0, 0],
6245        "8734": [0, 0.44444, 0, 0],
6246        "8736": [0, 0.69224, 0, 0],
6247        "8739": [0.25, 0.75, 0, 0],
6248        "8741": [0.25, 0.75, 0, 0],
6249        "8743": [0, 0.55556, 0, 0],
6250        "8744": [0, 0.55556, 0, 0],
6251        "8745": [0, 0.55556, 0, 0],
6252        "8746": [0, 0.55556, 0, 0],
6253        "8747": [0.19444, 0.69444, 0.12778, 0],
6254        "8764": [-0.10889, 0.39111, 0, 0],
6255        "8768": [0.19444, 0.69444, 0, 0],
6256        "8771": [0.00222, 0.50222, 0, 0],
6257        "8776": [0.02444, 0.52444, 0, 0],
6258        "8781": [0.00222, 0.50222, 0, 0],
6259        "8801": [0.00222, 0.50222, 0, 0],
6260        "8804": [0.19667, 0.69667, 0, 0],
6261        "8805": [0.19667, 0.69667, 0, 0],
6262        "8810": [0.08556, 0.58556, 0, 0],
6263        "8811": [0.08556, 0.58556, 0, 0],
6264        "8826": [0.08556, 0.58556, 0, 0],
6265        "8827": [0.08556, 0.58556, 0, 0],
6266        "8834": [0.08556, 0.58556, 0, 0],
6267        "8835": [0.08556, 0.58556, 0, 0],
6268        "8838": [0.19667, 0.69667, 0, 0],
6269        "8839": [0.19667, 0.69667, 0, 0],
6270        "8846": [0, 0.55556, 0, 0],
6271        "8849": [0.19667, 0.69667, 0, 0],
6272        "8850": [0.19667, 0.69667, 0, 0],
6273        "8851": [0, 0.55556, 0, 0],
6274        "8852": [0, 0.55556, 0, 0],
6275        "8853": [0.13333, 0.63333, 0, 0],
6276        "8854": [0.13333, 0.63333, 0, 0],
6277        "8855": [0.13333, 0.63333, 0, 0],
6278        "8856": [0.13333, 0.63333, 0, 0],
6279        "8857": [0.13333, 0.63333, 0, 0],
6280        "8866": [0, 0.69444, 0, 0],
6281        "8867": [0, 0.69444, 0, 0],
6282        "8868": [0, 0.69444, 0, 0],
6283        "8869": [0, 0.69444, 0, 0],
6284        "8900": [-0.02639, 0.47361, 0, 0],
6285        "8901": [-0.02639, 0.47361, 0, 0],
6286        "8902": [-0.02778, 0.47222, 0, 0],
6287        "8968": [0.25, 0.75, 0, 0],
6288        "8969": [0.25, 0.75, 0, 0],
6289        "8970": [0.25, 0.75, 0, 0],
6290        "8971": [0.25, 0.75, 0, 0],
6291        "8994": [-0.13889, 0.36111, 0, 0],
6292        "8995": [-0.13889, 0.36111, 0, 0],
6293        "9651": [0.19444, 0.69444, 0, 0],
6294        "9657": [-0.02778, 0.47222, 0, 0],
6295        "9661": [0.19444, 0.69444, 0, 0],
6296        "9667": [-0.02778, 0.47222, 0, 0],
6297        "9711": [0.19444, 0.69444, 0, 0],
6298        "9824": [0.12963, 0.69444, 0, 0],
6299        "9825": [0.12963, 0.69444, 0, 0],
6300        "9826": [0.12963, 0.69444, 0, 0],
6301        "9827": [0.12963, 0.69444, 0, 0],
6302        "9837": [0, 0.75, 0, 0],
6303        "9838": [0.19444, 0.69444, 0, 0],
6304        "9839": [0.19444, 0.69444, 0, 0],
6305        "10216": [0.25, 0.75, 0, 0],
6306        "10217": [0.25, 0.75, 0, 0],
6307        "10815": [0, 0.68611, 0, 0],
6308        "10927": [0.19667, 0.69667, 0, 0],
6309        "10928": [0.19667, 0.69667, 0, 0]
6310    },
6311    "Main-Italic": {
6312        "33": [0, 0.69444, 0.12417, 0],
6313        "34": [0, 0.69444, 0.06961, 0],
6314        "35": [0.19444, 0.69444, 0.06616, 0],
6315        "37": [0.05556, 0.75, 0.13639, 0],
6316        "38": [0, 0.69444, 0.09694, 0],
6317        "39": [0, 0.69444, 0.12417, 0],
6318        "40": [0.25, 0.75, 0.16194, 0],
6319        "41": [0.25, 0.75, 0.03694, 0],
6320        "42": [0, 0.75, 0.14917, 0],
6321        "43": [0.05667, 0.56167, 0.03694, 0],
6322        "44": [0.19444, 0.10556, 0, 0],
6323        "45": [0, 0.43056, 0.02826, 0],
6324        "46": [0, 0.10556, 0, 0],
6325        "47": [0.25, 0.75, 0.16194, 0],
6326        "48": [0, 0.64444, 0.13556, 0],
6327        "49": [0, 0.64444, 0.13556, 0],
6328        "50": [0, 0.64444, 0.13556, 0],
6329        "51": [0, 0.64444, 0.13556, 0],
6330        "52": [0.19444, 0.64444, 0.13556, 0],
6331        "53": [0, 0.64444, 0.13556, 0],
6332        "54": [0, 0.64444, 0.13556, 0],
6333        "55": [0.19444, 0.64444, 0.13556, 0],
6334        "56": [0, 0.64444, 0.13556, 0],
6335        "57": [0, 0.64444, 0.13556, 0],
6336        "58": [0, 0.43056, 0.0582, 0],
6337        "59": [0.19444, 0.43056, 0.0582, 0],
6338        "61": [-0.13313, 0.36687, 0.06616, 0],
6339        "63": [0, 0.69444, 0.1225, 0],
6340        "64": [0, 0.69444, 0.09597, 0],
6341        "65": [0, 0.68333, 0, 0],
6342        "66": [0, 0.68333, 0.10257, 0],
6343        "67": [0, 0.68333, 0.14528, 0],
6344        "68": [0, 0.68333, 0.09403, 0],
6345        "69": [0, 0.68333, 0.12028, 0],
6346        "70": [0, 0.68333, 0.13305, 0],
6347        "71": [0, 0.68333, 0.08722, 0],
6348        "72": [0, 0.68333, 0.16389, 0],
6349        "73": [0, 0.68333, 0.15806, 0],
6350        "74": [0, 0.68333, 0.14028, 0],
6351        "75": [0, 0.68333, 0.14528, 0],
6352        "76": [0, 0.68333, 0, 0],
6353        "77": [0, 0.68333, 0.16389, 0],
6354        "78": [0, 0.68333, 0.16389, 0],
6355        "79": [0, 0.68333, 0.09403, 0],
6356        "80": [0, 0.68333, 0.10257, 0],
6357        "81": [0.19444, 0.68333, 0.09403, 0],
6358        "82": [0, 0.68333, 0.03868, 0],
6359        "83": [0, 0.68333, 0.11972, 0],
6360        "84": [0, 0.68333, 0.13305, 0],
6361        "85": [0, 0.68333, 0.16389, 0],
6362        "86": [0, 0.68333, 0.18361, 0],
6363        "87": [0, 0.68333, 0.18361, 0],
6364        "88": [0, 0.68333, 0.15806, 0],
6365        "89": [0, 0.68333, 0.19383, 0],
6366        "90": [0, 0.68333, 0.14528, 0],
6367        "91": [0.25, 0.75, 0.1875, 0],
6368        "93": [0.25, 0.75, 0.10528, 0],
6369        "94": [0, 0.69444, 0.06646, 0],
6370        "95": [0.31, 0.12056, 0.09208, 0],
6371        "97": [0, 0.43056, 0.07671, 0],
6372        "98": [0, 0.69444, 0.06312, 0],
6373        "99": [0, 0.43056, 0.05653, 0],
6374        "100": [0, 0.69444, 0.10333, 0],
6375        "101": [0, 0.43056, 0.07514, 0],
6376        "102": [0.19444, 0.69444, 0.21194, 0],
6377        "103": [0.19444, 0.43056, 0.08847, 0],
6378        "104": [0, 0.69444, 0.07671, 0],
6379        "105": [0, 0.65536, 0.1019, 0],
6380        "106": [0.19444, 0.65536, 0.14467, 0],
6381        "107": [0, 0.69444, 0.10764, 0],
6382        "108": [0, 0.69444, 0.10333, 0],
6383        "109": [0, 0.43056, 0.07671, 0],
6384        "110": [0, 0.43056, 0.07671, 0],
6385        "111": [0, 0.43056, 0.06312, 0],
6386        "112": [0.19444, 0.43056, 0.06312, 0],
6387        "113": [0.19444, 0.43056, 0.08847, 0],
6388        "114": [0, 0.43056, 0.10764, 0],
6389        "115": [0, 0.43056, 0.08208, 0],
6390        "116": [0, 0.61508, 0.09486, 0],
6391        "117": [0, 0.43056, 0.07671, 0],
6392        "118": [0, 0.43056, 0.10764, 0],
6393        "119": [0, 0.43056, 0.10764, 0],
6394        "120": [0, 0.43056, 0.12042, 0],
6395        "121": [0.19444, 0.43056, 0.08847, 0],
6396        "122": [0, 0.43056, 0.12292, 0],
6397        "126": [0.35, 0.31786, 0.11585, 0],
6398        "163": [0, 0.69444, 0, 0],
6399        "305": [0, 0.43056, 0, 0.02778],
6400        "567": [0.19444, 0.43056, 0, 0.08334],
6401        "768": [0, 0.69444, 0, 0],
6402        "769": [0, 0.69444, 0.09694, 0],
6403        "770": [0, 0.69444, 0.06646, 0],
6404        "771": [0, 0.66786, 0.11585, 0],
6405        "772": [0, 0.56167, 0.10333, 0],
6406        "774": [0, 0.69444, 0.10806, 0],
6407        "775": [0, 0.66786, 0.11752, 0],
6408        "776": [0, 0.66786, 0.10474, 0],
6409        "778": [0, 0.69444, 0, 0],
6410        "779": [0, 0.69444, 0.1225, 0],
6411        "780": [0, 0.62847, 0.08295, 0],
6412        "915": [0, 0.68333, 0.13305, 0],
6413        "916": [0, 0.68333, 0, 0],
6414        "920": [0, 0.68333, 0.09403, 0],
6415        "923": [0, 0.68333, 0, 0],
6416        "926": [0, 0.68333, 0.15294, 0],
6417        "928": [0, 0.68333, 0.16389, 0],
6418        "931": [0, 0.68333, 0.12028, 0],
6419        "933": [0, 0.68333, 0.11111, 0],
6420        "934": [0, 0.68333, 0.05986, 0],
6421        "936": [0, 0.68333, 0.11111, 0],
6422        "937": [0, 0.68333, 0.10257, 0],
6423        "8211": [0, 0.43056, 0.09208, 0],
6424        "8212": [0, 0.43056, 0.09208, 0],
6425        "8216": [0, 0.69444, 0.12417, 0],
6426        "8217": [0, 0.69444, 0.12417, 0],
6427        "8220": [0, 0.69444, 0.1685, 0],
6428        "8221": [0, 0.69444, 0.06961, 0],
6429        "8463": [0, 0.68889, 0, 0]
6430    },
6431    "Main-Regular": {
6432        "32": [0, 0, 0, 0],
6433        "33": [0, 0.69444, 0, 0],
6434        "34": [0, 0.69444, 0, 0],
6435        "35": [0.19444, 0.69444, 0, 0],
6436        "36": [0.05556, 0.75, 0, 0],
6437        "37": [0.05556, 0.75, 0, 0],
6438        "38": [0, 0.69444, 0, 0],
6439        "39": [0, 0.69444, 0, 0],
6440        "40": [0.25, 0.75, 0, 0],
6441        "41": [0.25, 0.75, 0, 0],
6442        "42": [0, 0.75, 0, 0],
6443        "43": [0.08333, 0.58333, 0, 0],
6444        "44": [0.19444, 0.10556, 0, 0],
6445        "45": [0, 0.43056, 0, 0],
6446        "46": [0, 0.10556, 0, 0],
6447        "47": [0.25, 0.75, 0, 0],
6448        "48": [0, 0.64444, 0, 0],
6449        "49": [0, 0.64444, 0, 0],
6450        "50": [0, 0.64444, 0, 0],
6451        "51": [0, 0.64444, 0, 0],
6452        "52": [0, 0.64444, 0, 0],
6453        "53": [0, 0.64444, 0, 0],
6454        "54": [0, 0.64444, 0, 0],
6455        "55": [0, 0.64444, 0, 0],
6456        "56": [0, 0.64444, 0, 0],
6457        "57": [0, 0.64444, 0, 0],
6458        "58": [0, 0.43056, 0, 0],
6459        "59": [0.19444, 0.43056, 0, 0],
6460        "60": [0.0391, 0.5391, 0, 0],
6461        "61": [-0.13313, 0.36687, 0, 0],
6462        "62": [0.0391, 0.5391, 0, 0],
6463        "63": [0, 0.69444, 0, 0],
6464        "64": [0, 0.69444, 0, 0],
6465        "65": [0, 0.68333, 0, 0],
6466        "66": [0, 0.68333, 0, 0],
6467        "67": [0, 0.68333, 0, 0],
6468        "68": [0, 0.68333, 0, 0],
6469        "69": [0, 0.68333, 0, 0],
6470        "70": [0, 0.68333, 0, 0],
6471        "71": [0, 0.68333, 0, 0],
6472        "72": [0, 0.68333, 0, 0],
6473        "73": [0, 0.68333, 0, 0],
6474        "74": [0, 0.68333, 0, 0],
6475        "75": [0, 0.68333, 0, 0],
6476        "76": [0, 0.68333, 0, 0],
6477        "77": [0, 0.68333, 0, 0],
6478        "78": [0, 0.68333, 0, 0],
6479        "79": [0, 0.68333, 0, 0],
6480        "80": [0, 0.68333, 0, 0],
6481        "81": [0.19444, 0.68333, 0, 0],
6482        "82": [0, 0.68333, 0, 0],
6483        "83": [0, 0.68333, 0, 0],
6484        "84": [0, 0.68333, 0, 0],
6485        "85": [0, 0.68333, 0, 0],
6486        "86": [0, 0.68333, 0.01389, 0],
6487        "87": [0, 0.68333, 0.01389, 0],
6488        "88": [0, 0.68333, 0, 0],
6489        "89": [0, 0.68333, 0.025, 0],
6490        "90": [0, 0.68333, 0, 0],
6491        "91": [0.25, 0.75, 0, 0],
6492        "92": [0.25, 0.75, 0, 0],
6493        "93": [0.25, 0.75, 0, 0],
6494        "94": [0, 0.69444, 0, 0],
6495        "95": [0.31, 0.12056, 0.02778, 0],
6496        "96": [0, 0.69444, 0, 0],
6497        "97": [0, 0.43056, 0, 0],
6498        "98": [0, 0.69444, 0, 0],
6499        "99": [0, 0.43056, 0, 0],
6500        "100": [0, 0.69444, 0, 0],
6501        "101": [0, 0.43056, 0, 0],
6502        "102": [0, 0.69444, 0.07778, 0],
6503        "103": [0.19444, 0.43056, 0.01389, 0],
6504        "104": [0, 0.69444, 0, 0],
6505        "105": [0, 0.66786, 0, 0],
6506        "106": [0.19444, 0.66786, 0, 0],
6507        "107": [0, 0.69444, 0, 0],
6508        "108": [0, 0.69444, 0, 0],
6509        "109": [0, 0.43056, 0, 0],
6510        "110": [0, 0.43056, 0, 0],
6511        "111": [0, 0.43056, 0, 0],
6512        "112": [0.19444, 0.43056, 0, 0],
6513        "113": [0.19444, 0.43056, 0, 0],
6514        "114": [0, 0.43056, 0, 0],
6515        "115": [0, 0.43056, 0, 0],
6516        "116": [0, 0.61508, 0, 0],
6517        "117": [0, 0.43056, 0, 0],
6518        "118": [0, 0.43056, 0.01389, 0],
6519        "119": [0, 0.43056, 0.01389, 0],
6520        "120": [0, 0.43056, 0, 0],
6521        "121": [0.19444, 0.43056, 0.01389, 0],
6522        "122": [0, 0.43056, 0, 0],
6523        "123": [0.25, 0.75, 0, 0],
6524        "124": [0.25, 0.75, 0, 0],
6525        "125": [0.25, 0.75, 0, 0],
6526        "126": [0.35, 0.31786, 0, 0],
6527        "160": [0, 0, 0, 0],
6528        "168": [0, 0.66786, 0, 0],
6529        "172": [0, 0.43056, 0, 0],
6530        "175": [0, 0.56778, 0, 0],
6531        "176": [0, 0.69444, 0, 0],
6532        "177": [0.08333, 0.58333, 0, 0],
6533        "180": [0, 0.69444, 0, 0],
6534        "215": [0.08333, 0.58333, 0, 0],
6535        "247": [0.08333, 0.58333, 0, 0],
6536        "305": [0, 0.43056, 0, 0],
6537        "567": [0.19444, 0.43056, 0, 0],
6538        "710": [0, 0.69444, 0, 0],
6539        "711": [0, 0.62847, 0, 0],
6540        "713": [0, 0.56778, 0, 0],
6541        "714": [0, 0.69444, 0, 0],
6542        "715": [0, 0.69444, 0, 0],
6543        "728": [0, 0.69444, 0, 0],
6544        "729": [0, 0.66786, 0, 0],
6545        "730": [0, 0.69444, 0, 0],
6546        "732": [0, 0.66786, 0, 0],
6547        "768": [0, 0.69444, 0, 0],
6548        "769": [0, 0.69444, 0, 0],
6549        "770": [0, 0.69444, 0, 0],
6550        "771": [0, 0.66786, 0, 0],
6551        "772": [0, 0.56778, 0, 0],
6552        "774": [0, 0.69444, 0, 0],
6553        "775": [0, 0.66786, 0, 0],
6554        "776": [0, 0.66786, 0, 0],
6555        "778": [0, 0.69444, 0, 0],
6556        "779": [0, 0.69444, 0, 0],
6557        "780": [0, 0.62847, 0, 0],
6558        "824": [0.19444, 0.69444, 0, 0],
6559        "915": [0, 0.68333, 0, 0],
6560        "916": [0, 0.68333, 0, 0],
6561        "920": [0, 0.68333, 0, 0],
6562        "923": [0, 0.68333, 0, 0],
6563        "926": [0, 0.68333, 0, 0],
6564        "928": [0, 0.68333, 0, 0],
6565        "931": [0, 0.68333, 0, 0],
6566        "933": [0, 0.68333, 0, 0],
6567        "934": [0, 0.68333, 0, 0],
6568        "936": [0, 0.68333, 0, 0],
6569        "937": [0, 0.68333, 0, 0],
6570        "8211": [0, 0.43056, 0.02778, 0],
6571        "8212": [0, 0.43056, 0.02778, 0],
6572        "8216": [0, 0.69444, 0, 0],
6573        "8217": [0, 0.69444, 0, 0],
6574        "8220": [0, 0.69444, 0, 0],
6575        "8221": [0, 0.69444, 0, 0],
6576        "8224": [0.19444, 0.69444, 0, 0],
6577        "8225": [0.19444, 0.69444, 0, 0],
6578        "8230": [0, 0.12, 0, 0],
6579        "8242": [0, 0.55556, 0, 0],
6580        "8407": [0, 0.71444, 0.15382, 0],
6581        "8463": [0, 0.68889, 0, 0],
6582        "8465": [0, 0.69444, 0, 0],
6583        "8467": [0, 0.69444, 0, 0.11111],
6584        "8472": [0.19444, 0.43056, 0, 0.11111],
6585        "8476": [0, 0.69444, 0, 0],
6586        "8501": [0, 0.69444, 0, 0],
6587        "8592": [-0.13313, 0.36687, 0, 0],
6588        "8593": [0.19444, 0.69444, 0, 0],
6589        "8594": [-0.13313, 0.36687, 0, 0],
6590        "8595": [0.19444, 0.69444, 0, 0],
6591        "8596": [-0.13313, 0.36687, 0, 0],
6592        "8597": [0.25, 0.75, 0, 0],
6593        "8598": [0.19444, 0.69444, 0, 0],
6594        "8599": [0.19444, 0.69444, 0, 0],
6595        "8600": [0.19444, 0.69444, 0, 0],
6596        "8601": [0.19444, 0.69444, 0, 0],
6597        "8614": [0.011, 0.511, 0, 0],
6598        "8617": [0.011, 0.511, 0, 0],
6599        "8618": [0.011, 0.511, 0, 0],
6600        "8636": [-0.13313, 0.36687, 0, 0],
6601        "8637": [-0.13313, 0.36687, 0, 0],
6602        "8640": [-0.13313, 0.36687, 0, 0],
6603        "8641": [-0.13313, 0.36687, 0, 0],
6604        "8652": [0.011, 0.671, 0, 0],
6605        "8656": [-0.13313, 0.36687, 0, 0],
6606        "8657": [0.19444, 0.69444, 0, 0],
6607        "8658": [-0.13313, 0.36687, 0, 0],
6608        "8659": [0.19444, 0.69444, 0, 0],
6609        "8660": [-0.13313, 0.36687, 0, 0],
6610        "8661": [0.25, 0.75, 0, 0],
6611        "8704": [0, 0.69444, 0, 0],
6612        "8706": [0, 0.69444, 0.05556, 0.08334],
6613        "8707": [0, 0.69444, 0, 0],
6614        "8709": [0.05556, 0.75, 0, 0],
6615        "8711": [0, 0.68333, 0, 0],
6616        "8712": [0.0391, 0.5391, 0, 0],
6617        "8715": [0.0391, 0.5391, 0, 0],
6618        "8722": [0.08333, 0.58333, 0, 0],
6619        "8723": [0.08333, 0.58333, 0, 0],
6620        "8725": [0.25, 0.75, 0, 0],
6621        "8726": [0.25, 0.75, 0, 0],
6622        "8727": [-0.03472, 0.46528, 0, 0],
6623        "8728": [-0.05555, 0.44445, 0, 0],
6624        "8729": [-0.05555, 0.44445, 0, 0],
6625        "8730": [0.2, 0.8, 0, 0],
6626        "8733": [0, 0.43056, 0, 0],
6627        "8734": [0, 0.43056, 0, 0],
6628        "8736": [0, 0.69224, 0, 0],
6629        "8739": [0.25, 0.75, 0, 0],
6630        "8741": [0.25, 0.75, 0, 0],
6631        "8743": [0, 0.55556, 0, 0],
6632        "8744": [0, 0.55556, 0, 0],
6633        "8745": [0, 0.55556, 0, 0],
6634        "8746": [0, 0.55556, 0, 0],
6635        "8747": [0.19444, 0.69444, 0.11111, 0],
6636        "8764": [-0.13313, 0.36687, 0, 0],
6637        "8768": [0.19444, 0.69444, 0, 0],
6638        "8771": [-0.03625, 0.46375, 0, 0],
6639        "8773": [-0.022, 0.589, 0, 0],
6640        "8776": [-0.01688, 0.48312, 0, 0],
6641        "8781": [-0.03625, 0.46375, 0, 0],
6642        "8784": [-0.133, 0.67, 0, 0],
6643        "8800": [0.215, 0.716, 0, 0],
6644        "8801": [-0.03625, 0.46375, 0, 0],
6645        "8804": [0.13597, 0.63597, 0, 0],
6646        "8805": [0.13597, 0.63597, 0, 0],
6647        "8810": [0.0391, 0.5391, 0, 0],
6648        "8811": [0.0391, 0.5391, 0, 0],
6649        "8826": [0.0391, 0.5391, 0, 0],
6650        "8827": [0.0391, 0.5391, 0, 0],
6651        "8834": [0.0391, 0.5391, 0, 0],
6652        "8835": [0.0391, 0.5391, 0, 0],
6653        "8838": [0.13597, 0.63597, 0, 0],
6654        "8839": [0.13597, 0.63597, 0, 0],
6655        "8846": [0, 0.55556, 0, 0],
6656        "8849": [0.13597, 0.63597, 0, 0],
6657        "8850": [0.13597, 0.63597, 0, 0],
6658        "8851": [0, 0.55556, 0, 0],
6659        "8852": [0, 0.55556, 0, 0],
6660        "8853": [0.08333, 0.58333, 0, 0],
6661        "8854": [0.08333, 0.58333, 0, 0],
6662        "8855": [0.08333, 0.58333, 0, 0],
6663        "8856": [0.08333, 0.58333, 0, 0],
6664        "8857": [0.08333, 0.58333, 0, 0],
6665        "8866": [0, 0.69444, 0, 0],
6666        "8867": [0, 0.69444, 0, 0],
6667        "8868": [0, 0.69444, 0, 0],
6668        "8869": [0, 0.69444, 0, 0],
6669        "8872": [0.249, 0.75, 0, 0],
6670        "8900": [-0.05555, 0.44445, 0, 0],
6671        "8901": [-0.05555, 0.44445, 0, 0],
6672        "8902": [-0.03472, 0.46528, 0, 0],
6673        "8904": [0.005, 0.505, 0, 0],
6674        "8942": [0.03, 0.9, 0, 0],
6675        "8943": [-0.19, 0.31, 0, 0],
6676        "8945": [-0.1, 0.82, 0, 0],
6677        "8968": [0.25, 0.75, 0, 0],
6678        "8969": [0.25, 0.75, 0, 0],
6679        "8970": [0.25, 0.75, 0, 0],
6680        "8971": [0.25, 0.75, 0, 0],
6681        "8994": [-0.14236, 0.35764, 0, 0],
6682        "8995": [-0.14236, 0.35764, 0, 0],
6683        "9136": [0.244, 0.744, 0, 0],
6684        "9137": [0.244, 0.744, 0, 0],
6685        "9651": [0.19444, 0.69444, 0, 0],
6686        "9657": [-0.03472, 0.46528, 0, 0],
6687        "9661": [0.19444, 0.69444, 0, 0],
6688        "9667": [-0.03472, 0.46528, 0, 0],
6689        "9711": [0.19444, 0.69444, 0, 0],
6690        "9824": [0.12963, 0.69444, 0, 0],
6691        "9825": [0.12963, 0.69444, 0, 0],
6692        "9826": [0.12963, 0.69444, 0, 0],
6693        "9827": [0.12963, 0.69444, 0, 0],
6694        "9837": [0, 0.75, 0, 0],
6695        "9838": [0.19444, 0.69444, 0, 0],
6696        "9839": [0.19444, 0.69444, 0, 0],
6697        "10216": [0.25, 0.75, 0, 0],
6698        "10217": [0.25, 0.75, 0, 0],
6699        "10222": [0.244, 0.744, 0, 0],
6700        "10223": [0.244, 0.744, 0, 0],
6701        "10229": [0.011, 0.511, 0, 0],
6702        "10230": [0.011, 0.511, 0, 0],
6703        "10231": [0.011, 0.511, 0, 0],
6704        "10232": [0.024, 0.525, 0, 0],
6705        "10233": [0.024, 0.525, 0, 0],
6706        "10234": [0.024, 0.525, 0, 0],
6707        "10236": [0.011, 0.511, 0, 0],
6708        "10815": [0, 0.68333, 0, 0],
6709        "10927": [0.13597, 0.63597, 0, 0],
6710        "10928": [0.13597, 0.63597, 0, 0]
6711    },
6712    "Math-BoldItalic": {
6713        "47": [0.19444, 0.69444, 0, 0],
6714        "65": [0, 0.68611, 0, 0],
6715        "66": [0, 0.68611, 0.04835, 0],
6716        "67": [0, 0.68611, 0.06979, 0],
6717        "68": [0, 0.68611, 0.03194, 0],
6718        "69": [0, 0.68611, 0.05451, 0],
6719        "70": [0, 0.68611, 0.15972, 0],
6720        "71": [0, 0.68611, 0, 0],
6721        "72": [0, 0.68611, 0.08229, 0],
6722        "73": [0, 0.68611, 0.07778, 0],
6723        "74": [0, 0.68611, 0.10069, 0],
6724        "75": [0, 0.68611, 0.06979, 0],
6725        "76": [0, 0.68611, 0, 0],
6726        "77": [0, 0.68611, 0.11424, 0],
6727        "78": [0, 0.68611, 0.11424, 0],
6728        "79": [0, 0.68611, 0.03194, 0],
6729        "80": [0, 0.68611, 0.15972, 0],
6730        "81": [0.19444, 0.68611, 0, 0],
6731        "82": [0, 0.68611, 0.00421, 0],
6732        "83": [0, 0.68611, 0.05382, 0],
6733        "84": [0, 0.68611, 0.15972, 0],
6734        "85": [0, 0.68611, 0.11424, 0],
6735        "86": [0, 0.68611, 0.25555, 0],
6736        "87": [0, 0.68611, 0.15972, 0],
6737        "88": [0, 0.68611, 0.07778, 0],
6738        "89": [0, 0.68611, 0.25555, 0],
6739        "90": [0, 0.68611, 0.06979, 0],
6740        "97": [0, 0.44444, 0, 0],
6741        "98": [0, 0.69444, 0, 0],
6742        "99": [0, 0.44444, 0, 0],
6743        "100": [0, 0.69444, 0, 0],
6744        "101": [0, 0.44444, 0, 0],
6745        "102": [0.19444, 0.69444, 0.11042, 0],
6746        "103": [0.19444, 0.44444, 0.03704, 0],
6747        "104": [0, 0.69444, 0, 0],
6748        "105": [0, 0.69326, 0, 0],
6749        "106": [0.19444, 0.69326, 0.0622, 0],
6750        "107": [0, 0.69444, 0.01852, 0],
6751        "108": [0, 0.69444, 0.0088, 0],
6752        "109": [0, 0.44444, 0, 0],
6753        "110": [0, 0.44444, 0, 0],
6754        "111": [0, 0.44444, 0, 0],
6755        "112": [0.19444, 0.44444, 0, 0],
6756        "113": [0.19444, 0.44444, 0.03704, 0],
6757        "114": [0, 0.44444, 0.03194, 0],
6758        "115": [0, 0.44444, 0, 0],
6759        "116": [0, 0.63492, 0, 0],
6760        "117": [0, 0.44444, 0, 0],
6761        "118": [0, 0.44444, 0.03704, 0],
6762        "119": [0, 0.44444, 0.02778, 0],
6763        "120": [0, 0.44444, 0, 0],
6764        "121": [0.19444, 0.44444, 0.03704, 0],
6765        "122": [0, 0.44444, 0.04213, 0],
6766        "915": [0, 0.68611, 0.15972, 0],
6767        "916": [0, 0.68611, 0, 0],
6768        "920": [0, 0.68611, 0.03194, 0],
6769        "923": [0, 0.68611, 0, 0],
6770        "926": [0, 0.68611, 0.07458, 0],
6771        "928": [0, 0.68611, 0.08229, 0],
6772        "931": [0, 0.68611, 0.05451, 0],
6773        "933": [0, 0.68611, 0.15972, 0],
6774        "934": [0, 0.68611, 0, 0],
6775        "936": [0, 0.68611, 0.11653, 0],
6776        "937": [0, 0.68611, 0.04835, 0],
6777        "945": [0, 0.44444, 0, 0],
6778        "946": [0.19444, 0.69444, 0.03403, 0],
6779        "947": [0.19444, 0.44444, 0.06389, 0],
6780        "948": [0, 0.69444, 0.03819, 0],
6781        "949": [0, 0.44444, 0, 0],
6782        "950": [0.19444, 0.69444, 0.06215, 0],
6783        "951": [0.19444, 0.44444, 0.03704, 0],
6784        "952": [0, 0.69444, 0.03194, 0],
6785        "953": [0, 0.44444, 0, 0],
6786        "954": [0, 0.44444, 0, 0],
6787        "955": [0, 0.69444, 0, 0],
6788        "956": [0.19444, 0.44444, 0, 0],
6789        "957": [0, 0.44444, 0.06898, 0],
6790        "958": [0.19444, 0.69444, 0.03021, 0],
6791        "959": [0, 0.44444, 0, 0],
6792        "960": [0, 0.44444, 0.03704, 0],
6793        "961": [0.19444, 0.44444, 0, 0],
6794        "962": [0.09722, 0.44444, 0.07917, 0],
6795        "963": [0, 0.44444, 0.03704, 0],
6796        "964": [0, 0.44444, 0.13472, 0],
6797        "965": [0, 0.44444, 0.03704, 0],
6798        "966": [0.19444, 0.44444, 0, 0],
6799        "967": [0.19444, 0.44444, 0, 0],
6800        "968": [0.19444, 0.69444, 0.03704, 0],
6801        "969": [0, 0.44444, 0.03704, 0],
6802        "977": [0, 0.69444, 0, 0],
6803        "981": [0.19444, 0.69444, 0, 0],
6804        "982": [0, 0.44444, 0.03194, 0],
6805        "1009": [0.19444, 0.44444, 0, 0],
6806        "1013": [0, 0.44444, 0, 0]
6807    },
6808    "Math-Italic": {
6809        "47": [0.19444, 0.69444, 0, 0],
6810        "65": [0, 0.68333, 0, 0.13889],
6811        "66": [0, 0.68333, 0.05017, 0.08334],
6812        "67": [0, 0.68333, 0.07153, 0.08334],
6813        "68": [0, 0.68333, 0.02778, 0.05556],
6814        "69": [0, 0.68333, 0.05764, 0.08334],
6815        "70": [0, 0.68333, 0.13889, 0.08334],
6816        "71": [0, 0.68333, 0, 0.08334],
6817        "72": [0, 0.68333, 0.08125, 0.05556],
6818        "73": [0, 0.68333, 0.07847, 0.11111],
6819        "74": [0, 0.68333, 0.09618, 0.16667],
6820        "75": [0, 0.68333, 0.07153, 0.05556],
6821        "76": [0, 0.68333, 0, 0.02778],
6822        "77": [0, 0.68333, 0.10903, 0.08334],
6823        "78": [0, 0.68333, 0.10903, 0.08334],
6824        "79": [0, 0.68333, 0.02778, 0.08334],
6825        "80": [0, 0.68333, 0.13889, 0.08334],
6826        "81": [0.19444, 0.68333, 0, 0.08334],
6827        "82": [0, 0.68333, 0.00773, 0.08334],
6828        "83": [0, 0.68333, 0.05764, 0.08334],
6829        "84": [0, 0.68333, 0.13889, 0.08334],
6830        "85": [0, 0.68333, 0.10903, 0.02778],
6831        "86": [0, 0.68333, 0.22222, 0],
6832        "87": [0, 0.68333, 0.13889, 0],
6833        "88": [0, 0.68333, 0.07847, 0.08334],
6834        "89": [0, 0.68333, 0.22222, 0],
6835        "90": [0, 0.68333, 0.07153, 0.08334],
6836        "97": [0, 0.43056, 0, 0],
6837        "98": [0, 0.69444, 0, 0],
6838        "99": [0, 0.43056, 0, 0.05556],
6839        "100": [0, 0.69444, 0, 0.16667],
6840        "101": [0, 0.43056, 0, 0.05556],
6841        "102": [0.19444, 0.69444, 0.10764, 0.16667],
6842        "103": [0.19444, 0.43056, 0.03588, 0.02778],
6843        "104": [0, 0.69444, 0, 0],
6844        "105": [0, 0.65952, 0, 0],
6845        "106": [0.19444, 0.65952, 0.05724, 0],
6846        "107": [0, 0.69444, 0.03148, 0],
6847        "108": [0, 0.69444, 0.01968, 0.08334],
6848        "109": [0, 0.43056, 0, 0],
6849        "110": [0, 0.43056, 0, 0],
6850        "111": [0, 0.43056, 0, 0.05556],
6851        "112": [0.19444, 0.43056, 0, 0.08334],
6852        "113": [0.19444, 0.43056, 0.03588, 0.08334],
6853        "114": [0, 0.43056, 0.02778, 0.05556],
6854        "115": [0, 0.43056, 0, 0.05556],
6855        "116": [0, 0.61508, 0, 0.08334],
6856        "117": [0, 0.43056, 0, 0.02778],
6857        "118": [0, 0.43056, 0.03588, 0.02778],
6858        "119": [0, 0.43056, 0.02691, 0.08334],
6859        "120": [0, 0.43056, 0, 0.02778],
6860        "121": [0.19444, 0.43056, 0.03588, 0.05556],
6861        "122": [0, 0.43056, 0.04398, 0.05556],
6862        "915": [0, 0.68333, 0.13889, 0.08334],
6863        "916": [0, 0.68333, 0, 0.16667],
6864        "920": [0, 0.68333, 0.02778, 0.08334],
6865        "923": [0, 0.68333, 0, 0.16667],
6866        "926": [0, 0.68333, 0.07569, 0.08334],
6867        "928": [0, 0.68333, 0.08125, 0.05556],
6868        "931": [0, 0.68333, 0.05764, 0.08334],
6869        "933": [0, 0.68333, 0.13889, 0.05556],
6870        "934": [0, 0.68333, 0, 0.08334],
6871        "936": [0, 0.68333, 0.11, 0.05556],
6872        "937": [0, 0.68333, 0.05017, 0.08334],
6873        "945": [0, 0.43056, 0.0037, 0.02778],
6874        "946": [0.19444, 0.69444, 0.05278, 0.08334],
6875        "947": [0.19444, 0.43056, 0.05556, 0],
6876        "948": [0, 0.69444, 0.03785, 0.05556],
6877        "949": [0, 0.43056, 0, 0.08334],
6878        "950": [0.19444, 0.69444, 0.07378, 0.08334],
6879        "951": [0.19444, 0.43056, 0.03588, 0.05556],
6880        "952": [0, 0.69444, 0.02778, 0.08334],
6881        "953": [0, 0.43056, 0, 0.05556],
6882        "954": [0, 0.43056, 0, 0],
6883        "955": [0, 0.69444, 0, 0],
6884        "956": [0.19444, 0.43056, 0, 0.02778],
6885        "957": [0, 0.43056, 0.06366, 0.02778],
6886        "958": [0.19444, 0.69444, 0.04601, 0.11111],
6887        "959": [0, 0.43056, 0, 0.05556],
6888        "960": [0, 0.43056, 0.03588, 0],
6889        "961": [0.19444, 0.43056, 0, 0.08334],
6890        "962": [0.09722, 0.43056, 0.07986, 0.08334],
6891        "963": [0, 0.43056, 0.03588, 0],
6892        "964": [0, 0.43056, 0.1132, 0.02778],
6893        "965": [0, 0.43056, 0.03588, 0.02778],
6894        "966": [0.19444, 0.43056, 0, 0.08334],
6895        "967": [0.19444, 0.43056, 0, 0.05556],
6896        "968": [0.19444, 0.69444, 0.03588, 0.11111],
6897        "969": [0, 0.43056, 0.03588, 0],
6898        "977": [0, 0.69444, 0, 0.08334],
6899        "981": [0.19444, 0.69444, 0, 0.08334],
6900        "982": [0, 0.43056, 0.02778, 0],
6901        "1009": [0.19444, 0.43056, 0, 0.08334],
6902        "1013": [0, 0.43056, 0, 0.05556]
6903    },
6904    "Math-Regular": {
6905        "65": [0, 0.68333, 0, 0.13889],
6906        "66": [0, 0.68333, 0.05017, 0.08334],
6907        "67": [0, 0.68333, 0.07153, 0.08334],
6908        "68": [0, 0.68333, 0.02778, 0.05556],
6909        "69": [0, 0.68333, 0.05764, 0.08334],
6910        "70": [0, 0.68333, 0.13889, 0.08334],
6911        "71": [0, 0.68333, 0, 0.08334],
6912        "72": [0, 0.68333, 0.08125, 0.05556],
6913        "73": [0, 0.68333, 0.07847, 0.11111],
6914        "74": [0, 0.68333, 0.09618, 0.16667],
6915        "75": [0, 0.68333, 0.07153, 0.05556],
6916        "76": [0, 0.68333, 0, 0.02778],
6917        "77": [0, 0.68333, 0.10903, 0.08334],
6918        "78": [0, 0.68333, 0.10903, 0.08334],
6919        "79": [0, 0.68333, 0.02778, 0.08334],
6920        "80": [0, 0.68333, 0.13889, 0.08334],
6921        "81": [0.19444, 0.68333, 0, 0.08334],
6922        "82": [0, 0.68333, 0.00773, 0.08334],
6923        "83": [0, 0.68333, 0.05764, 0.08334],
6924        "84": [0, 0.68333, 0.13889, 0.08334],
6925        "85": [0, 0.68333, 0.10903, 0.02778],
6926        "86": [0, 0.68333, 0.22222, 0],
6927        "87": [0, 0.68333, 0.13889, 0],
6928        "88": [0, 0.68333, 0.07847, 0.08334],
6929        "89": [0, 0.68333, 0.22222, 0],
6930        "90": [0, 0.68333, 0.07153, 0.08334],
6931        "97": [0, 0.43056, 0, 0],
6932        "98": [0, 0.69444, 0, 0],
6933        "99": [0, 0.43056, 0, 0.05556],
6934        "100": [0, 0.69444, 0, 0.16667],
6935        "101": [0, 0.43056, 0, 0.05556],
6936        "102": [0.19444, 0.69444, 0.10764, 0.16667],
6937        "103": [0.19444, 0.43056, 0.03588, 0.02778],
6938        "104": [0, 0.69444, 0, 0],
6939        "105": [0, 0.65952, 0, 0],
6940        "106": [0.19444, 0.65952, 0.05724, 0],
6941        "107": [0, 0.69444, 0.03148, 0],
6942        "108": [0, 0.69444, 0.01968, 0.08334],
6943        "109": [0, 0.43056, 0, 0],
6944        "110": [0, 0.43056, 0, 0],
6945        "111": [0, 0.43056, 0, 0.05556],
6946        "112": [0.19444, 0.43056, 0, 0.08334],
6947        "113": [0.19444, 0.43056, 0.03588, 0.08334],
6948        "114": [0, 0.43056, 0.02778, 0.05556],
6949        "115": [0, 0.43056, 0, 0.05556],
6950        "116": [0, 0.61508, 0, 0.08334],
6951        "117": [0, 0.43056, 0, 0.02778],
6952        "118": [0, 0.43056, 0.03588, 0.02778],
6953        "119": [0, 0.43056, 0.02691, 0.08334],
6954        "120": [0, 0.43056, 0, 0.02778],
6955        "121": [0.19444, 0.43056, 0.03588, 0.05556],
6956        "122": [0, 0.43056, 0.04398, 0.05556],
6957        "915": [0, 0.68333, 0.13889, 0.08334],
6958        "916": [0, 0.68333, 0, 0.16667],
6959        "920": [0, 0.68333, 0.02778, 0.08334],
6960        "923": [0, 0.68333, 0, 0.16667],
6961        "926": [0, 0.68333, 0.07569, 0.08334],
6962        "928": [0, 0.68333, 0.08125, 0.05556],
6963        "931": [0, 0.68333, 0.05764, 0.08334],
6964        "933": [0, 0.68333, 0.13889, 0.05556],
6965        "934": [0, 0.68333, 0, 0.08334],
6966        "936": [0, 0.68333, 0.11, 0.05556],
6967        "937": [0, 0.68333, 0.05017, 0.08334],
6968        "945": [0, 0.43056, 0.0037, 0.02778],
6969        "946": [0.19444, 0.69444, 0.05278, 0.08334],
6970        "947": [0.19444, 0.43056, 0.05556, 0],
6971        "948": [0, 0.69444, 0.03785, 0.05556],
6972        "949": [0, 0.43056, 0, 0.08334],
6973        "950": [0.19444, 0.69444, 0.07378, 0.08334],
6974        "951": [0.19444, 0.43056, 0.03588, 0.05556],
6975        "952": [0, 0.69444, 0.02778, 0.08334],
6976        "953": [0, 0.43056, 0, 0.05556],
6977        "954": [0, 0.43056, 0, 0],
6978        "955": [0, 0.69444, 0, 0],
6979        "956": [0.19444, 0.43056, 0, 0.02778],
6980        "957": [0, 0.43056, 0.06366, 0.02778],
6981        "958": [0.19444, 0.69444, 0.04601, 0.11111],
6982        "959": [0, 0.43056, 0, 0.05556],
6983        "960": [0, 0.43056, 0.03588, 0],
6984        "961": [0.19444, 0.43056, 0, 0.08334],
6985        "962": [0.09722, 0.43056, 0.07986, 0.08334],
6986        "963": [0, 0.43056, 0.03588, 0],
6987        "964": [0, 0.43056, 0.1132, 0.02778],
6988        "965": [0, 0.43056, 0.03588, 0.02778],
6989        "966": [0.19444, 0.43056, 0, 0.08334],
6990        "967": [0.19444, 0.43056, 0, 0.05556],
6991        "968": [0.19444, 0.69444, 0.03588, 0.11111],
6992        "969": [0, 0.43056, 0.03588, 0],
6993        "977": [0, 0.69444, 0, 0.08334],
6994        "981": [0.19444, 0.69444, 0, 0.08334],
6995        "982": [0, 0.43056, 0.02778, 0],
6996        "1009": [0.19444, 0.43056, 0, 0.08334],
6997        "1013": [0, 0.43056, 0, 0.05556]
6998    },
6999    "SansSerif-Regular": {
7000        "33": [0, 0.69444, 0, 0],
7001        "34": [0, 0.69444, 0, 0],
7002        "35": [0.19444, 0.69444, 0, 0],
7003        "36": [0.05556, 0.75, 0, 0],
7004        "37": [0.05556, 0.75, 0, 0],
7005        "38": [0, 0.69444, 0, 0],
7006        "39": [0, 0.69444, 0, 0],
7007        "40": [0.25, 0.75, 0, 0],
7008        "41": [0.25, 0.75, 0, 0],
7009        "42": [0, 0.75, 0, 0],
7010        "43": [0.08333, 0.58333, 0, 0],
7011        "44": [0.125, 0.08333, 0, 0],
7012        "45": [0, 0.44444, 0, 0],
7013        "46": [0, 0.08333, 0, 0],
7014        "47": [0.25, 0.75, 0, 0],
7015        "48": [0, 0.65556, 0, 0],
7016        "49": [0, 0.65556, 0, 0],
7017        "50": [0, 0.65556, 0, 0],
7018        "51": [0, 0.65556, 0, 0],
7019        "52": [0, 0.65556, 0, 0],
7020        "53": [0, 0.65556, 0, 0],
7021        "54": [0, 0.65556, 0, 0],
7022        "55": [0, 0.65556, 0, 0],
7023        "56": [0, 0.65556, 0, 0],
7024        "57": [0, 0.65556, 0, 0],
7025        "58": [0, 0.44444, 0, 0],
7026        "59": [0.125, 0.44444, 0, 0],
7027        "61": [-0.13, 0.37, 0, 0],
7028        "63": [0, 0.69444, 0, 0],
7029        "64": [0, 0.69444, 0, 0],
7030        "65": [0, 0.69444, 0, 0],
7031        "66": [0, 0.69444, 0, 0],
7032        "67": [0, 0.69444, 0, 0],
7033        "68": [0, 0.69444, 0, 0],
7034        "69": [0, 0.69444, 0, 0],
7035        "70": [0, 0.69444, 0, 0],
7036        "71": [0, 0.69444, 0, 0],
7037        "72": [0, 0.69444, 0, 0],
7038        "73": [0, 0.69444, 0, 0],
7039        "74": [0, 0.69444, 0, 0],
7040        "75": [0, 0.69444, 0, 0],
7041        "76": [0, 0.69444, 0, 0],
7042        "77": [0, 0.69444, 0, 0],
7043        "78": [0, 0.69444, 0, 0],
7044        "79": [0, 0.69444, 0, 0],
7045        "80": [0, 0.69444, 0, 0],
7046        "81": [0.125, 0.69444, 0, 0],
7047        "82": [0, 0.69444, 0, 0],
7048        "83": [0, 0.69444, 0, 0],
7049        "84": [0, 0.69444, 0, 0],
7050        "85": [0, 0.69444, 0, 0],
7051        "86": [0, 0.69444, 0.01389, 0],
7052        "87": [0, 0.69444, 0.01389, 0],
7053        "88": [0, 0.69444, 0, 0],
7054        "89": [0, 0.69444, 0.025, 0],
7055        "90": [0, 0.69444, 0, 0],
7056        "91": [0.25, 0.75, 0, 0],
7057        "93": [0.25, 0.75, 0, 0],
7058        "94": [0, 0.69444, 0, 0],
7059        "95": [0.35, 0.09444, 0.02778, 0],
7060        "97": [0, 0.44444, 0, 0],
7061        "98": [0, 0.69444, 0, 0],
7062        "99": [0, 0.44444, 0, 0],
7063        "100": [0, 0.69444, 0, 0],
7064        "101": [0, 0.44444, 0, 0],
7065        "102": [0, 0.69444, 0.06944, 0],
7066        "103": [0.19444, 0.44444, 0.01389, 0],
7067        "104": [0, 0.69444, 0, 0],
7068        "105": [0, 0.67937, 0, 0],
7069        "106": [0.19444, 0.67937, 0, 0],
7070        "107": [0, 0.69444, 0, 0],
7071        "108": [0, 0.69444, 0, 0],
7072        "109": [0, 0.44444, 0, 0],
7073        "110": [0, 0.44444, 0, 0],
7074        "111": [0, 0.44444, 0, 0],
7075        "112": [0.19444, 0.44444, 0, 0],
7076        "113": [0.19444, 0.44444, 0, 0],
7077        "114": [0, 0.44444, 0.01389, 0],
7078        "115": [0, 0.44444, 0, 0],
7079        "116": [0, 0.57143, 0, 0],
7080        "117": [0, 0.44444, 0, 0],
7081        "118": [0, 0.44444, 0.01389, 0],
7082        "119": [0, 0.44444, 0.01389, 0],
7083        "120": [0, 0.44444, 0, 0],
7084        "121": [0.19444, 0.44444, 0.01389, 0],
7085        "122": [0, 0.44444, 0, 0],
7086        "126": [0.35, 0.32659, 0, 0],
7087        "305": [0, 0.44444, 0, 0],
7088        "567": [0.19444, 0.44444, 0, 0],
7089        "768": [0, 0.69444, 0, 0],
7090        "769": [0, 0.69444, 0, 0],
7091        "770": [0, 0.69444, 0, 0],
7092        "771": [0, 0.67659, 0, 0],
7093        "772": [0, 0.60889, 0, 0],
7094        "774": [0, 0.69444, 0, 0],
7095        "775": [0, 0.67937, 0, 0],
7096        "776": [0, 0.67937, 0, 0],
7097        "778": [0, 0.69444, 0, 0],
7098        "779": [0, 0.69444, 0, 0],
7099        "780": [0, 0.63194, 0, 0],
7100        "915": [0, 0.69444, 0, 0],
7101        "916": [0, 0.69444, 0, 0],
7102        "920": [0, 0.69444, 0, 0],
7103        "923": [0, 0.69444, 0, 0],
7104        "926": [0, 0.69444, 0, 0],
7105        "928": [0, 0.69444, 0, 0],
7106        "931": [0, 0.69444, 0, 0],
7107        "933": [0, 0.69444, 0, 0],
7108        "934": [0, 0.69444, 0, 0],
7109        "936": [0, 0.69444, 0, 0],
7110        "937": [0, 0.69444, 0, 0],
7111        "8211": [0, 0.44444, 0.02778, 0],
7112        "8212": [0, 0.44444, 0.02778, 0],
7113        "8216": [0, 0.69444, 0, 0],
7114        "8217": [0, 0.69444, 0, 0],
7115        "8220": [0, 0.69444, 0, 0],
7116        "8221": [0, 0.69444, 0, 0]
7117    },
7118    "Script-Regular": {
7119        "65": [0, 0.7, 0.22925, 0],
7120        "66": [0, 0.7, 0.04087, 0],
7121        "67": [0, 0.7, 0.1689, 0],
7122        "68": [0, 0.7, 0.09371, 0],
7123        "69": [0, 0.7, 0.18583, 0],
7124        "70": [0, 0.7, 0.13634, 0],
7125        "71": [0, 0.7, 0.17322, 0],
7126        "72": [0, 0.7, 0.29694, 0],
7127        "73": [0, 0.7, 0.19189, 0],
7128        "74": [0.27778, 0.7, 0.19189, 0],
7129        "75": [0, 0.7, 0.31259, 0],
7130        "76": [0, 0.7, 0.19189, 0],
7131        "77": [0, 0.7, 0.15981, 0],
7132        "78": [0, 0.7, 0.3525, 0],
7133        "79": [0, 0.7, 0.08078, 0],
7134        "80": [0, 0.7, 0.08078, 0],
7135        "81": [0, 0.7, 0.03305, 0],
7136        "82": [0, 0.7, 0.06259, 0],
7137        "83": [0, 0.7, 0.19189, 0],
7138        "84": [0, 0.7, 0.29087, 0],
7139        "85": [0, 0.7, 0.25815, 0],
7140        "86": [0, 0.7, 0.27523, 0],
7141        "87": [0, 0.7, 0.27523, 0],
7142        "88": [0, 0.7, 0.26006, 0],
7143        "89": [0, 0.7, 0.2939, 0],
7144        "90": [0, 0.7, 0.24037, 0]
7145    },
7146    "Size1-Regular": {
7147        "40": [0.35001, 0.85, 0, 0],
7148        "41": [0.35001, 0.85, 0, 0],
7149        "47": [0.35001, 0.85, 0, 0],
7150        "91": [0.35001, 0.85, 0, 0],
7151        "92": [0.35001, 0.85, 0, 0],
7152        "93": [0.35001, 0.85, 0, 0],
7153        "123": [0.35001, 0.85, 0, 0],
7154        "125": [0.35001, 0.85, 0, 0],
7155        "710": [0, 0.72222, 0, 0],
7156        "732": [0, 0.72222, 0, 0],
7157        "770": [0, 0.72222, 0, 0],
7158        "771": [0, 0.72222, 0, 0],
7159        "8214": [-0.00099, 0.601, 0, 0],
7160        "8593": [1e-05, 0.6, 0, 0],
7161        "8595": [1e-05, 0.6, 0, 0],
7162        "8657": [1e-05, 0.6, 0, 0],
7163        "8659": [1e-05, 0.6, 0, 0],
7164        "8719": [0.25001, 0.75, 0, 0],
7165        "8720": [0.25001, 0.75, 0, 0],
7166        "8721": [0.25001, 0.75, 0, 0],
7167        "8730": [0.35001, 0.85, 0, 0],
7168        "8739": [-0.00599, 0.606, 0, 0],
7169        "8741": [-0.00599, 0.606, 0, 0],
7170        "8747": [0.30612, 0.805, 0.19445, 0],
7171        "8748": [0.306, 0.805, 0.19445, 0],
7172        "8749": [0.306, 0.805, 0.19445, 0],
7173        "8750": [0.30612, 0.805, 0.19445, 0],
7174        "8896": [0.25001, 0.75, 0, 0],
7175        "8897": [0.25001, 0.75, 0, 0],
7176        "8898": [0.25001, 0.75, 0, 0],
7177        "8899": [0.25001, 0.75, 0, 0],
7178        "8968": [0.35001, 0.85, 0, 0],
7179        "8969": [0.35001, 0.85, 0, 0],
7180        "8970": [0.35001, 0.85, 0, 0],
7181        "8971": [0.35001, 0.85, 0, 0],
7182        "9168": [-0.00099, 0.601, 0, 0],
7183        "10216": [0.35001, 0.85, 0, 0],
7184        "10217": [0.35001, 0.85, 0, 0],
7185        "10752": [0.25001, 0.75, 0, 0],
7186        "10753": [0.25001, 0.75, 0, 0],
7187        "10754": [0.25001, 0.75, 0, 0],
7188        "10756": [0.25001, 0.75, 0, 0],
7189        "10758": [0.25001, 0.75, 0, 0]
7190    },
7191    "Size2-Regular": {
7192        "40": [0.65002, 1.15, 0, 0],
7193        "41": [0.65002, 1.15, 0, 0],
7194        "47": [0.65002, 1.15, 0, 0],
7195        "91": [0.65002, 1.15, 0, 0],
7196        "92": [0.65002, 1.15, 0, 0],
7197        "93": [0.65002, 1.15, 0, 0],
7198        "123": [0.65002, 1.15, 0, 0],
7199        "125": [0.65002, 1.15, 0, 0],
7200        "710": [0, 0.75, 0, 0],
7201        "732": [0, 0.75, 0, 0],
7202        "770": [0, 0.75, 0, 0],
7203        "771": [0, 0.75, 0, 0],
7204        "8719": [0.55001, 1.05, 0, 0],
7205        "8720": [0.55001, 1.05, 0, 0],
7206        "8721": [0.55001, 1.05, 0, 0],
7207        "8730": [0.65002, 1.15, 0, 0],
7208        "8747": [0.86225, 1.36, 0.44445, 0],
7209        "8748": [0.862, 1.36, 0.44445, 0],
7210        "8749": [0.862, 1.36, 0.44445, 0],
7211        "8750": [0.86225, 1.36, 0.44445, 0],
7212        "8896": [0.55001, 1.05, 0, 0],
7213        "8897": [0.55001, 1.05, 0, 0],
7214        "8898": [0.55001, 1.05, 0, 0],
7215        "8899": [0.55001, 1.05, 0, 0],
7216        "8968": [0.65002, 1.15, 0, 0],
7217        "8969": [0.65002, 1.15, 0, 0],
7218        "8970": [0.65002, 1.15, 0, 0],
7219        "8971": [0.65002, 1.15, 0, 0],
7220        "10216": [0.65002, 1.15, 0, 0],
7221        "10217": [0.65002, 1.15, 0, 0],
7222        "10752": [0.55001, 1.05, 0, 0],
7223        "10753": [0.55001, 1.05, 0, 0],
7224        "10754": [0.55001, 1.05, 0, 0],
7225        "10756": [0.55001, 1.05, 0, 0],
7226        "10758": [0.55001, 1.05, 0, 0]
7227    },
7228    "Size3-Regular": {
7229        "40": [0.95003, 1.45, 0, 0],
7230        "41": [0.95003, 1.45, 0, 0],
7231        "47": [0.95003, 1.45, 0, 0],
7232        "91": [0.95003, 1.45, 0, 0],
7233        "92": [0.95003, 1.45, 0, 0],
7234        "93": [0.95003, 1.45, 0, 0],
7235        "123": [0.95003, 1.45, 0, 0],
7236        "125": [0.95003, 1.45, 0, 0],
7237        "710": [0, 0.75, 0, 0],
7238        "732": [0, 0.75, 0, 0],
7239        "770": [0, 0.75, 0, 0],
7240        "771": [0, 0.75, 0, 0],
7241        "8730": [0.95003, 1.45, 0, 0],
7242        "8968": [0.95003, 1.45, 0, 0],
7243        "8969": [0.95003, 1.45, 0, 0],
7244        "8970": [0.95003, 1.45, 0, 0],
7245        "8971": [0.95003, 1.45, 0, 0],
7246        "10216": [0.95003, 1.45, 0, 0],
7247        "10217": [0.95003, 1.45, 0, 0]
7248    },
7249    "Size4-Regular": {
7250        "40": [1.25003, 1.75, 0, 0],
7251        "41": [1.25003, 1.75, 0, 0],
7252        "47": [1.25003, 1.75, 0, 0],
7253        "91": [1.25003, 1.75, 0, 0],
7254        "92": [1.25003, 1.75, 0, 0],
7255        "93": [1.25003, 1.75, 0, 0],
7256        "123": [1.25003, 1.75, 0, 0],
7257        "125": [1.25003, 1.75, 0, 0],
7258        "710": [0, 0.825, 0, 0],
7259        "732": [0, 0.825, 0, 0],
7260        "770": [0, 0.825, 0, 0],
7261        "771": [0, 0.825, 0, 0],
7262        "8730": [1.25003, 1.75, 0, 0],
7263        "8968": [1.25003, 1.75, 0, 0],
7264        "8969": [1.25003, 1.75, 0, 0],
7265        "8970": [1.25003, 1.75, 0, 0],
7266        "8971": [1.25003, 1.75, 0, 0],
7267        "9115": [0.64502, 1.155, 0, 0],
7268        "9116": [1e-05, 0.6, 0, 0],
7269        "9117": [0.64502, 1.155, 0, 0],
7270        "9118": [0.64502, 1.155, 0, 0],
7271        "9119": [1e-05, 0.6, 0, 0],
7272        "9120": [0.64502, 1.155, 0, 0],
7273        "9121": [0.64502, 1.155, 0, 0],
7274        "9122": [-0.00099, 0.601, 0, 0],
7275        "9123": [0.64502, 1.155, 0, 0],
7276        "9124": [0.64502, 1.155, 0, 0],
7277        "9125": [-0.00099, 0.601, 0, 0],
7278        "9126": [0.64502, 1.155, 0, 0],
7279        "9127": [1e-05, 0.9, 0, 0],
7280        "9128": [0.65002, 1.15, 0, 0],
7281        "9129": [0.90001, 0, 0, 0],
7282        "9130": [0, 0.3, 0, 0],
7283        "9131": [1e-05, 0.9, 0, 0],
7284        "9132": [0.65002, 1.15, 0, 0],
7285        "9133": [0.90001, 0, 0, 0],
7286        "9143": [0.88502, 0.915, 0, 0],
7287        "10216": [1.25003, 1.75, 0, 0],
7288        "10217": [1.25003, 1.75, 0, 0],
7289        "57344": [-0.00499, 0.605, 0, 0],
7290        "57345": [-0.00499, 0.605, 0, 0],
7291        "57680": [0, 0.12, 0, 0],
7292        "57681": [0, 0.12, 0, 0],
7293        "57682": [0, 0.12, 0, 0],
7294        "57683": [0, 0.12, 0, 0]
7295    },
7296    "Typewriter-Regular": {
7297        "33": [0, 0.61111, 0, 0],
7298        "34": [0, 0.61111, 0, 0],
7299        "35": [0, 0.61111, 0, 0],
7300        "36": [0.08333, 0.69444, 0, 0],
7301        "37": [0.08333, 0.69444, 0, 0],
7302        "38": [0, 0.61111, 0, 0],
7303        "39": [0, 0.61111, 0, 0],
7304        "40": [0.08333, 0.69444, 0, 0],
7305        "41": [0.08333, 0.69444, 0, 0],
7306        "42": [0, 0.52083, 0, 0],
7307        "43": [-0.08056, 0.53055, 0, 0],
7308        "44": [0.13889, 0.125, 0, 0],
7309        "45": [-0.08056, 0.53055, 0, 0],
7310        "46": [0, 0.125, 0, 0],
7311        "47": [0.08333, 0.69444, 0, 0],
7312        "48": [0, 0.61111, 0, 0],
7313        "49": [0, 0.61111, 0, 0],
7314        "50": [0, 0.61111, 0, 0],
7315        "51": [0, 0.61111, 0, 0],
7316        "52": [0, 0.61111, 0, 0],
7317        "53": [0, 0.61111, 0, 0],
7318        "54": [0, 0.61111, 0, 0],
7319        "55": [0, 0.61111, 0, 0],
7320        "56": [0, 0.61111, 0, 0],
7321        "57": [0, 0.61111, 0, 0],
7322        "58": [0, 0.43056, 0, 0],
7323        "59": [0.13889, 0.43056, 0, 0],
7324        "60": [-0.05556, 0.55556, 0, 0],
7325        "61": [-0.19549, 0.41562, 0, 0],
7326        "62": [-0.05556, 0.55556, 0, 0],
7327        "63": [0, 0.61111, 0, 0],
7328        "64": [0, 0.61111, 0, 0],
7329        "65": [0, 0.61111, 0, 0],
7330        "66": [0, 0.61111, 0, 0],
7331        "67": [0, 0.61111, 0, 0],
7332        "68": [0, 0.61111, 0, 0],
7333        "69": [0, 0.61111, 0, 0],
7334        "70": [0, 0.61111, 0, 0],
7335        "71": [0, 0.61111, 0, 0],
7336        "72": [0, 0.61111, 0, 0],
7337        "73": [0, 0.61111, 0, 0],
7338        "74": [0, 0.61111, 0, 0],
7339        "75": [0, 0.61111, 0, 0],
7340        "76": [0, 0.61111, 0, 0],
7341        "77": [0, 0.61111, 0, 0],
7342        "78": [0, 0.61111, 0, 0],
7343        "79": [0, 0.61111, 0, 0],
7344        "80": [0, 0.61111, 0, 0],
7345        "81": [0.13889, 0.61111, 0, 0],
7346        "82": [0, 0.61111, 0, 0],
7347        "83": [0, 0.61111, 0, 0],
7348        "84": [0, 0.61111, 0, 0],
7349        "85": [0, 0.61111, 0, 0],
7350        "86": [0, 0.61111, 0, 0],
7351        "87": [0, 0.61111, 0, 0],
7352        "88": [0, 0.61111, 0, 0],
7353        "89": [0, 0.61111, 0, 0],
7354        "90": [0, 0.61111, 0, 0],
7355        "91": [0.08333, 0.69444, 0, 0],
7356        "92": [0.08333, 0.69444, 0, 0],
7357        "93": [0.08333, 0.69444, 0, 0],
7358        "94": [0, 0.61111, 0, 0],
7359        "95": [0.09514, 0, 0, 0],
7360        "96": [0, 0.61111, 0, 0],
7361        "97": [0, 0.43056, 0, 0],
7362        "98": [0, 0.61111, 0, 0],
7363        "99": [0, 0.43056, 0, 0],
7364        "100": [0, 0.61111, 0, 0],
7365        "101": [0, 0.43056, 0, 0],
7366        "102": [0, 0.61111, 0, 0],
7367        "103": [0.22222, 0.43056, 0, 0],
7368        "104": [0, 0.61111, 0, 0],
7369        "105": [0, 0.61111, 0, 0],
7370        "106": [0.22222, 0.61111, 0, 0],
7371        "107": [0, 0.61111, 0, 0],
7372        "108": [0, 0.61111, 0, 0],
7373        "109": [0, 0.43056, 0, 0],
7374        "110": [0, 0.43056, 0, 0],
7375        "111": [0, 0.43056, 0, 0],
7376        "112": [0.22222, 0.43056, 0, 0],
7377        "113": [0.22222, 0.43056, 0, 0],
7378        "114": [0, 0.43056, 0, 0],
7379        "115": [0, 0.43056, 0, 0],
7380        "116": [0, 0.55358, 0, 0],
7381        "117": [0, 0.43056, 0, 0],
7382        "118": [0, 0.43056, 0, 0],
7383        "119": [0, 0.43056, 0, 0],
7384        "120": [0, 0.43056, 0, 0],
7385        "121": [0.22222, 0.43056, 0, 0],
7386        "122": [0, 0.43056, 0, 0],
7387        "123": [0.08333, 0.69444, 0, 0],
7388        "124": [0.08333, 0.69444, 0, 0],
7389        "125": [0.08333, 0.69444, 0, 0],
7390        "126": [0, 0.61111, 0, 0],
7391        "127": [0, 0.61111, 0, 0],
7392        "305": [0, 0.43056, 0, 0],
7393        "567": [0.22222, 0.43056, 0, 0],
7394        "768": [0, 0.61111, 0, 0],
7395        "769": [0, 0.61111, 0, 0],
7396        "770": [0, 0.61111, 0, 0],
7397        "771": [0, 0.61111, 0, 0],
7398        "772": [0, 0.56555, 0, 0],
7399        "774": [0, 0.61111, 0, 0],
7400        "776": [0, 0.61111, 0, 0],
7401        "778": [0, 0.61111, 0, 0],
7402        "780": [0, 0.56597, 0, 0],
7403        "915": [0, 0.61111, 0, 0],
7404        "916": [0, 0.61111, 0, 0],
7405        "920": [0, 0.61111, 0, 0],
7406        "923": [0, 0.61111, 0, 0],
7407        "926": [0, 0.61111, 0, 0],
7408        "928": [0, 0.61111, 0, 0],
7409        "931": [0, 0.61111, 0, 0],
7410        "933": [0, 0.61111, 0, 0],
7411        "934": [0, 0.61111, 0, 0],
7412        "936": [0, 0.61111, 0, 0],
7413        "937": [0, 0.61111, 0, 0],
7414        "2018": [0, 0.61111, 0, 0],
7415        "2019": [0, 0.61111, 0, 0],
7416        "8242": [0, 0.61111, 0, 0]
7417    }
7418};
7419
7420},{}],19:[function(require,module,exports){
7421var utils = require("./utils");
7422var ParseError = require("./ParseError");
7423var parseData = require("./parseData");
7424var ParseNode = parseData.ParseNode;
7425
7426/* This file contains a list of functions that we parse, identified by
7427 * the calls to defineFunction.
7428 *
7429 * The first argument to defineFunction is a single name or a list of names.
7430 * All functions named in such a list will share a single implementation.
7431 *
7432 * Each declared function can have associated properties, which
7433 * include the following:
7434 *
7435 *  - numArgs: The number of arguments the function takes.
7436 *             If this is the only property, it can be passed as a number
7437 *             instead of an element of a properties object.
7438 *  - argTypes: (optional) An array corresponding to each argument of the
7439 *              function, giving the type of argument that should be parsed. Its
7440 *              length should be equal to `numArgs + numOptionalArgs`. Valid
7441 *              types:
7442 *               - "size": A size-like thing, such as "1em" or "5ex"
7443 *               - "color": An html color, like "#abc" or "blue"
7444 *               - "original": The same type as the environment that the
7445 *                             function being parsed is in (e.g. used for the
7446 *                             bodies of functions like \color where the first
7447 *                             argument is special and the second argument is
7448 *                             parsed normally)
7449 *              Other possible types (probably shouldn't be used)
7450 *               - "text": Text-like (e.g. \text)
7451 *               - "math": Normal math
7452 *              If undefined, this will be treated as an appropriate length
7453 *              array of "original" strings
7454 *  - greediness: (optional) The greediness of the function to use ungrouped
7455 *                arguments.
7456 *
7457 *                E.g. if you have an expression
7458 *                  \sqrt \frac 1 2
7459 *                since \frac has greediness=2 vs \sqrt's greediness=1, \frac
7460 *                will use the two arguments '1' and '2' as its two arguments,
7461 *                then that whole function will be used as the argument to
7462 *                \sqrt. On the other hand, the expressions
7463 *                  \frac \frac 1 2 3
7464 *                and
7465 *                  \frac \sqrt 1 2
7466 *                will fail because \frac and \frac have equal greediness
7467 *                and \sqrt has a lower greediness than \frac respectively. To
7468 *                make these parse, we would have to change them to:
7469 *                  \frac {\frac 1 2} 3
7470 *                and
7471 *                  \frac {\sqrt 1} 2
7472 *
7473 *                The default value is `1`
7474 *  - allowedInText: (optional) Whether or not the function is allowed inside
7475 *                   text mode (default false)
7476 *  - numOptionalArgs: (optional) The number of optional arguments the function
7477 *                     should parse. If the optional arguments aren't found,
7478 *                     `null` will be passed to the handler in their place.
7479 *                     (default 0)
7480 *  - infix: (optional) Must be true if the function is an infix operator.
7481 *
7482 * The last argument is that implementation, the handler for the function(s).
7483 * It is called to handle these functions and their arguments.
7484 * It receives two arguments:
7485 *  - context contains information and references provided by the parser
7486 *  - args is an array of arguments obtained from TeX input
7487 * The context contains the following properties:
7488 *  - funcName: the text (i.e. name) of the function, including \
7489 *  - parser: the parser object
7490 *  - lexer: the lexer object
7491 *  - positions: the positions in the overall string of the function
7492 *               and the arguments.
7493 * The latter three should only be used to produce error messages.
7494 *
7495 * The function should return an object with the following keys:
7496 *  - type: The type of element that this is. This is then used in
7497 *          buildHTML/buildMathML to determine which function
7498 *          should be called to build this node into a DOM node
7499 * Any other data can be added to the object, which will be passed
7500 * in to the function in buildHTML/buildMathML as `group.value`.
7501 */
7502
7503function defineFunction(names, props, handler) {
7504    if (typeof names === "string") {
7505        names = [names];
7506    }
7507    if (typeof props === "number") {
7508        props = { numArgs: props };
7509    }
7510    // Set default values of functions
7511    var data = {
7512        numArgs: props.numArgs,
7513        argTypes: props.argTypes,
7514        greediness: (props.greediness === undefined) ? 1 : props.greediness,
7515        allowedInText: !!props.allowedInText,
7516        numOptionalArgs: props.numOptionalArgs || 0,
7517        infix: !!props.infix,
7518        handler: handler
7519    };
7520    for (var i = 0; i < names.length; ++i) {
7521        module.exports[names[i]] = data;
7522    }
7523}
7524
7525// Since the corresponding buildHTML/buildMathML function expects a
7526// list of elements, we normalize for different kinds of arguments
7527var ordargument = function(arg) {
7528    if (arg.type === "ordgroup") {
7529        return arg.value;
7530    } else {
7531        return [arg];
7532    }
7533};
7534
7535// A normal square root
7536defineFunction("\\sqrt", {
7537    numArgs: 1,
7538    numOptionalArgs: 1
7539}, function(context, args) {
7540    var index = args[0];
7541    var body = args[1];
7542    return {
7543        type: "sqrt",
7544        body: body,
7545        index: index
7546    };
7547});
7548
7549// Non-mathy text, possibly in a font
7550var textFunctionStyles = {
7551    "\\text": undefined, "\\textrm": "mathrm", "\\textsf": "mathsf",
7552    "\\texttt": "mathtt", "\\textnormal": "mathrm", "\\textbf": "mathbf",
7553    "\\textit": "textit"
7554};
7555
7556defineFunction([
7557    "\\text", "\\textrm", "\\textsf", "\\texttt", "\\textnormal",
7558    "\\textbf", "\\textit"
7559], {
7560    numArgs: 1,
7561    argTypes: ["text"],
7562    greediness: 2,
7563    allowedInText: true
7564}, function(context, args) {
7565    var body = args[0];
7566    return {
7567        type: "text",
7568        body: ordargument(body),
7569        style: textFunctionStyles[context.funcName]
7570    };
7571});
7572
7573// A two-argument custom color
7574defineFunction("\\color", {
7575    numArgs: 2,
7576    allowedInText: true,
7577    greediness: 3,
7578    argTypes: ["color", "original"]
7579}, function(context, args) {
7580    var color = args[0];
7581    var body = args[1];
7582    return {
7583        type: "color",
7584        color: color.value,
7585        value: ordargument(body)
7586    };
7587});
7588
7589// An overline
7590defineFunction("\\overline", {
7591    numArgs: 1
7592}, function(context, args) {
7593    var body = args[0];
7594    return {
7595        type: "overline",
7596        body: body
7597    };
7598});
7599
7600// An underline
7601defineFunction("\\underline", {
7602    numArgs: 1
7603}, function(context, args) {
7604    var body = args[0];
7605    return {
7606        type: "underline",
7607        body: body
7608    };
7609});
7610
7611// A box of the width and height
7612defineFunction("\\rule", {
7613    numArgs: 2,
7614    numOptionalArgs: 1,
7615    argTypes: ["size", "size", "size"]
7616}, function(context, args) {
7617    var shift = args[0];
7618    var width = args[1];
7619    var height = args[2];
7620    return {
7621        type: "rule",
7622        shift: shift && shift.value,
7623        width: width.value,
7624        height: height.value
7625    };
7626});
7627
7628// TODO: In TeX, \mkern only accepts mu-units, and \kern does not accept
7629// mu-units. In current KaTeX we relax this; both commands accept any unit.
7630defineFunction(["\\kern", "\\mkern"], {
7631    numArgs: 1,
7632    argTypes: ["size"]
7633}, function(context, args) {
7634    return {
7635        type: "kern",
7636        dimension: args[0].value
7637    };
7638});
7639
7640// A KaTeX logo
7641defineFunction("\\KaTeX", {
7642    numArgs: 0
7643}, function(context) {
7644    return {
7645        type: "katex"
7646    };
7647});
7648
7649defineFunction("\\phantom", {
7650    numArgs: 1
7651}, function(context, args) {
7652    var body = args[0];
7653    return {
7654        type: "phantom",
7655        value: ordargument(body)
7656    };
7657});
7658
7659// Math class commands except \mathop
7660defineFunction([
7661    "\\mathord", "\\mathbin", "\\mathrel", "\\mathopen",
7662    "\\mathclose", "\\mathpunct", "\\mathinner"
7663], {
7664    numArgs: 1
7665}, function(context, args) {
7666    var body = args[0];
7667    return {
7668        type: "mclass",
7669        mclass: "m" + context.funcName.substr(5),
7670        value: ordargument(body)
7671    };
7672});
7673
7674// Build a relation by placing one symbol on top of another
7675defineFunction("\\stackrel", {
7676    numArgs: 2
7677}, function(context, args) {
7678    var top = args[0];
7679    var bottom = args[1];
7680
7681    var bottomop = new ParseNode("op", {
7682        type: "op",
7683        limits: true,
7684        alwaysHandleSupSub: true,
7685        symbol: false,
7686        value: ordargument(bottom)
7687    }, bottom.mode);
7688
7689    var supsub = new ParseNode("supsub", {
7690        base: bottomop,
7691        sup: top,
7692        sub: null
7693    }, top.mode);
7694
7695    return {
7696        type: "mclass",
7697        mclass: "mrel",
7698        value: [supsub]
7699    };
7700});
7701
7702// \mod-type functions
7703defineFunction("\\bmod", {
7704    numArgs: 0
7705}, function(context, args) {
7706    return {
7707        type: "mod",
7708        modType: "bmod",
7709        value: null
7710    };
7711});
7712
7713defineFunction(["\\pod", "\\pmod", "\\mod"], {
7714    numArgs: 1
7715}, function(context, args) {
7716    var body = args[0];
7717    return {
7718        type: "mod",
7719        modType: context.funcName.substr(1),
7720        value: ordargument(body)
7721    };
7722});
7723
7724// Extra data needed for the delimiter handler down below
7725var delimiterSizes = {
7726    "\\bigl" : {mclass: "mopen",    size: 1},
7727    "\\Bigl" : {mclass: "mopen",    size: 2},
7728    "\\biggl": {mclass: "mopen",    size: 3},
7729    "\\Biggl": {mclass: "mopen",    size: 4},
7730    "\\bigr" : {mclass: "mclose",   size: 1},
7731    "\\Bigr" : {mclass: "mclose",   size: 2},
7732    "\\biggr": {mclass: "mclose",   size: 3},
7733    "\\Biggr": {mclass: "mclose",   size: 4},
7734    "\\bigm" : {mclass: "mrel",     size: 1},
7735    "\\Bigm" : {mclass: "mrel",     size: 2},
7736    "\\biggm": {mclass: "mrel",     size: 3},
7737    "\\Biggm": {mclass: "mrel",     size: 4},
7738    "\\big"  : {mclass: "mord",     size: 1},
7739    "\\Big"  : {mclass: "mord",     size: 2},
7740    "\\bigg" : {mclass: "mord",     size: 3},
7741    "\\Bigg" : {mclass: "mord",     size: 4}
7742};
7743
7744var delimiters = [
7745    "(", ")", "[", "\\lbrack", "]", "\\rbrack",
7746    "\\{", "\\lbrace", "\\}", "\\rbrace",
7747    "\\lfloor", "\\rfloor", "\\lceil", "\\rceil",
7748    "<", ">", "\\langle", "\\rangle", "\\lt", "\\gt",
7749    "\\lvert", "\\rvert", "\\lVert", "\\rVert",
7750    "\\lgroup", "\\rgroup", "\\lmoustache", "\\rmoustache",
7751    "/", "\\backslash",
7752    "|", "\\vert", "\\|", "\\Vert",
7753    "\\uparrow", "\\Uparrow",
7754    "\\downarrow", "\\Downarrow",
7755    "\\updownarrow", "\\Updownarrow",
7756    "."
7757];
7758
7759var fontAliases = {
7760    "\\Bbb": "\\mathbb",
7761    "\\bold": "\\mathbf",
7762    "\\frak": "\\mathfrak"
7763};
7764
7765// Single-argument color functions
7766defineFunction([
7767    "\\blue", "\\orange", "\\pink", "\\red",
7768    "\\green", "\\gray", "\\purple",
7769    "\\blueA", "\\blueB", "\\blueC", "\\blueD", "\\blueE",
7770    "\\tealA", "\\tealB", "\\tealC", "\\tealD", "\\tealE",
7771    "\\greenA", "\\greenB", "\\greenC", "\\greenD", "\\greenE",
7772    "\\goldA", "\\goldB", "\\goldC", "\\goldD", "\\goldE",
7773    "\\redA", "\\redB", "\\redC", "\\redD", "\\redE",
7774    "\\maroonA", "\\maroonB", "\\maroonC", "\\maroonD", "\\maroonE",
7775    "\\purpleA", "\\purpleB", "\\purpleC", "\\purpleD", "\\purpleE",
7776    "\\mintA", "\\mintB", "\\mintC",
7777    "\\grayA", "\\grayB", "\\grayC", "\\grayD", "\\grayE",
7778    "\\grayF", "\\grayG", "\\grayH", "\\grayI",
7779    "\\kaBlue", "\\kaGreen"
7780], {
7781    numArgs: 1,
7782    allowedInText: true,
7783    greediness: 3
7784}, function(context, args) {
7785    var body = args[0];
7786    return {
7787        type: "color",
7788        color: "katex-" + context.funcName.slice(1),
7789        value: ordargument(body)
7790    };
7791});
7792
7793// There are 2 flags for operators; whether they produce limits in
7794// displaystyle, and whether they are symbols and should grow in
7795// displaystyle. These four groups cover the four possible choices.
7796
7797// No limits, not symbols
7798defineFunction([
7799    "\\arcsin", "\\arccos", "\\arctan", "\\arg", "\\cos", "\\cosh",
7800    "\\cot", "\\coth", "\\csc", "\\deg", "\\dim", "\\exp", "\\hom",
7801    "\\ker", "\\lg", "\\ln", "\\log", "\\sec", "\\sin", "\\sinh",
7802    "\\tan", "\\tanh"
7803], {
7804    numArgs: 0
7805}, function(context) {
7806    return {
7807        type: "op",
7808        limits: false,
7809        symbol: false,
7810        body: context.funcName
7811    };
7812});
7813
7814// Limits, not symbols
7815defineFunction([
7816    "\\det", "\\gcd", "\\inf", "\\lim", "\\liminf", "\\limsup", "\\max",
7817    "\\min", "\\Pr", "\\sup"
7818], {
7819    numArgs: 0
7820}, function(context) {
7821    return {
7822        type: "op",
7823        limits: true,
7824        symbol: false,
7825        body: context.funcName
7826    };
7827});
7828
7829// No limits, symbols
7830defineFunction([
7831    "\\int", "\\iint", "\\iiint", "\\oint"
7832], {
7833    numArgs: 0
7834}, function(context) {
7835    return {
7836        type: "op",
7837        limits: false,
7838        symbol: true,
7839        body: context.funcName
7840    };
7841});
7842
7843// Limits, symbols
7844defineFunction([
7845    "\\coprod", "\\bigvee", "\\bigwedge", "\\biguplus", "\\bigcap",
7846    "\\bigcup", "\\intop", "\\prod", "\\sum", "\\bigotimes",
7847    "\\bigoplus", "\\bigodot", "\\bigsqcup", "\\smallint"
7848], {
7849    numArgs: 0
7850}, function(context) {
7851    return {
7852        type: "op",
7853        limits: true,
7854        symbol: true,
7855        body: context.funcName
7856    };
7857});
7858
7859// \mathop class command
7860defineFunction("\\mathop", {
7861    numArgs: 1
7862}, function(context, args) {
7863    var body = args[0];
7864    return {
7865        type: "op",
7866        limits: false,
7867        symbol: false,
7868        value: ordargument(body)
7869    };
7870});
7871
7872// Fractions
7873defineFunction([
7874    "\\dfrac", "\\frac", "\\tfrac",
7875    "\\dbinom", "\\binom", "\\tbinom",
7876    "\\\\atopfrac" // can’t be entered directly
7877], {
7878    numArgs: 2,
7879    greediness: 2
7880}, function(context, args) {
7881    var numer = args[0];
7882    var denom = args[1];
7883    var hasBarLine;
7884    var leftDelim = null;
7885    var rightDelim = null;
7886    var size = "auto";
7887
7888    switch (context.funcName) {
7889        case "\\dfrac":
7890        case "\\frac":
7891        case "\\tfrac":
7892            hasBarLine = true;
7893            break;
7894        case "\\\\atopfrac":
7895            hasBarLine = false;
7896            break;
7897        case "\\dbinom":
7898        case "\\binom":
7899        case "\\tbinom":
7900            hasBarLine = false;
7901            leftDelim = "(";
7902            rightDelim = ")";
7903            break;
7904        default:
7905            throw new Error("Unrecognized genfrac command");
7906    }
7907
7908    switch (context.funcName) {
7909        case "\\dfrac":
7910        case "\\dbinom":
7911            size = "display";
7912            break;
7913        case "\\tfrac":
7914        case "\\tbinom":
7915            size = "text";
7916            break;
7917    }
7918
7919    return {
7920        type: "genfrac",
7921        numer: numer,
7922        denom: denom,
7923        hasBarLine: hasBarLine,
7924        leftDelim: leftDelim,
7925        rightDelim: rightDelim,
7926        size: size
7927    };
7928});
7929
7930// Left and right overlap functions
7931defineFunction(["\\llap", "\\rlap"], {
7932    numArgs: 1,
7933    allowedInText: true
7934}, function(context, args) {
7935    var body = args[0];
7936    return {
7937        type: context.funcName.slice(1),
7938        body: body
7939    };
7940});
7941
7942// Delimiter functions
7943var checkDelimiter = function(delim, context) {
7944    if (utils.contains(delimiters, delim.value)) {
7945        return delim;
7946    } else {
7947        throw new ParseError(
7948            "Invalid delimiter: '" + delim.value + "' after '" +
7949            context.funcName + "'", delim);
7950    }
7951};
7952
7953defineFunction([
7954    "\\bigl", "\\Bigl", "\\biggl", "\\Biggl",
7955    "\\bigr", "\\Bigr", "\\biggr", "\\Biggr",
7956    "\\bigm", "\\Bigm", "\\biggm", "\\Biggm",
7957    "\\big",  "\\Big",  "\\bigg",  "\\Bigg"
7958], {
7959    numArgs: 1
7960}, function(context, args) {
7961    var delim = checkDelimiter(args[0], context);
7962
7963    return {
7964        type: "delimsizing",
7965        size: delimiterSizes[context.funcName].size,
7966        mclass: delimiterSizes[context.funcName].mclass,
7967        value: delim.value
7968    };
7969});
7970
7971defineFunction([
7972    "\\left", "\\right"
7973], {
7974    numArgs: 1
7975}, function(context, args) {
7976    var delim = checkDelimiter(args[0], context);
7977
7978    // \left and \right are caught somewhere in Parser.js, which is
7979    // why this data doesn't match what is in buildHTML.
7980    return {
7981        type: "leftright",
7982        value: delim.value
7983    };
7984});
7985
7986defineFunction("\\middle", {
7987    numArgs: 1
7988}, function(context, args) {
7989    var delim = checkDelimiter(args[0], context);
7990    if (!context.parser.leftrightDepth) {
7991        throw new ParseError("\\middle without preceding \\left", delim);
7992    }
7993
7994    return {
7995        type: "middle",
7996        value: delim.value
7997    };
7998});
7999
8000// Sizing functions (handled in Parser.js explicitly, hence no handler)
8001defineFunction([
8002    "\\tiny", "\\scriptsize", "\\footnotesize", "\\small",
8003    "\\normalsize", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge"
8004], 0, null);
8005
8006// Style changing functions (handled in Parser.js explicitly, hence no
8007// handler)
8008defineFunction([
8009    "\\displaystyle", "\\textstyle", "\\scriptstyle",
8010    "\\scriptscriptstyle"
8011], 0, null);
8012
8013defineFunction([
8014    // styles
8015    "\\mathrm", "\\mathit", "\\mathbf",
8016
8017    // families
8018    "\\mathbb", "\\mathcal", "\\mathfrak", "\\mathscr", "\\mathsf",
8019    "\\mathtt",
8020
8021    // aliases
8022    "\\Bbb", "\\bold", "\\frak"
8023], {
8024    numArgs: 1,
8025    greediness: 2
8026}, function(context, args) {
8027    var body = args[0];
8028    var func = context.funcName;
8029    if (func in fontAliases) {
8030        func = fontAliases[func];
8031    }
8032    return {
8033        type: "font",
8034        font: func.slice(1),
8035        body: body
8036    };
8037});
8038
8039// Accents
8040defineFunction([
8041    "\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve",
8042    "\\check", "\\hat", "\\vec", "\\dot"
8043    // We don't support expanding accents yet
8044    // "\\widetilde", "\\widehat"
8045], {
8046    numArgs: 1
8047}, function(context, args) {
8048    var base = args[0];
8049    return {
8050        type: "accent",
8051        accent: context.funcName,
8052        base: base
8053    };
8054});
8055
8056// Infix generalized fractions
8057defineFunction(["\\over", "\\choose", "\\atop"], {
8058    numArgs: 0,
8059    infix: true
8060}, function(context) {
8061    var replaceWith;
8062    switch (context.funcName) {
8063        case "\\over":
8064            replaceWith = "\\frac";
8065            break;
8066        case "\\choose":
8067            replaceWith = "\\binom";
8068            break;
8069        case "\\atop":
8070            replaceWith = "\\\\atopfrac";
8071            break;
8072        default:
8073            throw new Error("Unrecognized infix genfrac command");
8074    }
8075    return {
8076        type: "infix",
8077        replaceWith: replaceWith,
8078        token: context.token
8079    };
8080});
8081
8082// Row breaks for aligned data
8083defineFunction(["\\\\", "\\cr"], {
8084    numArgs: 0,
8085    numOptionalArgs: 1,
8086    argTypes: ["size"]
8087}, function(context, args) {
8088    var size = args[0];
8089    return {
8090        type: "cr",
8091        size: size
8092    };
8093});
8094
8095// Environment delimiters
8096defineFunction(["\\begin", "\\end"], {
8097    numArgs: 1,
8098    argTypes: ["text"]
8099}, function(context, args) {
8100    var nameGroup = args[0];
8101    if (nameGroup.type !== "ordgroup") {
8102        throw new ParseError("Invalid environment name", nameGroup);
8103    }
8104    var name = "";
8105    for (var i = 0; i < nameGroup.value.length; ++i) {
8106        name += nameGroup.value[i].value;
8107    }
8108    return {
8109        type: "environment",
8110        name: name,
8111        nameGroup: nameGroup
8112    };
8113});
8114
8115},{"./ParseError":6,"./parseData":21,"./utils":25}],20:[function(require,module,exports){
8116/**
8117 * These objects store data about MathML nodes. This is the MathML equivalent
8118 * of the types in domTree.js. Since MathML handles its own rendering, and
8119 * since we're mainly using MathML to improve accessibility, we don't manage
8120 * any of the styling state that the plain DOM nodes do.
8121 *
8122 * The `toNode` and `toMarkup` functions work simlarly to how they do in
8123 * domTree.js, creating namespaced DOM nodes and HTML text markup respectively.
8124 */
8125
8126var utils = require("./utils");
8127
8128/**
8129 * This node represents a general purpose MathML node of any type. The
8130 * constructor requires the type of node to create (for example, `"mo"` or
8131 * `"mspace"`, corresponding to `<mo>` and `<mspace>` tags).
8132 */
8133function MathNode(type, children) {
8134    this.type = type;
8135    this.attributes = {};
8136    this.children = children || [];
8137}
8138
8139/**
8140 * Sets an attribute on a MathML node. MathML depends on attributes to convey a
8141 * semantic content, so this is used heavily.
8142 */
8143MathNode.prototype.setAttribute = function(name, value) {
8144    this.attributes[name] = value;
8145};
8146
8147/**
8148 * Converts the math node into a MathML-namespaced DOM element.
8149 */
8150MathNode.prototype.toNode = function() {
8151    var node = document.createElementNS(
8152        "http://www.w3.org/1998/Math/MathML", this.type);
8153
8154    for (var attr in this.attributes) {
8155        if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
8156            node.setAttribute(attr, this.attributes[attr]);
8157        }
8158    }
8159
8160    for (var i = 0; i < this.children.length; i++) {
8161        node.appendChild(this.children[i].toNode());
8162    }
8163
8164    return node;
8165};
8166
8167/**
8168 * Converts the math node into an HTML markup string.
8169 */
8170MathNode.prototype.toMarkup = function() {
8171    var markup = "<" + this.type;
8172
8173    // Add the attributes
8174    for (var attr in this.attributes) {
8175        if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
8176            markup += " " + attr + "=\"";
8177            markup += utils.escape(this.attributes[attr]);
8178            markup += "\"";
8179        }
8180    }
8181
8182    markup += ">";
8183
8184    for (var i = 0; i < this.children.length; i++) {
8185        markup += this.children[i].toMarkup();
8186    }
8187
8188    markup += "</" + this.type + ">";
8189
8190    return markup;
8191};
8192
8193/**
8194 * This node represents a piece of text.
8195 */
8196function TextNode(text) {
8197    this.text = text;
8198}
8199
8200/**
8201 * Converts the text node into a DOM text node.
8202 */
8203TextNode.prototype.toNode = function() {
8204    return document.createTextNode(this.text);
8205};
8206
8207/**
8208 * Converts the text node into HTML markup (which is just the text itself).
8209 */
8210TextNode.prototype.toMarkup = function() {
8211    return utils.escape(this.text);
8212};
8213
8214module.exports = {
8215    MathNode: MathNode,
8216    TextNode: TextNode
8217};
8218
8219},{"./utils":25}],21:[function(require,module,exports){
8220/**
8221 * The resulting parse tree nodes of the parse tree.
8222 *
8223 * It is possible to provide position information, so that a ParseNode can
8224 * fulfil a role similar to a Token in error reporting.
8225 * For details on the corresponding properties see Token constructor.
8226 * Providing such information can lead to better error reporting.
8227 *
8228 * @param {string}  type       type of node, like e.g. "ordgroup"
8229 * @param {?object} value      type-specific representation of the node
8230 * @param {string}  mode       parse mode in action for this node,
8231 *                             "math" or "text"
8232 * @param {Token=} firstToken  first token of the input for this node,
8233 *                             will omit position information if unset
8234 * @param {Token=} lastToken   last token of the input for this node,
8235 *                             will default to firstToken if unset
8236 */
8237function ParseNode(type, value, mode, firstToken, lastToken) {
8238    this.type = type;
8239    this.value = value;
8240    this.mode = mode;
8241    if (firstToken && (!lastToken || lastToken.lexer === firstToken.lexer)) {
8242        this.lexer = firstToken.lexer;
8243        this.start = firstToken.start;
8244        this.end = (lastToken || firstToken).end;
8245    }
8246}
8247
8248module.exports = {
8249    ParseNode: ParseNode
8250};
8251
8252
8253},{}],22:[function(require,module,exports){
8254/**
8255 * Provides a single function for parsing an expression using a Parser
8256 * TODO(emily): Remove this
8257 */
8258
8259var Parser = require("./Parser");
8260
8261/**
8262 * Parses an expression using a Parser, then returns the parsed result.
8263 */
8264var parseTree = function(toParse, settings) {
8265    if (!(typeof toParse === 'string' || toParse instanceof String)) {
8266        throw new TypeError('KaTeX can only parse string typed expression');
8267    }
8268    var parser = new Parser(toParse, settings);
8269
8270    return parser.parse();
8271};
8272
8273module.exports = parseTree;
8274
8275},{"./Parser":7}],23:[function(require,module,exports){
8276/**
8277 * This file holds a list of all no-argument functions and single-character
8278 * symbols (like 'a' or ';').
8279 *
8280 * For each of the symbols, there are three properties they can have:
8281 * - font (required): the font to be used for this symbol. Either "main" (the
8282     normal font), or "ams" (the ams fonts).
8283 * - group (required): the ParseNode group type the symbol should have (i.e.
8284     "textord", "mathord", etc).
8285     See https://github.com/Khan/KaTeX/wiki/Examining-TeX#group-types
8286 * - replace: the character that this symbol or function should be
8287 *   replaced with (i.e. "\phi" has a replace value of "\u03d5", the phi
8288 *   character in the main font).
8289 *
8290 * The outermost map in the table indicates what mode the symbols should be
8291 * accepted in (e.g. "math" or "text").
8292 */
8293
8294module.exports = {
8295    math: {},
8296    text: {}
8297};
8298
8299function defineSymbol(mode, font, group, replace, name) {
8300    module.exports[mode][name] = {
8301        font: font,
8302        group: group,
8303        replace: replace
8304    };
8305}
8306
8307// Some abbreviations for commonly used strings.
8308// This helps minify the code, and also spotting typos using jshint.
8309
8310// modes:
8311var math = "math";
8312var text = "text";
8313
8314// fonts:
8315var main = "main";
8316var ams = "ams";
8317
8318// groups:
8319var accent = "accent";
8320var bin = "bin";
8321var close = "close";
8322var inner = "inner";
8323var mathord = "mathord";
8324var op = "op";
8325var open = "open";
8326var punct = "punct";
8327var rel = "rel";
8328var spacing = "spacing";
8329var textord = "textord";
8330
8331// Now comes the symbol table
8332
8333// Relation Symbols
8334defineSymbol(math, main, rel, "\u2261", "\\equiv");
8335defineSymbol(math, main, rel, "\u227a", "\\prec");
8336defineSymbol(math, main, rel, "\u227b", "\\succ");
8337defineSymbol(math, main, rel, "\u223c", "\\sim");
8338defineSymbol(math, main, rel, "\u22a5", "\\perp");
8339defineSymbol(math, main, rel, "\u2aaf", "\\preceq");
8340defineSymbol(math, main, rel, "\u2ab0", "\\succeq");
8341defineSymbol(math, main, rel, "\u2243", "\\simeq");
8342defineSymbol(math, main, rel, "\u2223", "\\mid");
8343defineSymbol(math, main, rel, "\u226a", "\\ll");
8344defineSymbol(math, main, rel, "\u226b", "\\gg");
8345defineSymbol(math, main, rel, "\u224d", "\\asymp");
8346defineSymbol(math, main, rel, "\u2225", "\\parallel");
8347defineSymbol(math, main, rel, "\u22c8", "\\bowtie");
8348defineSymbol(math, main, rel, "\u2323", "\\smile");
8349defineSymbol(math, main, rel, "\u2291", "\\sqsubseteq");
8350defineSymbol(math, main, rel, "\u2292", "\\sqsupseteq");
8351defineSymbol(math, main, rel, "\u2250", "\\doteq");
8352defineSymbol(math, main, rel, "\u2322", "\\frown");
8353defineSymbol(math, main, rel, "\u220b", "\\ni");
8354defineSymbol(math, main, rel, "\u221d", "\\propto");
8355defineSymbol(math, main, rel, "\u22a2", "\\vdash");
8356defineSymbol(math, main, rel, "\u22a3", "\\dashv");
8357defineSymbol(math, main, rel, "\u220b", "\\owns");
8358
8359// Punctuation
8360defineSymbol(math, main, punct, "\u002e", "\\ldotp");
8361defineSymbol(math, main, punct, "\u22c5", "\\cdotp");
8362
8363// Misc Symbols
8364defineSymbol(math, main, textord, "\u0023", "\\#");
8365defineSymbol(text, main, textord, "\u0023", "\\#");
8366defineSymbol(math, main, textord, "\u0026", "\\&");
8367defineSymbol(text, main, textord, "\u0026", "\\&");
8368defineSymbol(math, main, textord, "\u2135", "\\aleph");
8369defineSymbol(math, main, textord, "\u2200", "\\forall");
8370defineSymbol(math, main, textord, "\u210f", "\\hbar");
8371defineSymbol(math, main, textord, "\u2203", "\\exists");
8372defineSymbol(math, main, textord, "\u2207", "\\nabla");
8373defineSymbol(math, main, textord, "\u266d", "\\flat");
8374defineSymbol(math, main, textord, "\u2113", "\\ell");
8375defineSymbol(math, main, textord, "\u266e", "\\natural");
8376defineSymbol(math, main, textord, "\u2663", "\\clubsuit");
8377defineSymbol(math, main, textord, "\u2118", "\\wp");
8378defineSymbol(math, main, textord, "\u266f", "\\sharp");
8379defineSymbol(math, main, textord, "\u2662", "\\diamondsuit");
8380defineSymbol(math, main, textord, "\u211c", "\\Re");
8381defineSymbol(math, main, textord, "\u2661", "\\heartsuit");
8382defineSymbol(math, main, textord, "\u2111", "\\Im");
8383defineSymbol(math, main, textord, "\u2660", "\\spadesuit");
8384
8385// Math and Text
8386defineSymbol(math, main, textord, "\u2020", "\\dag");
8387defineSymbol(math, main, textord, "\u2021", "\\ddag");
8388
8389// Large Delimiters
8390defineSymbol(math, main, close, "\u23b1", "\\rmoustache");
8391defineSymbol(math, main, open, "\u23b0", "\\lmoustache");
8392defineSymbol(math, main, close, "\u27ef", "\\rgroup");
8393defineSymbol(math, main, open, "\u27ee", "\\lgroup");
8394
8395// Binary Operators
8396defineSymbol(math, main, bin, "\u2213", "\\mp");
8397defineSymbol(math, main, bin, "\u2296", "\\ominus");
8398defineSymbol(math, main, bin, "\u228e", "\\uplus");
8399defineSymbol(math, main, bin, "\u2293", "\\sqcap");
8400defineSymbol(math, main, bin, "\u2217", "\\ast");
8401defineSymbol(math, main, bin, "\u2294", "\\sqcup");
8402defineSymbol(math, main, bin, "\u25ef", "\\bigcirc");
8403defineSymbol(math, main, bin, "\u2219", "\\bullet");
8404defineSymbol(math, main, bin, "\u2021", "\\ddagger");
8405defineSymbol(math, main, bin, "\u2240", "\\wr");
8406defineSymbol(math, main, bin, "\u2a3f", "\\amalg");
8407
8408// Arrow Symbols
8409defineSymbol(math, main, rel, "\u27f5", "\\longleftarrow");
8410defineSymbol(math, main, rel, "\u21d0", "\\Leftarrow");
8411defineSymbol(math, main, rel, "\u27f8", "\\Longleftarrow");
8412defineSymbol(math, main, rel, "\u27f6", "\\longrightarrow");
8413defineSymbol(math, main, rel, "\u21d2", "\\Rightarrow");
8414defineSymbol(math, main, rel, "\u27f9", "\\Longrightarrow");
8415defineSymbol(math, main, rel, "\u2194", "\\leftrightarrow");
8416defineSymbol(math, main, rel, "\u27f7", "\\longleftrightarrow");
8417defineSymbol(math, main, rel, "\u21d4", "\\Leftrightarrow");
8418defineSymbol(math, main, rel, "\u27fa", "\\Longleftrightarrow");
8419defineSymbol(math, main, rel, "\u21a6", "\\mapsto");
8420defineSymbol(math, main, rel, "\u27fc", "\\longmapsto");
8421defineSymbol(math, main, rel, "\u2197", "\\nearrow");
8422defineSymbol(math, main, rel, "\u21a9", "\\hookleftarrow");
8423defineSymbol(math, main, rel, "\u21aa", "\\hookrightarrow");
8424defineSymbol(math, main, rel, "\u2198", "\\searrow");
8425defineSymbol(math, main, rel, "\u21bc", "\\leftharpoonup");
8426defineSymbol(math, main, rel, "\u21c0", "\\rightharpoonup");
8427defineSymbol(math, main, rel, "\u2199", "\\swarrow");
8428defineSymbol(math, main, rel, "\u21bd", "\\leftharpoondown");
8429defineSymbol(math, main, rel, "\u21c1", "\\rightharpoondown");
8430defineSymbol(math, main, rel, "\u2196", "\\nwarrow");
8431defineSymbol(math, main, rel, "\u21cc", "\\rightleftharpoons");
8432
8433// AMS Negated Binary Relations
8434defineSymbol(math, ams, rel, "\u226e", "\\nless");
8435defineSymbol(math, ams, rel, "\ue010", "\\nleqslant");
8436defineSymbol(math, ams, rel, "\ue011", "\\nleqq");
8437defineSymbol(math, ams, rel, "\u2a87", "\\lneq");
8438defineSymbol(math, ams, rel, "\u2268", "\\lneqq");
8439defineSymbol(math, ams, rel, "\ue00c", "\\lvertneqq");
8440defineSymbol(math, ams, rel, "\u22e6", "\\lnsim");
8441defineSymbol(math, ams, rel, "\u2a89", "\\lnapprox");
8442defineSymbol(math, ams, rel, "\u2280", "\\nprec");
8443defineSymbol(math, ams, rel, "\u22e0", "\\npreceq");
8444defineSymbol(math, ams, rel, "\u22e8", "\\precnsim");
8445defineSymbol(math, ams, rel, "\u2ab9", "\\precnapprox");
8446defineSymbol(math, ams, rel, "\u2241", "\\nsim");
8447defineSymbol(math, ams, rel, "\ue006", "\\nshortmid");
8448defineSymbol(math, ams, rel, "\u2224", "\\nmid");
8449defineSymbol(math, ams, rel, "\u22ac", "\\nvdash");
8450defineSymbol(math, ams, rel, "\u22ad", "\\nvDash");
8451defineSymbol(math, ams, rel, "\u22ea", "\\ntriangleleft");
8452defineSymbol(math, ams, rel, "\u22ec", "\\ntrianglelefteq");
8453defineSymbol(math, ams, rel, "\u228a", "\\subsetneq");
8454defineSymbol(math, ams, rel, "\ue01a", "\\varsubsetneq");
8455defineSymbol(math, ams, rel, "\u2acb", "\\subsetneqq");
8456defineSymbol(math, ams, rel, "\ue017", "\\varsubsetneqq");
8457defineSymbol(math, ams, rel, "\u226f", "\\ngtr");
8458defineSymbol(math, ams, rel, "\ue00f", "\\ngeqslant");
8459defineSymbol(math, ams, rel, "\ue00e", "\\ngeqq");
8460defineSymbol(math, ams, rel, "\u2a88", "\\gneq");
8461defineSymbol(math, ams, rel, "\u2269", "\\gneqq");
8462defineSymbol(math, ams, rel, "\ue00d", "\\gvertneqq");
8463defineSymbol(math, ams, rel, "\u22e7", "\\gnsim");
8464defineSymbol(math, ams, rel, "\u2a8a", "\\gnapprox");
8465defineSymbol(math, ams, rel, "\u2281", "\\nsucc");
8466defineSymbol(math, ams, rel, "\u22e1", "\\nsucceq");
8467defineSymbol(math, ams, rel, "\u22e9", "\\succnsim");
8468defineSymbol(math, ams, rel, "\u2aba", "\\succnapprox");
8469defineSymbol(math, ams, rel, "\u2246", "\\ncong");
8470defineSymbol(math, ams, rel, "\ue007", "\\nshortparallel");
8471defineSymbol(math, ams, rel, "\u2226", "\\nparallel");
8472defineSymbol(math, ams, rel, "\u22af", "\\nVDash");
8473defineSymbol(math, ams, rel, "\u22eb", "\\ntriangleright");
8474defineSymbol(math, ams, rel, "\u22ed", "\\ntrianglerighteq");
8475defineSymbol(math, ams, rel, "\ue018", "\\nsupseteqq");
8476defineSymbol(math, ams, rel, "\u228b", "\\supsetneq");
8477defineSymbol(math, ams, rel, "\ue01b", "\\varsupsetneq");
8478defineSymbol(math, ams, rel, "\u2acc", "\\supsetneqq");
8479defineSymbol(math, ams, rel, "\ue019", "\\varsupsetneqq");
8480defineSymbol(math, ams, rel, "\u22ae", "\\nVdash");
8481defineSymbol(math, ams, rel, "\u2ab5", "\\precneqq");
8482defineSymbol(math, ams, rel, "\u2ab6", "\\succneqq");
8483defineSymbol(math, ams, rel, "\ue016", "\\nsubseteqq");
8484defineSymbol(math, ams, bin, "\u22b4", "\\unlhd");
8485defineSymbol(math, ams, bin, "\u22b5", "\\unrhd");
8486
8487// AMS Negated Arrows
8488defineSymbol(math, ams, rel, "\u219a", "\\nleftarrow");
8489defineSymbol(math, ams, rel, "\u219b", "\\nrightarrow");
8490defineSymbol(math, ams, rel, "\u21cd", "\\nLeftarrow");
8491defineSymbol(math, ams, rel, "\u21cf", "\\nRightarrow");
8492defineSymbol(math, ams, rel, "\u21ae", "\\nleftrightarrow");
8493defineSymbol(math, ams, rel, "\u21ce", "\\nLeftrightarrow");
8494
8495// AMS Misc
8496defineSymbol(math, ams, rel, "\u25b3", "\\vartriangle");
8497defineSymbol(math, ams, textord, "\u210f", "\\hslash");
8498defineSymbol(math, ams, textord, "\u25bd", "\\triangledown");
8499defineSymbol(math, ams, textord, "\u25ca", "\\lozenge");
8500defineSymbol(math, ams, textord, "\u24c8", "\\circledS");
8501defineSymbol(math, ams, textord, "\u00ae", "\\circledR");
8502defineSymbol(math, ams, textord, "\u2221", "\\measuredangle");
8503defineSymbol(math, ams, textord, "\u2204", "\\nexists");
8504defineSymbol(math, ams, textord, "\u2127", "\\mho");
8505defineSymbol(math, ams, textord, "\u2132", "\\Finv");
8506defineSymbol(math, ams, textord, "\u2141", "\\Game");
8507defineSymbol(math, ams, textord, "\u006b", "\\Bbbk");
8508defineSymbol(math, ams, textord, "\u2035", "\\backprime");
8509defineSymbol(math, ams, textord, "\u25b2", "\\blacktriangle");
8510defineSymbol(math, ams, textord, "\u25bc", "\\blacktriangledown");
8511defineSymbol(math, ams, textord, "\u25a0", "\\blacksquare");
8512defineSymbol(math, ams, textord, "\u29eb", "\\blacklozenge");
8513defineSymbol(math, ams, textord, "\u2605", "\\bigstar");
8514defineSymbol(math, ams, textord, "\u2222", "\\sphericalangle");
8515defineSymbol(math, ams, textord, "\u2201", "\\complement");
8516defineSymbol(math, ams, textord, "\u00f0", "\\eth");
8517defineSymbol(math, ams, textord, "\u2571", "\\diagup");
8518defineSymbol(math, ams, textord, "\u2572", "\\diagdown");
8519defineSymbol(math, ams, textord, "\u25a1", "\\square");
8520defineSymbol(math, ams, textord, "\u25a1", "\\Box");
8521defineSymbol(math, ams, textord, "\u25ca", "\\Diamond");
8522defineSymbol(math, ams, textord, "\u00a5", "\\yen");
8523defineSymbol(math, ams, textord, "\u2713", "\\checkmark");
8524
8525// AMS Hebrew
8526defineSymbol(math, ams, textord, "\u2136", "\\beth");
8527defineSymbol(math, ams, textord, "\u2138", "\\daleth");
8528defineSymbol(math, ams, textord, "\u2137", "\\gimel");
8529
8530// AMS Greek
8531defineSymbol(math, ams, textord, "\u03dd", "\\digamma");
8532defineSymbol(math, ams, textord, "\u03f0", "\\varkappa");
8533
8534// AMS Delimiters
8535defineSymbol(math, ams, open, "\u250c", "\\ulcorner");
8536defineSymbol(math, ams, close, "\u2510", "\\urcorner");
8537defineSymbol(math, ams, open, "\u2514", "\\llcorner");
8538defineSymbol(math, ams, close, "\u2518", "\\lrcorner");
8539
8540// AMS Binary Relations
8541defineSymbol(math, ams, rel, "\u2266", "\\leqq");
8542defineSymbol(math, ams, rel, "\u2a7d", "\\leqslant");
8543defineSymbol(math, ams, rel, "\u2a95", "\\eqslantless");
8544defineSymbol(math, ams, rel, "\u2272", "\\lesssim");
8545defineSymbol(math, ams, rel, "\u2a85", "\\lessapprox");
8546defineSymbol(math, ams, rel, "\u224a", "\\approxeq");
8547defineSymbol(math, ams, bin, "\u22d6", "\\lessdot");
8548defineSymbol(math, ams, rel, "\u22d8", "\\lll");
8549defineSymbol(math, ams, rel, "\u2276", "\\lessgtr");
8550defineSymbol(math, ams, rel, "\u22da", "\\lesseqgtr");
8551defineSymbol(math, ams, rel, "\u2a8b", "\\lesseqqgtr");
8552defineSymbol(math, ams, rel, "\u2251", "\\doteqdot");
8553defineSymbol(math, ams, rel, "\u2253", "\\risingdotseq");
8554defineSymbol(math, ams, rel, "\u2252", "\\fallingdotseq");
8555defineSymbol(math, ams, rel, "\u223d", "\\backsim");
8556defineSymbol(math, ams, rel, "\u22cd", "\\backsimeq");
8557defineSymbol(math, ams, rel, "\u2ac5", "\\subseteqq");
8558defineSymbol(math, ams, rel, "\u22d0", "\\Subset");
8559defineSymbol(math, ams, rel, "\u228f", "\\sqsubset");
8560defineSymbol(math, ams, rel, "\u227c", "\\preccurlyeq");
8561defineSymbol(math, ams, rel, "\u22de", "\\curlyeqprec");
8562defineSymbol(math, ams, rel, "\u227e", "\\precsim");
8563defineSymbol(math, ams, rel, "\u2ab7", "\\precapprox");
8564defineSymbol(math, ams, rel, "\u22b2", "\\vartriangleleft");
8565defineSymbol(math, ams, rel, "\u22b4", "\\trianglelefteq");
8566defineSymbol(math, ams, rel, "\u22a8", "\\vDash");
8567defineSymbol(math, ams, rel, "\u22aa", "\\Vvdash");
8568defineSymbol(math, ams, rel, "\u2323", "\\smallsmile");
8569defineSymbol(math, ams, rel, "\u2322", "\\smallfrown");
8570defineSymbol(math, ams, rel, "\u224f", "\\bumpeq");
8571defineSymbol(math, ams, rel, "\u224e", "\\Bumpeq");
8572defineSymbol(math, ams, rel, "\u2267", "\\geqq");
8573defineSymbol(math, ams, rel, "\u2a7e", "\\geqslant");
8574defineSymbol(math, ams, rel, "\u2a96", "\\eqslantgtr");
8575defineSymbol(math, ams, rel, "\u2273", "\\gtrsim");
8576defineSymbol(math, ams, rel, "\u2a86", "\\gtrapprox");
8577defineSymbol(math, ams, bin, "\u22d7", "\\gtrdot");
8578defineSymbol(math, ams, rel, "\u22d9", "\\ggg");
8579defineSymbol(math, ams, rel, "\u2277", "\\gtrless");
8580defineSymbol(math, ams, rel, "\u22db", "\\gtreqless");
8581defineSymbol(math, ams, rel, "\u2a8c", "\\gtreqqless");
8582defineSymbol(math, ams, rel, "\u2256", "\\eqcirc");
8583defineSymbol(math, ams, rel, "\u2257", "\\circeq");
8584defineSymbol(math, ams, rel, "\u225c", "\\triangleq");
8585defineSymbol(math, ams, rel, "\u223c", "\\thicksim");
8586defineSymbol(math, ams, rel, "\u2248", "\\thickapprox");
8587defineSymbol(math, ams, rel, "\u2ac6", "\\supseteqq");
8588defineSymbol(math, ams, rel, "\u22d1", "\\Supset");
8589defineSymbol(math, ams, rel, "\u2290", "\\sqsupset");
8590defineSymbol(math, ams, rel, "\u227d", "\\succcurlyeq");
8591defineSymbol(math, ams, rel, "\u22df", "\\curlyeqsucc");
8592defineSymbol(math, ams, rel, "\u227f", "\\succsim");
8593defineSymbol(math, ams, rel, "\u2ab8", "\\succapprox");
8594defineSymbol(math, ams, rel, "\u22b3", "\\vartriangleright");
8595defineSymbol(math, ams, rel, "\u22b5", "\\trianglerighteq");
8596defineSymbol(math, ams, rel, "\u22a9", "\\Vdash");
8597defineSymbol(math, ams, rel, "\u2223", "\\shortmid");
8598defineSymbol(math, ams, rel, "\u2225", "\\shortparallel");
8599defineSymbol(math, ams, rel, "\u226c", "\\between");
8600defineSymbol(math, ams, rel, "\u22d4", "\\pitchfork");
8601defineSymbol(math, ams, rel, "\u221d", "\\varpropto");
8602defineSymbol(math, ams, rel, "\u25c0", "\\blacktriangleleft");
8603defineSymbol(math, ams, rel, "\u2234", "\\therefore");
8604defineSymbol(math, ams, rel, "\u220d", "\\backepsilon");
8605defineSymbol(math, ams, rel, "\u25b6", "\\blacktriangleright");
8606defineSymbol(math, ams, rel, "\u2235", "\\because");
8607defineSymbol(math, ams, rel, "\u22d8", "\\llless");
8608defineSymbol(math, ams, rel, "\u22d9", "\\gggtr");
8609defineSymbol(math, ams, bin, "\u22b2", "\\lhd");
8610defineSymbol(math, ams, bin, "\u22b3", "\\rhd");
8611defineSymbol(math, ams, rel, "\u2242", "\\eqsim");
8612defineSymbol(math, main, rel, "\u22c8", "\\Join");
8613defineSymbol(math, ams, rel, "\u2251", "\\Doteq");
8614
8615// AMS Binary Operators
8616defineSymbol(math, ams, bin, "\u2214", "\\dotplus");
8617defineSymbol(math, ams, bin, "\u2216", "\\smallsetminus");
8618defineSymbol(math, ams, bin, "\u22d2", "\\Cap");
8619defineSymbol(math, ams, bin, "\u22d3", "\\Cup");
8620defineSymbol(math, ams, bin, "\u2a5e", "\\doublebarwedge");
8621defineSymbol(math, ams, bin, "\u229f", "\\boxminus");
8622defineSymbol(math, ams, bin, "\u229e", "\\boxplus");
8623defineSymbol(math, ams, bin, "\u22c7", "\\divideontimes");
8624defineSymbol(math, ams, bin, "\u22c9", "\\ltimes");
8625defineSymbol(math, ams, bin, "\u22ca", "\\rtimes");
8626defineSymbol(math, ams, bin, "\u22cb", "\\leftthreetimes");
8627defineSymbol(math, ams, bin, "\u22cc", "\\rightthreetimes");
8628defineSymbol(math, ams, bin, "\u22cf", "\\curlywedge");
8629defineSymbol(math, ams, bin, "\u22ce", "\\curlyvee");
8630defineSymbol(math, ams, bin, "\u229d", "\\circleddash");
8631defineSymbol(math, ams, bin, "\u229b", "\\circledast");
8632defineSymbol(math, ams, bin, "\u22c5", "\\centerdot");
8633defineSymbol(math, ams, bin, "\u22ba", "\\intercal");
8634defineSymbol(math, ams, bin, "\u22d2", "\\doublecap");
8635defineSymbol(math, ams, bin, "\u22d3", "\\doublecup");
8636defineSymbol(math, ams, bin, "\u22a0", "\\boxtimes");
8637
8638// AMS Arrows
8639defineSymbol(math, ams, rel, "\u21e2", "\\dashrightarrow");
8640defineSymbol(math, ams, rel, "\u21e0", "\\dashleftarrow");
8641defineSymbol(math, ams, rel, "\u21c7", "\\leftleftarrows");
8642defineSymbol(math, ams, rel, "\u21c6", "\\leftrightarrows");
8643defineSymbol(math, ams, rel, "\u21da", "\\Lleftarrow");
8644defineSymbol(math, ams, rel, "\u219e", "\\twoheadleftarrow");
8645defineSymbol(math, ams, rel, "\u21a2", "\\leftarrowtail");
8646defineSymbol(math, ams, rel, "\u21ab", "\\looparrowleft");
8647defineSymbol(math, ams, rel, "\u21cb", "\\leftrightharpoons");
8648defineSymbol(math, ams, rel, "\u21b6", "\\curvearrowleft");
8649defineSymbol(math, ams, rel, "\u21ba", "\\circlearrowleft");
8650defineSymbol(math, ams, rel, "\u21b0", "\\Lsh");
8651defineSymbol(math, ams, rel, "\u21c8", "\\upuparrows");
8652defineSymbol(math, ams, rel, "\u21bf", "\\upharpoonleft");
8653defineSymbol(math, ams, rel, "\u21c3", "\\downharpoonleft");
8654defineSymbol(math, ams, rel, "\u22b8", "\\multimap");
8655defineSymbol(math, ams, rel, "\u21ad", "\\leftrightsquigarrow");
8656defineSymbol(math, ams, rel, "\u21c9", "\\rightrightarrows");
8657defineSymbol(math, ams, rel, "\u21c4", "\\rightleftarrows");
8658defineSymbol(math, ams, rel, "\u21a0", "\\twoheadrightarrow");
8659defineSymbol(math, ams, rel, "\u21a3", "\\rightarrowtail");
8660defineSymbol(math, ams, rel, "\u21ac", "\\looparrowright");
8661defineSymbol(math, ams, rel, "\u21b7", "\\curvearrowright");
8662defineSymbol(math, ams, rel, "\u21bb", "\\circlearrowright");
8663defineSymbol(math, ams, rel, "\u21b1", "\\Rsh");
8664defineSymbol(math, ams, rel, "\u21ca", "\\downdownarrows");
8665defineSymbol(math, ams, rel, "\u21be", "\\upharpoonright");
8666defineSymbol(math, ams, rel, "\u21c2", "\\downharpoonright");
8667defineSymbol(math, ams, rel, "\u21dd", "\\rightsquigarrow");
8668defineSymbol(math, ams, rel, "\u21dd", "\\leadsto");
8669defineSymbol(math, ams, rel, "\u21db", "\\Rrightarrow");
8670defineSymbol(math, ams, rel, "\u21be", "\\restriction");
8671
8672defineSymbol(math, main, textord, "\u2018", "`");
8673defineSymbol(math, main, textord, "$", "\\$");
8674defineSymbol(text, main, textord, "$", "\\$");
8675defineSymbol(math, main, textord, "%", "\\%");
8676defineSymbol(text, main, textord, "%", "\\%");
8677defineSymbol(math, main, textord, "_", "\\_");
8678defineSymbol(text, main, textord, "_", "\\_");
8679defineSymbol(math, main, textord, "\u2220", "\\angle");
8680defineSymbol(math, main, textord, "\u221e", "\\infty");
8681defineSymbol(math, main, textord, "\u2032", "\\prime");
8682defineSymbol(math, main, textord, "\u25b3", "\\triangle");
8683defineSymbol(math, main, textord, "\u0393", "\\Gamma");
8684defineSymbol(math, main, textord, "\u0394", "\\Delta");
8685defineSymbol(math, main, textord, "\u0398", "\\Theta");
8686defineSymbol(math, main, textord, "\u039b", "\\Lambda");
8687defineSymbol(math, main, textord, "\u039e", "\\Xi");
8688defineSymbol(math, main, textord, "\u03a0", "\\Pi");
8689defineSymbol(math, main, textord, "\u03a3", "\\Sigma");
8690defineSymbol(math, main, textord, "\u03a5", "\\Upsilon");
8691defineSymbol(math, main, textord, "\u03a6", "\\Phi");
8692defineSymbol(math, main, textord, "\u03a8", "\\Psi");
8693defineSymbol(math, main, textord, "\u03a9", "\\Omega");
8694defineSymbol(math, main, textord, "\u00ac", "\\neg");
8695defineSymbol(math, main, textord, "\u00ac", "\\lnot");
8696defineSymbol(math, main, textord, "\u22a4", "\\top");
8697defineSymbol(math, main, textord, "\u22a5", "\\bot");
8698defineSymbol(math, main, textord, "\u2205", "\\emptyset");
8699defineSymbol(math, ams, textord, "\u2205", "\\varnothing");
8700defineSymbol(math, main, mathord, "\u03b1", "\\alpha");
8701defineSymbol(math, main, mathord, "\u03b2", "\\beta");
8702defineSymbol(math, main, mathord, "\u03b3", "\\gamma");
8703defineSymbol(math, main, mathord, "\u03b4", "\\delta");
8704defineSymbol(math, main, mathord, "\u03f5", "\\epsilon");
8705defineSymbol(math, main, mathord, "\u03b6", "\\zeta");
8706defineSymbol(math, main, mathord, "\u03b7", "\\eta");
8707defineSymbol(math, main, mathord, "\u03b8", "\\theta");
8708defineSymbol(math, main, mathord, "\u03b9", "\\iota");
8709defineSymbol(math, main, mathord, "\u03ba", "\\kappa");
8710defineSymbol(math, main, mathord, "\u03bb", "\\lambda");
8711defineSymbol(math, main, mathord, "\u03bc", "\\mu");
8712defineSymbol(math, main, mathord, "\u03bd", "\\nu");
8713defineSymbol(math, main, mathord, "\u03be", "\\xi");
8714defineSymbol(math, main, mathord, "o", "\\omicron");
8715defineSymbol(math, main, mathord, "\u03c0", "\\pi");
8716defineSymbol(math, main, mathord, "\u03c1", "\\rho");
8717defineSymbol(math, main, mathord, "\u03c3", "\\sigma");
8718defineSymbol(math, main, mathord, "\u03c4", "\\tau");
8719defineSymbol(math, main, mathord, "\u03c5", "\\upsilon");
8720defineSymbol(math, main, mathord, "\u03d5", "\\phi");
8721defineSymbol(math, main, mathord, "\u03c7", "\\chi");
8722defineSymbol(math, main, mathord, "\u03c8", "\\psi");
8723defineSymbol(math, main, mathord, "\u03c9", "\\omega");
8724defineSymbol(math, main, mathord, "\u03b5", "\\varepsilon");
8725defineSymbol(math, main, mathord, "\u03d1", "\\vartheta");
8726defineSymbol(math, main, mathord, "\u03d6", "\\varpi");
8727defineSymbol(math, main, mathord, "\u03f1", "\\varrho");
8728defineSymbol(math, main, mathord, "\u03c2", "\\varsigma");
8729defineSymbol(math, main, mathord, "\u03c6", "\\varphi");
8730defineSymbol(math, main, bin, "\u2217", "*");
8731defineSymbol(math, main, bin, "+", "+");
8732defineSymbol(math, main, bin, "\u2212", "-");
8733defineSymbol(math, main, bin, "\u22c5", "\\cdot");
8734defineSymbol(math, main, bin, "\u2218", "\\circ");
8735defineSymbol(math, main, bin, "\u00f7", "\\div");
8736defineSymbol(math, main, bin, "\u00b1", "\\pm");
8737defineSymbol(math, main, bin, "\u00d7", "\\times");
8738defineSymbol(math, main, bin, "\u2229", "\\cap");
8739defineSymbol(math, main, bin, "\u222a", "\\cup");
8740defineSymbol(math, main, bin, "\u2216", "\\setminus");
8741defineSymbol(math, main, bin, "\u2227", "\\land");
8742defineSymbol(math, main, bin, "\u2228", "\\lor");
8743defineSymbol(math, main, bin, "\u2227", "\\wedge");
8744defineSymbol(math, main, bin, "\u2228", "\\vee");
8745defineSymbol(math, main, textord, "\u221a", "\\surd");
8746defineSymbol(math, main, open, "(", "(");
8747defineSymbol(math, main, open, "[", "[");
8748defineSymbol(math, main, open, "\u27e8", "\\langle");
8749defineSymbol(math, main, open, "\u2223", "\\lvert");
8750defineSymbol(math, main, open, "\u2225", "\\lVert");
8751defineSymbol(math, main, close, ")", ")");
8752defineSymbol(math, main, close, "]", "]");
8753defineSymbol(math, main, close, "?", "?");
8754defineSymbol(math, main, close, "!", "!");
8755defineSymbol(math, main, close, "\u27e9", "\\rangle");
8756defineSymbol(math, main, close, "\u2223", "\\rvert");
8757defineSymbol(math, main, close, "\u2225", "\\rVert");
8758defineSymbol(math, main, rel, "=", "=");
8759defineSymbol(math, main, rel, "<", "<");
8760defineSymbol(math, main, rel, ">", ">");
8761defineSymbol(math, main, rel, ":", ":");
8762defineSymbol(math, main, rel, "\u2248", "\\approx");
8763defineSymbol(math, main, rel, "\u2245", "\\cong");
8764defineSymbol(math, main, rel, "\u2265", "\\ge");
8765defineSymbol(math, main, rel, "\u2265", "\\geq");
8766defineSymbol(math, main, rel, "\u2190", "\\gets");
8767defineSymbol(math, main, rel, ">", "\\gt");
8768defineSymbol(math, main, rel, "\u2208", "\\in");
8769defineSymbol(math, main, rel, "\u2209", "\\notin");
8770defineSymbol(math, main, rel, "\u2282", "\\subset");
8771defineSymbol(math, main, rel, "\u2283", "\\supset");
8772defineSymbol(math, main, rel, "\u2286", "\\subseteq");
8773defineSymbol(math, main, rel, "\u2287", "\\supseteq");
8774defineSymbol(math, ams, rel, "\u2288", "\\nsubseteq");
8775defineSymbol(math, ams, rel, "\u2289", "\\nsupseteq");
8776defineSymbol(math, main, rel, "\u22a8", "\\models");
8777defineSymbol(math, main, rel, "\u2190", "\\leftarrow");
8778defineSymbol(math, main, rel, "\u2264", "\\le");
8779defineSymbol(math, main, rel, "\u2264", "\\leq");
8780defineSymbol(math, main, rel, "<", "\\lt");
8781defineSymbol(math, main, rel, "\u2260", "\\ne");
8782defineSymbol(math, main, rel, "\u2260", "\\neq");
8783defineSymbol(math, main, rel, "\u2192", "\\rightarrow");
8784defineSymbol(math, main, rel, "\u2192", "\\to");
8785defineSymbol(math, ams, rel, "\u2271", "\\ngeq");
8786defineSymbol(math, ams, rel, "\u2270", "\\nleq");
8787defineSymbol(math, main, spacing, null, "\\!");
8788defineSymbol(math, main, spacing, "\u00a0", "\\ ");
8789defineSymbol(math, main, spacing, "\u00a0", "~");
8790defineSymbol(math, main, spacing, null, "\\,");
8791defineSymbol(math, main, spacing, null, "\\:");
8792defineSymbol(math, main, spacing, null, "\\;");
8793defineSymbol(math, main, spacing, null, "\\enspace");
8794defineSymbol(math, main, spacing, null, "\\qquad");
8795defineSymbol(math, main, spacing, null, "\\quad");
8796defineSymbol(math, main, spacing, "\u00a0", "\\space");
8797defineSymbol(math, main, punct, ",", ",");
8798defineSymbol(math, main, punct, ";", ";");
8799defineSymbol(math, main, punct, ":", "\\colon");
8800defineSymbol(math, ams, bin, "\u22bc", "\\barwedge");
8801defineSymbol(math, ams, bin, "\u22bb", "\\veebar");
8802defineSymbol(math, main, bin, "\u2299", "\\odot");
8803defineSymbol(math, main, bin, "\u2295", "\\oplus");
8804defineSymbol(math, main, bin, "\u2297", "\\otimes");
8805defineSymbol(math, main, textord, "\u2202", "\\partial");
8806defineSymbol(math, main, bin, "\u2298", "\\oslash");
8807defineSymbol(math, ams, bin, "\u229a", "\\circledcirc");
8808defineSymbol(math, ams, bin, "\u22a1", "\\boxdot");
8809defineSymbol(math, main, bin, "\u25b3", "\\bigtriangleup");
8810defineSymbol(math, main, bin, "\u25bd", "\\bigtriangledown");
8811defineSymbol(math, main, bin, "\u2020", "\\dagger");
8812defineSymbol(math, main, bin, "\u22c4", "\\diamond");
8813defineSymbol(math, main, bin, "\u22c6", "\\star");
8814defineSymbol(math, main, bin, "\u25c3", "\\triangleleft");
8815defineSymbol(math, main, bin, "\u25b9", "\\triangleright");
8816defineSymbol(math, main, open, "{", "\\{");
8817defineSymbol(text, main, textord, "{", "\\{");
8818defineSymbol(math, main, close, "}", "\\}");
8819defineSymbol(text, main, textord, "}", "\\}");
8820defineSymbol(math, main, open, "{", "\\lbrace");
8821defineSymbol(math, main, close, "}", "\\rbrace");
8822defineSymbol(math, main, open, "[", "\\lbrack");
8823defineSymbol(math, main, close, "]", "\\rbrack");
8824defineSymbol(math, main, open, "\u230a", "\\lfloor");
8825defineSymbol(math, main, close, "\u230b", "\\rfloor");
8826defineSymbol(math, main, open, "\u2308", "\\lceil");
8827defineSymbol(math, main, close, "\u2309", "\\rceil");
8828defineSymbol(math, main, textord, "\\", "\\backslash");
8829defineSymbol(math, main, textord, "\u2223", "|");
8830defineSymbol(math, main, textord, "\u2223", "\\vert");
8831defineSymbol(math, main, textord, "\u2225", "\\|");
8832defineSymbol(math, main, textord, "\u2225", "\\Vert");
8833defineSymbol(math, main, rel, "\u2191", "\\uparrow");
8834defineSymbol(math, main, rel, "\u21d1", "\\Uparrow");
8835defineSymbol(math, main, rel, "\u2193", "\\downarrow");
8836defineSymbol(math, main, rel, "\u21d3", "\\Downarrow");
8837defineSymbol(math, main, rel, "\u2195", "\\updownarrow");
8838defineSymbol(math, main, rel, "\u21d5", "\\Updownarrow");
8839defineSymbol(math, math, op, "\u2210", "\\coprod");
8840defineSymbol(math, math, op, "\u22c1", "\\bigvee");
8841defineSymbol(math, math, op, "\u22c0", "\\bigwedge");
8842defineSymbol(math, math, op, "\u2a04", "\\biguplus");
8843defineSymbol(math, math, op, "\u22c2", "\\bigcap");
8844defineSymbol(math, math, op, "\u22c3", "\\bigcup");
8845defineSymbol(math, math, op, "\u222b", "\\int");
8846defineSymbol(math, math, op, "\u222b", "\\intop");
8847defineSymbol(math, math, op, "\u222c", "\\iint");
8848defineSymbol(math, math, op, "\u222d", "\\iiint");
8849defineSymbol(math, math, op, "\u220f", "\\prod");
8850defineSymbol(math, math, op, "\u2211", "\\sum");
8851defineSymbol(math, math, op, "\u2a02", "\\bigotimes");
8852defineSymbol(math, math, op, "\u2a01", "\\bigoplus");
8853defineSymbol(math, math, op, "\u2a00", "\\bigodot");
8854defineSymbol(math, math, op, "\u222e", "\\oint");
8855defineSymbol(math, math, op, "\u2a06", "\\bigsqcup");
8856defineSymbol(math, math, op, "\u222b", "\\smallint");
8857defineSymbol(text, main, inner, "\u2026", "\\textellipsis");
8858defineSymbol(math, main, inner, "\u2026", "\\mathellipsis");
8859defineSymbol(text, main, inner, "\u2026", "\\ldots");
8860defineSymbol(math, main, inner, "\u2026", "\\ldots");
8861defineSymbol(math, main, inner, "\u22ef", "\\cdots");
8862defineSymbol(math, main, inner, "\u22f1", "\\ddots");
8863defineSymbol(math, main, textord, "\u22ee", "\\vdots");
8864defineSymbol(math, main, accent, "\u00b4", "\\acute");
8865defineSymbol(math, main, accent, "\u0060", "\\grave");
8866defineSymbol(math, main, accent, "\u00a8", "\\ddot");
8867defineSymbol(math, main, accent, "\u007e", "\\tilde");
8868defineSymbol(math, main, accent, "\u00af", "\\bar");
8869defineSymbol(math, main, accent, "\u02d8", "\\breve");
8870defineSymbol(math, main, accent, "\u02c7", "\\check");
8871defineSymbol(math, main, accent, "\u005e", "\\hat");
8872defineSymbol(math, main, accent, "\u20d7", "\\vec");
8873defineSymbol(math, main, accent, "\u02d9", "\\dot");
8874defineSymbol(math, main, mathord, "\u0131", "\\imath");
8875defineSymbol(math, main, mathord, "\u0237", "\\jmath");
8876
8877defineSymbol(text, main, textord, "\u2013", "--");
8878defineSymbol(text, main, textord, "\u2014", "---");
8879defineSymbol(text, main, textord, "\u2018", "`");
8880defineSymbol(text, main, textord, "\u2019", "'");
8881defineSymbol(text, main, textord, "\u201c", "``");
8882defineSymbol(text, main, textord, "\u201d", "''");
8883defineSymbol(math, main, textord, "\u00b0", "\\degree");
8884defineSymbol(text, main, textord, "\u00b0", "\\degree");
8885defineSymbol(math, main, mathord, "\u00a3", "\\pounds");
8886defineSymbol(math, ams, textord, "\u2720", "\\maltese");
8887defineSymbol(text, ams, textord, "\u2720", "\\maltese");
8888
8889defineSymbol(text, main, spacing, "\u00a0", "\\ ");
8890defineSymbol(text, main, spacing, "\u00a0", " ");
8891defineSymbol(text, main, spacing, "\u00a0", "~");
8892
8893// There are lots of symbols which are the same, so we add them in afterwards.
8894var i;
8895var ch;
8896
8897// All of these are textords in math mode
8898var mathTextSymbols = "0123456789/@.\"";
8899for (i = 0; i < mathTextSymbols.length; i++) {
8900    ch = mathTextSymbols.charAt(i);
8901    defineSymbol(math, main, textord, ch, ch);
8902}
8903
8904// All of these are textords in text mode
8905var textSymbols = "0123456789!@*()-=+[]\";:?/.,";
8906for (i = 0; i < textSymbols.length; i++) {
8907    ch = textSymbols.charAt(i);
8908    defineSymbol(text, main, textord, ch, ch);
8909}
8910
8911// All of these are textords in text mode, and mathords in math mode
8912var letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
8913for (i = 0; i < letters.length; i++) {
8914    ch = letters.charAt(i);
8915    defineSymbol(math, main, mathord, ch, ch);
8916    defineSymbol(text, main, textord, ch, ch);
8917}
8918
8919// Latin-1 letters
8920for (i = 0x00C0; i <= 0x00D6; i++) {
8921    ch = String.fromCharCode(i);
8922    defineSymbol(text, main, textord, ch, ch);
8923}
8924
8925for (i = 0x00D8; i <= 0x00F6; i++) {
8926    ch = String.fromCharCode(i);
8927    defineSymbol(text, main, textord, ch, ch);
8928}
8929
8930for (i = 0x00F8; i <= 0x00FF; i++) {
8931    ch = String.fromCharCode(i);
8932    defineSymbol(text, main, textord, ch, ch);
8933}
8934
8935// Cyrillic
8936for (i = 0x0410; i <= 0x044F; i++) {
8937    ch = String.fromCharCode(i);
8938    defineSymbol(text, main, textord, ch, ch);
8939}
8940
8941// Unicode versions of existing characters
8942defineSymbol(text, main, textord, "\u2013", "–");
8943defineSymbol(text, main, textord, "\u2014", "—");
8944defineSymbol(text, main, textord, "\u2018", "‘");
8945defineSymbol(text, main, textord, "\u2019", "’");
8946defineSymbol(text, main, textord, "\u201c", "“");
8947defineSymbol(text, main, textord, "\u201d", "”");
8948
8949},{}],24:[function(require,module,exports){
8950var hangulRegex = /[\uAC00-\uD7AF]/;
8951
8952// This regex combines
8953// - Hiragana: [\u3040-\u309F]
8954// - Katakana: [\u30A0-\u30FF]
8955// - CJK ideograms: [\u4E00-\u9FAF]
8956// - Hangul syllables: [\uAC00-\uD7AF]
8957// Notably missing are halfwidth Katakana and Romanji glyphs.
8958var cjkRegex =
8959    /[\u3040-\u309F]|[\u30A0-\u30FF]|[\u4E00-\u9FAF]|[\uAC00-\uD7AF]/;
8960
8961module.exports = {
8962    cjkRegex: cjkRegex,
8963    hangulRegex: hangulRegex
8964};
8965
8966},{}],25:[function(require,module,exports){
8967/**
8968 * This file contains a list of utility functions which are useful in other
8969 * files.
8970 */
8971
8972/**
8973 * Provide an `indexOf` function which works in IE8, but defers to native if
8974 * possible.
8975 */
8976var nativeIndexOf = Array.prototype.indexOf;
8977var indexOf = function(list, elem) {
8978    if (list == null) {
8979        return -1;
8980    }
8981    if (nativeIndexOf && list.indexOf === nativeIndexOf) {
8982        return list.indexOf(elem);
8983    }
8984    var i = 0;
8985    var l = list.length;
8986    for (; i < l; i++) {
8987        if (list[i] === elem) {
8988            return i;
8989        }
8990    }
8991    return -1;
8992};
8993
8994/**
8995 * Return whether an element is contained in a list
8996 */
8997var contains = function(list, elem) {
8998    return indexOf(list, elem) !== -1;
8999};
9000
9001/**
9002 * Provide a default value if a setting is undefined
9003 */
9004var deflt = function(setting, defaultIfUndefined) {
9005    return setting === undefined ? defaultIfUndefined : setting;
9006};
9007
9008// hyphenate and escape adapted from Facebook's React under Apache 2 license
9009
9010var uppercase = /([A-Z])/g;
9011var hyphenate = function(str) {
9012    return str.replace(uppercase, "-$1").toLowerCase();
9013};
9014
9015var ESCAPE_LOOKUP = {
9016    "&": "&amp;",
9017    ">": "&gt;",
9018    "<": "&lt;",
9019    "\"": "&quot;",
9020    "'": "&#x27;"
9021};
9022
9023var ESCAPE_REGEX = /[&><"']/g;
9024
9025function escaper(match) {
9026    return ESCAPE_LOOKUP[match];
9027}
9028
9029/**
9030 * Escapes text to prevent scripting attacks.
9031 *
9032 * @param {*} text Text value to escape.
9033 * @return {string} An escaped string.
9034 */
9035function escape(text) {
9036    return ("" + text).replace(ESCAPE_REGEX, escaper);
9037}
9038
9039/**
9040 * A function to set the text content of a DOM element in all supported
9041 * browsers. Note that we don't define this if there is no document.
9042 */
9043var setTextContent;
9044if (typeof document !== "undefined") {
9045    var testNode = document.createElement("span");
9046    if ("textContent" in testNode) {
9047        setTextContent = function(node, text) {
9048            node.textContent = text;
9049        };
9050    } else {
9051        setTextContent = function(node, text) {
9052            node.innerText = text;
9053        };
9054    }
9055}
9056
9057/**
9058 * A function to clear a node.
9059 */
9060function clearNode(node) {
9061    setTextContent(node, "");
9062}
9063
9064module.exports = {
9065    contains: contains,
9066    deflt: deflt,
9067    escape: escape,
9068    hyphenate: hyphenate,
9069    indexOf: indexOf,
9070    setTextContent: setTextContent,
9071    clearNode: clearNode
9072};
9073
9074},{}]},{},[1])(1)
9075});