www

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

katex.mjs (583216B)


      1 /**
      2  * Lexing or parsing positional information for error reporting.
      3  * This object is immutable.
      4  */
      5 class SourceLocation {
      6   // The + prefix indicates that these fields aren't writeable
      7   // Lexer holding the input string.
      8   // Start offset, zero-based inclusive.
      9   // End offset, zero-based exclusive.
     10   constructor(lexer, start, end) {
     11     this.lexer = void 0;
     12     this.start = void 0;
     13     this.end = void 0;
     14     this.lexer = lexer;
     15     this.start = start;
     16     this.end = end;
     17   }
     18   /**
     19    * Merges two `SourceLocation`s from location providers, given they are
     20    * provided in order of appearance.
     21    * - Returns the first one's location if only the first is provided.
     22    * - Returns a merged range of the first and the last if both are provided
     23    *   and their lexers match.
     24    * - Otherwise, returns null.
     25    */
     26 
     27 
     28   static range(first, second) {
     29     if (!second) {
     30       return first && first.loc;
     31     } else if (!first || !first.loc || !second.loc || first.loc.lexer !== second.loc.lexer) {
     32       return null;
     33     } else {
     34       return new SourceLocation(first.loc.lexer, first.loc.start, second.loc.end);
     35     }
     36   }
     37 
     38 }
     39 
     40 /**
     41  * Interface required to break circular dependency between Token, Lexer, and
     42  * ParseError.
     43  */
     44 
     45 /**
     46  * The resulting token returned from `lex`.
     47  *
     48  * It consists of the token text plus some position information.
     49  * The position information is essentially a range in an input string,
     50  * but instead of referencing the bare input string, we refer to the lexer.
     51  * That way it is possible to attach extra metadata to the input string,
     52  * like for example a file name or similar.
     53  *
     54  * The position information is optional, so it is OK to construct synthetic
     55  * tokens if appropriate. Not providing available position information may
     56  * lead to degraded error reporting, though.
     57  */
     58 class Token {
     59   // don't expand the token
     60   // used in \noexpand
     61   constructor(text, // the text of this token
     62   loc) {
     63     this.text = void 0;
     64     this.loc = void 0;
     65     this.noexpand = void 0;
     66     this.treatAsRelax = void 0;
     67     this.text = text;
     68     this.loc = loc;
     69   }
     70   /**
     71    * Given a pair of tokens (this and endToken), compute a `Token` encompassing
     72    * the whole input range enclosed by these two.
     73    */
     74 
     75 
     76   range(endToken, // last token of the range, inclusive
     77   text) {
     78     return new Token(text, SourceLocation.range(this, endToken));
     79   }
     80 
     81 }
     82 
     83 /**
     84  * This is the ParseError class, which is the main error thrown by KaTeX
     85  * functions when something has gone wrong. This is used to distinguish internal
     86  * errors from errors in the expression that the user provided.
     87  *
     88  * If possible, a caller should provide a Token or ParseNode with information
     89  * about where in the source string the problem occurred.
     90  */
     91 class ParseError {
     92   // Error position based on passed-in Token or ParseNode.
     93   constructor(message, // The error message
     94   token) {
     95     this.position = void 0;
     96     var error = "KaTeX parse error: " + message;
     97     var start;
     98     var loc = token && token.loc;
     99 
    100     if (loc && loc.start <= loc.end) {
    101       // If we have the input and a position, make the error a bit fancier
    102       // Get the input
    103       var input = loc.lexer.input; // Prepend some information
    104 
    105       start = loc.start;
    106       var end = loc.end;
    107 
    108       if (start === input.length) {
    109         error += " at end of input: ";
    110       } else {
    111         error += " at position " + (start + 1) + ": ";
    112       } // Underline token in question using combining underscores
    113 
    114 
    115       var underlined = input.slice(start, end).replace(/[^]/g, "$&\u0332"); // Extract some context from the input and add it to the error
    116 
    117       var left;
    118 
    119       if (start > 15) {
    120         left = "…" + input.slice(start - 15, start);
    121       } else {
    122         left = input.slice(0, start);
    123       }
    124 
    125       var right;
    126 
    127       if (end + 15 < input.length) {
    128         right = input.slice(end, end + 15) + "…";
    129       } else {
    130         right = input.slice(end);
    131       }
    132 
    133       error += left + underlined + right;
    134     } // Some hackery to make ParseError a prototype of Error
    135     // See http://stackoverflow.com/a/8460753
    136 
    137 
    138     var self = new Error(error);
    139     self.name = "ParseError"; // $FlowFixMe
    140 
    141     self.__proto__ = ParseError.prototype; // $FlowFixMe
    142 
    143     self.position = start;
    144     return self;
    145   }
    146 
    147 } // $FlowFixMe More hackery
    148 
    149 
    150 ParseError.prototype.__proto__ = Error.prototype;
    151 
    152 /**
    153  * This file contains a list of utility functions which are useful in other
    154  * files.
    155  */
    156 
    157 /**
    158  * Return whether an element is contained in a list
    159  */
    160 var contains = function contains(list, elem) {
    161   return list.indexOf(elem) !== -1;
    162 };
    163 /**
    164  * Provide a default value if a setting is undefined
    165  * NOTE: Couldn't use `T` as the output type due to facebook/flow#5022.
    166  */
    167 
    168 
    169 var deflt = function deflt(setting, defaultIfUndefined) {
    170   return setting === undefined ? defaultIfUndefined : setting;
    171 }; // hyphenate and escape adapted from Facebook's React under Apache 2 license
    172 
    173 
    174 var uppercase = /([A-Z])/g;
    175 
    176 var hyphenate = function hyphenate(str) {
    177   return str.replace(uppercase, "-$1").toLowerCase();
    178 };
    179 
    180 var ESCAPE_LOOKUP = {
    181   "&": "&amp;",
    182   ">": "&gt;",
    183   "<": "&lt;",
    184   "\"": "&quot;",
    185   "'": "&#x27;"
    186 };
    187 var ESCAPE_REGEX = /[&><"']/g;
    188 /**
    189  * Escapes text to prevent scripting attacks.
    190  */
    191 
    192 function escape(text) {
    193   return String(text).replace(ESCAPE_REGEX, match => ESCAPE_LOOKUP[match]);
    194 }
    195 /**
    196  * Sometimes we want to pull out the innermost element of a group. In most
    197  * cases, this will just be the group itself, but when ordgroups and colors have
    198  * a single element, we want to pull that out.
    199  */
    200 
    201 
    202 var getBaseElem = function getBaseElem(group) {
    203   if (group.type === "ordgroup") {
    204     if (group.body.length === 1) {
    205       return getBaseElem(group.body[0]);
    206     } else {
    207       return group;
    208     }
    209   } else if (group.type === "color") {
    210     if (group.body.length === 1) {
    211       return getBaseElem(group.body[0]);
    212     } else {
    213       return group;
    214     }
    215   } else if (group.type === "font") {
    216     return getBaseElem(group.body);
    217   } else {
    218     return group;
    219   }
    220 };
    221 /**
    222  * TeXbook algorithms often reference "character boxes", which are simply groups
    223  * with a single character in them. To decide if something is a character box,
    224  * we find its innermost group, and see if it is a single character.
    225  */
    226 
    227 
    228 var isCharacterBox = function isCharacterBox(group) {
    229   var baseElem = getBaseElem(group); // These are all they types of groups which hold single characters
    230 
    231   return baseElem.type === "mathord" || baseElem.type === "textord" || baseElem.type === "atom";
    232 };
    233 
    234 var assert = function assert(value) {
    235   if (!value) {
    236     throw new Error('Expected non-null, but got ' + String(value));
    237   }
    238 
    239   return value;
    240 };
    241 /**
    242  * Return the protocol of a URL, or "_relative" if the URL does not specify a
    243  * protocol (and thus is relative).
    244  */
    245 
    246 var protocolFromUrl = function protocolFromUrl(url) {
    247   var protocol = /^\s*([^\\/#]*?)(?::|&#0*58|&#x0*3a)/i.exec(url);
    248   return protocol != null ? protocol[1] : "_relative";
    249 };
    250 var utils = {
    251   contains,
    252   deflt,
    253   escape,
    254   hyphenate,
    255   getBaseElem,
    256   isCharacterBox,
    257   protocolFromUrl
    258 };
    259 
    260 /* eslint no-console:0 */
    261 
    262 /**
    263  * The main Settings object
    264  *
    265  * The current options stored are:
    266  *  - displayMode: Whether the expression should be typeset as inline math
    267  *                 (false, the default), meaning that the math starts in
    268  *                 \textstyle and is placed in an inline-block); or as display
    269  *                 math (true), meaning that the math starts in \displaystyle
    270  *                 and is placed in a block with vertical margin.
    271  */
    272 class Settings {
    273   constructor(options) {
    274     this.displayMode = void 0;
    275     this.output = void 0;
    276     this.leqno = void 0;
    277     this.fleqn = void 0;
    278     this.throwOnError = void 0;
    279     this.errorColor = void 0;
    280     this.macros = void 0;
    281     this.minRuleThickness = void 0;
    282     this.colorIsTextColor = void 0;
    283     this.strict = void 0;
    284     this.trust = void 0;
    285     this.maxSize = void 0;
    286     this.maxExpand = void 0;
    287     this.globalGroup = void 0;
    288     // allow null options
    289     options = options || {};
    290     this.displayMode = utils.deflt(options.displayMode, false);
    291     this.output = utils.deflt(options.output, "htmlAndMathml");
    292     this.leqno = utils.deflt(options.leqno, false);
    293     this.fleqn = utils.deflt(options.fleqn, false);
    294     this.throwOnError = utils.deflt(options.throwOnError, true);
    295     this.errorColor = utils.deflt(options.errorColor, "#cc0000");
    296     this.macros = options.macros || {};
    297     this.minRuleThickness = Math.max(0, utils.deflt(options.minRuleThickness, 0));
    298     this.colorIsTextColor = utils.deflt(options.colorIsTextColor, false);
    299     this.strict = utils.deflt(options.strict, "warn");
    300     this.trust = utils.deflt(options.trust, false);
    301     this.maxSize = Math.max(0, utils.deflt(options.maxSize, Infinity));
    302     this.maxExpand = Math.max(0, utils.deflt(options.maxExpand, 1000));
    303     this.globalGroup = utils.deflt(options.globalGroup, false);
    304   }
    305   /**
    306    * Report nonstrict (non-LaTeX-compatible) input.
    307    * Can safely not be called if `this.strict` is false in JavaScript.
    308    */
    309 
    310 
    311   reportNonstrict(errorCode, errorMsg, token) {
    312     var strict = this.strict;
    313 
    314     if (typeof strict === "function") {
    315       // Allow return value of strict function to be boolean or string
    316       // (or null/undefined, meaning no further processing).
    317       strict = strict(errorCode, errorMsg, token);
    318     }
    319 
    320     if (!strict || strict === "ignore") {
    321       return;
    322     } else if (strict === true || strict === "error") {
    323       throw new ParseError("LaTeX-incompatible input and strict mode is set to 'error': " + (errorMsg + " [" + errorCode + "]"), token);
    324     } else if (strict === "warn") {
    325       typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to 'warn': " + (errorMsg + " [" + errorCode + "]"));
    326     } else {
    327       // won't happen in type-safe code
    328       typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to " + ("unrecognized '" + strict + "': " + errorMsg + " [" + errorCode + "]"));
    329     }
    330   }
    331   /**
    332    * Check whether to apply strict (LaTeX-adhering) behavior for unusual
    333    * input (like `\\`).  Unlike `nonstrict`, will not throw an error;
    334    * instead, "error" translates to a return value of `true`, while "ignore"
    335    * translates to a return value of `false`.  May still print a warning:
    336    * "warn" prints a warning and returns `false`.
    337    * This is for the second category of `errorCode`s listed in the README.
    338    */
    339 
    340 
    341   useStrictBehavior(errorCode, errorMsg, token) {
    342     var strict = this.strict;
    343 
    344     if (typeof strict === "function") {
    345       // Allow return value of strict function to be boolean or string
    346       // (or null/undefined, meaning no further processing).
    347       // But catch any exceptions thrown by function, treating them
    348       // like "error".
    349       try {
    350         strict = strict(errorCode, errorMsg, token);
    351       } catch (error) {
    352         strict = "error";
    353       }
    354     }
    355 
    356     if (!strict || strict === "ignore") {
    357       return false;
    358     } else if (strict === true || strict === "error") {
    359       return true;
    360     } else if (strict === "warn") {
    361       typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to 'warn': " + (errorMsg + " [" + errorCode + "]"));
    362       return false;
    363     } else {
    364       // won't happen in type-safe code
    365       typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to " + ("unrecognized '" + strict + "': " + errorMsg + " [" + errorCode + "]"));
    366       return false;
    367     }
    368   }
    369   /**
    370    * Check whether to test potentially dangerous input, and return
    371    * `true` (trusted) or `false` (untrusted).  The sole argument `context`
    372    * should be an object with `command` field specifying the relevant LaTeX
    373    * command (as a string starting with `\`), and any other arguments, etc.
    374    * If `context` has a `url` field, a `protocol` field will automatically
    375    * get added by this function (changing the specified object).
    376    */
    377 
    378 
    379   isTrusted(context) {
    380     if (context.url && !context.protocol) {
    381       context.protocol = utils.protocolFromUrl(context.url);
    382     }
    383 
    384     var trust = typeof this.trust === "function" ? this.trust(context) : this.trust;
    385     return Boolean(trust);
    386   }
    387 
    388 }
    389 
    390 /**
    391  * This file contains information and classes for the various kinds of styles
    392  * used in TeX. It provides a generic `Style` class, which holds information
    393  * about a specific style. It then provides instances of all the different kinds
    394  * of styles possible, and provides functions to move between them and get
    395  * information about them.
    396  */
    397 
    398 /**
    399  * The main style class. Contains a unique id for the style, a size (which is
    400  * the same for cramped and uncramped version of a style), and a cramped flag.
    401  */
    402 class Style {
    403   constructor(id, size, cramped) {
    404     this.id = void 0;
    405     this.size = void 0;
    406     this.cramped = void 0;
    407     this.id = id;
    408     this.size = size;
    409     this.cramped = cramped;
    410   }
    411   /**
    412    * Get the style of a superscript given a base in the current style.
    413    */
    414 
    415 
    416   sup() {
    417     return styles[sup[this.id]];
    418   }
    419   /**
    420    * Get the style of a subscript given a base in the current style.
    421    */
    422 
    423 
    424   sub() {
    425     return styles[sub[this.id]];
    426   }
    427   /**
    428    * Get the style of a fraction numerator given the fraction in the current
    429    * style.
    430    */
    431 
    432 
    433   fracNum() {
    434     return styles[fracNum[this.id]];
    435   }
    436   /**
    437    * Get the style of a fraction denominator given the fraction in the current
    438    * style.
    439    */
    440 
    441 
    442   fracDen() {
    443     return styles[fracDen[this.id]];
    444   }
    445   /**
    446    * Get the cramped version of a style (in particular, cramping a cramped style
    447    * doesn't change the style).
    448    */
    449 
    450 
    451   cramp() {
    452     return styles[cramp[this.id]];
    453   }
    454   /**
    455    * Get a text or display version of this style.
    456    */
    457 
    458 
    459   text() {
    460     return styles[text[this.id]];
    461   }
    462   /**
    463    * Return true if this style is tightly spaced (scriptstyle/scriptscriptstyle)
    464    */
    465 
    466 
    467   isTight() {
    468     return this.size >= 2;
    469   }
    470 
    471 } // Export an interface for type checking, but don't expose the implementation.
    472 // This way, no more styles can be generated.
    473 
    474 
    475 // IDs of the different styles
    476 var D = 0;
    477 var Dc = 1;
    478 var T = 2;
    479 var Tc = 3;
    480 var S = 4;
    481 var Sc = 5;
    482 var SS = 6;
    483 var SSc = 7; // Instances of the different styles
    484 
    485 var styles = [new Style(D, 0, false), new Style(Dc, 0, true), new Style(T, 1, false), new Style(Tc, 1, true), new Style(S, 2, false), new Style(Sc, 2, true), new Style(SS, 3, false), new Style(SSc, 3, true)]; // Lookup tables for switching from one style to another
    486 
    487 var sup = [S, Sc, S, Sc, SS, SSc, SS, SSc];
    488 var sub = [Sc, Sc, Sc, Sc, SSc, SSc, SSc, SSc];
    489 var fracNum = [T, Tc, S, Sc, SS, SSc, SS, SSc];
    490 var fracDen = [Tc, Tc, Sc, Sc, SSc, SSc, SSc, SSc];
    491 var cramp = [Dc, Dc, Tc, Tc, Sc, Sc, SSc, SSc];
    492 var text = [D, Dc, T, Tc, T, Tc, T, Tc]; // We only export some of the styles.
    493 
    494 var Style$1 = {
    495   DISPLAY: styles[D],
    496   TEXT: styles[T],
    497   SCRIPT: styles[S],
    498   SCRIPTSCRIPT: styles[SS]
    499 };
    500 
    501 /*
    502  * This file defines the Unicode scripts and script families that we
    503  * support. To add new scripts or families, just add a new entry to the
    504  * scriptData array below. Adding scripts to the scriptData array allows
    505  * characters from that script to appear in \text{} environments.
    506  */
    507 
    508 /**
    509  * Each script or script family has a name and an array of blocks.
    510  * Each block is an array of two numbers which specify the start and
    511  * end points (inclusive) of a block of Unicode codepoints.
    512  */
    513 
    514 /**
    515  * Unicode block data for the families of scripts we support in \text{}.
    516  * Scripts only need to appear here if they do not have font metrics.
    517  */
    518 var scriptData = [{
    519   // Latin characters beyond the Latin-1 characters we have metrics for.
    520   // Needed for Czech, Hungarian and Turkish text, for example.
    521   name: 'latin',
    522   blocks: [[0x0100, 0x024f], // Latin Extended-A and Latin Extended-B
    523   [0x0300, 0x036f] // Combining Diacritical marks
    524   ]
    525 }, {
    526   // The Cyrillic script used by Russian and related languages.
    527   // A Cyrillic subset used to be supported as explicitly defined
    528   // symbols in symbols.js
    529   name: 'cyrillic',
    530   blocks: [[0x0400, 0x04ff]]
    531 }, {
    532   // Armenian
    533   name: 'armenian',
    534   blocks: [[0x0530, 0x058F]]
    535 }, {
    536   // The Brahmic scripts of South and Southeast Asia
    537   // Devanagari (0900–097F)
    538   // Bengali (0980–09FF)
    539   // Gurmukhi (0A00–0A7F)
    540   // Gujarati (0A80–0AFF)
    541   // Oriya (0B00–0B7F)
    542   // Tamil (0B80–0BFF)
    543   // Telugu (0C00–0C7F)
    544   // Kannada (0C80–0CFF)
    545   // Malayalam (0D00–0D7F)
    546   // Sinhala (0D80–0DFF)
    547   // Thai (0E00–0E7F)
    548   // Lao (0E80–0EFF)
    549   // Tibetan (0F00–0FFF)
    550   // Myanmar (1000–109F)
    551   name: 'brahmic',
    552   blocks: [[0x0900, 0x109F]]
    553 }, {
    554   name: 'georgian',
    555   blocks: [[0x10A0, 0x10ff]]
    556 }, {
    557   // Chinese and Japanese.
    558   // The "k" in cjk is for Korean, but we've separated Korean out
    559   name: "cjk",
    560   blocks: [[0x3000, 0x30FF], // CJK symbols and punctuation, Hiragana, Katakana
    561   [0x4E00, 0x9FAF], // CJK ideograms
    562   [0xFF00, 0xFF60] // Fullwidth punctuation
    563   // TODO: add halfwidth Katakana and Romanji glyphs
    564   ]
    565 }, {
    566   // Korean
    567   name: 'hangul',
    568   blocks: [[0xAC00, 0xD7AF]]
    569 }];
    570 /**
    571  * Given a codepoint, return the name of the script or script family
    572  * it is from, or null if it is not part of a known block
    573  */
    574 
    575 function scriptFromCodepoint(codepoint) {
    576   for (var i = 0; i < scriptData.length; i++) {
    577     var script = scriptData[i];
    578 
    579     for (var _i = 0; _i < script.blocks.length; _i++) {
    580       var block = script.blocks[_i];
    581 
    582       if (codepoint >= block[0] && codepoint <= block[1]) {
    583         return script.name;
    584       }
    585     }
    586   }
    587 
    588   return null;
    589 }
    590 /**
    591  * A flattened version of all the supported blocks in a single array.
    592  * This is an optimization to make supportedCodepoint() fast.
    593  */
    594 
    595 var allBlocks = [];
    596 scriptData.forEach(s => s.blocks.forEach(b => allBlocks.push(...b)));
    597 /**
    598  * Given a codepoint, return true if it falls within one of the
    599  * scripts or script families defined above and false otherwise.
    600  *
    601  * Micro benchmarks shows that this is faster than
    602  * /[\u3000-\u30FF\u4E00-\u9FAF\uFF00-\uFF60\uAC00-\uD7AF\u0900-\u109F]/.test()
    603  * in Firefox, Chrome and Node.
    604  */
    605 
    606 function supportedCodepoint(codepoint) {
    607   for (var i = 0; i < allBlocks.length; i += 2) {
    608     if (codepoint >= allBlocks[i] && codepoint <= allBlocks[i + 1]) {
    609       return true;
    610     }
    611   }
    612 
    613   return false;
    614 }
    615 
    616 /**
    617  * This file provides support to domTree.js and delimiter.js.
    618  * It's a storehouse of path geometry for SVG images.
    619  */
    620 // In all paths below, the viewBox-to-em scale is 1000:1.
    621 var hLinePad = 80; // padding above a sqrt viniculum. Prevents image cropping.
    622 // The viniculum of a \sqrt can be made thicker by a KaTeX rendering option.
    623 // Think of variable extraViniculum as two detours in the SVG path.
    624 // The detour begins at the lower left of the area labeled extraViniculum below.
    625 // The detour proceeds one extraViniculum distance up and slightly to the right,
    626 // displacing the radiused corner between surd and viniculum. The radius is
    627 // traversed as usual, then the detour resumes. It goes right, to the end of
    628 // the very long viniculumn, then down one extraViniculum distance,
    629 // after which it resumes regular path geometry for the radical.
    630 
    631 /*                                                  viniculum
    632                                                    /
    633          /▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒←extraViniculum
    634         / █████████████████████←0.04em (40 unit) std viniculum thickness
    635        / /
    636       / /
    637      / /\
    638     / / surd
    639 */
    640 
    641 var sqrtMain = function sqrtMain(extraViniculum, hLinePad) {
    642   // sqrtMain path geometry is from glyph U221A in the font KaTeX Main
    643   return "M95," + (622 + extraViniculum + hLinePad) + "\nc-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14\nc0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54\nc44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10\ns173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429\nc69,-144,104.5,-217.7,106.5,-221\nl" + extraViniculum / 2.075 + " -" + extraViniculum + "\nc5.3,-9.3,12,-14,20,-14\nH400000v" + (40 + extraViniculum) + "H845.2724\ns-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7\nc-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z\nM" + (834 + extraViniculum) + " " + hLinePad + "h400000v" + (40 + extraViniculum) + "h-400000z";
    644 };
    645 
    646 var sqrtSize1 = function sqrtSize1(extraViniculum, hLinePad) {
    647   // size1 is from glyph U221A in the font KaTeX_Size1-Regular
    648   return "M263," + (601 + extraViniculum + hLinePad) + "c0.7,0,18,39.7,52,119\nc34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120\nc340,-704.7,510.7,-1060.3,512,-1067\nl" + extraViniculum / 2.084 + " -" + extraViniculum + "\nc4.7,-7.3,11,-11,19,-11\nH40000v" + (40 + extraViniculum) + "H1012.3\ns-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232\nc-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1\ns-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26\nc-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60z\nM" + (1001 + extraViniculum) + " " + hLinePad + "h400000v" + (40 + extraViniculum) + "h-400000z";
    649 };
    650 
    651 var sqrtSize2 = function sqrtSize2(extraViniculum, hLinePad) {
    652   // size2 is from glyph U221A in the font KaTeX_Size2-Regular
    653   return "M983 " + (10 + extraViniculum + hLinePad) + "\nl" + extraViniculum / 3.13 + " -" + extraViniculum + "\nc4,-6.7,10,-10,18,-10 H400000v" + (40 + extraViniculum) + "\nH1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7\ns-12,0,-12,0c-1.3,-3.3,-3.7,-11.7,-7,-25c-35.3,-125.3,-106.7,-373.3,-214,-744\nc-10,12,-21,25,-33,39s-32,39,-32,39c-6,-5.3,-15,-14,-27,-26s25,-30,25,-30\nc26.7,-32.7,52,-63,76,-91s52,-60,52,-60s208,722,208,722\nc56,-175.3,126.3,-397.3,211,-666c84.7,-268.7,153.8,-488.2,207.5,-658.5\nc53.7,-170.3,84.5,-266.8,92.5,-289.5z\nM" + (1001 + extraViniculum) + " " + hLinePad + "h400000v" + (40 + extraViniculum) + "h-400000z";
    654 };
    655 
    656 var sqrtSize3 = function sqrtSize3(extraViniculum, hLinePad) {
    657   // size3 is from glyph U221A in the font KaTeX_Size3-Regular
    658   return "M424," + (2398 + extraViniculum + hLinePad) + "\nc-1.3,-0.7,-38.5,-172,-111.5,-514c-73,-342,-109.8,-513.3,-110.5,-514\nc0,-2,-10.7,14.3,-32,49c-4.7,7.3,-9.8,15.7,-15.5,25c-5.7,9.3,-9.8,16,-12.5,20\ns-5,7,-5,7c-4,-3.3,-8.3,-7.7,-13,-13s-13,-13,-13,-13s76,-122,76,-122s77,-121,77,-121\ns209,968,209,968c0,-2,84.7,-361.7,254,-1079c169.3,-717.3,254.7,-1077.7,256,-1081\nl" + extraViniculum / 4.223 + " -" + extraViniculum + "c4,-6.7,10,-10,18,-10 H400000\nv" + (40 + extraViniculum) + "H1014.6\ns-87.3,378.7,-272.6,1166c-185.3,787.3,-279.3,1182.3,-282,1185\nc-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2z M" + (1001 + extraViniculum) + " " + hLinePad + "\nh400000v" + (40 + extraViniculum) + "h-400000z";
    659 };
    660 
    661 var sqrtSize4 = function sqrtSize4(extraViniculum, hLinePad) {
    662   // size4 is from glyph U221A in the font KaTeX_Size4-Regular
    663   return "M473," + (2713 + extraViniculum + hLinePad) + "\nc339.3,-1799.3,509.3,-2700,510,-2702 l" + extraViniculum / 5.298 + " -" + extraViniculum + "\nc3.3,-7.3,9.3,-11,18,-11 H400000v" + (40 + extraViniculum) + "H1017.7\ns-90.5,478,-276.2,1466c-185.7,988,-279.5,1483,-281.5,1485c-2,6,-10,9,-24,9\nc-8,0,-12,-0.7,-12,-2c0,-1.3,-5.3,-32,-16,-92c-50.7,-293.3,-119.7,-693.3,-207,-1200\nc0,-1.3,-5.3,8.7,-16,30c-10.7,21.3,-21.3,42.7,-32,64s-16,33,-16,33s-26,-26,-26,-26\ns76,-153,76,-153s77,-151,77,-151c0.7,0.7,35.7,202,105,604c67.3,400.7,102,602.7,104,\n606zM" + (1001 + extraViniculum) + " " + hLinePad + "h400000v" + (40 + extraViniculum) + "H1017.7z";
    664 };
    665 
    666 var phasePath = function phasePath(y) {
    667   var x = y / 2; // x coordinate at top of angle
    668 
    669   return "M400000 " + y + " H0 L" + x + " 0 l65 45 L145 " + (y - 80) + " H400000z";
    670 };
    671 
    672 var sqrtTall = function sqrtTall(extraViniculum, hLinePad, viewBoxHeight) {
    673   // sqrtTall is from glyph U23B7 in the font KaTeX_Size4-Regular
    674   // One path edge has a variable length. It runs vertically from the viniculumn
    675   // to a point near (14 units) the bottom of the surd. The viniculum
    676   // is normally 40 units thick. So the length of the line in question is:
    677   var vertSegment = viewBoxHeight - 54 - hLinePad - extraViniculum;
    678   return "M702 " + (extraViniculum + hLinePad) + "H400000" + (40 + extraViniculum) + "\nH742v" + vertSegment + "l-4 4-4 4c-.667.7 -2 1.5-4 2.5s-4.167 1.833-6.5 2.5-5.5 1-9.5 1\nh-12l-28-84c-16.667-52-96.667 -294.333-240-727l-212 -643 -85 170\nc-4-3.333-8.333-7.667-13 -13l-13-13l77-155 77-156c66 199.333 139 419.667\n219 661 l218 661zM702 " + hLinePad + "H400000v" + (40 + extraViniculum) + "H742z";
    679 };
    680 
    681 var sqrtPath = function sqrtPath(size, extraViniculum, viewBoxHeight) {
    682   extraViniculum = 1000 * extraViniculum; // Convert from document ems to viewBox.
    683 
    684   var path = "";
    685 
    686   switch (size) {
    687     case "sqrtMain":
    688       path = sqrtMain(extraViniculum, hLinePad);
    689       break;
    690 
    691     case "sqrtSize1":
    692       path = sqrtSize1(extraViniculum, hLinePad);
    693       break;
    694 
    695     case "sqrtSize2":
    696       path = sqrtSize2(extraViniculum, hLinePad);
    697       break;
    698 
    699     case "sqrtSize3":
    700       path = sqrtSize3(extraViniculum, hLinePad);
    701       break;
    702 
    703     case "sqrtSize4":
    704       path = sqrtSize4(extraViniculum, hLinePad);
    705       break;
    706 
    707     case "sqrtTall":
    708       path = sqrtTall(extraViniculum, hLinePad, viewBoxHeight);
    709   }
    710 
    711   return path;
    712 };
    713 var innerPath = function innerPath(name, height) {
    714   // The inner part of stretchy tall delimiters
    715   switch (name) {
    716     case "\u239c":
    717       return "M291 0 H417 V" + height + " H291z M291 0 H417 V" + height + " H291z";
    718 
    719     case "\u2223":
    720       return "M145 0 H188 V" + height + " H145z M145 0 H188 V" + height + " H145z";
    721 
    722     case "\u2225":
    723       return "M145 0 H188 V" + height + " H145z M145 0 H188 V" + height + " H145z" + ("M367 0 H410 V" + height + " H367z M367 0 H410 V" + height + " H367z");
    724 
    725     case "\u239f":
    726       return "M457 0 H583 V" + height + " H457z M457 0 H583 V" + height + " H457z";
    727 
    728     case "\u23a2":
    729       return "M319 0 H403 V" + height + " H319z M319 0 H403 V" + height + " H319z";
    730 
    731     case "\u23a5":
    732       return "M263 0 H347 V" + height + " H263z M263 0 H347 V" + height + " H263z";
    733 
    734     case "\u23aa":
    735       return "M384 0 H504 V" + height + " H384z M384 0 H504 V" + height + " H384z";
    736 
    737     case "\u23d0":
    738       return "M312 0 H355 V" + height + " H312z M312 0 H355 V" + height + " H312z";
    739 
    740     case "\u2016":
    741       return "M257 0 H300 V" + height + " H257z M257 0 H300 V" + height + " H257z" + ("M478 0 H521 V" + height + " H478z M478 0 H521 V" + height + " H478z");
    742 
    743     default:
    744       return "";
    745   }
    746 };
    747 var path = {
    748   // The doubleleftarrow geometry is from glyph U+21D0 in the font KaTeX Main
    749   doubleleftarrow: "M262 157\nl10-10c34-36 62.7-77 86-123 3.3-8 5-13.3 5-16 0-5.3-6.7-8-20-8-7.3\n 0-12.2.5-14.5 1.5-2.3 1-4.8 4.5-7.5 10.5-49.3 97.3-121.7 169.3-217 216-28\n 14-57.3 25-88 33-6.7 2-11 3.8-13 5.5-2 1.7-3 4.2-3 7.5s1 5.8 3 7.5\nc2 1.7 6.3 3.5 13 5.5 68 17.3 128.2 47.8 180.5 91.5 52.3 43.7 93.8 96.2 124.5\n 157.5 9.3 8 15.3 12.3 18 13h6c12-.7 18-4 18-10 0-2-1.7-7-5-15-23.3-46-52-87\n-86-123l-10-10h399738v-40H218c328 0 0 0 0 0l-10-8c-26.7-20-65.7-43-117-69 2.7\n-2 6-3.7 10-5 36.7-16 72.3-37.3 107-64l10-8h399782v-40z\nm8 0v40h399730v-40zm0 194v40h399730v-40z",
    750   // doublerightarrow is from glyph U+21D2 in font KaTeX Main
    751   doublerightarrow: "M399738 392l\n-10 10c-34 36-62.7 77-86 123-3.3 8-5 13.3-5 16 0 5.3 6.7 8 20 8 7.3 0 12.2-.5\n 14.5-1.5 2.3-1 4.8-4.5 7.5-10.5 49.3-97.3 121.7-169.3 217-216 28-14 57.3-25 88\n-33 6.7-2 11-3.8 13-5.5 2-1.7 3-4.2 3-7.5s-1-5.8-3-7.5c-2-1.7-6.3-3.5-13-5.5-68\n-17.3-128.2-47.8-180.5-91.5-52.3-43.7-93.8-96.2-124.5-157.5-9.3-8-15.3-12.3-18\n-13h-6c-12 .7-18 4-18 10 0 2 1.7 7 5 15 23.3 46 52 87 86 123l10 10H0v40h399782\nc-328 0 0 0 0 0l10 8c26.7 20 65.7 43 117 69-2.7 2-6 3.7-10 5-36.7 16-72.3 37.3\n-107 64l-10 8H0v40zM0 157v40h399730v-40zm0 194v40h399730v-40z",
    752   // leftarrow is from glyph U+2190 in font KaTeX Main
    753   leftarrow: "M400000 241H110l3-3c68.7-52.7 113.7-120\n 135-202 4-14.7 6-23 6-25 0-7.3-7-11-21-11-8 0-13.2.8-15.5 2.5-2.3 1.7-4.2 5.8\n-5.5 12.5-1.3 4.7-2.7 10.3-4 17-12 48.7-34.8 92-68.5 130S65.3 228.3 18 247\nc-10 4-16 7.7-18 11 0 8.7 6 14.3 18 17 47.3 18.7 87.8 47 121.5 85S196 441.3 208\n 490c.7 2 1.3 5 2 9s1.2 6.7 1.5 8c.3 1.3 1 3.3 2 6s2.2 4.5 3.5 5.5c1.3 1 3.3\n 1.8 6 2.5s6 1 10 1c14 0 21-3.7 21-11 0-2-2-10.3-6-25-20-79.3-65-146.7-135-202\n l-3-3h399890zM100 241v40h399900v-40z",
    754   // overbrace is from glyphs U+23A9/23A8/23A7 in font KaTeX_Size4-Regular
    755   leftbrace: "M6 548l-6-6v-35l6-11c56-104 135.3-181.3 238-232 57.3-28.7 117\n-45 179-50h399577v120H403c-43.3 7-81 15-113 26-100.7 33-179.7 91-237 174-2.7\n 5-6 9-10 13-.7 1-7.3 1-20 1H6z",
    756   leftbraceunder: "M0 6l6-6h17c12.688 0 19.313.3 20 1 4 4 7.313 8.3 10 13\n 35.313 51.3 80.813 93.8 136.5 127.5 55.688 33.7 117.188 55.8 184.5 66.5.688\n 0 2 .3 4 1 18.688 2.7 76 4.3 172 5h399450v120H429l-6-1c-124.688-8-235-61.7\n-331-161C60.687 138.7 32.312 99.3 7 54L0 41V6z",
    757   // overgroup is from the MnSymbol package (public domain)
    758   leftgroup: "M400000 80\nH435C64 80 168.3 229.4 21 260c-5.9 1.2-18 0-18 0-2 0-3-1-3-3v-38C76 61 257 0\n 435 0h399565z",
    759   leftgroupunder: "M400000 262\nH435C64 262 168.3 112.6 21 82c-5.9-1.2-18 0-18 0-2 0-3 1-3 3v38c76 158 257 219\n 435 219h399565z",
    760   // Harpoons are from glyph U+21BD in font KaTeX Main
    761   leftharpoon: "M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3\n-3.3 10.2-9.5 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5\n-18.3 3-21-1.3-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7\n-196 228-6.7 4.7-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40z",
    762   leftharpoonplus: "M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3-3.3 10.2-9.5\n 20.5-18.5s17.8-15.8 22.5-20.5c50.7-52 88-110.3 112-175 4-11.3 5-18.3 3-21-1.3\n-4-7.3-6-18-6-8 0-13 .7-15 2s-4.7 6.7-8 16c-42 98.7-107.3 174.7-196 228-6.7 4.7\n-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40zM0 435v40h400000v-40z\nm0 0v40h400000v-40z",
    763   leftharpoondown: "M7 241c-4 4-6.333 8.667-7 14 0 5.333.667 9 2 11s5.333\n 5.333 12 10c90.667 54 156 130 196 228 3.333 10.667 6.333 16.333 9 17 2 .667 5\n 1 9 1h5c10.667 0 16.667-2 18-6 2-2.667 1-9.667-3-21-32-87.333-82.667-157.667\n-152-211l-3-3h399907v-40zM93 281 H400000 v-40L7 241z",
    764   leftharpoondownplus: "M7 435c-4 4-6.3 8.7-7 14 0 5.3.7 9 2 11s5.3 5.3 12\n 10c90.7 54 156 130 196 228 3.3 10.7 6.3 16.3 9 17 2 .7 5 1 9 1h5c10.7 0 16.7\n-2 18-6 2-2.7 1-9.7-3-21-32-87.3-82.7-157.7-152-211l-3-3h399907v-40H7zm93 0\nv40h399900v-40zM0 241v40h399900v-40zm0 0v40h399900v-40z",
    765   // hook is from glyph U+21A9 in font KaTeX Main
    766   lefthook: "M400000 281 H103s-33-11.2-61-33.5S0 197.3 0 164s14.2-61.2 42.5\n-83.5C70.8 58.2 104 47 142 47 c16.7 0 25 6.7 25 20 0 12-8.7 18.7-26 20-40 3.3\n-68.7 15.7-86 37-10 12-15 25.3-15 40 0 22.7 9.8 40.7 29.5 54 19.7 13.3 43.5 21\n 71.5 23h399859zM103 281v-40h399897v40z",
    767   leftlinesegment: "M40 281 V428 H0 V94 H40 V241 H400000 v40z\nM40 281 V428 H0 V94 H40 V241 H400000 v40z",
    768   leftmapsto: "M40 281 V448H0V74H40V241H400000v40z\nM40 281 V448H0V74H40V241H400000v40z",
    769   // tofrom is from glyph U+21C4 in font KaTeX AMS Regular
    770   leftToFrom: "M0 147h400000v40H0zm0 214c68 40 115.7 95.7 143 167h22c15.3 0 23\n-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69-70-101l-7-8h399905v-40H95l7-8\nc28.7-32 52-65.7 70-101 10.7-23.3 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 265.3\n 68 321 0 361zm0-174v-40h399900v40zm100 154v40h399900v-40z",
    771   longequal: "M0 50 h400000 v40H0z m0 194h40000v40H0z\nM0 50 h400000 v40H0z m0 194h40000v40H0z",
    772   midbrace: "M200428 334\nc-100.7-8.3-195.3-44-280-108-55.3-42-101.7-93-139-153l-9-14c-2.7 4-5.7 8.7-9 14\n-53.3 86.7-123.7 153-211 199-66.7 36-137.3 56.3-212 62H0V214h199568c178.3-11.7\n 311.7-78.3 403-201 6-8 9.7-12 11-12 .7-.7 6.7-1 18-1s17.3.3 18 1c1.3 0 5 4 11\n 12 44.7 59.3 101.3 106.3 170 141s145.3 54.3 229 60h199572v120z",
    773   midbraceunder: "M199572 214\nc100.7 8.3 195.3 44 280 108 55.3 42 101.7 93 139 153l9 14c2.7-4 5.7-8.7 9-14\n 53.3-86.7 123.7-153 211-199 66.7-36 137.3-56.3 212-62h199568v120H200432c-178.3\n 11.7-311.7 78.3-403 201-6 8-9.7 12-11 12-.7.7-6.7 1-18 1s-17.3-.3-18-1c-1.3 0\n-5-4-11-12-44.7-59.3-101.3-106.3-170-141s-145.3-54.3-229-60H0V214z",
    774   oiintSize1: "M512.6 71.6c272.6 0 320.3 106.8 320.3 178.2 0 70.8-47.7 177.6\n-320.3 177.6S193.1 320.6 193.1 249.8c0-71.4 46.9-178.2 319.5-178.2z\nm368.1 178.2c0-86.4-60.9-215.4-368.1-215.4-306.4 0-367.3 129-367.3 215.4 0 85.8\n60.9 214.8 367.3 214.8 307.2 0 368.1-129 368.1-214.8z",
    775   oiintSize2: "M757.8 100.1c384.7 0 451.1 137.6 451.1 230 0 91.3-66.4 228.8\n-451.1 228.8-386.3 0-452.7-137.5-452.7-228.8 0-92.4 66.4-230 452.7-230z\nm502.4 230c0-111.2-82.4-277.2-502.4-277.2s-504 166-504 277.2\nc0 110 84 276 504 276s502.4-166 502.4-276z",
    776   oiiintSize1: "M681.4 71.6c408.9 0 480.5 106.8 480.5 178.2 0 70.8-71.6 177.6\n-480.5 177.6S202.1 320.6 202.1 249.8c0-71.4 70.5-178.2 479.3-178.2z\nm525.8 178.2c0-86.4-86.8-215.4-525.7-215.4-437.9 0-524.7 129-524.7 215.4 0\n85.8 86.8 214.8 524.7 214.8 438.9 0 525.7-129 525.7-214.8z",
    777   oiiintSize2: "M1021.2 53c603.6 0 707.8 165.8 707.8 277.2 0 110-104.2 275.8\n-707.8 275.8-606 0-710.2-165.8-710.2-275.8C311 218.8 415.2 53 1021.2 53z\nm770.4 277.1c0-131.2-126.4-327.6-770.5-327.6S248.4 198.9 248.4 330.1\nc0 130 128.8 326.4 772.7 326.4s770.5-196.4 770.5-326.4z",
    778   rightarrow: "M0 241v40h399891c-47.3 35.3-84 78-110 128\n-16.7 32-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20\n 11 8 0 13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7\n 39-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85\n-40.5-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n 151.7 139 205zm0 0v40h399900v-40z",
    779   rightbrace: "M400000 542l\n-6 6h-17c-12.7 0-19.3-.3-20-1-4-4-7.3-8.3-10-13-35.3-51.3-80.8-93.8-136.5-127.5\ns-117.2-55.8-184.5-66.5c-.7 0-2-.3-4-1-18.7-2.7-76-4.3-172-5H0V214h399571l6 1\nc124.7 8 235 61.7 331 161 31.3 33.3 59.7 72.7 85 118l7 13v35z",
    780   rightbraceunder: "M399994 0l6 6v35l-6 11c-56 104-135.3 181.3-238 232-57.3\n 28.7-117 45-179 50H-300V214h399897c43.3-7 81-15 113-26 100.7-33 179.7-91 237\n-174 2.7-5 6-9 10-13 .7-1 7.3-1 20-1h17z",
    781   rightgroup: "M0 80h399565c371 0 266.7 149.4 414 180 5.9 1.2 18 0 18 0 2 0\n 3-1 3-3v-38c-76-158-257-219-435-219H0z",
    782   rightgroupunder: "M0 262h399565c371 0 266.7-149.4 414-180 5.9-1.2 18 0 18\n 0 2 0 3 1 3 3v38c-76 158-257 219-435 219H0z",
    783   rightharpoon: "M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3\n-3.7-15.3-11-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2\n-10.7 0-16.7 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58\n 69.2 92 94.5zm0 0v40h399900v-40z",
    784   rightharpoonplus: "M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3-3.7-15.3-11\n-18-92.7-56.7-159-133.7-199-231-3.3-9.3-6-14.7-8-16-2-1.3-7-2-15-2-10.7 0-16.7\n 2-18 6-2 2.7-1 9.7 3 21 15.3 42 36.7 81.8 64 119.5 27.3 37.7 58 69.2 92 94.5z\nm0 0v40h399900v-40z m100 194v40h399900v-40zm0 0v40h399900v-40z",
    785   rightharpoondown: "M399747 511c0 7.3 6.7 11 20 11 8 0 13-.8 15-2.5s4.7-6.8\n 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3 8.5-5.8 9.5\n-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3-64.7 57-92 95\n-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 241v40h399900v-40z",
    786   rightharpoondownplus: "M399747 705c0 7.3 6.7 11 20 11 8 0 13-.8\n 15-2.5s4.7-6.8 8-15.5c40-94 99.3-166.3 178-217 13.3-8 20.3-12.3 21-13 5.3-3.3\n 8.5-5.8 9.5-7.5 1-1.7 1.5-5.2 1.5-10.5s-2.3-10.3-7-15H0v40h399908c-34 25.3\n-64.7 57-92 95-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 435v40h399900v-40z\nm0-194v40h400000v-40zm0 0v40h400000v-40z",
    787   righthook: "M399859 241c-764 0 0 0 0 0 40-3.3 68.7-15.7 86-37 10-12 15-25.3\n 15-40 0-22.7-9.8-40.7-29.5-54-19.7-13.3-43.5-21-71.5-23-17.3-1.3-26-8-26-20 0\n-13.3 8.7-20 26-20 38 0 71 11.2 99 33.5 0 0 7 5.6 21 16.7 14 11.2 21 33.5 21\n 66.8s-14 61.2-42 83.5c-28 22.3-61 33.5-99 33.5L0 241z M0 281v-40h399859v40z",
    788   rightlinesegment: "M399960 241 V94 h40 V428 h-40 V281 H0 v-40z\nM399960 241 V94 h40 V428 h-40 V281 H0 v-40z",
    789   rightToFrom: "M400000 167c-70.7-42-118-97.7-142-167h-23c-15.3 0-23 .3-23\n 1 0 1.3 5.3 13.7 16 37 18 35.3 41.3 69 70 101l7 8H0v40h399905l-7 8c-28.7 32\n-52 65.7-70 101-10.7 23.3-16 35.7-16 37 0 .7 7.7 1 23 1h23c24-69.3 71.3-125 142\n-167z M100 147v40h399900v-40zM0 341v40h399900v-40z",
    790   // twoheadleftarrow is from glyph U+219E in font KaTeX AMS Regular
    791   twoheadleftarrow: "M0 167c68 40\n 115.7 95.7 143 167h22c15.3 0 23-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69\n-70-101l-7-8h125l9 7c50.7 39.3 85 86 103 140h46c0-4.7-6.3-18.7-19-42-18-35.3\n-40-67.3-66-96l-9-9h399716v-40H284l9-9c26-28.7 48-60.7 66-96 12.7-23.333 19\n-37.333 19-42h-46c-18 54-52.3 100.7-103 140l-9 7H95l7-8c28.7-32 52-65.7 70-101\n 10.7-23.333 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 71.3 68 127 0 167z",
    792   twoheadrightarrow: "M400000 167\nc-68-40-115.7-95.7-143-167h-22c-15.3 0-23 .3-23 1 0 1.3 5.3 13.7 16 37 18 35.3\n 41.3 69 70 101l7 8h-125l-9-7c-50.7-39.3-85-86-103-140h-46c0 4.7 6.3 18.7 19 42\n 18 35.3 40 67.3 66 96l9 9H0v40h399716l-9 9c-26 28.7-48 60.7-66 96-12.7 23.333\n-19 37.333-19 42h46c18-54 52.3-100.7 103-140l9-7h125l-7 8c-28.7 32-52 65.7-70\n 101-10.7 23.333-16 35.7-16 37 0 .7 7.7 1 23 1h22c27.3-71.3 75-127 143-167z",
    793   // tilde1 is a modified version of a glyph from the MnSymbol package
    794   tilde1: "M200 55.538c-77 0-168 73.953-177 73.953-3 0-7\n-2.175-9-5.437L2 97c-1-2-2-4-2-6 0-4 2-7 5-9l20-12C116 12 171 0 207 0c86 0\n 114 68 191 68 78 0 168-68 177-68 4 0 7 2 9 5l12 19c1 2.175 2 4.35 2 6.525 0\n 4.35-2 7.613-5 9.788l-19 13.05c-92 63.077-116.937 75.308-183 76.128\n-68.267.847-113-73.952-191-73.952z",
    795   // ditto tilde2, tilde3, & tilde4
    796   tilde2: "M344 55.266c-142 0-300.638 81.316-311.5 86.418\n-8.01 3.762-22.5 10.91-23.5 5.562L1 120c-1-2-1-3-1-4 0-5 3-9 8-10l18.4-9C160.9\n 31.9 283 0 358 0c148 0 188 122 331 122s314-97 326-97c4 0 8 2 10 7l7 21.114\nc1 2.14 1 3.21 1 4.28 0 5.347-3 9.626-7 10.696l-22.3 12.622C852.6 158.372 751\n 181.476 676 181.476c-149 0-189-126.21-332-126.21z",
    797   tilde3: "M786 59C457 59 32 175.242 13 175.242c-6 0-10-3.457\n-11-10.37L.15 138c-1-7 3-12 10-13l19.2-6.4C378.4 40.7 634.3 0 804.3 0c337 0\n 411.8 157 746.8 157 328 0 754-112 773-112 5 0 10 3 11 9l1 14.075c1 8.066-.697\n 16.595-6.697 17.492l-21.052 7.31c-367.9 98.146-609.15 122.696-778.15 122.696\n -338 0-409-156.573-744-156.573z",
    798   tilde4: "M786 58C457 58 32 177.487 13 177.487c-6 0-10-3.345\n-11-10.035L.15 143c-1-7 3-12 10-13l22-6.7C381.2 35 637.15 0 807.15 0c337 0 409\n 177 744 177 328 0 754-127 773-127 5 0 10 3 11 9l1 14.794c1 7.805-3 13.38-9\n 14.495l-20.7 5.574c-366.85 99.79-607.3 139.372-776.3 139.372-338 0-409\n -175.236-744-175.236z",
    799   // vec is from glyph U+20D7 in font KaTeX Main
    800   vec: "M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5\n3.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11\n10.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63\n-1.333 1.333-3.167 3.5-5.5 6.5s-4 4.833-5 5.5c-1 .667-2.5 1.333-4.5 2s-4.333 1\n-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59\nH213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359\nc-16-25.333-24-45-24-59z",
    801   // widehat1 is a modified version of a glyph from the MnSymbol package
    802   widehat1: "M529 0h5l519 115c5 1 9 5 9 10 0 1-1 2-1 3l-4 22\nc-1 5-5 9-11 9h-2L532 67 19 159h-2c-5 0-9-4-11-9l-5-22c-1-6 2-12 8-13z",
    803   // ditto widehat2, widehat3, & widehat4
    804   widehat2: "M1181 0h2l1171 176c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 220h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",
    805   widehat3: "M1181 0h2l1171 236c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 280h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",
    806   widehat4: "M1181 0h2l1171 296c6 0 10 5 10 11l-2 23c-1 6-5 10\n-11 10h-1L1182 67 15 340h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z",
    807   // widecheck paths are all inverted versions of widehat
    808   widecheck1: "M529,159h5l519,-115c5,-1,9,-5,9,-10c0,-1,-1,-2,-1,-3l-4,-22c-1,\n-5,-5,-9,-11,-9h-2l-512,92l-513,-92h-2c-5,0,-9,4,-11,9l-5,22c-1,6,2,12,8,13z",
    809   widecheck2: "M1181,220h2l1171,-176c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,153l-1167,-153h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",
    810   widecheck3: "M1181,280h2l1171,-236c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,213l-1167,-213h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",
    811   widecheck4: "M1181,340h2l1171,-296c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,\n-11,-10h-1l-1168,273l-1167,-273h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z",
    812   // The next ten paths support reaction arrows from the mhchem package.
    813   // Arrows for \ce{<-->} are offset from xAxis by 0.22ex, per mhchem in LaTeX
    814   // baraboveleftarrow is mostly from from glyph U+2190 in font KaTeX Main
    815   baraboveleftarrow: "M400000 620h-399890l3 -3c68.7 -52.7 113.7 -120 135 -202\nc4 -14.7 6 -23 6 -25c0 -7.3 -7 -11 -21 -11c-8 0 -13.2 0.8 -15.5 2.5\nc-2.3 1.7 -4.2 5.8 -5.5 12.5c-1.3 4.7 -2.7 10.3 -4 17c-12 48.7 -34.8 92 -68.5 130\ns-74.2 66.3 -121.5 85c-10 4 -16 7.7 -18 11c0 8.7 6 14.3 18 17c47.3 18.7 87.8 47\n121.5 85s56.5 81.3 68.5 130c0.7 2 1.3 5 2 9s1.2 6.7 1.5 8c0.3 1.3 1 3.3 2 6\ns2.2 4.5 3.5 5.5c1.3 1 3.3 1.8 6 2.5s6 1 10 1c14 0 21 -3.7 21 -11\nc0 -2 -2 -10.3 -6 -25c-20 -79.3 -65 -146.7 -135 -202l-3 -3h399890z\nM100 620v40h399900v-40z M0 241v40h399900v-40zM0 241v40h399900v-40z",
    816   // rightarrowabovebar is mostly from glyph U+2192, KaTeX Main
    817   rightarrowabovebar: "M0 241v40h399891c-47.3 35.3-84 78-110 128-16.7 32\n-27.7 63.7-33 95 0 1.3-.2 2.7-.5 4-.3 1.3-.5 2.3-.5 3 0 7.3 6.7 11 20 11 8 0\n13.2-.8 15.5-2.5 2.3-1.7 4.2-5.5 5.5-11.5 2-13.3 5.7-27 11-41 14.7-44.7 39\n-84.5 73-119.5s73.7-60.2 119-75.5c6-2 9-5.7 9-11s-3-9-9-11c-45.3-15.3-85-40.5\n-119-75.5s-58.3-74.8-73-119.5c-4.7-14-8.3-27.3-11-40-1.3-6.7-3.2-10.8-5.5\n-12.5-2.3-1.7-7.5-2.5-15.5-2.5-14 0-21 3.7-21 11 0 2 2 10.3 6 25 20.7 83.3 67\n151.7 139 205zm96 379h399894v40H0zm0 0h399904v40H0z",
    818   // The short left harpoon has 0.5em (i.e. 500 units) kern on the left end.
    819   // Ref from mhchem.sty: \rlap{\raisebox{-.22ex}{$\kern0.5em
    820   baraboveshortleftharpoon: "M507,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17\nc2,0.7,5,1,9,1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21\nc-32,-87.3,-82.7,-157.7,-152,-211c0,0,-3,-3,-3,-3l399351,0l0,-40\nc-398570,0,-399437,0,-399437,0z M593 435 v40 H399500 v-40z\nM0 281 v-40 H399908 v40z M0 281 v-40 H399908 v40z",
    821   rightharpoonaboveshortbar: "M0,241 l0,40c399126,0,399993,0,399993,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM0 241 v40 H399908 v-40z M0 475 v-40 H399500 v40z M0 475 v-40 H399500 v40z",
    822   shortbaraboveleftharpoon: "M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11\nc1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17c2,0.7,5,1,9,\n1c0,0,5,0,5,0c10.7,0,16.7,-2,18,-6c2,-2.7,1,-9.7,-3,-21c-32,-87.3,-82.7,-157.7,\n-152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z\nM93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z",
    823   shortrightharpoonabovebar: "M53,241l0,40c398570,0,399437,0,399437,0\nc4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,\n-231c-3.3,-9.3,-6,-14.7,-8,-16c-2,-1.3,-7,-2,-15,-2c-10.7,0,-16.7,2,-18,6\nc-2,2.7,-1,9.7,3,21c15.3,42,36.7,81.8,64,119.5c27.3,37.7,58,69.2,92,94.5z\nM500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z"
    824 };
    825 
    826 /**
    827  * This node represents a document fragment, which contains elements, but when
    828  * placed into the DOM doesn't have any representation itself. It only contains
    829  * children and doesn't have any DOM node properties.
    830  */
    831 class DocumentFragment {
    832   // HtmlDomNode
    833   // Never used; needed for satisfying interface.
    834   constructor(children) {
    835     this.children = void 0;
    836     this.classes = void 0;
    837     this.height = void 0;
    838     this.depth = void 0;
    839     this.maxFontSize = void 0;
    840     this.style = void 0;
    841     this.children = children;
    842     this.classes = [];
    843     this.height = 0;
    844     this.depth = 0;
    845     this.maxFontSize = 0;
    846     this.style = {};
    847   }
    848 
    849   hasClass(className) {
    850     return utils.contains(this.classes, className);
    851   }
    852   /** Convert the fragment into a node. */
    853 
    854 
    855   toNode() {
    856     var frag = document.createDocumentFragment();
    857 
    858     for (var i = 0; i < this.children.length; i++) {
    859       frag.appendChild(this.children[i].toNode());
    860     }
    861 
    862     return frag;
    863   }
    864   /** Convert the fragment into HTML markup. */
    865 
    866 
    867   toMarkup() {
    868     var markup = ""; // Simply concatenate the markup for the children together.
    869 
    870     for (var i = 0; i < this.children.length; i++) {
    871       markup += this.children[i].toMarkup();
    872     }
    873 
    874     return markup;
    875   }
    876   /**
    877    * Converts the math node into a string, similar to innerText. Applies to
    878    * MathDomNode's only.
    879    */
    880 
    881 
    882   toText() {
    883     // To avoid this, we would subclass documentFragment separately for
    884     // MathML, but polyfills for subclassing is expensive per PR 1469.
    885     // $FlowFixMe: Only works for ChildType = MathDomNode.
    886     var toText = child => child.toText();
    887 
    888     return this.children.map(toText).join("");
    889   }
    890 
    891 }
    892 
    893 /**
    894  * These objects store the data about the DOM nodes we create, as well as some
    895  * extra data. They can then be transformed into real DOM nodes with the
    896  * `toNode` function or HTML markup using `toMarkup`. They are useful for both
    897  * storing extra properties on the nodes, as well as providing a way to easily
    898  * work with the DOM.
    899  *
    900  * Similar functions for working with MathML nodes exist in mathMLTree.js.
    901  *
    902  * TODO: refactor `span` and `anchor` into common superclass when
    903  * target environments support class inheritance
    904  */
    905 
    906 /**
    907  * Create an HTML className based on a list of classes. In addition to joining
    908  * with spaces, we also remove empty classes.
    909  */
    910 var createClass = function createClass(classes) {
    911   return classes.filter(cls => cls).join(" ");
    912 };
    913 
    914 var initNode = function initNode(classes, options, style) {
    915   this.classes = classes || [];
    916   this.attributes = {};
    917   this.height = 0;
    918   this.depth = 0;
    919   this.maxFontSize = 0;
    920   this.style = style || {};
    921 
    922   if (options) {
    923     if (options.style.isTight()) {
    924       this.classes.push("mtight");
    925     }
    926 
    927     var color = options.getColor();
    928 
    929     if (color) {
    930       this.style.color = color;
    931     }
    932   }
    933 };
    934 /**
    935  * Convert into an HTML node
    936  */
    937 
    938 
    939 var toNode = function toNode(tagName) {
    940   var node = document.createElement(tagName); // Apply the class
    941 
    942   node.className = createClass(this.classes); // Apply inline styles
    943 
    944   for (var style in this.style) {
    945     if (this.style.hasOwnProperty(style)) {
    946       // $FlowFixMe Flow doesn't seem to understand span.style's type.
    947       node.style[style] = this.style[style];
    948     }
    949   } // Apply attributes
    950 
    951 
    952   for (var attr in this.attributes) {
    953     if (this.attributes.hasOwnProperty(attr)) {
    954       node.setAttribute(attr, this.attributes[attr]);
    955     }
    956   } // Append the children, also as HTML nodes
    957 
    958 
    959   for (var i = 0; i < this.children.length; i++) {
    960     node.appendChild(this.children[i].toNode());
    961   }
    962 
    963   return node;
    964 };
    965 /**
    966  * Convert into an HTML markup string
    967  */
    968 
    969 
    970 var toMarkup = function toMarkup(tagName) {
    971   var markup = "<" + tagName; // Add the class
    972 
    973   if (this.classes.length) {
    974     markup += " class=\"" + utils.escape(createClass(this.classes)) + "\"";
    975   }
    976 
    977   var styles = ""; // Add the styles, after hyphenation
    978 
    979   for (var style in this.style) {
    980     if (this.style.hasOwnProperty(style)) {
    981       styles += utils.hyphenate(style) + ":" + this.style[style] + ";";
    982     }
    983   }
    984 
    985   if (styles) {
    986     markup += " style=\"" + utils.escape(styles) + "\"";
    987   } // Add the attributes
    988 
    989 
    990   for (var attr in this.attributes) {
    991     if (this.attributes.hasOwnProperty(attr)) {
    992       markup += " " + attr + "=\"" + utils.escape(this.attributes[attr]) + "\"";
    993     }
    994   }
    995 
    996   markup += ">"; // Add the markup of the children, also as markup
    997 
    998   for (var i = 0; i < this.children.length; i++) {
    999     markup += this.children[i].toMarkup();
   1000   }
   1001 
   1002   markup += "</" + tagName + ">";
   1003   return markup;
   1004 }; // Making the type below exact with all optional fields doesn't work due to
   1005 // - https://github.com/facebook/flow/issues/4582
   1006 // - https://github.com/facebook/flow/issues/5688
   1007 // However, since *all* fields are optional, $Shape<> works as suggested in 5688
   1008 // above.
   1009 // This type does not include all CSS properties. Additional properties should
   1010 // be added as needed.
   1011 
   1012 
   1013 /**
   1014  * This node represents a span node, with a className, a list of children, and
   1015  * an inline style. It also contains information about its height, depth, and
   1016  * maxFontSize.
   1017  *
   1018  * Represents two types with different uses: SvgSpan to wrap an SVG and DomSpan
   1019  * otherwise. This typesafety is important when HTML builders access a span's
   1020  * children.
   1021  */
   1022 class Span {
   1023   constructor(classes, children, options, style) {
   1024     this.children = void 0;
   1025     this.attributes = void 0;
   1026     this.classes = void 0;
   1027     this.height = void 0;
   1028     this.depth = void 0;
   1029     this.width = void 0;
   1030     this.maxFontSize = void 0;
   1031     this.style = void 0;
   1032     initNode.call(this, classes, options, style);
   1033     this.children = children || [];
   1034   }
   1035   /**
   1036    * Sets an arbitrary attribute on the span. Warning: use this wisely. Not
   1037    * all browsers support attributes the same, and having too many custom
   1038    * attributes is probably bad.
   1039    */
   1040 
   1041 
   1042   setAttribute(attribute, value) {
   1043     this.attributes[attribute] = value;
   1044   }
   1045 
   1046   hasClass(className) {
   1047     return utils.contains(this.classes, className);
   1048   }
   1049 
   1050   toNode() {
   1051     return toNode.call(this, "span");
   1052   }
   1053 
   1054   toMarkup() {
   1055     return toMarkup.call(this, "span");
   1056   }
   1057 
   1058 }
   1059 /**
   1060  * This node represents an anchor (<a>) element with a hyperlink.  See `span`
   1061  * for further details.
   1062  */
   1063 
   1064 class Anchor {
   1065   constructor(href, classes, children, options) {
   1066     this.children = void 0;
   1067     this.attributes = void 0;
   1068     this.classes = void 0;
   1069     this.height = void 0;
   1070     this.depth = void 0;
   1071     this.maxFontSize = void 0;
   1072     this.style = void 0;
   1073     initNode.call(this, classes, options);
   1074     this.children = children || [];
   1075     this.setAttribute('href', href);
   1076   }
   1077 
   1078   setAttribute(attribute, value) {
   1079     this.attributes[attribute] = value;
   1080   }
   1081 
   1082   hasClass(className) {
   1083     return utils.contains(this.classes, className);
   1084   }
   1085 
   1086   toNode() {
   1087     return toNode.call(this, "a");
   1088   }
   1089 
   1090   toMarkup() {
   1091     return toMarkup.call(this, "a");
   1092   }
   1093 
   1094 }
   1095 /**
   1096  * This node represents an image embed (<img>) element.
   1097  */
   1098 
   1099 class Img {
   1100   constructor(src, alt, style) {
   1101     this.src = void 0;
   1102     this.alt = void 0;
   1103     this.classes = void 0;
   1104     this.height = void 0;
   1105     this.depth = void 0;
   1106     this.maxFontSize = void 0;
   1107     this.style = void 0;
   1108     this.alt = alt;
   1109     this.src = src;
   1110     this.classes = ["mord"];
   1111     this.style = style;
   1112   }
   1113 
   1114   hasClass(className) {
   1115     return utils.contains(this.classes, className);
   1116   }
   1117 
   1118   toNode() {
   1119     var node = document.createElement("img");
   1120     node.src = this.src;
   1121     node.alt = this.alt;
   1122     node.className = "mord"; // Apply inline styles
   1123 
   1124     for (var style in this.style) {
   1125       if (this.style.hasOwnProperty(style)) {
   1126         // $FlowFixMe
   1127         node.style[style] = this.style[style];
   1128       }
   1129     }
   1130 
   1131     return node;
   1132   }
   1133 
   1134   toMarkup() {
   1135     var markup = "<img  src='" + this.src + " 'alt='" + this.alt + "' "; // Add the styles, after hyphenation
   1136 
   1137     var styles = "";
   1138 
   1139     for (var style in this.style) {
   1140       if (this.style.hasOwnProperty(style)) {
   1141         styles += utils.hyphenate(style) + ":" + this.style[style] + ";";
   1142       }
   1143     }
   1144 
   1145     if (styles) {
   1146       markup += " style=\"" + utils.escape(styles) + "\"";
   1147     }
   1148 
   1149     markup += "'/>";
   1150     return markup;
   1151   }
   1152 
   1153 }
   1154 var iCombinations = {
   1155   'î': '\u0131\u0302',
   1156   'ï': '\u0131\u0308',
   1157   'í': '\u0131\u0301',
   1158   // 'ī': '\u0131\u0304', // enable when we add Extended Latin
   1159   'ì': '\u0131\u0300'
   1160 };
   1161 /**
   1162  * A symbol node contains information about a single symbol. It either renders
   1163  * to a single text node, or a span with a single text node in it, depending on
   1164  * whether it has CSS classes, styles, or needs italic correction.
   1165  */
   1166 
   1167 class SymbolNode {
   1168   constructor(text, height, depth, italic, skew, width, classes, style) {
   1169     this.text = void 0;
   1170     this.height = void 0;
   1171     this.depth = void 0;
   1172     this.italic = void 0;
   1173     this.skew = void 0;
   1174     this.width = void 0;
   1175     this.maxFontSize = void 0;
   1176     this.classes = void 0;
   1177     this.style = void 0;
   1178     this.text = text;
   1179     this.height = height || 0;
   1180     this.depth = depth || 0;
   1181     this.italic = italic || 0;
   1182     this.skew = skew || 0;
   1183     this.width = width || 0;
   1184     this.classes = classes || [];
   1185     this.style = style || {};
   1186     this.maxFontSize = 0; // Mark text from non-Latin scripts with specific classes so that we
   1187     // can specify which fonts to use.  This allows us to render these
   1188     // characters with a serif font in situations where the browser would
   1189     // either default to a sans serif or render a placeholder character.
   1190     // We use CSS class names like cjk_fallback, hangul_fallback and
   1191     // brahmic_fallback. See ./unicodeScripts.js for the set of possible
   1192     // script names
   1193 
   1194     var script = scriptFromCodepoint(this.text.charCodeAt(0));
   1195 
   1196     if (script) {
   1197       this.classes.push(script + "_fallback");
   1198     }
   1199 
   1200     if (/[îïíì]/.test(this.text)) {
   1201       // add ī when we add Extended Latin
   1202       this.text = iCombinations[this.text];
   1203     }
   1204   }
   1205 
   1206   hasClass(className) {
   1207     return utils.contains(this.classes, className);
   1208   }
   1209   /**
   1210    * Creates a text node or span from a symbol node. Note that a span is only
   1211    * created if it is needed.
   1212    */
   1213 
   1214 
   1215   toNode() {
   1216     var node = document.createTextNode(this.text);
   1217     var span = null;
   1218 
   1219     if (this.italic > 0) {
   1220       span = document.createElement("span");
   1221       span.style.marginRight = this.italic + "em";
   1222     }
   1223 
   1224     if (this.classes.length > 0) {
   1225       span = span || document.createElement("span");
   1226       span.className = createClass(this.classes);
   1227     }
   1228 
   1229     for (var style in this.style) {
   1230       if (this.style.hasOwnProperty(style)) {
   1231         span = span || document.createElement("span"); // $FlowFixMe Flow doesn't seem to understand span.style's type.
   1232 
   1233         span.style[style] = this.style[style];
   1234       }
   1235     }
   1236 
   1237     if (span) {
   1238       span.appendChild(node);
   1239       return span;
   1240     } else {
   1241       return node;
   1242     }
   1243   }
   1244   /**
   1245    * Creates markup for a symbol node.
   1246    */
   1247 
   1248 
   1249   toMarkup() {
   1250     // TODO(alpert): More duplication than I'd like from
   1251     // span.prototype.toMarkup and symbolNode.prototype.toNode...
   1252     var needsSpan = false;
   1253     var markup = "<span";
   1254 
   1255     if (this.classes.length) {
   1256       needsSpan = true;
   1257       markup += " class=\"";
   1258       markup += utils.escape(createClass(this.classes));
   1259       markup += "\"";
   1260     }
   1261 
   1262     var styles = "";
   1263 
   1264     if (this.italic > 0) {
   1265       styles += "margin-right:" + this.italic + "em;";
   1266     }
   1267 
   1268     for (var style in this.style) {
   1269       if (this.style.hasOwnProperty(style)) {
   1270         styles += utils.hyphenate(style) + ":" + this.style[style] + ";";
   1271       }
   1272     }
   1273 
   1274     if (styles) {
   1275       needsSpan = true;
   1276       markup += " style=\"" + utils.escape(styles) + "\"";
   1277     }
   1278 
   1279     var escaped = utils.escape(this.text);
   1280 
   1281     if (needsSpan) {
   1282       markup += ">";
   1283       markup += escaped;
   1284       markup += "</span>";
   1285       return markup;
   1286     } else {
   1287       return escaped;
   1288     }
   1289   }
   1290 
   1291 }
   1292 /**
   1293  * SVG nodes are used to render stretchy wide elements.
   1294  */
   1295 
   1296 class SvgNode {
   1297   constructor(children, attributes) {
   1298     this.children = void 0;
   1299     this.attributes = void 0;
   1300     this.children = children || [];
   1301     this.attributes = attributes || {};
   1302   }
   1303 
   1304   toNode() {
   1305     var svgNS = "http://www.w3.org/2000/svg";
   1306     var node = document.createElementNS(svgNS, "svg"); // Apply attributes
   1307 
   1308     for (var attr in this.attributes) {
   1309       if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
   1310         node.setAttribute(attr, this.attributes[attr]);
   1311       }
   1312     }
   1313 
   1314     for (var i = 0; i < this.children.length; i++) {
   1315       node.appendChild(this.children[i].toNode());
   1316     }
   1317 
   1318     return node;
   1319   }
   1320 
   1321   toMarkup() {
   1322     var markup = "<svg"; // Apply attributes
   1323 
   1324     for (var attr in this.attributes) {
   1325       if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
   1326         markup += " " + attr + "='" + this.attributes[attr] + "'";
   1327       }
   1328     }
   1329 
   1330     markup += ">";
   1331 
   1332     for (var i = 0; i < this.children.length; i++) {
   1333       markup += this.children[i].toMarkup();
   1334     }
   1335 
   1336     markup += "</svg>";
   1337     return markup;
   1338   }
   1339 
   1340 }
   1341 class PathNode {
   1342   constructor(pathName, alternate) {
   1343     this.pathName = void 0;
   1344     this.alternate = void 0;
   1345     this.pathName = pathName;
   1346     this.alternate = alternate; // Used only for \sqrt, \phase, & tall delims
   1347   }
   1348 
   1349   toNode() {
   1350     var svgNS = "http://www.w3.org/2000/svg";
   1351     var node = document.createElementNS(svgNS, "path");
   1352 
   1353     if (this.alternate) {
   1354       node.setAttribute("d", this.alternate);
   1355     } else {
   1356       node.setAttribute("d", path[this.pathName]);
   1357     }
   1358 
   1359     return node;
   1360   }
   1361 
   1362   toMarkup() {
   1363     if (this.alternate) {
   1364       return "<path d='" + this.alternate + "'/>";
   1365     } else {
   1366       return "<path d='" + path[this.pathName] + "'/>";
   1367     }
   1368   }
   1369 
   1370 }
   1371 class LineNode {
   1372   constructor(attributes) {
   1373     this.attributes = void 0;
   1374     this.attributes = attributes || {};
   1375   }
   1376 
   1377   toNode() {
   1378     var svgNS = "http://www.w3.org/2000/svg";
   1379     var node = document.createElementNS(svgNS, "line"); // Apply attributes
   1380 
   1381     for (var attr in this.attributes) {
   1382       if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
   1383         node.setAttribute(attr, this.attributes[attr]);
   1384       }
   1385     }
   1386 
   1387     return node;
   1388   }
   1389 
   1390   toMarkup() {
   1391     var markup = "<line";
   1392 
   1393     for (var attr in this.attributes) {
   1394       if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
   1395         markup += " " + attr + "='" + this.attributes[attr] + "'";
   1396       }
   1397     }
   1398 
   1399     markup += "/>";
   1400     return markup;
   1401   }
   1402 
   1403 }
   1404 function assertSymbolDomNode(group) {
   1405   if (group instanceof SymbolNode) {
   1406     return group;
   1407   } else {
   1408     throw new Error("Expected symbolNode but got " + String(group) + ".");
   1409   }
   1410 }
   1411 function assertSpan(group) {
   1412   if (group instanceof Span) {
   1413     return group;
   1414   } else {
   1415     throw new Error("Expected span<HtmlDomNode> but got " + String(group) + ".");
   1416   }
   1417 }
   1418 
   1419 // This file is GENERATED by buildMetrics.sh. DO NOT MODIFY.
   1420 var fontMetricsData = {
   1421   "AMS-Regular": {
   1422     "32": [0, 0, 0, 0, 0.25],
   1423     "65": [0, 0.68889, 0, 0, 0.72222],
   1424     "66": [0, 0.68889, 0, 0, 0.66667],
   1425     "67": [0, 0.68889, 0, 0, 0.72222],
   1426     "68": [0, 0.68889, 0, 0, 0.72222],
   1427     "69": [0, 0.68889, 0, 0, 0.66667],
   1428     "70": [0, 0.68889, 0, 0, 0.61111],
   1429     "71": [0, 0.68889, 0, 0, 0.77778],
   1430     "72": [0, 0.68889, 0, 0, 0.77778],
   1431     "73": [0, 0.68889, 0, 0, 0.38889],
   1432     "74": [0.16667, 0.68889, 0, 0, 0.5],
   1433     "75": [0, 0.68889, 0, 0, 0.77778],
   1434     "76": [0, 0.68889, 0, 0, 0.66667],
   1435     "77": [0, 0.68889, 0, 0, 0.94445],
   1436     "78": [0, 0.68889, 0, 0, 0.72222],
   1437     "79": [0.16667, 0.68889, 0, 0, 0.77778],
   1438     "80": [0, 0.68889, 0, 0, 0.61111],
   1439     "81": [0.16667, 0.68889, 0, 0, 0.77778],
   1440     "82": [0, 0.68889, 0, 0, 0.72222],
   1441     "83": [0, 0.68889, 0, 0, 0.55556],
   1442     "84": [0, 0.68889, 0, 0, 0.66667],
   1443     "85": [0, 0.68889, 0, 0, 0.72222],
   1444     "86": [0, 0.68889, 0, 0, 0.72222],
   1445     "87": [0, 0.68889, 0, 0, 1.0],
   1446     "88": [0, 0.68889, 0, 0, 0.72222],
   1447     "89": [0, 0.68889, 0, 0, 0.72222],
   1448     "90": [0, 0.68889, 0, 0, 0.66667],
   1449     "107": [0, 0.68889, 0, 0, 0.55556],
   1450     "160": [0, 0, 0, 0, 0.25],
   1451     "165": [0, 0.675, 0.025, 0, 0.75],
   1452     "174": [0.15559, 0.69224, 0, 0, 0.94666],
   1453     "240": [0, 0.68889, 0, 0, 0.55556],
   1454     "295": [0, 0.68889, 0, 0, 0.54028],
   1455     "710": [0, 0.825, 0, 0, 2.33334],
   1456     "732": [0, 0.9, 0, 0, 2.33334],
   1457     "770": [0, 0.825, 0, 0, 2.33334],
   1458     "771": [0, 0.9, 0, 0, 2.33334],
   1459     "989": [0.08167, 0.58167, 0, 0, 0.77778],
   1460     "1008": [0, 0.43056, 0.04028, 0, 0.66667],
   1461     "8245": [0, 0.54986, 0, 0, 0.275],
   1462     "8463": [0, 0.68889, 0, 0, 0.54028],
   1463     "8487": [0, 0.68889, 0, 0, 0.72222],
   1464     "8498": [0, 0.68889, 0, 0, 0.55556],
   1465     "8502": [0, 0.68889, 0, 0, 0.66667],
   1466     "8503": [0, 0.68889, 0, 0, 0.44445],
   1467     "8504": [0, 0.68889, 0, 0, 0.66667],
   1468     "8513": [0, 0.68889, 0, 0, 0.63889],
   1469     "8592": [-0.03598, 0.46402, 0, 0, 0.5],
   1470     "8594": [-0.03598, 0.46402, 0, 0, 0.5],
   1471     "8602": [-0.13313, 0.36687, 0, 0, 1.0],
   1472     "8603": [-0.13313, 0.36687, 0, 0, 1.0],
   1473     "8606": [0.01354, 0.52239, 0, 0, 1.0],
   1474     "8608": [0.01354, 0.52239, 0, 0, 1.0],
   1475     "8610": [0.01354, 0.52239, 0, 0, 1.11111],
   1476     "8611": [0.01354, 0.52239, 0, 0, 1.11111],
   1477     "8619": [0, 0.54986, 0, 0, 1.0],
   1478     "8620": [0, 0.54986, 0, 0, 1.0],
   1479     "8621": [-0.13313, 0.37788, 0, 0, 1.38889],
   1480     "8622": [-0.13313, 0.36687, 0, 0, 1.0],
   1481     "8624": [0, 0.69224, 0, 0, 0.5],
   1482     "8625": [0, 0.69224, 0, 0, 0.5],
   1483     "8630": [0, 0.43056, 0, 0, 1.0],
   1484     "8631": [0, 0.43056, 0, 0, 1.0],
   1485     "8634": [0.08198, 0.58198, 0, 0, 0.77778],
   1486     "8635": [0.08198, 0.58198, 0, 0, 0.77778],
   1487     "8638": [0.19444, 0.69224, 0, 0, 0.41667],
   1488     "8639": [0.19444, 0.69224, 0, 0, 0.41667],
   1489     "8642": [0.19444, 0.69224, 0, 0, 0.41667],
   1490     "8643": [0.19444, 0.69224, 0, 0, 0.41667],
   1491     "8644": [0.1808, 0.675, 0, 0, 1.0],
   1492     "8646": [0.1808, 0.675, 0, 0, 1.0],
   1493     "8647": [0.1808, 0.675, 0, 0, 1.0],
   1494     "8648": [0.19444, 0.69224, 0, 0, 0.83334],
   1495     "8649": [0.1808, 0.675, 0, 0, 1.0],
   1496     "8650": [0.19444, 0.69224, 0, 0, 0.83334],
   1497     "8651": [0.01354, 0.52239, 0, 0, 1.0],
   1498     "8652": [0.01354, 0.52239, 0, 0, 1.0],
   1499     "8653": [-0.13313, 0.36687, 0, 0, 1.0],
   1500     "8654": [-0.13313, 0.36687, 0, 0, 1.0],
   1501     "8655": [-0.13313, 0.36687, 0, 0, 1.0],
   1502     "8666": [0.13667, 0.63667, 0, 0, 1.0],
   1503     "8667": [0.13667, 0.63667, 0, 0, 1.0],
   1504     "8669": [-0.13313, 0.37788, 0, 0, 1.0],
   1505     "8672": [-0.064, 0.437, 0, 0, 1.334],
   1506     "8674": [-0.064, 0.437, 0, 0, 1.334],
   1507     "8705": [0, 0.825, 0, 0, 0.5],
   1508     "8708": [0, 0.68889, 0, 0, 0.55556],
   1509     "8709": [0.08167, 0.58167, 0, 0, 0.77778],
   1510     "8717": [0, 0.43056, 0, 0, 0.42917],
   1511     "8722": [-0.03598, 0.46402, 0, 0, 0.5],
   1512     "8724": [0.08198, 0.69224, 0, 0, 0.77778],
   1513     "8726": [0.08167, 0.58167, 0, 0, 0.77778],
   1514     "8733": [0, 0.69224, 0, 0, 0.77778],
   1515     "8736": [0, 0.69224, 0, 0, 0.72222],
   1516     "8737": [0, 0.69224, 0, 0, 0.72222],
   1517     "8738": [0.03517, 0.52239, 0, 0, 0.72222],
   1518     "8739": [0.08167, 0.58167, 0, 0, 0.22222],
   1519     "8740": [0.25142, 0.74111, 0, 0, 0.27778],
   1520     "8741": [0.08167, 0.58167, 0, 0, 0.38889],
   1521     "8742": [0.25142, 0.74111, 0, 0, 0.5],
   1522     "8756": [0, 0.69224, 0, 0, 0.66667],
   1523     "8757": [0, 0.69224, 0, 0, 0.66667],
   1524     "8764": [-0.13313, 0.36687, 0, 0, 0.77778],
   1525     "8765": [-0.13313, 0.37788, 0, 0, 0.77778],
   1526     "8769": [-0.13313, 0.36687, 0, 0, 0.77778],
   1527     "8770": [-0.03625, 0.46375, 0, 0, 0.77778],
   1528     "8774": [0.30274, 0.79383, 0, 0, 0.77778],
   1529     "8776": [-0.01688, 0.48312, 0, 0, 0.77778],
   1530     "8778": [0.08167, 0.58167, 0, 0, 0.77778],
   1531     "8782": [0.06062, 0.54986, 0, 0, 0.77778],
   1532     "8783": [0.06062, 0.54986, 0, 0, 0.77778],
   1533     "8785": [0.08198, 0.58198, 0, 0, 0.77778],
   1534     "8786": [0.08198, 0.58198, 0, 0, 0.77778],
   1535     "8787": [0.08198, 0.58198, 0, 0, 0.77778],
   1536     "8790": [0, 0.69224, 0, 0, 0.77778],
   1537     "8791": [0.22958, 0.72958, 0, 0, 0.77778],
   1538     "8796": [0.08198, 0.91667, 0, 0, 0.77778],
   1539     "8806": [0.25583, 0.75583, 0, 0, 0.77778],
   1540     "8807": [0.25583, 0.75583, 0, 0, 0.77778],
   1541     "8808": [0.25142, 0.75726, 0, 0, 0.77778],
   1542     "8809": [0.25142, 0.75726, 0, 0, 0.77778],
   1543     "8812": [0.25583, 0.75583, 0, 0, 0.5],
   1544     "8814": [0.20576, 0.70576, 0, 0, 0.77778],
   1545     "8815": [0.20576, 0.70576, 0, 0, 0.77778],
   1546     "8816": [0.30274, 0.79383, 0, 0, 0.77778],
   1547     "8817": [0.30274, 0.79383, 0, 0, 0.77778],
   1548     "8818": [0.22958, 0.72958, 0, 0, 0.77778],
   1549     "8819": [0.22958, 0.72958, 0, 0, 0.77778],
   1550     "8822": [0.1808, 0.675, 0, 0, 0.77778],
   1551     "8823": [0.1808, 0.675, 0, 0, 0.77778],
   1552     "8828": [0.13667, 0.63667, 0, 0, 0.77778],
   1553     "8829": [0.13667, 0.63667, 0, 0, 0.77778],
   1554     "8830": [0.22958, 0.72958, 0, 0, 0.77778],
   1555     "8831": [0.22958, 0.72958, 0, 0, 0.77778],
   1556     "8832": [0.20576, 0.70576, 0, 0, 0.77778],
   1557     "8833": [0.20576, 0.70576, 0, 0, 0.77778],
   1558     "8840": [0.30274, 0.79383, 0, 0, 0.77778],
   1559     "8841": [0.30274, 0.79383, 0, 0, 0.77778],
   1560     "8842": [0.13597, 0.63597, 0, 0, 0.77778],
   1561     "8843": [0.13597, 0.63597, 0, 0, 0.77778],
   1562     "8847": [0.03517, 0.54986, 0, 0, 0.77778],
   1563     "8848": [0.03517, 0.54986, 0, 0, 0.77778],
   1564     "8858": [0.08198, 0.58198, 0, 0, 0.77778],
   1565     "8859": [0.08198, 0.58198, 0, 0, 0.77778],
   1566     "8861": [0.08198, 0.58198, 0, 0, 0.77778],
   1567     "8862": [0, 0.675, 0, 0, 0.77778],
   1568     "8863": [0, 0.675, 0, 0, 0.77778],
   1569     "8864": [0, 0.675, 0, 0, 0.77778],
   1570     "8865": [0, 0.675, 0, 0, 0.77778],
   1571     "8872": [0, 0.69224, 0, 0, 0.61111],
   1572     "8873": [0, 0.69224, 0, 0, 0.72222],
   1573     "8874": [0, 0.69224, 0, 0, 0.88889],
   1574     "8876": [0, 0.68889, 0, 0, 0.61111],
   1575     "8877": [0, 0.68889, 0, 0, 0.61111],
   1576     "8878": [0, 0.68889, 0, 0, 0.72222],
   1577     "8879": [0, 0.68889, 0, 0, 0.72222],
   1578     "8882": [0.03517, 0.54986, 0, 0, 0.77778],
   1579     "8883": [0.03517, 0.54986, 0, 0, 0.77778],
   1580     "8884": [0.13667, 0.63667, 0, 0, 0.77778],
   1581     "8885": [0.13667, 0.63667, 0, 0, 0.77778],
   1582     "8888": [0, 0.54986, 0, 0, 1.11111],
   1583     "8890": [0.19444, 0.43056, 0, 0, 0.55556],
   1584     "8891": [0.19444, 0.69224, 0, 0, 0.61111],
   1585     "8892": [0.19444, 0.69224, 0, 0, 0.61111],
   1586     "8901": [0, 0.54986, 0, 0, 0.27778],
   1587     "8903": [0.08167, 0.58167, 0, 0, 0.77778],
   1588     "8905": [0.08167, 0.58167, 0, 0, 0.77778],
   1589     "8906": [0.08167, 0.58167, 0, 0, 0.77778],
   1590     "8907": [0, 0.69224, 0, 0, 0.77778],
   1591     "8908": [0, 0.69224, 0, 0, 0.77778],
   1592     "8909": [-0.03598, 0.46402, 0, 0, 0.77778],
   1593     "8910": [0, 0.54986, 0, 0, 0.76042],
   1594     "8911": [0, 0.54986, 0, 0, 0.76042],
   1595     "8912": [0.03517, 0.54986, 0, 0, 0.77778],
   1596     "8913": [0.03517, 0.54986, 0, 0, 0.77778],
   1597     "8914": [0, 0.54986, 0, 0, 0.66667],
   1598     "8915": [0, 0.54986, 0, 0, 0.66667],
   1599     "8916": [0, 0.69224, 0, 0, 0.66667],
   1600     "8918": [0.0391, 0.5391, 0, 0, 0.77778],
   1601     "8919": [0.0391, 0.5391, 0, 0, 0.77778],
   1602     "8920": [0.03517, 0.54986, 0, 0, 1.33334],
   1603     "8921": [0.03517, 0.54986, 0, 0, 1.33334],
   1604     "8922": [0.38569, 0.88569, 0, 0, 0.77778],
   1605     "8923": [0.38569, 0.88569, 0, 0, 0.77778],
   1606     "8926": [0.13667, 0.63667, 0, 0, 0.77778],
   1607     "8927": [0.13667, 0.63667, 0, 0, 0.77778],
   1608     "8928": [0.30274, 0.79383, 0, 0, 0.77778],
   1609     "8929": [0.30274, 0.79383, 0, 0, 0.77778],
   1610     "8934": [0.23222, 0.74111, 0, 0, 0.77778],
   1611     "8935": [0.23222, 0.74111, 0, 0, 0.77778],
   1612     "8936": [0.23222, 0.74111, 0, 0, 0.77778],
   1613     "8937": [0.23222, 0.74111, 0, 0, 0.77778],
   1614     "8938": [0.20576, 0.70576, 0, 0, 0.77778],
   1615     "8939": [0.20576, 0.70576, 0, 0, 0.77778],
   1616     "8940": [0.30274, 0.79383, 0, 0, 0.77778],
   1617     "8941": [0.30274, 0.79383, 0, 0, 0.77778],
   1618     "8994": [0.19444, 0.69224, 0, 0, 0.77778],
   1619     "8995": [0.19444, 0.69224, 0, 0, 0.77778],
   1620     "9416": [0.15559, 0.69224, 0, 0, 0.90222],
   1621     "9484": [0, 0.69224, 0, 0, 0.5],
   1622     "9488": [0, 0.69224, 0, 0, 0.5],
   1623     "9492": [0, 0.37788, 0, 0, 0.5],
   1624     "9496": [0, 0.37788, 0, 0, 0.5],
   1625     "9585": [0.19444, 0.68889, 0, 0, 0.88889],
   1626     "9586": [0.19444, 0.74111, 0, 0, 0.88889],
   1627     "9632": [0, 0.675, 0, 0, 0.77778],
   1628     "9633": [0, 0.675, 0, 0, 0.77778],
   1629     "9650": [0, 0.54986, 0, 0, 0.72222],
   1630     "9651": [0, 0.54986, 0, 0, 0.72222],
   1631     "9654": [0.03517, 0.54986, 0, 0, 0.77778],
   1632     "9660": [0, 0.54986, 0, 0, 0.72222],
   1633     "9661": [0, 0.54986, 0, 0, 0.72222],
   1634     "9664": [0.03517, 0.54986, 0, 0, 0.77778],
   1635     "9674": [0.11111, 0.69224, 0, 0, 0.66667],
   1636     "9733": [0.19444, 0.69224, 0, 0, 0.94445],
   1637     "10003": [0, 0.69224, 0, 0, 0.83334],
   1638     "10016": [0, 0.69224, 0, 0, 0.83334],
   1639     "10731": [0.11111, 0.69224, 0, 0, 0.66667],
   1640     "10846": [0.19444, 0.75583, 0, 0, 0.61111],
   1641     "10877": [0.13667, 0.63667, 0, 0, 0.77778],
   1642     "10878": [0.13667, 0.63667, 0, 0, 0.77778],
   1643     "10885": [0.25583, 0.75583, 0, 0, 0.77778],
   1644     "10886": [0.25583, 0.75583, 0, 0, 0.77778],
   1645     "10887": [0.13597, 0.63597, 0, 0, 0.77778],
   1646     "10888": [0.13597, 0.63597, 0, 0, 0.77778],
   1647     "10889": [0.26167, 0.75726, 0, 0, 0.77778],
   1648     "10890": [0.26167, 0.75726, 0, 0, 0.77778],
   1649     "10891": [0.48256, 0.98256, 0, 0, 0.77778],
   1650     "10892": [0.48256, 0.98256, 0, 0, 0.77778],
   1651     "10901": [0.13667, 0.63667, 0, 0, 0.77778],
   1652     "10902": [0.13667, 0.63667, 0, 0, 0.77778],
   1653     "10933": [0.25142, 0.75726, 0, 0, 0.77778],
   1654     "10934": [0.25142, 0.75726, 0, 0, 0.77778],
   1655     "10935": [0.26167, 0.75726, 0, 0, 0.77778],
   1656     "10936": [0.26167, 0.75726, 0, 0, 0.77778],
   1657     "10937": [0.26167, 0.75726, 0, 0, 0.77778],
   1658     "10938": [0.26167, 0.75726, 0, 0, 0.77778],
   1659     "10949": [0.25583, 0.75583, 0, 0, 0.77778],
   1660     "10950": [0.25583, 0.75583, 0, 0, 0.77778],
   1661     "10955": [0.28481, 0.79383, 0, 0, 0.77778],
   1662     "10956": [0.28481, 0.79383, 0, 0, 0.77778],
   1663     "57350": [0.08167, 0.58167, 0, 0, 0.22222],
   1664     "57351": [0.08167, 0.58167, 0, 0, 0.38889],
   1665     "57352": [0.08167, 0.58167, 0, 0, 0.77778],
   1666     "57353": [0, 0.43056, 0.04028, 0, 0.66667],
   1667     "57356": [0.25142, 0.75726, 0, 0, 0.77778],
   1668     "57357": [0.25142, 0.75726, 0, 0, 0.77778],
   1669     "57358": [0.41951, 0.91951, 0, 0, 0.77778],
   1670     "57359": [0.30274, 0.79383, 0, 0, 0.77778],
   1671     "57360": [0.30274, 0.79383, 0, 0, 0.77778],
   1672     "57361": [0.41951, 0.91951, 0, 0, 0.77778],
   1673     "57366": [0.25142, 0.75726, 0, 0, 0.77778],
   1674     "57367": [0.25142, 0.75726, 0, 0, 0.77778],
   1675     "57368": [0.25142, 0.75726, 0, 0, 0.77778],
   1676     "57369": [0.25142, 0.75726, 0, 0, 0.77778],
   1677     "57370": [0.13597, 0.63597, 0, 0, 0.77778],
   1678     "57371": [0.13597, 0.63597, 0, 0, 0.77778]
   1679   },
   1680   "Caligraphic-Regular": {
   1681     "32": [0, 0, 0, 0, 0.25],
   1682     "65": [0, 0.68333, 0, 0.19445, 0.79847],
   1683     "66": [0, 0.68333, 0.03041, 0.13889, 0.65681],
   1684     "67": [0, 0.68333, 0.05834, 0.13889, 0.52653],
   1685     "68": [0, 0.68333, 0.02778, 0.08334, 0.77139],
   1686     "69": [0, 0.68333, 0.08944, 0.11111, 0.52778],
   1687     "70": [0, 0.68333, 0.09931, 0.11111, 0.71875],
   1688     "71": [0.09722, 0.68333, 0.0593, 0.11111, 0.59487],
   1689     "72": [0, 0.68333, 0.00965, 0.11111, 0.84452],
   1690     "73": [0, 0.68333, 0.07382, 0, 0.54452],
   1691     "74": [0.09722, 0.68333, 0.18472, 0.16667, 0.67778],
   1692     "75": [0, 0.68333, 0.01445, 0.05556, 0.76195],
   1693     "76": [0, 0.68333, 0, 0.13889, 0.68972],
   1694     "77": [0, 0.68333, 0, 0.13889, 1.2009],
   1695     "78": [0, 0.68333, 0.14736, 0.08334, 0.82049],
   1696     "79": [0, 0.68333, 0.02778, 0.11111, 0.79611],
   1697     "80": [0, 0.68333, 0.08222, 0.08334, 0.69556],
   1698     "81": [0.09722, 0.68333, 0, 0.11111, 0.81667],
   1699     "82": [0, 0.68333, 0, 0.08334, 0.8475],
   1700     "83": [0, 0.68333, 0.075, 0.13889, 0.60556],
   1701     "84": [0, 0.68333, 0.25417, 0, 0.54464],
   1702     "85": [0, 0.68333, 0.09931, 0.08334, 0.62583],
   1703     "86": [0, 0.68333, 0.08222, 0, 0.61278],
   1704     "87": [0, 0.68333, 0.08222, 0.08334, 0.98778],
   1705     "88": [0, 0.68333, 0.14643, 0.13889, 0.7133],
   1706     "89": [0.09722, 0.68333, 0.08222, 0.08334, 0.66834],
   1707     "90": [0, 0.68333, 0.07944, 0.13889, 0.72473],
   1708     "160": [0, 0, 0, 0, 0.25]
   1709   },
   1710   "Fraktur-Regular": {
   1711     "32": [0, 0, 0, 0, 0.25],
   1712     "33": [0, 0.69141, 0, 0, 0.29574],
   1713     "34": [0, 0.69141, 0, 0, 0.21471],
   1714     "38": [0, 0.69141, 0, 0, 0.73786],
   1715     "39": [0, 0.69141, 0, 0, 0.21201],
   1716     "40": [0.24982, 0.74947, 0, 0, 0.38865],
   1717     "41": [0.24982, 0.74947, 0, 0, 0.38865],
   1718     "42": [0, 0.62119, 0, 0, 0.27764],
   1719     "43": [0.08319, 0.58283, 0, 0, 0.75623],
   1720     "44": [0, 0.10803, 0, 0, 0.27764],
   1721     "45": [0.08319, 0.58283, 0, 0, 0.75623],
   1722     "46": [0, 0.10803, 0, 0, 0.27764],
   1723     "47": [0.24982, 0.74947, 0, 0, 0.50181],
   1724     "48": [0, 0.47534, 0, 0, 0.50181],
   1725     "49": [0, 0.47534, 0, 0, 0.50181],
   1726     "50": [0, 0.47534, 0, 0, 0.50181],
   1727     "51": [0.18906, 0.47534, 0, 0, 0.50181],
   1728     "52": [0.18906, 0.47534, 0, 0, 0.50181],
   1729     "53": [0.18906, 0.47534, 0, 0, 0.50181],
   1730     "54": [0, 0.69141, 0, 0, 0.50181],
   1731     "55": [0.18906, 0.47534, 0, 0, 0.50181],
   1732     "56": [0, 0.69141, 0, 0, 0.50181],
   1733     "57": [0.18906, 0.47534, 0, 0, 0.50181],
   1734     "58": [0, 0.47534, 0, 0, 0.21606],
   1735     "59": [0.12604, 0.47534, 0, 0, 0.21606],
   1736     "61": [-0.13099, 0.36866, 0, 0, 0.75623],
   1737     "63": [0, 0.69141, 0, 0, 0.36245],
   1738     "65": [0, 0.69141, 0, 0, 0.7176],
   1739     "66": [0, 0.69141, 0, 0, 0.88397],
   1740     "67": [0, 0.69141, 0, 0, 0.61254],
   1741     "68": [0, 0.69141, 0, 0, 0.83158],
   1742     "69": [0, 0.69141, 0, 0, 0.66278],
   1743     "70": [0.12604, 0.69141, 0, 0, 0.61119],
   1744     "71": [0, 0.69141, 0, 0, 0.78539],
   1745     "72": [0.06302, 0.69141, 0, 0, 0.7203],
   1746     "73": [0, 0.69141, 0, 0, 0.55448],
   1747     "74": [0.12604, 0.69141, 0, 0, 0.55231],
   1748     "75": [0, 0.69141, 0, 0, 0.66845],
   1749     "76": [0, 0.69141, 0, 0, 0.66602],
   1750     "77": [0, 0.69141, 0, 0, 1.04953],
   1751     "78": [0, 0.69141, 0, 0, 0.83212],
   1752     "79": [0, 0.69141, 0, 0, 0.82699],
   1753     "80": [0.18906, 0.69141, 0, 0, 0.82753],
   1754     "81": [0.03781, 0.69141, 0, 0, 0.82699],
   1755     "82": [0, 0.69141, 0, 0, 0.82807],
   1756     "83": [0, 0.69141, 0, 0, 0.82861],
   1757     "84": [0, 0.69141, 0, 0, 0.66899],
   1758     "85": [0, 0.69141, 0, 0, 0.64576],
   1759     "86": [0, 0.69141, 0, 0, 0.83131],
   1760     "87": [0, 0.69141, 0, 0, 1.04602],
   1761     "88": [0, 0.69141, 0, 0, 0.71922],
   1762     "89": [0.18906, 0.69141, 0, 0, 0.83293],
   1763     "90": [0.12604, 0.69141, 0, 0, 0.60201],
   1764     "91": [0.24982, 0.74947, 0, 0, 0.27764],
   1765     "93": [0.24982, 0.74947, 0, 0, 0.27764],
   1766     "94": [0, 0.69141, 0, 0, 0.49965],
   1767     "97": [0, 0.47534, 0, 0, 0.50046],
   1768     "98": [0, 0.69141, 0, 0, 0.51315],
   1769     "99": [0, 0.47534, 0, 0, 0.38946],
   1770     "100": [0, 0.62119, 0, 0, 0.49857],
   1771     "101": [0, 0.47534, 0, 0, 0.40053],
   1772     "102": [0.18906, 0.69141, 0, 0, 0.32626],
   1773     "103": [0.18906, 0.47534, 0, 0, 0.5037],
   1774     "104": [0.18906, 0.69141, 0, 0, 0.52126],
   1775     "105": [0, 0.69141, 0, 0, 0.27899],
   1776     "106": [0, 0.69141, 0, 0, 0.28088],
   1777     "107": [0, 0.69141, 0, 0, 0.38946],
   1778     "108": [0, 0.69141, 0, 0, 0.27953],
   1779     "109": [0, 0.47534, 0, 0, 0.76676],
   1780     "110": [0, 0.47534, 0, 0, 0.52666],
   1781     "111": [0, 0.47534, 0, 0, 0.48885],
   1782     "112": [0.18906, 0.52396, 0, 0, 0.50046],
   1783     "113": [0.18906, 0.47534, 0, 0, 0.48912],
   1784     "114": [0, 0.47534, 0, 0, 0.38919],
   1785     "115": [0, 0.47534, 0, 0, 0.44266],
   1786     "116": [0, 0.62119, 0, 0, 0.33301],
   1787     "117": [0, 0.47534, 0, 0, 0.5172],
   1788     "118": [0, 0.52396, 0, 0, 0.5118],
   1789     "119": [0, 0.52396, 0, 0, 0.77351],
   1790     "120": [0.18906, 0.47534, 0, 0, 0.38865],
   1791     "121": [0.18906, 0.47534, 0, 0, 0.49884],
   1792     "122": [0.18906, 0.47534, 0, 0, 0.39054],
   1793     "160": [0, 0, 0, 0, 0.25],
   1794     "8216": [0, 0.69141, 0, 0, 0.21471],
   1795     "8217": [0, 0.69141, 0, 0, 0.21471],
   1796     "58112": [0, 0.62119, 0, 0, 0.49749],
   1797     "58113": [0, 0.62119, 0, 0, 0.4983],
   1798     "58114": [0.18906, 0.69141, 0, 0, 0.33328],
   1799     "58115": [0.18906, 0.69141, 0, 0, 0.32923],
   1800     "58116": [0.18906, 0.47534, 0, 0, 0.50343],
   1801     "58117": [0, 0.69141, 0, 0, 0.33301],
   1802     "58118": [0, 0.62119, 0, 0, 0.33409],
   1803     "58119": [0, 0.47534, 0, 0, 0.50073]
   1804   },
   1805   "Main-Bold": {
   1806     "32": [0, 0, 0, 0, 0.25],
   1807     "33": [0, 0.69444, 0, 0, 0.35],
   1808     "34": [0, 0.69444, 0, 0, 0.60278],
   1809     "35": [0.19444, 0.69444, 0, 0, 0.95833],
   1810     "36": [0.05556, 0.75, 0, 0, 0.575],
   1811     "37": [0.05556, 0.75, 0, 0, 0.95833],
   1812     "38": [0, 0.69444, 0, 0, 0.89444],
   1813     "39": [0, 0.69444, 0, 0, 0.31944],
   1814     "40": [0.25, 0.75, 0, 0, 0.44722],
   1815     "41": [0.25, 0.75, 0, 0, 0.44722],
   1816     "42": [0, 0.75, 0, 0, 0.575],
   1817     "43": [0.13333, 0.63333, 0, 0, 0.89444],
   1818     "44": [0.19444, 0.15556, 0, 0, 0.31944],
   1819     "45": [0, 0.44444, 0, 0, 0.38333],
   1820     "46": [0, 0.15556, 0, 0, 0.31944],
   1821     "47": [0.25, 0.75, 0, 0, 0.575],
   1822     "48": [0, 0.64444, 0, 0, 0.575],
   1823     "49": [0, 0.64444, 0, 0, 0.575],
   1824     "50": [0, 0.64444, 0, 0, 0.575],
   1825     "51": [0, 0.64444, 0, 0, 0.575],
   1826     "52": [0, 0.64444, 0, 0, 0.575],
   1827     "53": [0, 0.64444, 0, 0, 0.575],
   1828     "54": [0, 0.64444, 0, 0, 0.575],
   1829     "55": [0, 0.64444, 0, 0, 0.575],
   1830     "56": [0, 0.64444, 0, 0, 0.575],
   1831     "57": [0, 0.64444, 0, 0, 0.575],
   1832     "58": [0, 0.44444, 0, 0, 0.31944],
   1833     "59": [0.19444, 0.44444, 0, 0, 0.31944],
   1834     "60": [0.08556, 0.58556, 0, 0, 0.89444],
   1835     "61": [-0.10889, 0.39111, 0, 0, 0.89444],
   1836     "62": [0.08556, 0.58556, 0, 0, 0.89444],
   1837     "63": [0, 0.69444, 0, 0, 0.54305],
   1838     "64": [0, 0.69444, 0, 0, 0.89444],
   1839     "65": [0, 0.68611, 0, 0, 0.86944],
   1840     "66": [0, 0.68611, 0, 0, 0.81805],
   1841     "67": [0, 0.68611, 0, 0, 0.83055],
   1842     "68": [0, 0.68611, 0, 0, 0.88194],
   1843     "69": [0, 0.68611, 0, 0, 0.75555],
   1844     "70": [0, 0.68611, 0, 0, 0.72361],
   1845     "71": [0, 0.68611, 0, 0, 0.90416],
   1846     "72": [0, 0.68611, 0, 0, 0.9],
   1847     "73": [0, 0.68611, 0, 0, 0.43611],
   1848     "74": [0, 0.68611, 0, 0, 0.59444],
   1849     "75": [0, 0.68611, 0, 0, 0.90138],
   1850     "76": [0, 0.68611, 0, 0, 0.69166],
   1851     "77": [0, 0.68611, 0, 0, 1.09166],
   1852     "78": [0, 0.68611, 0, 0, 0.9],
   1853     "79": [0, 0.68611, 0, 0, 0.86388],
   1854     "80": [0, 0.68611, 0, 0, 0.78611],
   1855     "81": [0.19444, 0.68611, 0, 0, 0.86388],
   1856     "82": [0, 0.68611, 0, 0, 0.8625],
   1857     "83": [0, 0.68611, 0, 0, 0.63889],
   1858     "84": [0, 0.68611, 0, 0, 0.8],
   1859     "85": [0, 0.68611, 0, 0, 0.88472],
   1860     "86": [0, 0.68611, 0.01597, 0, 0.86944],
   1861     "87": [0, 0.68611, 0.01597, 0, 1.18888],
   1862     "88": [0, 0.68611, 0, 0, 0.86944],
   1863     "89": [0, 0.68611, 0.02875, 0, 0.86944],
   1864     "90": [0, 0.68611, 0, 0, 0.70277],
   1865     "91": [0.25, 0.75, 0, 0, 0.31944],
   1866     "92": [0.25, 0.75, 0, 0, 0.575],
   1867     "93": [0.25, 0.75, 0, 0, 0.31944],
   1868     "94": [0, 0.69444, 0, 0, 0.575],
   1869     "95": [0.31, 0.13444, 0.03194, 0, 0.575],
   1870     "97": [0, 0.44444, 0, 0, 0.55902],
   1871     "98": [0, 0.69444, 0, 0, 0.63889],
   1872     "99": [0, 0.44444, 0, 0, 0.51111],
   1873     "100": [0, 0.69444, 0, 0, 0.63889],
   1874     "101": [0, 0.44444, 0, 0, 0.52708],
   1875     "102": [0, 0.69444, 0.10903, 0, 0.35139],
   1876     "103": [0.19444, 0.44444, 0.01597, 0, 0.575],
   1877     "104": [0, 0.69444, 0, 0, 0.63889],
   1878     "105": [0, 0.69444, 0, 0, 0.31944],
   1879     "106": [0.19444, 0.69444, 0, 0, 0.35139],
   1880     "107": [0, 0.69444, 0, 0, 0.60694],
   1881     "108": [0, 0.69444, 0, 0, 0.31944],
   1882     "109": [0, 0.44444, 0, 0, 0.95833],
   1883     "110": [0, 0.44444, 0, 0, 0.63889],
   1884     "111": [0, 0.44444, 0, 0, 0.575],
   1885     "112": [0.19444, 0.44444, 0, 0, 0.63889],
   1886     "113": [0.19444, 0.44444, 0, 0, 0.60694],
   1887     "114": [0, 0.44444, 0, 0, 0.47361],
   1888     "115": [0, 0.44444, 0, 0, 0.45361],
   1889     "116": [0, 0.63492, 0, 0, 0.44722],
   1890     "117": [0, 0.44444, 0, 0, 0.63889],
   1891     "118": [0, 0.44444, 0.01597, 0, 0.60694],
   1892     "119": [0, 0.44444, 0.01597, 0, 0.83055],
   1893     "120": [0, 0.44444, 0, 0, 0.60694],
   1894     "121": [0.19444, 0.44444, 0.01597, 0, 0.60694],
   1895     "122": [0, 0.44444, 0, 0, 0.51111],
   1896     "123": [0.25, 0.75, 0, 0, 0.575],
   1897     "124": [0.25, 0.75, 0, 0, 0.31944],
   1898     "125": [0.25, 0.75, 0, 0, 0.575],
   1899     "126": [0.35, 0.34444, 0, 0, 0.575],
   1900     "160": [0, 0, 0, 0, 0.25],
   1901     "163": [0, 0.69444, 0, 0, 0.86853],
   1902     "168": [0, 0.69444, 0, 0, 0.575],
   1903     "172": [0, 0.44444, 0, 0, 0.76666],
   1904     "176": [0, 0.69444, 0, 0, 0.86944],
   1905     "177": [0.13333, 0.63333, 0, 0, 0.89444],
   1906     "184": [0.17014, 0, 0, 0, 0.51111],
   1907     "198": [0, 0.68611, 0, 0, 1.04166],
   1908     "215": [0.13333, 0.63333, 0, 0, 0.89444],
   1909     "216": [0.04861, 0.73472, 0, 0, 0.89444],
   1910     "223": [0, 0.69444, 0, 0, 0.59722],
   1911     "230": [0, 0.44444, 0, 0, 0.83055],
   1912     "247": [0.13333, 0.63333, 0, 0, 0.89444],
   1913     "248": [0.09722, 0.54167, 0, 0, 0.575],
   1914     "305": [0, 0.44444, 0, 0, 0.31944],
   1915     "338": [0, 0.68611, 0, 0, 1.16944],
   1916     "339": [0, 0.44444, 0, 0, 0.89444],
   1917     "567": [0.19444, 0.44444, 0, 0, 0.35139],
   1918     "710": [0, 0.69444, 0, 0, 0.575],
   1919     "711": [0, 0.63194, 0, 0, 0.575],
   1920     "713": [0, 0.59611, 0, 0, 0.575],
   1921     "714": [0, 0.69444, 0, 0, 0.575],
   1922     "715": [0, 0.69444, 0, 0, 0.575],
   1923     "728": [0, 0.69444, 0, 0, 0.575],
   1924     "729": [0, 0.69444, 0, 0, 0.31944],
   1925     "730": [0, 0.69444, 0, 0, 0.86944],
   1926     "732": [0, 0.69444, 0, 0, 0.575],
   1927     "733": [0, 0.69444, 0, 0, 0.575],
   1928     "915": [0, 0.68611, 0, 0, 0.69166],
   1929     "916": [0, 0.68611, 0, 0, 0.95833],
   1930     "920": [0, 0.68611, 0, 0, 0.89444],
   1931     "923": [0, 0.68611, 0, 0, 0.80555],
   1932     "926": [0, 0.68611, 0, 0, 0.76666],
   1933     "928": [0, 0.68611, 0, 0, 0.9],
   1934     "931": [0, 0.68611, 0, 0, 0.83055],
   1935     "933": [0, 0.68611, 0, 0, 0.89444],
   1936     "934": [0, 0.68611, 0, 0, 0.83055],
   1937     "936": [0, 0.68611, 0, 0, 0.89444],
   1938     "937": [0, 0.68611, 0, 0, 0.83055],
   1939     "8211": [0, 0.44444, 0.03194, 0, 0.575],
   1940     "8212": [0, 0.44444, 0.03194, 0, 1.14999],
   1941     "8216": [0, 0.69444, 0, 0, 0.31944],
   1942     "8217": [0, 0.69444, 0, 0, 0.31944],
   1943     "8220": [0, 0.69444, 0, 0, 0.60278],
   1944     "8221": [0, 0.69444, 0, 0, 0.60278],
   1945     "8224": [0.19444, 0.69444, 0, 0, 0.51111],
   1946     "8225": [0.19444, 0.69444, 0, 0, 0.51111],
   1947     "8242": [0, 0.55556, 0, 0, 0.34444],
   1948     "8407": [0, 0.72444, 0.15486, 0, 0.575],
   1949     "8463": [0, 0.69444, 0, 0, 0.66759],
   1950     "8465": [0, 0.69444, 0, 0, 0.83055],
   1951     "8467": [0, 0.69444, 0, 0, 0.47361],
   1952     "8472": [0.19444, 0.44444, 0, 0, 0.74027],
   1953     "8476": [0, 0.69444, 0, 0, 0.83055],
   1954     "8501": [0, 0.69444, 0, 0, 0.70277],
   1955     "8592": [-0.10889, 0.39111, 0, 0, 1.14999],
   1956     "8593": [0.19444, 0.69444, 0, 0, 0.575],
   1957     "8594": [-0.10889, 0.39111, 0, 0, 1.14999],
   1958     "8595": [0.19444, 0.69444, 0, 0, 0.575],
   1959     "8596": [-0.10889, 0.39111, 0, 0, 1.14999],
   1960     "8597": [0.25, 0.75, 0, 0, 0.575],
   1961     "8598": [0.19444, 0.69444, 0, 0, 1.14999],
   1962     "8599": [0.19444, 0.69444, 0, 0, 1.14999],
   1963     "8600": [0.19444, 0.69444, 0, 0, 1.14999],
   1964     "8601": [0.19444, 0.69444, 0, 0, 1.14999],
   1965     "8636": [-0.10889, 0.39111, 0, 0, 1.14999],
   1966     "8637": [-0.10889, 0.39111, 0, 0, 1.14999],
   1967     "8640": [-0.10889, 0.39111, 0, 0, 1.14999],
   1968     "8641": [-0.10889, 0.39111, 0, 0, 1.14999],
   1969     "8656": [-0.10889, 0.39111, 0, 0, 1.14999],
   1970     "8657": [0.19444, 0.69444, 0, 0, 0.70277],
   1971     "8658": [-0.10889, 0.39111, 0, 0, 1.14999],
   1972     "8659": [0.19444, 0.69444, 0, 0, 0.70277],
   1973     "8660": [-0.10889, 0.39111, 0, 0, 1.14999],
   1974     "8661": [0.25, 0.75, 0, 0, 0.70277],
   1975     "8704": [0, 0.69444, 0, 0, 0.63889],
   1976     "8706": [0, 0.69444, 0.06389, 0, 0.62847],
   1977     "8707": [0, 0.69444, 0, 0, 0.63889],
   1978     "8709": [0.05556, 0.75, 0, 0, 0.575],
   1979     "8711": [0, 0.68611, 0, 0, 0.95833],
   1980     "8712": [0.08556, 0.58556, 0, 0, 0.76666],
   1981     "8715": [0.08556, 0.58556, 0, 0, 0.76666],
   1982     "8722": [0.13333, 0.63333, 0, 0, 0.89444],
   1983     "8723": [0.13333, 0.63333, 0, 0, 0.89444],
   1984     "8725": [0.25, 0.75, 0, 0, 0.575],
   1985     "8726": [0.25, 0.75, 0, 0, 0.575],
   1986     "8727": [-0.02778, 0.47222, 0, 0, 0.575],
   1987     "8728": [-0.02639, 0.47361, 0, 0, 0.575],
   1988     "8729": [-0.02639, 0.47361, 0, 0, 0.575],
   1989     "8730": [0.18, 0.82, 0, 0, 0.95833],
   1990     "8733": [0, 0.44444, 0, 0, 0.89444],
   1991     "8734": [0, 0.44444, 0, 0, 1.14999],
   1992     "8736": [0, 0.69224, 0, 0, 0.72222],
   1993     "8739": [0.25, 0.75, 0, 0, 0.31944],
   1994     "8741": [0.25, 0.75, 0, 0, 0.575],
   1995     "8743": [0, 0.55556, 0, 0, 0.76666],
   1996     "8744": [0, 0.55556, 0, 0, 0.76666],
   1997     "8745": [0, 0.55556, 0, 0, 0.76666],
   1998     "8746": [0, 0.55556, 0, 0, 0.76666],
   1999     "8747": [0.19444, 0.69444, 0.12778, 0, 0.56875],
   2000     "8764": [-0.10889, 0.39111, 0, 0, 0.89444],
   2001     "8768": [0.19444, 0.69444, 0, 0, 0.31944],
   2002     "8771": [0.00222, 0.50222, 0, 0, 0.89444],
   2003     "8776": [0.02444, 0.52444, 0, 0, 0.89444],
   2004     "8781": [0.00222, 0.50222, 0, 0, 0.89444],
   2005     "8801": [0.00222, 0.50222, 0, 0, 0.89444],
   2006     "8804": [0.19667, 0.69667, 0, 0, 0.89444],
   2007     "8805": [0.19667, 0.69667, 0, 0, 0.89444],
   2008     "8810": [0.08556, 0.58556, 0, 0, 1.14999],
   2009     "8811": [0.08556, 0.58556, 0, 0, 1.14999],
   2010     "8826": [0.08556, 0.58556, 0, 0, 0.89444],
   2011     "8827": [0.08556, 0.58556, 0, 0, 0.89444],
   2012     "8834": [0.08556, 0.58556, 0, 0, 0.89444],
   2013     "8835": [0.08556, 0.58556, 0, 0, 0.89444],
   2014     "8838": [0.19667, 0.69667, 0, 0, 0.89444],
   2015     "8839": [0.19667, 0.69667, 0, 0, 0.89444],
   2016     "8846": [0, 0.55556, 0, 0, 0.76666],
   2017     "8849": [0.19667, 0.69667, 0, 0, 0.89444],
   2018     "8850": [0.19667, 0.69667, 0, 0, 0.89444],
   2019     "8851": [0, 0.55556, 0, 0, 0.76666],
   2020     "8852": [0, 0.55556, 0, 0, 0.76666],
   2021     "8853": [0.13333, 0.63333, 0, 0, 0.89444],
   2022     "8854": [0.13333, 0.63333, 0, 0, 0.89444],
   2023     "8855": [0.13333, 0.63333, 0, 0, 0.89444],
   2024     "8856": [0.13333, 0.63333, 0, 0, 0.89444],
   2025     "8857": [0.13333, 0.63333, 0, 0, 0.89444],
   2026     "8866": [0, 0.69444, 0, 0, 0.70277],
   2027     "8867": [0, 0.69444, 0, 0, 0.70277],
   2028     "8868": [0, 0.69444, 0, 0, 0.89444],
   2029     "8869": [0, 0.69444, 0, 0, 0.89444],
   2030     "8900": [-0.02639, 0.47361, 0, 0, 0.575],
   2031     "8901": [-0.02639, 0.47361, 0, 0, 0.31944],
   2032     "8902": [-0.02778, 0.47222, 0, 0, 0.575],
   2033     "8968": [0.25, 0.75, 0, 0, 0.51111],
   2034     "8969": [0.25, 0.75, 0, 0, 0.51111],
   2035     "8970": [0.25, 0.75, 0, 0, 0.51111],
   2036     "8971": [0.25, 0.75, 0, 0, 0.51111],
   2037     "8994": [-0.13889, 0.36111, 0, 0, 1.14999],
   2038     "8995": [-0.13889, 0.36111, 0, 0, 1.14999],
   2039     "9651": [0.19444, 0.69444, 0, 0, 1.02222],
   2040     "9657": [-0.02778, 0.47222, 0, 0, 0.575],
   2041     "9661": [0.19444, 0.69444, 0, 0, 1.02222],
   2042     "9667": [-0.02778, 0.47222, 0, 0, 0.575],
   2043     "9711": [0.19444, 0.69444, 0, 0, 1.14999],
   2044     "9824": [0.12963, 0.69444, 0, 0, 0.89444],
   2045     "9825": [0.12963, 0.69444, 0, 0, 0.89444],
   2046     "9826": [0.12963, 0.69444, 0, 0, 0.89444],
   2047     "9827": [0.12963, 0.69444, 0, 0, 0.89444],
   2048     "9837": [0, 0.75, 0, 0, 0.44722],
   2049     "9838": [0.19444, 0.69444, 0, 0, 0.44722],
   2050     "9839": [0.19444, 0.69444, 0, 0, 0.44722],
   2051     "10216": [0.25, 0.75, 0, 0, 0.44722],
   2052     "10217": [0.25, 0.75, 0, 0, 0.44722],
   2053     "10815": [0, 0.68611, 0, 0, 0.9],
   2054     "10927": [0.19667, 0.69667, 0, 0, 0.89444],
   2055     "10928": [0.19667, 0.69667, 0, 0, 0.89444],
   2056     "57376": [0.19444, 0.69444, 0, 0, 0]
   2057   },
   2058   "Main-BoldItalic": {
   2059     "32": [0, 0, 0, 0, 0.25],
   2060     "33": [0, 0.69444, 0.11417, 0, 0.38611],
   2061     "34": [0, 0.69444, 0.07939, 0, 0.62055],
   2062     "35": [0.19444, 0.69444, 0.06833, 0, 0.94444],
   2063     "37": [0.05556, 0.75, 0.12861, 0, 0.94444],
   2064     "38": [0, 0.69444, 0.08528, 0, 0.88555],
   2065     "39": [0, 0.69444, 0.12945, 0, 0.35555],
   2066     "40": [0.25, 0.75, 0.15806, 0, 0.47333],
   2067     "41": [0.25, 0.75, 0.03306, 0, 0.47333],
   2068     "42": [0, 0.75, 0.14333, 0, 0.59111],
   2069     "43": [0.10333, 0.60333, 0.03306, 0, 0.88555],
   2070     "44": [0.19444, 0.14722, 0, 0, 0.35555],
   2071     "45": [0, 0.44444, 0.02611, 0, 0.41444],
   2072     "46": [0, 0.14722, 0, 0, 0.35555],
   2073     "47": [0.25, 0.75, 0.15806, 0, 0.59111],
   2074     "48": [0, 0.64444, 0.13167, 0, 0.59111],
   2075     "49": [0, 0.64444, 0.13167, 0, 0.59111],
   2076     "50": [0, 0.64444, 0.13167, 0, 0.59111],
   2077     "51": [0, 0.64444, 0.13167, 0, 0.59111],
   2078     "52": [0.19444, 0.64444, 0.13167, 0, 0.59111],
   2079     "53": [0, 0.64444, 0.13167, 0, 0.59111],
   2080     "54": [0, 0.64444, 0.13167, 0, 0.59111],
   2081     "55": [0.19444, 0.64444, 0.13167, 0, 0.59111],
   2082     "56": [0, 0.64444, 0.13167, 0, 0.59111],
   2083     "57": [0, 0.64444, 0.13167, 0, 0.59111],
   2084     "58": [0, 0.44444, 0.06695, 0, 0.35555],
   2085     "59": [0.19444, 0.44444, 0.06695, 0, 0.35555],
   2086     "61": [-0.10889, 0.39111, 0.06833, 0, 0.88555],
   2087     "63": [0, 0.69444, 0.11472, 0, 0.59111],
   2088     "64": [0, 0.69444, 0.09208, 0, 0.88555],
   2089     "65": [0, 0.68611, 0, 0, 0.86555],
   2090     "66": [0, 0.68611, 0.0992, 0, 0.81666],
   2091     "67": [0, 0.68611, 0.14208, 0, 0.82666],
   2092     "68": [0, 0.68611, 0.09062, 0, 0.87555],
   2093     "69": [0, 0.68611, 0.11431, 0, 0.75666],
   2094     "70": [0, 0.68611, 0.12903, 0, 0.72722],
   2095     "71": [0, 0.68611, 0.07347, 0, 0.89527],
   2096     "72": [0, 0.68611, 0.17208, 0, 0.8961],
   2097     "73": [0, 0.68611, 0.15681, 0, 0.47166],
   2098     "74": [0, 0.68611, 0.145, 0, 0.61055],
   2099     "75": [0, 0.68611, 0.14208, 0, 0.89499],
   2100     "76": [0, 0.68611, 0, 0, 0.69777],
   2101     "77": [0, 0.68611, 0.17208, 0, 1.07277],
   2102     "78": [0, 0.68611, 0.17208, 0, 0.8961],
   2103     "79": [0, 0.68611, 0.09062, 0, 0.85499],
   2104     "80": [0, 0.68611, 0.0992, 0, 0.78721],
   2105     "81": [0.19444, 0.68611, 0.09062, 0, 0.85499],
   2106     "82": [0, 0.68611, 0.02559, 0, 0.85944],
   2107     "83": [0, 0.68611, 0.11264, 0, 0.64999],
   2108     "84": [0, 0.68611, 0.12903, 0, 0.7961],
   2109     "85": [0, 0.68611, 0.17208, 0, 0.88083],
   2110     "86": [0, 0.68611, 0.18625, 0, 0.86555],
   2111     "87": [0, 0.68611, 0.18625, 0, 1.15999],
   2112     "88": [0, 0.68611, 0.15681, 0, 0.86555],
   2113     "89": [0, 0.68611, 0.19803, 0, 0.86555],
   2114     "90": [0, 0.68611, 0.14208, 0, 0.70888],
   2115     "91": [0.25, 0.75, 0.1875, 0, 0.35611],
   2116     "93": [0.25, 0.75, 0.09972, 0, 0.35611],
   2117     "94": [0, 0.69444, 0.06709, 0, 0.59111],
   2118     "95": [0.31, 0.13444, 0.09811, 0, 0.59111],
   2119     "97": [0, 0.44444, 0.09426, 0, 0.59111],
   2120     "98": [0, 0.69444, 0.07861, 0, 0.53222],
   2121     "99": [0, 0.44444, 0.05222, 0, 0.53222],
   2122     "100": [0, 0.69444, 0.10861, 0, 0.59111],
   2123     "101": [0, 0.44444, 0.085, 0, 0.53222],
   2124     "102": [0.19444, 0.69444, 0.21778, 0, 0.4],
   2125     "103": [0.19444, 0.44444, 0.105, 0, 0.53222],
   2126     "104": [0, 0.69444, 0.09426, 0, 0.59111],
   2127     "105": [0, 0.69326, 0.11387, 0, 0.35555],
   2128     "106": [0.19444, 0.69326, 0.1672, 0, 0.35555],
   2129     "107": [0, 0.69444, 0.11111, 0, 0.53222],
   2130     "108": [0, 0.69444, 0.10861, 0, 0.29666],
   2131     "109": [0, 0.44444, 0.09426, 0, 0.94444],
   2132     "110": [0, 0.44444, 0.09426, 0, 0.64999],
   2133     "111": [0, 0.44444, 0.07861, 0, 0.59111],
   2134     "112": [0.19444, 0.44444, 0.07861, 0, 0.59111],
   2135     "113": [0.19444, 0.44444, 0.105, 0, 0.53222],
   2136     "114": [0, 0.44444, 0.11111, 0, 0.50167],
   2137     "115": [0, 0.44444, 0.08167, 0, 0.48694],
   2138     "116": [0, 0.63492, 0.09639, 0, 0.385],
   2139     "117": [0, 0.44444, 0.09426, 0, 0.62055],
   2140     "118": [0, 0.44444, 0.11111, 0, 0.53222],
   2141     "119": [0, 0.44444, 0.11111, 0, 0.76777],
   2142     "120": [0, 0.44444, 0.12583, 0, 0.56055],
   2143     "121": [0.19444, 0.44444, 0.105, 0, 0.56166],
   2144     "122": [0, 0.44444, 0.13889, 0, 0.49055],
   2145     "126": [0.35, 0.34444, 0.11472, 0, 0.59111],
   2146     "160": [0, 0, 0, 0, 0.25],
   2147     "168": [0, 0.69444, 0.11473, 0, 0.59111],
   2148     "176": [0, 0.69444, 0, 0, 0.94888],
   2149     "184": [0.17014, 0, 0, 0, 0.53222],
   2150     "198": [0, 0.68611, 0.11431, 0, 1.02277],
   2151     "216": [0.04861, 0.73472, 0.09062, 0, 0.88555],
   2152     "223": [0.19444, 0.69444, 0.09736, 0, 0.665],
   2153     "230": [0, 0.44444, 0.085, 0, 0.82666],
   2154     "248": [0.09722, 0.54167, 0.09458, 0, 0.59111],
   2155     "305": [0, 0.44444, 0.09426, 0, 0.35555],
   2156     "338": [0, 0.68611, 0.11431, 0, 1.14054],
   2157     "339": [0, 0.44444, 0.085, 0, 0.82666],
   2158     "567": [0.19444, 0.44444, 0.04611, 0, 0.385],
   2159     "710": [0, 0.69444, 0.06709, 0, 0.59111],
   2160     "711": [0, 0.63194, 0.08271, 0, 0.59111],
   2161     "713": [0, 0.59444, 0.10444, 0, 0.59111],
   2162     "714": [0, 0.69444, 0.08528, 0, 0.59111],
   2163     "715": [0, 0.69444, 0, 0, 0.59111],
   2164     "728": [0, 0.69444, 0.10333, 0, 0.59111],
   2165     "729": [0, 0.69444, 0.12945, 0, 0.35555],
   2166     "730": [0, 0.69444, 0, 0, 0.94888],
   2167     "732": [0, 0.69444, 0.11472, 0, 0.59111],
   2168     "733": [0, 0.69444, 0.11472, 0, 0.59111],
   2169     "915": [0, 0.68611, 0.12903, 0, 0.69777],
   2170     "916": [0, 0.68611, 0, 0, 0.94444],
   2171     "920": [0, 0.68611, 0.09062, 0, 0.88555],
   2172     "923": [0, 0.68611, 0, 0, 0.80666],
   2173     "926": [0, 0.68611, 0.15092, 0, 0.76777],
   2174     "928": [0, 0.68611, 0.17208, 0, 0.8961],
   2175     "931": [0, 0.68611, 0.11431, 0, 0.82666],
   2176     "933": [0, 0.68611, 0.10778, 0, 0.88555],
   2177     "934": [0, 0.68611, 0.05632, 0, 0.82666],
   2178     "936": [0, 0.68611, 0.10778, 0, 0.88555],
   2179     "937": [0, 0.68611, 0.0992, 0, 0.82666],
   2180     "8211": [0, 0.44444, 0.09811, 0, 0.59111],
   2181     "8212": [0, 0.44444, 0.09811, 0, 1.18221],
   2182     "8216": [0, 0.69444, 0.12945, 0, 0.35555],
   2183     "8217": [0, 0.69444, 0.12945, 0, 0.35555],
   2184     "8220": [0, 0.69444, 0.16772, 0, 0.62055],
   2185     "8221": [0, 0.69444, 0.07939, 0, 0.62055]
   2186   },
   2187   "Main-Italic": {
   2188     "32": [0, 0, 0, 0, 0.25],
   2189     "33": [0, 0.69444, 0.12417, 0, 0.30667],
   2190     "34": [0, 0.69444, 0.06961, 0, 0.51444],
   2191     "35": [0.19444, 0.69444, 0.06616, 0, 0.81777],
   2192     "37": [0.05556, 0.75, 0.13639, 0, 0.81777],
   2193     "38": [0, 0.69444, 0.09694, 0, 0.76666],
   2194     "39": [0, 0.69444, 0.12417, 0, 0.30667],
   2195     "40": [0.25, 0.75, 0.16194, 0, 0.40889],
   2196     "41": [0.25, 0.75, 0.03694, 0, 0.40889],
   2197     "42": [0, 0.75, 0.14917, 0, 0.51111],
   2198     "43": [0.05667, 0.56167, 0.03694, 0, 0.76666],
   2199     "44": [0.19444, 0.10556, 0, 0, 0.30667],
   2200     "45": [0, 0.43056, 0.02826, 0, 0.35778],
   2201     "46": [0, 0.10556, 0, 0, 0.30667],
   2202     "47": [0.25, 0.75, 0.16194, 0, 0.51111],
   2203     "48": [0, 0.64444, 0.13556, 0, 0.51111],
   2204     "49": [0, 0.64444, 0.13556, 0, 0.51111],
   2205     "50": [0, 0.64444, 0.13556, 0, 0.51111],
   2206     "51": [0, 0.64444, 0.13556, 0, 0.51111],
   2207     "52": [0.19444, 0.64444, 0.13556, 0, 0.51111],
   2208     "53": [0, 0.64444, 0.13556, 0, 0.51111],
   2209     "54": [0, 0.64444, 0.13556, 0, 0.51111],
   2210     "55": [0.19444, 0.64444, 0.13556, 0, 0.51111],
   2211     "56": [0, 0.64444, 0.13556, 0, 0.51111],
   2212     "57": [0, 0.64444, 0.13556, 0, 0.51111],
   2213     "58": [0, 0.43056, 0.0582, 0, 0.30667],
   2214     "59": [0.19444, 0.43056, 0.0582, 0, 0.30667],
   2215     "61": [-0.13313, 0.36687, 0.06616, 0, 0.76666],
   2216     "63": [0, 0.69444, 0.1225, 0, 0.51111],
   2217     "64": [0, 0.69444, 0.09597, 0, 0.76666],
   2218     "65": [0, 0.68333, 0, 0, 0.74333],
   2219     "66": [0, 0.68333, 0.10257, 0, 0.70389],
   2220     "67": [0, 0.68333, 0.14528, 0, 0.71555],
   2221     "68": [0, 0.68333, 0.09403, 0, 0.755],
   2222     "69": [0, 0.68333, 0.12028, 0, 0.67833],
   2223     "70": [0, 0.68333, 0.13305, 0, 0.65277],
   2224     "71": [0, 0.68333, 0.08722, 0, 0.77361],
   2225     "72": [0, 0.68333, 0.16389, 0, 0.74333],
   2226     "73": [0, 0.68333, 0.15806, 0, 0.38555],
   2227     "74": [0, 0.68333, 0.14028, 0, 0.525],
   2228     "75": [0, 0.68333, 0.14528, 0, 0.76888],
   2229     "76": [0, 0.68333, 0, 0, 0.62722],
   2230     "77": [0, 0.68333, 0.16389, 0, 0.89666],
   2231     "78": [0, 0.68333, 0.16389, 0, 0.74333],
   2232     "79": [0, 0.68333, 0.09403, 0, 0.76666],
   2233     "80": [0, 0.68333, 0.10257, 0, 0.67833],
   2234     "81": [0.19444, 0.68333, 0.09403, 0, 0.76666],
   2235     "82": [0, 0.68333, 0.03868, 0, 0.72944],
   2236     "83": [0, 0.68333, 0.11972, 0, 0.56222],
   2237     "84": [0, 0.68333, 0.13305, 0, 0.71555],
   2238     "85": [0, 0.68333, 0.16389, 0, 0.74333],
   2239     "86": [0, 0.68333, 0.18361, 0, 0.74333],
   2240     "87": [0, 0.68333, 0.18361, 0, 0.99888],
   2241     "88": [0, 0.68333, 0.15806, 0, 0.74333],
   2242     "89": [0, 0.68333, 0.19383, 0, 0.74333],
   2243     "90": [0, 0.68333, 0.14528, 0, 0.61333],
   2244     "91": [0.25, 0.75, 0.1875, 0, 0.30667],
   2245     "93": [0.25, 0.75, 0.10528, 0, 0.30667],
   2246     "94": [0, 0.69444, 0.06646, 0, 0.51111],
   2247     "95": [0.31, 0.12056, 0.09208, 0, 0.51111],
   2248     "97": [0, 0.43056, 0.07671, 0, 0.51111],
   2249     "98": [0, 0.69444, 0.06312, 0, 0.46],
   2250     "99": [0, 0.43056, 0.05653, 0, 0.46],
   2251     "100": [0, 0.69444, 0.10333, 0, 0.51111],
   2252     "101": [0, 0.43056, 0.07514, 0, 0.46],
   2253     "102": [0.19444, 0.69444, 0.21194, 0, 0.30667],
   2254     "103": [0.19444, 0.43056, 0.08847, 0, 0.46],
   2255     "104": [0, 0.69444, 0.07671, 0, 0.51111],
   2256     "105": [0, 0.65536, 0.1019, 0, 0.30667],
   2257     "106": [0.19444, 0.65536, 0.14467, 0, 0.30667],
   2258     "107": [0, 0.69444, 0.10764, 0, 0.46],
   2259     "108": [0, 0.69444, 0.10333, 0, 0.25555],
   2260     "109": [0, 0.43056, 0.07671, 0, 0.81777],
   2261     "110": [0, 0.43056, 0.07671, 0, 0.56222],
   2262     "111": [0, 0.43056, 0.06312, 0, 0.51111],
   2263     "112": [0.19444, 0.43056, 0.06312, 0, 0.51111],
   2264     "113": [0.19444, 0.43056, 0.08847, 0, 0.46],
   2265     "114": [0, 0.43056, 0.10764, 0, 0.42166],
   2266     "115": [0, 0.43056, 0.08208, 0, 0.40889],
   2267     "116": [0, 0.61508, 0.09486, 0, 0.33222],
   2268     "117": [0, 0.43056, 0.07671, 0, 0.53666],
   2269     "118": [0, 0.43056, 0.10764, 0, 0.46],
   2270     "119": [0, 0.43056, 0.10764, 0, 0.66444],
   2271     "120": [0, 0.43056, 0.12042, 0, 0.46389],
   2272     "121": [0.19444, 0.43056, 0.08847, 0, 0.48555],
   2273     "122": [0, 0.43056, 0.12292, 0, 0.40889],
   2274     "126": [0.35, 0.31786, 0.11585, 0, 0.51111],
   2275     "160": [0, 0, 0, 0, 0.25],
   2276     "168": [0, 0.66786, 0.10474, 0, 0.51111],
   2277     "176": [0, 0.69444, 0, 0, 0.83129],
   2278     "184": [0.17014, 0, 0, 0, 0.46],
   2279     "198": [0, 0.68333, 0.12028, 0, 0.88277],
   2280     "216": [0.04861, 0.73194, 0.09403, 0, 0.76666],
   2281     "223": [0.19444, 0.69444, 0.10514, 0, 0.53666],
   2282     "230": [0, 0.43056, 0.07514, 0, 0.71555],
   2283     "248": [0.09722, 0.52778, 0.09194, 0, 0.51111],
   2284     "338": [0, 0.68333, 0.12028, 0, 0.98499],
   2285     "339": [0, 0.43056, 0.07514, 0, 0.71555],
   2286     "710": [0, 0.69444, 0.06646, 0, 0.51111],
   2287     "711": [0, 0.62847, 0.08295, 0, 0.51111],
   2288     "713": [0, 0.56167, 0.10333, 0, 0.51111],
   2289     "714": [0, 0.69444, 0.09694, 0, 0.51111],
   2290     "715": [0, 0.69444, 0, 0, 0.51111],
   2291     "728": [0, 0.69444, 0.10806, 0, 0.51111],
   2292     "729": [0, 0.66786, 0.11752, 0, 0.30667],
   2293     "730": [0, 0.69444, 0, 0, 0.83129],
   2294     "732": [0, 0.66786, 0.11585, 0, 0.51111],
   2295     "733": [0, 0.69444, 0.1225, 0, 0.51111],
   2296     "915": [0, 0.68333, 0.13305, 0, 0.62722],
   2297     "916": [0, 0.68333, 0, 0, 0.81777],
   2298     "920": [0, 0.68333, 0.09403, 0, 0.76666],
   2299     "923": [0, 0.68333, 0, 0, 0.69222],
   2300     "926": [0, 0.68333, 0.15294, 0, 0.66444],
   2301     "928": [0, 0.68333, 0.16389, 0, 0.74333],
   2302     "931": [0, 0.68333, 0.12028, 0, 0.71555],
   2303     "933": [0, 0.68333, 0.11111, 0, 0.76666],
   2304     "934": [0, 0.68333, 0.05986, 0, 0.71555],
   2305     "936": [0, 0.68333, 0.11111, 0, 0.76666],
   2306     "937": [0, 0.68333, 0.10257, 0, 0.71555],
   2307     "8211": [0, 0.43056, 0.09208, 0, 0.51111],
   2308     "8212": [0, 0.43056, 0.09208, 0, 1.02222],
   2309     "8216": [0, 0.69444, 0.12417, 0, 0.30667],
   2310     "8217": [0, 0.69444, 0.12417, 0, 0.30667],
   2311     "8220": [0, 0.69444, 0.1685, 0, 0.51444],
   2312     "8221": [0, 0.69444, 0.06961, 0, 0.51444],
   2313     "8463": [0, 0.68889, 0, 0, 0.54028]
   2314   },
   2315   "Main-Regular": {
   2316     "32": [0, 0, 0, 0, 0.25],
   2317     "33": [0, 0.69444, 0, 0, 0.27778],
   2318     "34": [0, 0.69444, 0, 0, 0.5],
   2319     "35": [0.19444, 0.69444, 0, 0, 0.83334],
   2320     "36": [0.05556, 0.75, 0, 0, 0.5],
   2321     "37": [0.05556, 0.75, 0, 0, 0.83334],
   2322     "38": [0, 0.69444, 0, 0, 0.77778],
   2323     "39": [0, 0.69444, 0, 0, 0.27778],
   2324     "40": [0.25, 0.75, 0, 0, 0.38889],
   2325     "41": [0.25, 0.75, 0, 0, 0.38889],
   2326     "42": [0, 0.75, 0, 0, 0.5],
   2327     "43": [0.08333, 0.58333, 0, 0, 0.77778],
   2328     "44": [0.19444, 0.10556, 0, 0, 0.27778],
   2329     "45": [0, 0.43056, 0, 0, 0.33333],
   2330     "46": [0, 0.10556, 0, 0, 0.27778],
   2331     "47": [0.25, 0.75, 0, 0, 0.5],
   2332     "48": [0, 0.64444, 0, 0, 0.5],
   2333     "49": [0, 0.64444, 0, 0, 0.5],
   2334     "50": [0, 0.64444, 0, 0, 0.5],
   2335     "51": [0, 0.64444, 0, 0, 0.5],
   2336     "52": [0, 0.64444, 0, 0, 0.5],
   2337     "53": [0, 0.64444, 0, 0, 0.5],
   2338     "54": [0, 0.64444, 0, 0, 0.5],
   2339     "55": [0, 0.64444, 0, 0, 0.5],
   2340     "56": [0, 0.64444, 0, 0, 0.5],
   2341     "57": [0, 0.64444, 0, 0, 0.5],
   2342     "58": [0, 0.43056, 0, 0, 0.27778],
   2343     "59": [0.19444, 0.43056, 0, 0, 0.27778],
   2344     "60": [0.0391, 0.5391, 0, 0, 0.77778],
   2345     "61": [-0.13313, 0.36687, 0, 0, 0.77778],
   2346     "62": [0.0391, 0.5391, 0, 0, 0.77778],
   2347     "63": [0, 0.69444, 0, 0, 0.47222],
   2348     "64": [0, 0.69444, 0, 0, 0.77778],
   2349     "65": [0, 0.68333, 0, 0, 0.75],
   2350     "66": [0, 0.68333, 0, 0, 0.70834],
   2351     "67": [0, 0.68333, 0, 0, 0.72222],
   2352     "68": [0, 0.68333, 0, 0, 0.76389],
   2353     "69": [0, 0.68333, 0, 0, 0.68056],
   2354     "70": [0, 0.68333, 0, 0, 0.65278],
   2355     "71": [0, 0.68333, 0, 0, 0.78472],
   2356     "72": [0, 0.68333, 0, 0, 0.75],
   2357     "73": [0, 0.68333, 0, 0, 0.36111],
   2358     "74": [0, 0.68333, 0, 0, 0.51389],
   2359     "75": [0, 0.68333, 0, 0, 0.77778],
   2360     "76": [0, 0.68333, 0, 0, 0.625],
   2361     "77": [0, 0.68333, 0, 0, 0.91667],
   2362     "78": [0, 0.68333, 0, 0, 0.75],
   2363     "79": [0, 0.68333, 0, 0, 0.77778],
   2364     "80": [0, 0.68333, 0, 0, 0.68056],
   2365     "81": [0.19444, 0.68333, 0, 0, 0.77778],
   2366     "82": [0, 0.68333, 0, 0, 0.73611],
   2367     "83": [0, 0.68333, 0, 0, 0.55556],
   2368     "84": [0, 0.68333, 0, 0, 0.72222],
   2369     "85": [0, 0.68333, 0, 0, 0.75],
   2370     "86": [0, 0.68333, 0.01389, 0, 0.75],
   2371     "87": [0, 0.68333, 0.01389, 0, 1.02778],
   2372     "88": [0, 0.68333, 0, 0, 0.75],
   2373     "89": [0, 0.68333, 0.025, 0, 0.75],
   2374     "90": [0, 0.68333, 0, 0, 0.61111],
   2375     "91": [0.25, 0.75, 0, 0, 0.27778],
   2376     "92": [0.25, 0.75, 0, 0, 0.5],
   2377     "93": [0.25, 0.75, 0, 0, 0.27778],
   2378     "94": [0, 0.69444, 0, 0, 0.5],
   2379     "95": [0.31, 0.12056, 0.02778, 0, 0.5],
   2380     "97": [0, 0.43056, 0, 0, 0.5],
   2381     "98": [0, 0.69444, 0, 0, 0.55556],
   2382     "99": [0, 0.43056, 0, 0, 0.44445],
   2383     "100": [0, 0.69444, 0, 0, 0.55556],
   2384     "101": [0, 0.43056, 0, 0, 0.44445],
   2385     "102": [0, 0.69444, 0.07778, 0, 0.30556],
   2386     "103": [0.19444, 0.43056, 0.01389, 0, 0.5],
   2387     "104": [0, 0.69444, 0, 0, 0.55556],
   2388     "105": [0, 0.66786, 0, 0, 0.27778],
   2389     "106": [0.19444, 0.66786, 0, 0, 0.30556],
   2390     "107": [0, 0.69444, 0, 0, 0.52778],
   2391     "108": [0, 0.69444, 0, 0, 0.27778],
   2392     "109": [0, 0.43056, 0, 0, 0.83334],
   2393     "110": [0, 0.43056, 0, 0, 0.55556],
   2394     "111": [0, 0.43056, 0, 0, 0.5],
   2395     "112": [0.19444, 0.43056, 0, 0, 0.55556],
   2396     "113": [0.19444, 0.43056, 0, 0, 0.52778],
   2397     "114": [0, 0.43056, 0, 0, 0.39167],
   2398     "115": [0, 0.43056, 0, 0, 0.39445],
   2399     "116": [0, 0.61508, 0, 0, 0.38889],
   2400     "117": [0, 0.43056, 0, 0, 0.55556],
   2401     "118": [0, 0.43056, 0.01389, 0, 0.52778],
   2402     "119": [0, 0.43056, 0.01389, 0, 0.72222],
   2403     "120": [0, 0.43056, 0, 0, 0.52778],
   2404     "121": [0.19444, 0.43056, 0.01389, 0, 0.52778],
   2405     "122": [0, 0.43056, 0, 0, 0.44445],
   2406     "123": [0.25, 0.75, 0, 0, 0.5],
   2407     "124": [0.25, 0.75, 0, 0, 0.27778],
   2408     "125": [0.25, 0.75, 0, 0, 0.5],
   2409     "126": [0.35, 0.31786, 0, 0, 0.5],
   2410     "160": [0, 0, 0, 0, 0.25],
   2411     "163": [0, 0.69444, 0, 0, 0.76909],
   2412     "167": [0.19444, 0.69444, 0, 0, 0.44445],
   2413     "168": [0, 0.66786, 0, 0, 0.5],
   2414     "172": [0, 0.43056, 0, 0, 0.66667],
   2415     "176": [0, 0.69444, 0, 0, 0.75],
   2416     "177": [0.08333, 0.58333, 0, 0, 0.77778],
   2417     "182": [0.19444, 0.69444, 0, 0, 0.61111],
   2418     "184": [0.17014, 0, 0, 0, 0.44445],
   2419     "198": [0, 0.68333, 0, 0, 0.90278],
   2420     "215": [0.08333, 0.58333, 0, 0, 0.77778],
   2421     "216": [0.04861, 0.73194, 0, 0, 0.77778],
   2422     "223": [0, 0.69444, 0, 0, 0.5],
   2423     "230": [0, 0.43056, 0, 0, 0.72222],
   2424     "247": [0.08333, 0.58333, 0, 0, 0.77778],
   2425     "248": [0.09722, 0.52778, 0, 0, 0.5],
   2426     "305": [0, 0.43056, 0, 0, 0.27778],
   2427     "338": [0, 0.68333, 0, 0, 1.01389],
   2428     "339": [0, 0.43056, 0, 0, 0.77778],
   2429     "567": [0.19444, 0.43056, 0, 0, 0.30556],
   2430     "710": [0, 0.69444, 0, 0, 0.5],
   2431     "711": [0, 0.62847, 0, 0, 0.5],
   2432     "713": [0, 0.56778, 0, 0, 0.5],
   2433     "714": [0, 0.69444, 0, 0, 0.5],
   2434     "715": [0, 0.69444, 0, 0, 0.5],
   2435     "728": [0, 0.69444, 0, 0, 0.5],
   2436     "729": [0, 0.66786, 0, 0, 0.27778],
   2437     "730": [0, 0.69444, 0, 0, 0.75],
   2438     "732": [0, 0.66786, 0, 0, 0.5],
   2439     "733": [0, 0.69444, 0, 0, 0.5],
   2440     "915": [0, 0.68333, 0, 0, 0.625],
   2441     "916": [0, 0.68333, 0, 0, 0.83334],
   2442     "920": [0, 0.68333, 0, 0, 0.77778],
   2443     "923": [0, 0.68333, 0, 0, 0.69445],
   2444     "926": [0, 0.68333, 0, 0, 0.66667],
   2445     "928": [0, 0.68333, 0, 0, 0.75],
   2446     "931": [0, 0.68333, 0, 0, 0.72222],
   2447     "933": [0, 0.68333, 0, 0, 0.77778],
   2448     "934": [0, 0.68333, 0, 0, 0.72222],
   2449     "936": [0, 0.68333, 0, 0, 0.77778],
   2450     "937": [0, 0.68333, 0, 0, 0.72222],
   2451     "8211": [0, 0.43056, 0.02778, 0, 0.5],
   2452     "8212": [0, 0.43056, 0.02778, 0, 1.0],
   2453     "8216": [0, 0.69444, 0, 0, 0.27778],
   2454     "8217": [0, 0.69444, 0, 0, 0.27778],
   2455     "8220": [0, 0.69444, 0, 0, 0.5],
   2456     "8221": [0, 0.69444, 0, 0, 0.5],
   2457     "8224": [0.19444, 0.69444, 0, 0, 0.44445],
   2458     "8225": [0.19444, 0.69444, 0, 0, 0.44445],
   2459     "8230": [0, 0.12, 0, 0, 1.172],
   2460     "8242": [0, 0.55556, 0, 0, 0.275],
   2461     "8407": [0, 0.71444, 0.15382, 0, 0.5],
   2462     "8463": [0, 0.68889, 0, 0, 0.54028],
   2463     "8465": [0, 0.69444, 0, 0, 0.72222],
   2464     "8467": [0, 0.69444, 0, 0.11111, 0.41667],
   2465     "8472": [0.19444, 0.43056, 0, 0.11111, 0.63646],
   2466     "8476": [0, 0.69444, 0, 0, 0.72222],
   2467     "8501": [0, 0.69444, 0, 0, 0.61111],
   2468     "8592": [-0.13313, 0.36687, 0, 0, 1.0],
   2469     "8593": [0.19444, 0.69444, 0, 0, 0.5],
   2470     "8594": [-0.13313, 0.36687, 0, 0, 1.0],
   2471     "8595": [0.19444, 0.69444, 0, 0, 0.5],
   2472     "8596": [-0.13313, 0.36687, 0, 0, 1.0],
   2473     "8597": [0.25, 0.75, 0, 0, 0.5],
   2474     "8598": [0.19444, 0.69444, 0, 0, 1.0],
   2475     "8599": [0.19444, 0.69444, 0, 0, 1.0],
   2476     "8600": [0.19444, 0.69444, 0, 0, 1.0],
   2477     "8601": [0.19444, 0.69444, 0, 0, 1.0],
   2478     "8614": [0.011, 0.511, 0, 0, 1.0],
   2479     "8617": [0.011, 0.511, 0, 0, 1.126],
   2480     "8618": [0.011, 0.511, 0, 0, 1.126],
   2481     "8636": [-0.13313, 0.36687, 0, 0, 1.0],
   2482     "8637": [-0.13313, 0.36687, 0, 0, 1.0],
   2483     "8640": [-0.13313, 0.36687, 0, 0, 1.0],
   2484     "8641": [-0.13313, 0.36687, 0, 0, 1.0],
   2485     "8652": [0.011, 0.671, 0, 0, 1.0],
   2486     "8656": [-0.13313, 0.36687, 0, 0, 1.0],
   2487     "8657": [0.19444, 0.69444, 0, 0, 0.61111],
   2488     "8658": [-0.13313, 0.36687, 0, 0, 1.0],
   2489     "8659": [0.19444, 0.69444, 0, 0, 0.61111],
   2490     "8660": [-0.13313, 0.36687, 0, 0, 1.0],
   2491     "8661": [0.25, 0.75, 0, 0, 0.61111],
   2492     "8704": [0, 0.69444, 0, 0, 0.55556],
   2493     "8706": [0, 0.69444, 0.05556, 0.08334, 0.5309],
   2494     "8707": [0, 0.69444, 0, 0, 0.55556],
   2495     "8709": [0.05556, 0.75, 0, 0, 0.5],
   2496     "8711": [0, 0.68333, 0, 0, 0.83334],
   2497     "8712": [0.0391, 0.5391, 0, 0, 0.66667],
   2498     "8715": [0.0391, 0.5391, 0, 0, 0.66667],
   2499     "8722": [0.08333, 0.58333, 0, 0, 0.77778],
   2500     "8723": [0.08333, 0.58333, 0, 0, 0.77778],
   2501     "8725": [0.25, 0.75, 0, 0, 0.5],
   2502     "8726": [0.25, 0.75, 0, 0, 0.5],
   2503     "8727": [-0.03472, 0.46528, 0, 0, 0.5],
   2504     "8728": [-0.05555, 0.44445, 0, 0, 0.5],
   2505     "8729": [-0.05555, 0.44445, 0, 0, 0.5],
   2506     "8730": [0.2, 0.8, 0, 0, 0.83334],
   2507     "8733": [0, 0.43056, 0, 0, 0.77778],
   2508     "8734": [0, 0.43056, 0, 0, 1.0],
   2509     "8736": [0, 0.69224, 0, 0, 0.72222],
   2510     "8739": [0.25, 0.75, 0, 0, 0.27778],
   2511     "8741": [0.25, 0.75, 0, 0, 0.5],
   2512     "8743": [0, 0.55556, 0, 0, 0.66667],
   2513     "8744": [0, 0.55556, 0, 0, 0.66667],
   2514     "8745": [0, 0.55556, 0, 0, 0.66667],
   2515     "8746": [0, 0.55556, 0, 0, 0.66667],
   2516     "8747": [0.19444, 0.69444, 0.11111, 0, 0.41667],
   2517     "8764": [-0.13313, 0.36687, 0, 0, 0.77778],
   2518     "8768": [0.19444, 0.69444, 0, 0, 0.27778],
   2519     "8771": [-0.03625, 0.46375, 0, 0, 0.77778],
   2520     "8773": [-0.022, 0.589, 0, 0, 1.0],
   2521     "8776": [-0.01688, 0.48312, 0, 0, 0.77778],
   2522     "8781": [-0.03625, 0.46375, 0, 0, 0.77778],
   2523     "8784": [-0.133, 0.67, 0, 0, 0.778],
   2524     "8801": [-0.03625, 0.46375, 0, 0, 0.77778],
   2525     "8804": [0.13597, 0.63597, 0, 0, 0.77778],
   2526     "8805": [0.13597, 0.63597, 0, 0, 0.77778],
   2527     "8810": [0.0391, 0.5391, 0, 0, 1.0],
   2528     "8811": [0.0391, 0.5391, 0, 0, 1.0],
   2529     "8826": [0.0391, 0.5391, 0, 0, 0.77778],
   2530     "8827": [0.0391, 0.5391, 0, 0, 0.77778],
   2531     "8834": [0.0391, 0.5391, 0, 0, 0.77778],
   2532     "8835": [0.0391, 0.5391, 0, 0, 0.77778],
   2533     "8838": [0.13597, 0.63597, 0, 0, 0.77778],
   2534     "8839": [0.13597, 0.63597, 0, 0, 0.77778],
   2535     "8846": [0, 0.55556, 0, 0, 0.66667],
   2536     "8849": [0.13597, 0.63597, 0, 0, 0.77778],
   2537     "8850": [0.13597, 0.63597, 0, 0, 0.77778],
   2538     "8851": [0, 0.55556, 0, 0, 0.66667],
   2539     "8852": [0, 0.55556, 0, 0, 0.66667],
   2540     "8853": [0.08333, 0.58333, 0, 0, 0.77778],
   2541     "8854": [0.08333, 0.58333, 0, 0, 0.77778],
   2542     "8855": [0.08333, 0.58333, 0, 0, 0.77778],
   2543     "8856": [0.08333, 0.58333, 0, 0, 0.77778],
   2544     "8857": [0.08333, 0.58333, 0, 0, 0.77778],
   2545     "8866": [0, 0.69444, 0, 0, 0.61111],
   2546     "8867": [0, 0.69444, 0, 0, 0.61111],
   2547     "8868": [0, 0.69444, 0, 0, 0.77778],
   2548     "8869": [0, 0.69444, 0, 0, 0.77778],
   2549     "8872": [0.249, 0.75, 0, 0, 0.867],
   2550     "8900": [-0.05555, 0.44445, 0, 0, 0.5],
   2551     "8901": [-0.05555, 0.44445, 0, 0, 0.27778],
   2552     "8902": [-0.03472, 0.46528, 0, 0, 0.5],
   2553     "8904": [0.005, 0.505, 0, 0, 0.9],
   2554     "8942": [0.03, 0.9, 0, 0, 0.278],
   2555     "8943": [-0.19, 0.31, 0, 0, 1.172],
   2556     "8945": [-0.1, 0.82, 0, 0, 1.282],
   2557     "8968": [0.25, 0.75, 0, 0, 0.44445],
   2558     "8969": [0.25, 0.75, 0, 0, 0.44445],
   2559     "8970": [0.25, 0.75, 0, 0, 0.44445],
   2560     "8971": [0.25, 0.75, 0, 0, 0.44445],
   2561     "8994": [-0.14236, 0.35764, 0, 0, 1.0],
   2562     "8995": [-0.14236, 0.35764, 0, 0, 1.0],
   2563     "9136": [0.244, 0.744, 0, 0, 0.412],
   2564     "9137": [0.244, 0.744, 0, 0, 0.412],
   2565     "9651": [0.19444, 0.69444, 0, 0, 0.88889],
   2566     "9657": [-0.03472, 0.46528, 0, 0, 0.5],
   2567     "9661": [0.19444, 0.69444, 0, 0, 0.88889],
   2568     "9667": [-0.03472, 0.46528, 0, 0, 0.5],
   2569     "9711": [0.19444, 0.69444, 0, 0, 1.0],
   2570     "9824": [0.12963, 0.69444, 0, 0, 0.77778],
   2571     "9825": [0.12963, 0.69444, 0, 0, 0.77778],
   2572     "9826": [0.12963, 0.69444, 0, 0, 0.77778],
   2573     "9827": [0.12963, 0.69444, 0, 0, 0.77778],
   2574     "9837": [0, 0.75, 0, 0, 0.38889],
   2575     "9838": [0.19444, 0.69444, 0, 0, 0.38889],
   2576     "9839": [0.19444, 0.69444, 0, 0, 0.38889],
   2577     "10216": [0.25, 0.75, 0, 0, 0.38889],
   2578     "10217": [0.25, 0.75, 0, 0, 0.38889],
   2579     "10222": [0.244, 0.744, 0, 0, 0.412],
   2580     "10223": [0.244, 0.744, 0, 0, 0.412],
   2581     "10229": [0.011, 0.511, 0, 0, 1.609],
   2582     "10230": [0.011, 0.511, 0, 0, 1.638],
   2583     "10231": [0.011, 0.511, 0, 0, 1.859],
   2584     "10232": [0.024, 0.525, 0, 0, 1.609],
   2585     "10233": [0.024, 0.525, 0, 0, 1.638],
   2586     "10234": [0.024, 0.525, 0, 0, 1.858],
   2587     "10236": [0.011, 0.511, 0, 0, 1.638],
   2588     "10815": [0, 0.68333, 0, 0, 0.75],
   2589     "10927": [0.13597, 0.63597, 0, 0, 0.77778],
   2590     "10928": [0.13597, 0.63597, 0, 0, 0.77778],
   2591     "57376": [0.19444, 0.69444, 0, 0, 0]
   2592   },
   2593   "Math-BoldItalic": {
   2594     "32": [0, 0, 0, 0, 0.25],
   2595     "48": [0, 0.44444, 0, 0, 0.575],
   2596     "49": [0, 0.44444, 0, 0, 0.575],
   2597     "50": [0, 0.44444, 0, 0, 0.575],
   2598     "51": [0.19444, 0.44444, 0, 0, 0.575],
   2599     "52": [0.19444, 0.44444, 0, 0, 0.575],
   2600     "53": [0.19444, 0.44444, 0, 0, 0.575],
   2601     "54": [0, 0.64444, 0, 0, 0.575],
   2602     "55": [0.19444, 0.44444, 0, 0, 0.575],
   2603     "56": [0, 0.64444, 0, 0, 0.575],
   2604     "57": [0.19444, 0.44444, 0, 0, 0.575],
   2605     "65": [0, 0.68611, 0, 0, 0.86944],
   2606     "66": [0, 0.68611, 0.04835, 0, 0.8664],
   2607     "67": [0, 0.68611, 0.06979, 0, 0.81694],
   2608     "68": [0, 0.68611, 0.03194, 0, 0.93812],
   2609     "69": [0, 0.68611, 0.05451, 0, 0.81007],
   2610     "70": [0, 0.68611, 0.15972, 0, 0.68889],
   2611     "71": [0, 0.68611, 0, 0, 0.88673],
   2612     "72": [0, 0.68611, 0.08229, 0, 0.98229],
   2613     "73": [0, 0.68611, 0.07778, 0, 0.51111],
   2614     "74": [0, 0.68611, 0.10069, 0, 0.63125],
   2615     "75": [0, 0.68611, 0.06979, 0, 0.97118],
   2616     "76": [0, 0.68611, 0, 0, 0.75555],
   2617     "77": [0, 0.68611, 0.11424, 0, 1.14201],
   2618     "78": [0, 0.68611, 0.11424, 0, 0.95034],
   2619     "79": [0, 0.68611, 0.03194, 0, 0.83666],
   2620     "80": [0, 0.68611, 0.15972, 0, 0.72309],
   2621     "81": [0.19444, 0.68611, 0, 0, 0.86861],
   2622     "82": [0, 0.68611, 0.00421, 0, 0.87235],
   2623     "83": [0, 0.68611, 0.05382, 0, 0.69271],
   2624     "84": [0, 0.68611, 0.15972, 0, 0.63663],
   2625     "85": [0, 0.68611, 0.11424, 0, 0.80027],
   2626     "86": [0, 0.68611, 0.25555, 0, 0.67778],
   2627     "87": [0, 0.68611, 0.15972, 0, 1.09305],
   2628     "88": [0, 0.68611, 0.07778, 0, 0.94722],
   2629     "89": [0, 0.68611, 0.25555, 0, 0.67458],
   2630     "90": [0, 0.68611, 0.06979, 0, 0.77257],
   2631     "97": [0, 0.44444, 0, 0, 0.63287],
   2632     "98": [0, 0.69444, 0, 0, 0.52083],
   2633     "99": [0, 0.44444, 0, 0, 0.51342],
   2634     "100": [0, 0.69444, 0, 0, 0.60972],
   2635     "101": [0, 0.44444, 0, 0, 0.55361],
   2636     "102": [0.19444, 0.69444, 0.11042, 0, 0.56806],
   2637     "103": [0.19444, 0.44444, 0.03704, 0, 0.5449],
   2638     "104": [0, 0.69444, 0, 0, 0.66759],
   2639     "105": [0, 0.69326, 0, 0, 0.4048],
   2640     "106": [0.19444, 0.69326, 0.0622, 0, 0.47083],
   2641     "107": [0, 0.69444, 0.01852, 0, 0.6037],
   2642     "108": [0, 0.69444, 0.0088, 0, 0.34815],
   2643     "109": [0, 0.44444, 0, 0, 1.0324],
   2644     "110": [0, 0.44444, 0, 0, 0.71296],
   2645     "111": [0, 0.44444, 0, 0, 0.58472],
   2646     "112": [0.19444, 0.44444, 0, 0, 0.60092],
   2647     "113": [0.19444, 0.44444, 0.03704, 0, 0.54213],
   2648     "114": [0, 0.44444, 0.03194, 0, 0.5287],
   2649     "115": [0, 0.44444, 0, 0, 0.53125],
   2650     "116": [0, 0.63492, 0, 0, 0.41528],
   2651     "117": [0, 0.44444, 0, 0, 0.68102],
   2652     "118": [0, 0.44444, 0.03704, 0, 0.56666],
   2653     "119": [0, 0.44444, 0.02778, 0, 0.83148],
   2654     "120": [0, 0.44444, 0, 0, 0.65903],
   2655     "121": [0.19444, 0.44444, 0.03704, 0, 0.59028],
   2656     "122": [0, 0.44444, 0.04213, 0, 0.55509],
   2657     "160": [0, 0, 0, 0, 0.25],
   2658     "915": [0, 0.68611, 0.15972, 0, 0.65694],
   2659     "916": [0, 0.68611, 0, 0, 0.95833],
   2660     "920": [0, 0.68611, 0.03194, 0, 0.86722],
   2661     "923": [0, 0.68611, 0, 0, 0.80555],
   2662     "926": [0, 0.68611, 0.07458, 0, 0.84125],
   2663     "928": [0, 0.68611, 0.08229, 0, 0.98229],
   2664     "931": [0, 0.68611, 0.05451, 0, 0.88507],
   2665     "933": [0, 0.68611, 0.15972, 0, 0.67083],
   2666     "934": [0, 0.68611, 0, 0, 0.76666],
   2667     "936": [0, 0.68611, 0.11653, 0, 0.71402],
   2668     "937": [0, 0.68611, 0.04835, 0, 0.8789],
   2669     "945": [0, 0.44444, 0, 0, 0.76064],
   2670     "946": [0.19444, 0.69444, 0.03403, 0, 0.65972],
   2671     "947": [0.19444, 0.44444, 0.06389, 0, 0.59003],
   2672     "948": [0, 0.69444, 0.03819, 0, 0.52222],
   2673     "949": [0, 0.44444, 0, 0, 0.52882],
   2674     "950": [0.19444, 0.69444, 0.06215, 0, 0.50833],
   2675     "951": [0.19444, 0.44444, 0.03704, 0, 0.6],
   2676     "952": [0, 0.69444, 0.03194, 0, 0.5618],
   2677     "953": [0, 0.44444, 0, 0, 0.41204],
   2678     "954": [0, 0.44444, 0, 0, 0.66759],
   2679     "955": [0, 0.69444, 0, 0, 0.67083],
   2680     "956": [0.19444, 0.44444, 0, 0, 0.70787],
   2681     "957": [0, 0.44444, 0.06898, 0, 0.57685],
   2682     "958": [0.19444, 0.69444, 0.03021, 0, 0.50833],
   2683     "959": [0, 0.44444, 0, 0, 0.58472],
   2684     "960": [0, 0.44444, 0.03704, 0, 0.68241],
   2685     "961": [0.19444, 0.44444, 0, 0, 0.6118],
   2686     "962": [0.09722, 0.44444, 0.07917, 0, 0.42361],
   2687     "963": [0, 0.44444, 0.03704, 0, 0.68588],
   2688     "964": [0, 0.44444, 0.13472, 0, 0.52083],
   2689     "965": [0, 0.44444, 0.03704, 0, 0.63055],
   2690     "966": [0.19444, 0.44444, 0, 0, 0.74722],
   2691     "967": [0.19444, 0.44444, 0, 0, 0.71805],
   2692     "968": [0.19444, 0.69444, 0.03704, 0, 0.75833],
   2693     "969": [0, 0.44444, 0.03704, 0, 0.71782],
   2694     "977": [0, 0.69444, 0, 0, 0.69155],
   2695     "981": [0.19444, 0.69444, 0, 0, 0.7125],
   2696     "982": [0, 0.44444, 0.03194, 0, 0.975],
   2697     "1009": [0.19444, 0.44444, 0, 0, 0.6118],
   2698     "1013": [0, 0.44444, 0, 0, 0.48333],
   2699     "57649": [0, 0.44444, 0, 0, 0.39352],
   2700     "57911": [0.19444, 0.44444, 0, 0, 0.43889]
   2701   },
   2702   "Math-Italic": {
   2703     "32": [0, 0, 0, 0, 0.25],
   2704     "48": [0, 0.43056, 0, 0, 0.5],
   2705     "49": [0, 0.43056, 0, 0, 0.5],
   2706     "50": [0, 0.43056, 0, 0, 0.5],
   2707     "51": [0.19444, 0.43056, 0, 0, 0.5],
   2708     "52": [0.19444, 0.43056, 0, 0, 0.5],
   2709     "53": [0.19444, 0.43056, 0, 0, 0.5],
   2710     "54": [0, 0.64444, 0, 0, 0.5],
   2711     "55": [0.19444, 0.43056, 0, 0, 0.5],
   2712     "56": [0, 0.64444, 0, 0, 0.5],
   2713     "57": [0.19444, 0.43056, 0, 0, 0.5],
   2714     "65": [0, 0.68333, 0, 0.13889, 0.75],
   2715     "66": [0, 0.68333, 0.05017, 0.08334, 0.75851],
   2716     "67": [0, 0.68333, 0.07153, 0.08334, 0.71472],
   2717     "68": [0, 0.68333, 0.02778, 0.05556, 0.82792],
   2718     "69": [0, 0.68333, 0.05764, 0.08334, 0.7382],
   2719     "70": [0, 0.68333, 0.13889, 0.08334, 0.64306],
   2720     "71": [0, 0.68333, 0, 0.08334, 0.78625],
   2721     "72": [0, 0.68333, 0.08125, 0.05556, 0.83125],
   2722     "73": [0, 0.68333, 0.07847, 0.11111, 0.43958],
   2723     "74": [0, 0.68333, 0.09618, 0.16667, 0.55451],
   2724     "75": [0, 0.68333, 0.07153, 0.05556, 0.84931],
   2725     "76": [0, 0.68333, 0, 0.02778, 0.68056],
   2726     "77": [0, 0.68333, 0.10903, 0.08334, 0.97014],
   2727     "78": [0, 0.68333, 0.10903, 0.08334, 0.80347],
   2728     "79": [0, 0.68333, 0.02778, 0.08334, 0.76278],
   2729     "80": [0, 0.68333, 0.13889, 0.08334, 0.64201],
   2730     "81": [0.19444, 0.68333, 0, 0.08334, 0.79056],
   2731     "82": [0, 0.68333, 0.00773, 0.08334, 0.75929],
   2732     "83": [0, 0.68333, 0.05764, 0.08334, 0.6132],
   2733     "84": [0, 0.68333, 0.13889, 0.08334, 0.58438],
   2734     "85": [0, 0.68333, 0.10903, 0.02778, 0.68278],
   2735     "86": [0, 0.68333, 0.22222, 0, 0.58333],
   2736     "87": [0, 0.68333, 0.13889, 0, 0.94445],
   2737     "88": [0, 0.68333, 0.07847, 0.08334, 0.82847],
   2738     "89": [0, 0.68333, 0.22222, 0, 0.58056],
   2739     "90": [0, 0.68333, 0.07153, 0.08334, 0.68264],
   2740     "97": [0, 0.43056, 0, 0, 0.52859],
   2741     "98": [0, 0.69444, 0, 0, 0.42917],
   2742     "99": [0, 0.43056, 0, 0.05556, 0.43276],
   2743     "100": [0, 0.69444, 0, 0.16667, 0.52049],
   2744     "101": [0, 0.43056, 0, 0.05556, 0.46563],
   2745     "102": [0.19444, 0.69444, 0.10764, 0.16667, 0.48959],
   2746     "103": [0.19444, 0.43056, 0.03588, 0.02778, 0.47697],
   2747     "104": [0, 0.69444, 0, 0, 0.57616],
   2748     "105": [0, 0.65952, 0, 0, 0.34451],
   2749     "106": [0.19444, 0.65952, 0.05724, 0, 0.41181],
   2750     "107": [0, 0.69444, 0.03148, 0, 0.5206],
   2751     "108": [0, 0.69444, 0.01968, 0.08334, 0.29838],
   2752     "109": [0, 0.43056, 0, 0, 0.87801],
   2753     "110": [0, 0.43056, 0, 0, 0.60023],
   2754     "111": [0, 0.43056, 0, 0.05556, 0.48472],
   2755     "112": [0.19444, 0.43056, 0, 0.08334, 0.50313],
   2756     "113": [0.19444, 0.43056, 0.03588, 0.08334, 0.44641],
   2757     "114": [0, 0.43056, 0.02778, 0.05556, 0.45116],
   2758     "115": [0, 0.43056, 0, 0.05556, 0.46875],
   2759     "116": [0, 0.61508, 0, 0.08334, 0.36111],
   2760     "117": [0, 0.43056, 0, 0.02778, 0.57246],
   2761     "118": [0, 0.43056, 0.03588, 0.02778, 0.48472],
   2762     "119": [0, 0.43056, 0.02691, 0.08334, 0.71592],
   2763     "120": [0, 0.43056, 0, 0.02778, 0.57153],
   2764     "121": [0.19444, 0.43056, 0.03588, 0.05556, 0.49028],
   2765     "122": [0, 0.43056, 0.04398, 0.05556, 0.46505],
   2766     "160": [0, 0, 0, 0, 0.25],
   2767     "915": [0, 0.68333, 0.13889, 0.08334, 0.61528],
   2768     "916": [0, 0.68333, 0, 0.16667, 0.83334],
   2769     "920": [0, 0.68333, 0.02778, 0.08334, 0.76278],
   2770     "923": [0, 0.68333, 0, 0.16667, 0.69445],
   2771     "926": [0, 0.68333, 0.07569, 0.08334, 0.74236],
   2772     "928": [0, 0.68333, 0.08125, 0.05556, 0.83125],
   2773     "931": [0, 0.68333, 0.05764, 0.08334, 0.77986],
   2774     "933": [0, 0.68333, 0.13889, 0.05556, 0.58333],
   2775     "934": [0, 0.68333, 0, 0.08334, 0.66667],
   2776     "936": [0, 0.68333, 0.11, 0.05556, 0.61222],
   2777     "937": [0, 0.68333, 0.05017, 0.08334, 0.7724],
   2778     "945": [0, 0.43056, 0.0037, 0.02778, 0.6397],
   2779     "946": [0.19444, 0.69444, 0.05278, 0.08334, 0.56563],
   2780     "947": [0.19444, 0.43056, 0.05556, 0, 0.51773],
   2781     "948": [0, 0.69444, 0.03785, 0.05556, 0.44444],
   2782     "949": [0, 0.43056, 0, 0.08334, 0.46632],
   2783     "950": [0.19444, 0.69444, 0.07378, 0.08334, 0.4375],
   2784     "951": [0.19444, 0.43056, 0.03588, 0.05556, 0.49653],
   2785     "952": [0, 0.69444, 0.02778, 0.08334, 0.46944],
   2786     "953": [0, 0.43056, 0, 0.05556, 0.35394],
   2787     "954": [0, 0.43056, 0, 0, 0.57616],
   2788     "955": [0, 0.69444, 0, 0, 0.58334],
   2789     "956": [0.19444, 0.43056, 0, 0.02778, 0.60255],
   2790     "957": [0, 0.43056, 0.06366, 0.02778, 0.49398],
   2791     "958": [0.19444, 0.69444, 0.04601, 0.11111, 0.4375],
   2792     "959": [0, 0.43056, 0, 0.05556, 0.48472],
   2793     "960": [0, 0.43056, 0.03588, 0, 0.57003],
   2794     "961": [0.19444, 0.43056, 0, 0.08334, 0.51702],
   2795     "962": [0.09722, 0.43056, 0.07986, 0.08334, 0.36285],
   2796     "963": [0, 0.43056, 0.03588, 0, 0.57141],
   2797     "964": [0, 0.43056, 0.1132, 0.02778, 0.43715],
   2798     "965": [0, 0.43056, 0.03588, 0.02778, 0.54028],
   2799     "966": [0.19444, 0.43056, 0, 0.08334, 0.65417],
   2800     "967": [0.19444, 0.43056, 0, 0.05556, 0.62569],
   2801     "968": [0.19444, 0.69444, 0.03588, 0.11111, 0.65139],
   2802     "969": [0, 0.43056, 0.03588, 0, 0.62245],
   2803     "977": [0, 0.69444, 0, 0.08334, 0.59144],
   2804     "981": [0.19444, 0.69444, 0, 0.08334, 0.59583],
   2805     "982": [0, 0.43056, 0.02778, 0, 0.82813],
   2806     "1009": [0.19444, 0.43056, 0, 0.08334, 0.51702],
   2807     "1013": [0, 0.43056, 0, 0.05556, 0.4059],
   2808     "57649": [0, 0.43056, 0, 0.02778, 0.32246],
   2809     "57911": [0.19444, 0.43056, 0, 0.08334, 0.38403]
   2810   },
   2811   "SansSerif-Bold": {
   2812     "32": [0, 0, 0, 0, 0.25],
   2813     "33": [0, 0.69444, 0, 0, 0.36667],
   2814     "34": [0, 0.69444, 0, 0, 0.55834],
   2815     "35": [0.19444, 0.69444, 0, 0, 0.91667],
   2816     "36": [0.05556, 0.75, 0, 0, 0.55],
   2817     "37": [0.05556, 0.75, 0, 0, 1.02912],
   2818     "38": [0, 0.69444, 0, 0, 0.83056],
   2819     "39": [0, 0.69444, 0, 0, 0.30556],
   2820     "40": [0.25, 0.75, 0, 0, 0.42778],
   2821     "41": [0.25, 0.75, 0, 0, 0.42778],
   2822     "42": [0, 0.75, 0, 0, 0.55],
   2823     "43": [0.11667, 0.61667, 0, 0, 0.85556],
   2824     "44": [0.10556, 0.13056, 0, 0, 0.30556],
   2825     "45": [0, 0.45833, 0, 0, 0.36667],
   2826     "46": [0, 0.13056, 0, 0, 0.30556],
   2827     "47": [0.25, 0.75, 0, 0, 0.55],
   2828     "48": [0, 0.69444, 0, 0, 0.55],
   2829     "49": [0, 0.69444, 0, 0, 0.55],
   2830     "50": [0, 0.69444, 0, 0, 0.55],
   2831     "51": [0, 0.69444, 0, 0, 0.55],
   2832     "52": [0, 0.69444, 0, 0, 0.55],
   2833     "53": [0, 0.69444, 0, 0, 0.55],
   2834     "54": [0, 0.69444, 0, 0, 0.55],
   2835     "55": [0, 0.69444, 0, 0, 0.55],
   2836     "56": [0, 0.69444, 0, 0, 0.55],
   2837     "57": [0, 0.69444, 0, 0, 0.55],
   2838     "58": [0, 0.45833, 0, 0, 0.30556],
   2839     "59": [0.10556, 0.45833, 0, 0, 0.30556],
   2840     "61": [-0.09375, 0.40625, 0, 0, 0.85556],
   2841     "63": [0, 0.69444, 0, 0, 0.51945],
   2842     "64": [0, 0.69444, 0, 0, 0.73334],
   2843     "65": [0, 0.69444, 0, 0, 0.73334],
   2844     "66": [0, 0.69444, 0, 0, 0.73334],
   2845     "67": [0, 0.69444, 0, 0, 0.70278],
   2846     "68": [0, 0.69444, 0, 0, 0.79445],
   2847     "69": [0, 0.69444, 0, 0, 0.64167],
   2848     "70": [0, 0.69444, 0, 0, 0.61111],
   2849     "71": [0, 0.69444, 0, 0, 0.73334],
   2850     "72": [0, 0.69444, 0, 0, 0.79445],
   2851     "73": [0, 0.69444, 0, 0, 0.33056],
   2852     "74": [0, 0.69444, 0, 0, 0.51945],
   2853     "75": [0, 0.69444, 0, 0, 0.76389],
   2854     "76": [0, 0.69444, 0, 0, 0.58056],
   2855     "77": [0, 0.69444, 0, 0, 0.97778],
   2856     "78": [0, 0.69444, 0, 0, 0.79445],
   2857     "79": [0, 0.69444, 0, 0, 0.79445],
   2858     "80": [0, 0.69444, 0, 0, 0.70278],
   2859     "81": [0.10556, 0.69444, 0, 0, 0.79445],
   2860     "82": [0, 0.69444, 0, 0, 0.70278],
   2861     "83": [0, 0.69444, 0, 0, 0.61111],
   2862     "84": [0, 0.69444, 0, 0, 0.73334],
   2863     "85": [0, 0.69444, 0, 0, 0.76389],
   2864     "86": [0, 0.69444, 0.01528, 0, 0.73334],
   2865     "87": [0, 0.69444, 0.01528, 0, 1.03889],
   2866     "88": [0, 0.69444, 0, 0, 0.73334],
   2867     "89": [0, 0.69444, 0.0275, 0, 0.73334],
   2868     "90": [0, 0.69444, 0, 0, 0.67223],
   2869     "91": [0.25, 0.75, 0, 0, 0.34306],
   2870     "93": [0.25, 0.75, 0, 0, 0.34306],
   2871     "94": [0, 0.69444, 0, 0, 0.55],
   2872     "95": [0.35, 0.10833, 0.03056, 0, 0.55],
   2873     "97": [0, 0.45833, 0, 0, 0.525],
   2874     "98": [0, 0.69444, 0, 0, 0.56111],
   2875     "99": [0, 0.45833, 0, 0, 0.48889],
   2876     "100": [0, 0.69444, 0, 0, 0.56111],
   2877     "101": [0, 0.45833, 0, 0, 0.51111],
   2878     "102": [0, 0.69444, 0.07639, 0, 0.33611],
   2879     "103": [0.19444, 0.45833, 0.01528, 0, 0.55],
   2880     "104": [0, 0.69444, 0, 0, 0.56111],
   2881     "105": [0, 0.69444, 0, 0, 0.25556],
   2882     "106": [0.19444, 0.69444, 0, 0, 0.28611],
   2883     "107": [0, 0.69444, 0, 0, 0.53056],
   2884     "108": [0, 0.69444, 0, 0, 0.25556],
   2885     "109": [0, 0.45833, 0, 0, 0.86667],
   2886     "110": [0, 0.45833, 0, 0, 0.56111],
   2887     "111": [0, 0.45833, 0, 0, 0.55],
   2888     "112": [0.19444, 0.45833, 0, 0, 0.56111],
   2889     "113": [0.19444, 0.45833, 0, 0, 0.56111],
   2890     "114": [0, 0.45833, 0.01528, 0, 0.37222],
   2891     "115": [0, 0.45833, 0, 0, 0.42167],
   2892     "116": [0, 0.58929, 0, 0, 0.40417],
   2893     "117": [0, 0.45833, 0, 0, 0.56111],
   2894     "118": [0, 0.45833, 0.01528, 0, 0.5],
   2895     "119": [0, 0.45833, 0.01528, 0, 0.74445],
   2896     "120": [0, 0.45833, 0, 0, 0.5],
   2897     "121": [0.19444, 0.45833, 0.01528, 0, 0.5],
   2898     "122": [0, 0.45833, 0, 0, 0.47639],
   2899     "126": [0.35, 0.34444, 0, 0, 0.55],
   2900     "160": [0, 0, 0, 0, 0.25],
   2901     "168": [0, 0.69444, 0, 0, 0.55],
   2902     "176": [0, 0.69444, 0, 0, 0.73334],
   2903     "180": [0, 0.69444, 0, 0, 0.55],
   2904     "184": [0.17014, 0, 0, 0, 0.48889],
   2905     "305": [0, 0.45833, 0, 0, 0.25556],
   2906     "567": [0.19444, 0.45833, 0, 0, 0.28611],
   2907     "710": [0, 0.69444, 0, 0, 0.55],
   2908     "711": [0, 0.63542, 0, 0, 0.55],
   2909     "713": [0, 0.63778, 0, 0, 0.55],
   2910     "728": [0, 0.69444, 0, 0, 0.55],
   2911     "729": [0, 0.69444, 0, 0, 0.30556],
   2912     "730": [0, 0.69444, 0, 0, 0.73334],
   2913     "732": [0, 0.69444, 0, 0, 0.55],
   2914     "733": [0, 0.69444, 0, 0, 0.55],
   2915     "915": [0, 0.69444, 0, 0, 0.58056],
   2916     "916": [0, 0.69444, 0, 0, 0.91667],
   2917     "920": [0, 0.69444, 0, 0, 0.85556],
   2918     "923": [0, 0.69444, 0, 0, 0.67223],
   2919     "926": [0, 0.69444, 0, 0, 0.73334],
   2920     "928": [0, 0.69444, 0, 0, 0.79445],
   2921     "931": [0, 0.69444, 0, 0, 0.79445],
   2922     "933": [0, 0.69444, 0, 0, 0.85556],
   2923     "934": [0, 0.69444, 0, 0, 0.79445],
   2924     "936": [0, 0.69444, 0, 0, 0.85556],
   2925     "937": [0, 0.69444, 0, 0, 0.79445],
   2926     "8211": [0, 0.45833, 0.03056, 0, 0.55],
   2927     "8212": [0, 0.45833, 0.03056, 0, 1.10001],
   2928     "8216": [0, 0.69444, 0, 0, 0.30556],
   2929     "8217": [0, 0.69444, 0, 0, 0.30556],
   2930     "8220": [0, 0.69444, 0, 0, 0.55834],
   2931     "8221": [0, 0.69444, 0, 0, 0.55834]
   2932   },
   2933   "SansSerif-Italic": {
   2934     "32": [0, 0, 0, 0, 0.25],
   2935     "33": [0, 0.69444, 0.05733, 0, 0.31945],
   2936     "34": [0, 0.69444, 0.00316, 0, 0.5],
   2937     "35": [0.19444, 0.69444, 0.05087, 0, 0.83334],
   2938     "36": [0.05556, 0.75, 0.11156, 0, 0.5],
   2939     "37": [0.05556, 0.75, 0.03126, 0, 0.83334],
   2940     "38": [0, 0.69444, 0.03058, 0, 0.75834],
   2941     "39": [0, 0.69444, 0.07816, 0, 0.27778],
   2942     "40": [0.25, 0.75, 0.13164, 0, 0.38889],
   2943     "41": [0.25, 0.75, 0.02536, 0, 0.38889],
   2944     "42": [0, 0.75, 0.11775, 0, 0.5],
   2945     "43": [0.08333, 0.58333, 0.02536, 0, 0.77778],
   2946     "44": [0.125, 0.08333, 0, 0, 0.27778],
   2947     "45": [0, 0.44444, 0.01946, 0, 0.33333],
   2948     "46": [0, 0.08333, 0, 0, 0.27778],
   2949     "47": [0.25, 0.75, 0.13164, 0, 0.5],
   2950     "48": [0, 0.65556, 0.11156, 0, 0.5],
   2951     "49": [0, 0.65556, 0.11156, 0, 0.5],
   2952     "50": [0, 0.65556, 0.11156, 0, 0.5],
   2953     "51": [0, 0.65556, 0.11156, 0, 0.5],
   2954     "52": [0, 0.65556, 0.11156, 0, 0.5],
   2955     "53": [0, 0.65556, 0.11156, 0, 0.5],
   2956     "54": [0, 0.65556, 0.11156, 0, 0.5],
   2957     "55": [0, 0.65556, 0.11156, 0, 0.5],
   2958     "56": [0, 0.65556, 0.11156, 0, 0.5],
   2959     "57": [0, 0.65556, 0.11156, 0, 0.5],
   2960     "58": [0, 0.44444, 0.02502, 0, 0.27778],
   2961     "59": [0.125, 0.44444, 0.02502, 0, 0.27778],
   2962     "61": [-0.13, 0.37, 0.05087, 0, 0.77778],
   2963     "63": [0, 0.69444, 0.11809, 0, 0.47222],
   2964     "64": [0, 0.69444, 0.07555, 0, 0.66667],
   2965     "65": [0, 0.69444, 0, 0, 0.66667],
   2966     "66": [0, 0.69444, 0.08293, 0, 0.66667],
   2967     "67": [0, 0.69444, 0.11983, 0, 0.63889],
   2968     "68": [0, 0.69444, 0.07555, 0, 0.72223],
   2969     "69": [0, 0.69444, 0.11983, 0, 0.59722],
   2970     "70": [0, 0.69444, 0.13372, 0, 0.56945],
   2971     "71": [0, 0.69444, 0.11983, 0, 0.66667],
   2972     "72": [0, 0.69444, 0.08094, 0, 0.70834],
   2973     "73": [0, 0.69444, 0.13372, 0, 0.27778],
   2974     "74": [0, 0.69444, 0.08094, 0, 0.47222],
   2975     "75": [0, 0.69444, 0.11983, 0, 0.69445],
   2976     "76": [0, 0.69444, 0, 0, 0.54167],
   2977     "77": [0, 0.69444, 0.08094, 0, 0.875],
   2978     "78": [0, 0.69444, 0.08094, 0, 0.70834],
   2979     "79": [0, 0.69444, 0.07555, 0, 0.73611],
   2980     "80": [0, 0.69444, 0.08293, 0, 0.63889],
   2981     "81": [0.125, 0.69444, 0.07555, 0, 0.73611],
   2982     "82": [0, 0.69444, 0.08293, 0, 0.64584],
   2983     "83": [0, 0.69444, 0.09205, 0, 0.55556],
   2984     "84": [0, 0.69444, 0.13372, 0, 0.68056],
   2985     "85": [0, 0.69444, 0.08094, 0, 0.6875],
   2986     "86": [0, 0.69444, 0.1615, 0, 0.66667],
   2987     "87": [0, 0.69444, 0.1615, 0, 0.94445],
   2988     "88": [0, 0.69444, 0.13372, 0, 0.66667],
   2989     "89": [0, 0.69444, 0.17261, 0, 0.66667],
   2990     "90": [0, 0.69444, 0.11983, 0, 0.61111],
   2991     "91": [0.25, 0.75, 0.15942, 0, 0.28889],
   2992     "93": [0.25, 0.75, 0.08719, 0, 0.28889],
   2993     "94": [0, 0.69444, 0.0799, 0, 0.5],
   2994     "95": [0.35, 0.09444, 0.08616, 0, 0.5],
   2995     "97": [0, 0.44444, 0.00981, 0, 0.48056],
   2996     "98": [0, 0.69444, 0.03057, 0, 0.51667],
   2997     "99": [0, 0.44444, 0.08336, 0, 0.44445],
   2998     "100": [0, 0.69444, 0.09483, 0, 0.51667],
   2999     "101": [0, 0.44444, 0.06778, 0, 0.44445],
   3000     "102": [0, 0.69444, 0.21705, 0, 0.30556],
   3001     "103": [0.19444, 0.44444, 0.10836, 0, 0.5],
   3002     "104": [0, 0.69444, 0.01778, 0, 0.51667],
   3003     "105": [0, 0.67937, 0.09718, 0, 0.23889],
   3004     "106": [0.19444, 0.67937, 0.09162, 0, 0.26667],
   3005     "107": [0, 0.69444, 0.08336, 0, 0.48889],
   3006     "108": [0, 0.69444, 0.09483, 0, 0.23889],
   3007     "109": [0, 0.44444, 0.01778, 0, 0.79445],
   3008     "110": [0, 0.44444, 0.01778, 0, 0.51667],
   3009     "111": [0, 0.44444, 0.06613, 0, 0.5],
   3010     "112": [0.19444, 0.44444, 0.0389, 0, 0.51667],
   3011     "113": [0.19444, 0.44444, 0.04169, 0, 0.51667],
   3012     "114": [0, 0.44444, 0.10836, 0, 0.34167],
   3013     "115": [0, 0.44444, 0.0778, 0, 0.38333],
   3014     "116": [0, 0.57143, 0.07225, 0, 0.36111],
   3015     "117": [0, 0.44444, 0.04169, 0, 0.51667],
   3016     "118": [0, 0.44444, 0.10836, 0, 0.46111],
   3017     "119": [0, 0.44444, 0.10836, 0, 0.68334],
   3018     "120": [0, 0.44444, 0.09169, 0, 0.46111],
   3019     "121": [0.19444, 0.44444, 0.10836, 0, 0.46111],
   3020     "122": [0, 0.44444, 0.08752, 0, 0.43472],
   3021     "126": [0.35, 0.32659, 0.08826, 0, 0.5],
   3022     "160": [0, 0, 0, 0, 0.25],
   3023     "168": [0, 0.67937, 0.06385, 0, 0.5],
   3024     "176": [0, 0.69444, 0, 0, 0.73752],
   3025     "184": [0.17014, 0, 0, 0, 0.44445],
   3026     "305": [0, 0.44444, 0.04169, 0, 0.23889],
   3027     "567": [0.19444, 0.44444, 0.04169, 0, 0.26667],
   3028     "710": [0, 0.69444, 0.0799, 0, 0.5],
   3029     "711": [0, 0.63194, 0.08432, 0, 0.5],
   3030     "713": [0, 0.60889, 0.08776, 0, 0.5],
   3031     "714": [0, 0.69444, 0.09205, 0, 0.5],
   3032     "715": [0, 0.69444, 0, 0, 0.5],
   3033     "728": [0, 0.69444, 0.09483, 0, 0.5],
   3034     "729": [0, 0.67937, 0.07774, 0, 0.27778],
   3035     "730": [0, 0.69444, 0, 0, 0.73752],
   3036     "732": [0, 0.67659, 0.08826, 0, 0.5],
   3037     "733": [0, 0.69444, 0.09205, 0, 0.5],
   3038     "915": [0, 0.69444, 0.13372, 0, 0.54167],
   3039     "916": [0, 0.69444, 0, 0, 0.83334],
   3040     "920": [0, 0.69444, 0.07555, 0, 0.77778],
   3041     "923": [0, 0.69444, 0, 0, 0.61111],
   3042     "926": [0, 0.69444, 0.12816, 0, 0.66667],
   3043     "928": [0, 0.69444, 0.08094, 0, 0.70834],
   3044     "931": [0, 0.69444, 0.11983, 0, 0.72222],
   3045     "933": [0, 0.69444, 0.09031, 0, 0.77778],
   3046     "934": [0, 0.69444, 0.04603, 0, 0.72222],
   3047     "936": [0, 0.69444, 0.09031, 0, 0.77778],
   3048     "937": [0, 0.69444, 0.08293, 0, 0.72222],
   3049     "8211": [0, 0.44444, 0.08616, 0, 0.5],
   3050     "8212": [0, 0.44444, 0.08616, 0, 1.0],
   3051     "8216": [0, 0.69444, 0.07816, 0, 0.27778],
   3052     "8217": [0, 0.69444, 0.07816, 0, 0.27778],
   3053     "8220": [0, 0.69444, 0.14205, 0, 0.5],
   3054     "8221": [0, 0.69444, 0.00316, 0, 0.5]
   3055   },
   3056   "SansSerif-Regular": {
   3057     "32": [0, 0, 0, 0, 0.25],
   3058     "33": [0, 0.69444, 0, 0, 0.31945],
   3059     "34": [0, 0.69444, 0, 0, 0.5],
   3060     "35": [0.19444, 0.69444, 0, 0, 0.83334],
   3061     "36": [0.05556, 0.75, 0, 0, 0.5],
   3062     "37": [0.05556, 0.75, 0, 0, 0.83334],
   3063     "38": [0, 0.69444, 0, 0, 0.75834],
   3064     "39": [0, 0.69444, 0, 0, 0.27778],
   3065     "40": [0.25, 0.75, 0, 0, 0.38889],
   3066     "41": [0.25, 0.75, 0, 0, 0.38889],
   3067     "42": [0, 0.75, 0, 0, 0.5],
   3068     "43": [0.08333, 0.58333, 0, 0, 0.77778],
   3069     "44": [0.125, 0.08333, 0, 0, 0.27778],
   3070     "45": [0, 0.44444, 0, 0, 0.33333],
   3071     "46": [0, 0.08333, 0, 0, 0.27778],
   3072     "47": [0.25, 0.75, 0, 0, 0.5],
   3073     "48": [0, 0.65556, 0, 0, 0.5],
   3074     "49": [0, 0.65556, 0, 0, 0.5],
   3075     "50": [0, 0.65556, 0, 0, 0.5],
   3076     "51": [0, 0.65556, 0, 0, 0.5],
   3077     "52": [0, 0.65556, 0, 0, 0.5],
   3078     "53": [0, 0.65556, 0, 0, 0.5],
   3079     "54": [0, 0.65556, 0, 0, 0.5],
   3080     "55": [0, 0.65556, 0, 0, 0.5],
   3081     "56": [0, 0.65556, 0, 0, 0.5],
   3082     "57": [0, 0.65556, 0, 0, 0.5],
   3083     "58": [0, 0.44444, 0, 0, 0.27778],
   3084     "59": [0.125, 0.44444, 0, 0, 0.27778],
   3085     "61": [-0.13, 0.37, 0, 0, 0.77778],
   3086     "63": [0, 0.69444, 0, 0, 0.47222],
   3087     "64": [0, 0.69444, 0, 0, 0.66667],
   3088     "65": [0, 0.69444, 0, 0, 0.66667],
   3089     "66": [0, 0.69444, 0, 0, 0.66667],
   3090     "67": [0, 0.69444, 0, 0, 0.63889],
   3091     "68": [0, 0.69444, 0, 0, 0.72223],
   3092     "69": [0, 0.69444, 0, 0, 0.59722],
   3093     "70": [0, 0.69444, 0, 0, 0.56945],
   3094     "71": [0, 0.69444, 0, 0, 0.66667],
   3095     "72": [0, 0.69444, 0, 0, 0.70834],
   3096     "73": [0, 0.69444, 0, 0, 0.27778],
   3097     "74": [0, 0.69444, 0, 0, 0.47222],
   3098     "75": [0, 0.69444, 0, 0, 0.69445],
   3099     "76": [0, 0.69444, 0, 0, 0.54167],
   3100     "77": [0, 0.69444, 0, 0, 0.875],
   3101     "78": [0, 0.69444, 0, 0, 0.70834],
   3102     "79": [0, 0.69444, 0, 0, 0.73611],
   3103     "80": [0, 0.69444, 0, 0, 0.63889],
   3104     "81": [0.125, 0.69444, 0, 0, 0.73611],
   3105     "82": [0, 0.69444, 0, 0, 0.64584],
   3106     "83": [0, 0.69444, 0, 0, 0.55556],
   3107     "84": [0, 0.69444, 0, 0, 0.68056],
   3108     "85": [0, 0.69444, 0, 0, 0.6875],
   3109     "86": [0, 0.69444, 0.01389, 0, 0.66667],
   3110     "87": [0, 0.69444, 0.01389, 0, 0.94445],
   3111     "88": [0, 0.69444, 0, 0, 0.66667],
   3112     "89": [0, 0.69444, 0.025, 0, 0.66667],
   3113     "90": [0, 0.69444, 0, 0, 0.61111],
   3114     "91": [0.25, 0.75, 0, 0, 0.28889],
   3115     "93": [0.25, 0.75, 0, 0, 0.28889],
   3116     "94": [0, 0.69444, 0, 0, 0.5],
   3117     "95": [0.35, 0.09444, 0.02778, 0, 0.5],
   3118     "97": [0, 0.44444, 0, 0, 0.48056],
   3119     "98": [0, 0.69444, 0, 0, 0.51667],
   3120     "99": [0, 0.44444, 0, 0, 0.44445],
   3121     "100": [0, 0.69444, 0, 0, 0.51667],
   3122     "101": [0, 0.44444, 0, 0, 0.44445],
   3123     "102": [0, 0.69444, 0.06944, 0, 0.30556],
   3124     "103": [0.19444, 0.44444, 0.01389, 0, 0.5],
   3125     "104": [0, 0.69444, 0, 0, 0.51667],
   3126     "105": [0, 0.67937, 0, 0, 0.23889],
   3127     "106": [0.19444, 0.67937, 0, 0, 0.26667],
   3128     "107": [0, 0.69444, 0, 0, 0.48889],
   3129     "108": [0, 0.69444, 0, 0, 0.23889],
   3130     "109": [0, 0.44444, 0, 0, 0.79445],
   3131     "110": [0, 0.44444, 0, 0, 0.51667],
   3132     "111": [0, 0.44444, 0, 0, 0.5],
   3133     "112": [0.19444, 0.44444, 0, 0, 0.51667],
   3134     "113": [0.19444, 0.44444, 0, 0, 0.51667],
   3135     "114": [0, 0.44444, 0.01389, 0, 0.34167],
   3136     "115": [0, 0.44444, 0, 0, 0.38333],
   3137     "116": [0, 0.57143, 0, 0, 0.36111],
   3138     "117": [0, 0.44444, 0, 0, 0.51667],
   3139     "118": [0, 0.44444, 0.01389, 0, 0.46111],
   3140     "119": [0, 0.44444, 0.01389, 0, 0.68334],
   3141     "120": [0, 0.44444, 0, 0, 0.46111],
   3142     "121": [0.19444, 0.44444, 0.01389, 0, 0.46111],
   3143     "122": [0, 0.44444, 0, 0, 0.43472],
   3144     "126": [0.35, 0.32659, 0, 0, 0.5],
   3145     "160": [0, 0, 0, 0, 0.25],
   3146     "168": [0, 0.67937, 0, 0, 0.5],
   3147     "176": [0, 0.69444, 0, 0, 0.66667],
   3148     "184": [0.17014, 0, 0, 0, 0.44445],
   3149     "305": [0, 0.44444, 0, 0, 0.23889],
   3150     "567": [0.19444, 0.44444, 0, 0, 0.26667],
   3151     "710": [0, 0.69444, 0, 0, 0.5],
   3152     "711": [0, 0.63194, 0, 0, 0.5],
   3153     "713": [0, 0.60889, 0, 0, 0.5],
   3154     "714": [0, 0.69444, 0, 0, 0.5],
   3155     "715": [0, 0.69444, 0, 0, 0.5],
   3156     "728": [0, 0.69444, 0, 0, 0.5],
   3157     "729": [0, 0.67937, 0, 0, 0.27778],
   3158     "730": [0, 0.69444, 0, 0, 0.66667],
   3159     "732": [0, 0.67659, 0, 0, 0.5],
   3160     "733": [0, 0.69444, 0, 0, 0.5],
   3161     "915": [0, 0.69444, 0, 0, 0.54167],
   3162     "916": [0, 0.69444, 0, 0, 0.83334],
   3163     "920": [0, 0.69444, 0, 0, 0.77778],
   3164     "923": [0, 0.69444, 0, 0, 0.61111],
   3165     "926": [0, 0.69444, 0, 0, 0.66667],
   3166     "928": [0, 0.69444, 0, 0, 0.70834],
   3167     "931": [0, 0.69444, 0, 0, 0.72222],
   3168     "933": [0, 0.69444, 0, 0, 0.77778],
   3169     "934": [0, 0.69444, 0, 0, 0.72222],
   3170     "936": [0, 0.69444, 0, 0, 0.77778],
   3171     "937": [0, 0.69444, 0, 0, 0.72222],
   3172     "8211": [0, 0.44444, 0.02778, 0, 0.5],
   3173     "8212": [0, 0.44444, 0.02778, 0, 1.0],
   3174     "8216": [0, 0.69444, 0, 0, 0.27778],
   3175     "8217": [0, 0.69444, 0, 0, 0.27778],
   3176     "8220": [0, 0.69444, 0, 0, 0.5],
   3177     "8221": [0, 0.69444, 0, 0, 0.5]
   3178   },
   3179   "Script-Regular": {
   3180     "32": [0, 0, 0, 0, 0.25],
   3181     "65": [0, 0.7, 0.22925, 0, 0.80253],
   3182     "66": [0, 0.7, 0.04087, 0, 0.90757],
   3183     "67": [0, 0.7, 0.1689, 0, 0.66619],
   3184     "68": [0, 0.7, 0.09371, 0, 0.77443],
   3185     "69": [0, 0.7, 0.18583, 0, 0.56162],
   3186     "70": [0, 0.7, 0.13634, 0, 0.89544],
   3187     "71": [0, 0.7, 0.17322, 0, 0.60961],
   3188     "72": [0, 0.7, 0.29694, 0, 0.96919],
   3189     "73": [0, 0.7, 0.19189, 0, 0.80907],
   3190     "74": [0.27778, 0.7, 0.19189, 0, 1.05159],
   3191     "75": [0, 0.7, 0.31259, 0, 0.91364],
   3192     "76": [0, 0.7, 0.19189, 0, 0.87373],
   3193     "77": [0, 0.7, 0.15981, 0, 1.08031],
   3194     "78": [0, 0.7, 0.3525, 0, 0.9015],
   3195     "79": [0, 0.7, 0.08078, 0, 0.73787],
   3196     "80": [0, 0.7, 0.08078, 0, 1.01262],
   3197     "81": [0, 0.7, 0.03305, 0, 0.88282],
   3198     "82": [0, 0.7, 0.06259, 0, 0.85],
   3199     "83": [0, 0.7, 0.19189, 0, 0.86767],
   3200     "84": [0, 0.7, 0.29087, 0, 0.74697],
   3201     "85": [0, 0.7, 0.25815, 0, 0.79996],
   3202     "86": [0, 0.7, 0.27523, 0, 0.62204],
   3203     "87": [0, 0.7, 0.27523, 0, 0.80532],
   3204     "88": [0, 0.7, 0.26006, 0, 0.94445],
   3205     "89": [0, 0.7, 0.2939, 0, 0.70961],
   3206     "90": [0, 0.7, 0.24037, 0, 0.8212],
   3207     "160": [0, 0, 0, 0, 0.25]
   3208   },
   3209   "Size1-Regular": {
   3210     "32": [0, 0, 0, 0, 0.25],
   3211     "40": [0.35001, 0.85, 0, 0, 0.45834],
   3212     "41": [0.35001, 0.85, 0, 0, 0.45834],
   3213     "47": [0.35001, 0.85, 0, 0, 0.57778],
   3214     "91": [0.35001, 0.85, 0, 0, 0.41667],
   3215     "92": [0.35001, 0.85, 0, 0, 0.57778],
   3216     "93": [0.35001, 0.85, 0, 0, 0.41667],
   3217     "123": [0.35001, 0.85, 0, 0, 0.58334],
   3218     "125": [0.35001, 0.85, 0, 0, 0.58334],
   3219     "160": [0, 0, 0, 0, 0.25],
   3220     "710": [0, 0.72222, 0, 0, 0.55556],
   3221     "732": [0, 0.72222, 0, 0, 0.55556],
   3222     "770": [0, 0.72222, 0, 0, 0.55556],
   3223     "771": [0, 0.72222, 0, 0, 0.55556],
   3224     "8214": [-0.00099, 0.601, 0, 0, 0.77778],
   3225     "8593": [1e-05, 0.6, 0, 0, 0.66667],
   3226     "8595": [1e-05, 0.6, 0, 0, 0.66667],
   3227     "8657": [1e-05, 0.6, 0, 0, 0.77778],
   3228     "8659": [1e-05, 0.6, 0, 0, 0.77778],
   3229     "8719": [0.25001, 0.75, 0, 0, 0.94445],
   3230     "8720": [0.25001, 0.75, 0, 0, 0.94445],
   3231     "8721": [0.25001, 0.75, 0, 0, 1.05556],
   3232     "8730": [0.35001, 0.85, 0, 0, 1.0],
   3233     "8739": [-0.00599, 0.606, 0, 0, 0.33333],
   3234     "8741": [-0.00599, 0.606, 0, 0, 0.55556],
   3235     "8747": [0.30612, 0.805, 0.19445, 0, 0.47222],
   3236     "8748": [0.306, 0.805, 0.19445, 0, 0.47222],
   3237     "8749": [0.306, 0.805, 0.19445, 0, 0.47222],
   3238     "8750": [0.30612, 0.805, 0.19445, 0, 0.47222],
   3239     "8896": [0.25001, 0.75, 0, 0, 0.83334],
   3240     "8897": [0.25001, 0.75, 0, 0, 0.83334],
   3241     "8898": [0.25001, 0.75, 0, 0, 0.83334],
   3242     "8899": [0.25001, 0.75, 0, 0, 0.83334],
   3243     "8968": [0.35001, 0.85, 0, 0, 0.47222],
   3244     "8969": [0.35001, 0.85, 0, 0, 0.47222],
   3245     "8970": [0.35001, 0.85, 0, 0, 0.47222],
   3246     "8971": [0.35001, 0.85, 0, 0, 0.47222],
   3247     "9168": [-0.00099, 0.601, 0, 0, 0.66667],
   3248     "10216": [0.35001, 0.85, 0, 0, 0.47222],
   3249     "10217": [0.35001, 0.85, 0, 0, 0.47222],
   3250     "10752": [0.25001, 0.75, 0, 0, 1.11111],
   3251     "10753": [0.25001, 0.75, 0, 0, 1.11111],
   3252     "10754": [0.25001, 0.75, 0, 0, 1.11111],
   3253     "10756": [0.25001, 0.75, 0, 0, 0.83334],
   3254     "10758": [0.25001, 0.75, 0, 0, 0.83334]
   3255   },
   3256   "Size2-Regular": {
   3257     "32": [0, 0, 0, 0, 0.25],
   3258     "40": [0.65002, 1.15, 0, 0, 0.59722],
   3259     "41": [0.65002, 1.15, 0, 0, 0.59722],
   3260     "47": [0.65002, 1.15, 0, 0, 0.81111],
   3261     "91": [0.65002, 1.15, 0, 0, 0.47222],
   3262     "92": [0.65002, 1.15, 0, 0, 0.81111],
   3263     "93": [0.65002, 1.15, 0, 0, 0.47222],
   3264     "123": [0.65002, 1.15, 0, 0, 0.66667],
   3265     "125": [0.65002, 1.15, 0, 0, 0.66667],
   3266     "160": [0, 0, 0, 0, 0.25],
   3267     "710": [0, 0.75, 0, 0, 1.0],
   3268     "732": [0, 0.75, 0, 0, 1.0],
   3269     "770": [0, 0.75, 0, 0, 1.0],
   3270     "771": [0, 0.75, 0, 0, 1.0],
   3271     "8719": [0.55001, 1.05, 0, 0, 1.27778],
   3272     "8720": [0.55001, 1.05, 0, 0, 1.27778],
   3273     "8721": [0.55001, 1.05, 0, 0, 1.44445],
   3274     "8730": [0.65002, 1.15, 0, 0, 1.0],
   3275     "8747": [0.86225, 1.36, 0.44445, 0, 0.55556],
   3276     "8748": [0.862, 1.36, 0.44445, 0, 0.55556],
   3277     "8749": [0.862, 1.36, 0.44445, 0, 0.55556],
   3278     "8750": [0.86225, 1.36, 0.44445, 0, 0.55556],
   3279     "8896": [0.55001, 1.05, 0, 0, 1.11111],
   3280     "8897": [0.55001, 1.05, 0, 0, 1.11111],
   3281     "8898": [0.55001, 1.05, 0, 0, 1.11111],
   3282     "8899": [0.55001, 1.05, 0, 0, 1.11111],
   3283     "8968": [0.65002, 1.15, 0, 0, 0.52778],
   3284     "8969": [0.65002, 1.15, 0, 0, 0.52778],
   3285     "8970": [0.65002, 1.15, 0, 0, 0.52778],
   3286     "8971": [0.65002, 1.15, 0, 0, 0.52778],
   3287     "10216": [0.65002, 1.15, 0, 0, 0.61111],
   3288     "10217": [0.65002, 1.15, 0, 0, 0.61111],
   3289     "10752": [0.55001, 1.05, 0, 0, 1.51112],
   3290     "10753": [0.55001, 1.05, 0, 0, 1.51112],
   3291     "10754": [0.55001, 1.05, 0, 0, 1.51112],
   3292     "10756": [0.55001, 1.05, 0, 0, 1.11111],
   3293     "10758": [0.55001, 1.05, 0, 0, 1.11111]
   3294   },
   3295   "Size3-Regular": {
   3296     "32": [0, 0, 0, 0, 0.25],
   3297     "40": [0.95003, 1.45, 0, 0, 0.73611],
   3298     "41": [0.95003, 1.45, 0, 0, 0.73611],
   3299     "47": [0.95003, 1.45, 0, 0, 1.04445],
   3300     "91": [0.95003, 1.45, 0, 0, 0.52778],
   3301     "92": [0.95003, 1.45, 0, 0, 1.04445],
   3302     "93": [0.95003, 1.45, 0, 0, 0.52778],
   3303     "123": [0.95003, 1.45, 0, 0, 0.75],
   3304     "125": [0.95003, 1.45, 0, 0, 0.75],
   3305     "160": [0, 0, 0, 0, 0.25],
   3306     "710": [0, 0.75, 0, 0, 1.44445],
   3307     "732": [0, 0.75, 0, 0, 1.44445],
   3308     "770": [0, 0.75, 0, 0, 1.44445],
   3309     "771": [0, 0.75, 0, 0, 1.44445],
   3310     "8730": [0.95003, 1.45, 0, 0, 1.0],
   3311     "8968": [0.95003, 1.45, 0, 0, 0.58334],
   3312     "8969": [0.95003, 1.45, 0, 0, 0.58334],
   3313     "8970": [0.95003, 1.45, 0, 0, 0.58334],
   3314     "8971": [0.95003, 1.45, 0, 0, 0.58334],
   3315     "10216": [0.95003, 1.45, 0, 0, 0.75],
   3316     "10217": [0.95003, 1.45, 0, 0, 0.75]
   3317   },
   3318   "Size4-Regular": {
   3319     "32": [0, 0, 0, 0, 0.25],
   3320     "40": [1.25003, 1.75, 0, 0, 0.79167],
   3321     "41": [1.25003, 1.75, 0, 0, 0.79167],
   3322     "47": [1.25003, 1.75, 0, 0, 1.27778],
   3323     "91": [1.25003, 1.75, 0, 0, 0.58334],
   3324     "92": [1.25003, 1.75, 0, 0, 1.27778],
   3325     "93": [1.25003, 1.75, 0, 0, 0.58334],
   3326     "123": [1.25003, 1.75, 0, 0, 0.80556],
   3327     "125": [1.25003, 1.75, 0, 0, 0.80556],
   3328     "160": [0, 0, 0, 0, 0.25],
   3329     "710": [0, 0.825, 0, 0, 1.8889],
   3330     "732": [0, 0.825, 0, 0, 1.8889],
   3331     "770": [0, 0.825, 0, 0, 1.8889],
   3332     "771": [0, 0.825, 0, 0, 1.8889],
   3333     "8730": [1.25003, 1.75, 0, 0, 1.0],
   3334     "8968": [1.25003, 1.75, 0, 0, 0.63889],
   3335     "8969": [1.25003, 1.75, 0, 0, 0.63889],
   3336     "8970": [1.25003, 1.75, 0, 0, 0.63889],
   3337     "8971": [1.25003, 1.75, 0, 0, 0.63889],
   3338     "9115": [0.64502, 1.155, 0, 0, 0.875],
   3339     "9116": [1e-05, 0.6, 0, 0, 0.875],
   3340     "9117": [0.64502, 1.155, 0, 0, 0.875],
   3341     "9118": [0.64502, 1.155, 0, 0, 0.875],
   3342     "9119": [1e-05, 0.6, 0, 0, 0.875],
   3343     "9120": [0.64502, 1.155, 0, 0, 0.875],
   3344     "9121": [0.64502, 1.155, 0, 0, 0.66667],
   3345     "9122": [-0.00099, 0.601, 0, 0, 0.66667],
   3346     "9123": [0.64502, 1.155, 0, 0, 0.66667],
   3347     "9124": [0.64502, 1.155, 0, 0, 0.66667],
   3348     "9125": [-0.00099, 0.601, 0, 0, 0.66667],
   3349     "9126": [0.64502, 1.155, 0, 0, 0.66667],
   3350     "9127": [1e-05, 0.9, 0, 0, 0.88889],
   3351     "9128": [0.65002, 1.15, 0, 0, 0.88889],
   3352     "9129": [0.90001, 0, 0, 0, 0.88889],
   3353     "9130": [0, 0.3, 0, 0, 0.88889],
   3354     "9131": [1e-05, 0.9, 0, 0, 0.88889],
   3355     "9132": [0.65002, 1.15, 0, 0, 0.88889],
   3356     "9133": [0.90001, 0, 0, 0, 0.88889],
   3357     "9143": [0.88502, 0.915, 0, 0, 1.05556],
   3358     "10216": [1.25003, 1.75, 0, 0, 0.80556],
   3359     "10217": [1.25003, 1.75, 0, 0, 0.80556],
   3360     "57344": [-0.00499, 0.605, 0, 0, 1.05556],
   3361     "57345": [-0.00499, 0.605, 0, 0, 1.05556],
   3362     "57680": [0, 0.12, 0, 0, 0.45],
   3363     "57681": [0, 0.12, 0, 0, 0.45],
   3364     "57682": [0, 0.12, 0, 0, 0.45],
   3365     "57683": [0, 0.12, 0, 0, 0.45]
   3366   },
   3367   "Typewriter-Regular": {
   3368     "32": [0, 0, 0, 0, 0.525],
   3369     "33": [0, 0.61111, 0, 0, 0.525],
   3370     "34": [0, 0.61111, 0, 0, 0.525],
   3371     "35": [0, 0.61111, 0, 0, 0.525],
   3372     "36": [0.08333, 0.69444, 0, 0, 0.525],
   3373     "37": [0.08333, 0.69444, 0, 0, 0.525],
   3374     "38": [0, 0.61111, 0, 0, 0.525],
   3375     "39": [0, 0.61111, 0, 0, 0.525],
   3376     "40": [0.08333, 0.69444, 0, 0, 0.525],
   3377     "41": [0.08333, 0.69444, 0, 0, 0.525],
   3378     "42": [0, 0.52083, 0, 0, 0.525],
   3379     "43": [-0.08056, 0.53055, 0, 0, 0.525],
   3380     "44": [0.13889, 0.125, 0, 0, 0.525],
   3381     "45": [-0.08056, 0.53055, 0, 0, 0.525],
   3382     "46": [0, 0.125, 0, 0, 0.525],
   3383     "47": [0.08333, 0.69444, 0, 0, 0.525],
   3384     "48": [0, 0.61111, 0, 0, 0.525],
   3385     "49": [0, 0.61111, 0, 0, 0.525],
   3386     "50": [0, 0.61111, 0, 0, 0.525],
   3387     "51": [0, 0.61111, 0, 0, 0.525],
   3388     "52": [0, 0.61111, 0, 0, 0.525],
   3389     "53": [0, 0.61111, 0, 0, 0.525],
   3390     "54": [0, 0.61111, 0, 0, 0.525],
   3391     "55": [0, 0.61111, 0, 0, 0.525],
   3392     "56": [0, 0.61111, 0, 0, 0.525],
   3393     "57": [0, 0.61111, 0, 0, 0.525],
   3394     "58": [0, 0.43056, 0, 0, 0.525],
   3395     "59": [0.13889, 0.43056, 0, 0, 0.525],
   3396     "60": [-0.05556, 0.55556, 0, 0, 0.525],
   3397     "61": [-0.19549, 0.41562, 0, 0, 0.525],
   3398     "62": [-0.05556, 0.55556, 0, 0, 0.525],
   3399     "63": [0, 0.61111, 0, 0, 0.525],
   3400     "64": [0, 0.61111, 0, 0, 0.525],
   3401     "65": [0, 0.61111, 0, 0, 0.525],
   3402     "66": [0, 0.61111, 0, 0, 0.525],
   3403     "67": [0, 0.61111, 0, 0, 0.525],
   3404     "68": [0, 0.61111, 0, 0, 0.525],
   3405     "69": [0, 0.61111, 0, 0, 0.525],
   3406     "70": [0, 0.61111, 0, 0, 0.525],
   3407     "71": [0, 0.61111, 0, 0, 0.525],
   3408     "72": [0, 0.61111, 0, 0, 0.525],
   3409     "73": [0, 0.61111, 0, 0, 0.525],
   3410     "74": [0, 0.61111, 0, 0, 0.525],
   3411     "75": [0, 0.61111, 0, 0, 0.525],
   3412     "76": [0, 0.61111, 0, 0, 0.525],
   3413     "77": [0, 0.61111, 0, 0, 0.525],
   3414     "78": [0, 0.61111, 0, 0, 0.525],
   3415     "79": [0, 0.61111, 0, 0, 0.525],
   3416     "80": [0, 0.61111, 0, 0, 0.525],
   3417     "81": [0.13889, 0.61111, 0, 0, 0.525],
   3418     "82": [0, 0.61111, 0, 0, 0.525],
   3419     "83": [0, 0.61111, 0, 0, 0.525],
   3420     "84": [0, 0.61111, 0, 0, 0.525],
   3421     "85": [0, 0.61111, 0, 0, 0.525],
   3422     "86": [0, 0.61111, 0, 0, 0.525],
   3423     "87": [0, 0.61111, 0, 0, 0.525],
   3424     "88": [0, 0.61111, 0, 0, 0.525],
   3425     "89": [0, 0.61111, 0, 0, 0.525],
   3426     "90": [0, 0.61111, 0, 0, 0.525],
   3427     "91": [0.08333, 0.69444, 0, 0, 0.525],
   3428     "92": [0.08333, 0.69444, 0, 0, 0.525],
   3429     "93": [0.08333, 0.69444, 0, 0, 0.525],
   3430     "94": [0, 0.61111, 0, 0, 0.525],
   3431     "95": [0.09514, 0, 0, 0, 0.525],
   3432     "96": [0, 0.61111, 0, 0, 0.525],
   3433     "97": [0, 0.43056, 0, 0, 0.525],
   3434     "98": [0, 0.61111, 0, 0, 0.525],
   3435     "99": [0, 0.43056, 0, 0, 0.525],
   3436     "100": [0, 0.61111, 0, 0, 0.525],
   3437     "101": [0, 0.43056, 0, 0, 0.525],
   3438     "102": [0, 0.61111, 0, 0, 0.525],
   3439     "103": [0.22222, 0.43056, 0, 0, 0.525],
   3440     "104": [0, 0.61111, 0, 0, 0.525],
   3441     "105": [0, 0.61111, 0, 0, 0.525],
   3442     "106": [0.22222, 0.61111, 0, 0, 0.525],
   3443     "107": [0, 0.61111, 0, 0, 0.525],
   3444     "108": [0, 0.61111, 0, 0, 0.525],
   3445     "109": [0, 0.43056, 0, 0, 0.525],
   3446     "110": [0, 0.43056, 0, 0, 0.525],
   3447     "111": [0, 0.43056, 0, 0, 0.525],
   3448     "112": [0.22222, 0.43056, 0, 0, 0.525],
   3449     "113": [0.22222, 0.43056, 0, 0, 0.525],
   3450     "114": [0, 0.43056, 0, 0, 0.525],
   3451     "115": [0, 0.43056, 0, 0, 0.525],
   3452     "116": [0, 0.55358, 0, 0, 0.525],
   3453     "117": [0, 0.43056, 0, 0, 0.525],
   3454     "118": [0, 0.43056, 0, 0, 0.525],
   3455     "119": [0, 0.43056, 0, 0, 0.525],
   3456     "120": [0, 0.43056, 0, 0, 0.525],
   3457     "121": [0.22222, 0.43056, 0, 0, 0.525],
   3458     "122": [0, 0.43056, 0, 0, 0.525],
   3459     "123": [0.08333, 0.69444, 0, 0, 0.525],
   3460     "124": [0.08333, 0.69444, 0, 0, 0.525],
   3461     "125": [0.08333, 0.69444, 0, 0, 0.525],
   3462     "126": [0, 0.61111, 0, 0, 0.525],
   3463     "127": [0, 0.61111, 0, 0, 0.525],
   3464     "160": [0, 0, 0, 0, 0.525],
   3465     "176": [0, 0.61111, 0, 0, 0.525],
   3466     "184": [0.19445, 0, 0, 0, 0.525],
   3467     "305": [0, 0.43056, 0, 0, 0.525],
   3468     "567": [0.22222, 0.43056, 0, 0, 0.525],
   3469     "711": [0, 0.56597, 0, 0, 0.525],
   3470     "713": [0, 0.56555, 0, 0, 0.525],
   3471     "714": [0, 0.61111, 0, 0, 0.525],
   3472     "715": [0, 0.61111, 0, 0, 0.525],
   3473     "728": [0, 0.61111, 0, 0, 0.525],
   3474     "730": [0, 0.61111, 0, 0, 0.525],
   3475     "770": [0, 0.61111, 0, 0, 0.525],
   3476     "771": [0, 0.61111, 0, 0, 0.525],
   3477     "776": [0, 0.61111, 0, 0, 0.525],
   3478     "915": [0, 0.61111, 0, 0, 0.525],
   3479     "916": [0, 0.61111, 0, 0, 0.525],
   3480     "920": [0, 0.61111, 0, 0, 0.525],
   3481     "923": [0, 0.61111, 0, 0, 0.525],
   3482     "926": [0, 0.61111, 0, 0, 0.525],
   3483     "928": [0, 0.61111, 0, 0, 0.525],
   3484     "931": [0, 0.61111, 0, 0, 0.525],
   3485     "933": [0, 0.61111, 0, 0, 0.525],
   3486     "934": [0, 0.61111, 0, 0, 0.525],
   3487     "936": [0, 0.61111, 0, 0, 0.525],
   3488     "937": [0, 0.61111, 0, 0, 0.525],
   3489     "8216": [0, 0.61111, 0, 0, 0.525],
   3490     "8217": [0, 0.61111, 0, 0, 0.525],
   3491     "8242": [0, 0.61111, 0, 0, 0.525],
   3492     "9251": [0.11111, 0.21944, 0, 0, 0.525]
   3493   }
   3494 };
   3495 
   3496 /**
   3497  * This file contains metrics regarding fonts and individual symbols. The sigma
   3498  * and xi variables, as well as the metricMap map contain data extracted from
   3499  * TeX, TeX font metrics, and the TTF files. These data are then exposed via the
   3500  * `metrics` variable and the getCharacterMetrics function.
   3501  */
   3502 // In TeX, there are actually three sets of dimensions, one for each of
   3503 // textstyle (size index 5 and higher: >=9pt), scriptstyle (size index 3 and 4:
   3504 // 7-8pt), and scriptscriptstyle (size index 1 and 2: 5-6pt).  These are
   3505 // provided in the the arrays below, in that order.
   3506 //
   3507 // The font metrics are stored in fonts cmsy10, cmsy7, and cmsy5 respsectively.
   3508 // This was determined by running the following script:
   3509 //
   3510 //     latex -interaction=nonstopmode \
   3511 //     '\documentclass{article}\usepackage{amsmath}\begin{document}' \
   3512 //     '$a$ \expandafter\show\the\textfont2' \
   3513 //     '\expandafter\show\the\scriptfont2' \
   3514 //     '\expandafter\show\the\scriptscriptfont2' \
   3515 //     '\stop'
   3516 //
   3517 // The metrics themselves were retreived using the following commands:
   3518 //
   3519 //     tftopl cmsy10
   3520 //     tftopl cmsy7
   3521 //     tftopl cmsy5
   3522 //
   3523 // The output of each of these commands is quite lengthy.  The only part we
   3524 // care about is the FONTDIMEN section. Each value is measured in EMs.
   3525 var sigmasAndXis = {
   3526   slant: [0.250, 0.250, 0.250],
   3527   // sigma1
   3528   space: [0.000, 0.000, 0.000],
   3529   // sigma2
   3530   stretch: [0.000, 0.000, 0.000],
   3531   // sigma3
   3532   shrink: [0.000, 0.000, 0.000],
   3533   // sigma4
   3534   xHeight: [0.431, 0.431, 0.431],
   3535   // sigma5
   3536   quad: [1.000, 1.171, 1.472],
   3537   // sigma6
   3538   extraSpace: [0.000, 0.000, 0.000],
   3539   // sigma7
   3540   num1: [0.677, 0.732, 0.925],
   3541   // sigma8
   3542   num2: [0.394, 0.384, 0.387],
   3543   // sigma9
   3544   num3: [0.444, 0.471, 0.504],
   3545   // sigma10
   3546   denom1: [0.686, 0.752, 1.025],
   3547   // sigma11
   3548   denom2: [0.345, 0.344, 0.532],
   3549   // sigma12
   3550   sup1: [0.413, 0.503, 0.504],
   3551   // sigma13
   3552   sup2: [0.363, 0.431, 0.404],
   3553   // sigma14
   3554   sup3: [0.289, 0.286, 0.294],
   3555   // sigma15
   3556   sub1: [0.150, 0.143, 0.200],
   3557   // sigma16
   3558   sub2: [0.247, 0.286, 0.400],
   3559   // sigma17
   3560   supDrop: [0.386, 0.353, 0.494],
   3561   // sigma18
   3562   subDrop: [0.050, 0.071, 0.100],
   3563   // sigma19
   3564   delim1: [2.390, 1.700, 1.980],
   3565   // sigma20
   3566   delim2: [1.010, 1.157, 1.420],
   3567   // sigma21
   3568   axisHeight: [0.250, 0.250, 0.250],
   3569   // sigma22
   3570   // These font metrics are extracted from TeX by using tftopl on cmex10.tfm;
   3571   // they correspond to the font parameters of the extension fonts (family 3).
   3572   // See the TeXbook, page 441. In AMSTeX, the extension fonts scale; to
   3573   // match cmex7, we'd use cmex7.tfm values for script and scriptscript
   3574   // values.
   3575   defaultRuleThickness: [0.04, 0.049, 0.049],
   3576   // xi8; cmex7: 0.049
   3577   bigOpSpacing1: [0.111, 0.111, 0.111],
   3578   // xi9
   3579   bigOpSpacing2: [0.166, 0.166, 0.166],
   3580   // xi10
   3581   bigOpSpacing3: [0.2, 0.2, 0.2],
   3582   // xi11
   3583   bigOpSpacing4: [0.6, 0.611, 0.611],
   3584   // xi12; cmex7: 0.611
   3585   bigOpSpacing5: [0.1, 0.143, 0.143],
   3586   // xi13; cmex7: 0.143
   3587   // The \sqrt rule width is taken from the height of the surd character.
   3588   // Since we use the same font at all sizes, this thickness doesn't scale.
   3589   sqrtRuleThickness: [0.04, 0.04, 0.04],
   3590   // This value determines how large a pt is, for metrics which are defined
   3591   // in terms of pts.
   3592   // This value is also used in katex.less; if you change it make sure the
   3593   // values match.
   3594   ptPerEm: [10.0, 10.0, 10.0],
   3595   // The space between adjacent `|` columns in an array definition. From
   3596   // `\showthe\doublerulesep` in LaTeX. Equals 2.0 / ptPerEm.
   3597   doubleRuleSep: [0.2, 0.2, 0.2],
   3598   // The width of separator lines in {array} environments. From
   3599   // `\showthe\arrayrulewidth` in LaTeX. Equals 0.4 / ptPerEm.
   3600   arrayRuleWidth: [0.04, 0.04, 0.04],
   3601   // Two values from LaTeX source2e:
   3602   fboxsep: [0.3, 0.3, 0.3],
   3603   //        3 pt / ptPerEm
   3604   fboxrule: [0.04, 0.04, 0.04] // 0.4 pt / ptPerEm
   3605 
   3606 }; // This map contains a mapping from font name and character code to character
   3607 // should have Latin-1 and Cyrillic characters, but may not depending on the
   3608 // operating system.  The metrics do not account for extra height from the
   3609 // accents.  In the case of Cyrillic characters which have both ascenders and
   3610 // descenders we prefer approximations with ascenders, primarily to prevent
   3611 // the fraction bar or root line from intersecting the glyph.
   3612 // TODO(kevinb) allow union of multiple glyph metrics for better accuracy.
   3613 
   3614 var extraCharacterMap = {
   3615   // Latin-1
   3616   'Å': 'A',
   3617   'Ç': 'C',
   3618   'Ð': 'D',
   3619   'Þ': 'o',
   3620   'å': 'a',
   3621   'ç': 'c',
   3622   'ð': 'd',
   3623   'þ': 'o',
   3624   // Cyrillic
   3625   'А': 'A',
   3626   'Б': 'B',
   3627   'В': 'B',
   3628   'Г': 'F',
   3629   'Д': 'A',
   3630   'Е': 'E',
   3631   'Ж': 'K',
   3632   'З': '3',
   3633   'И': 'N',
   3634   'Й': 'N',
   3635   'К': 'K',
   3636   'Л': 'N',
   3637   'М': 'M',
   3638   'Н': 'H',
   3639   'О': 'O',
   3640   'П': 'N',
   3641   'Р': 'P',
   3642   'С': 'C',
   3643   'Т': 'T',
   3644   'У': 'y',
   3645   'Ф': 'O',
   3646   'Х': 'X',
   3647   'Ц': 'U',
   3648   'Ч': 'h',
   3649   'Ш': 'W',
   3650   'Щ': 'W',
   3651   'Ъ': 'B',
   3652   'Ы': 'X',
   3653   'Ь': 'B',
   3654   'Э': '3',
   3655   'Ю': 'X',
   3656   'Я': 'R',
   3657   'а': 'a',
   3658   'б': 'b',
   3659   'в': 'a',
   3660   'г': 'r',
   3661   'д': 'y',
   3662   'е': 'e',
   3663   'ж': 'm',
   3664   'з': 'e',
   3665   'и': 'n',
   3666   'й': 'n',
   3667   'к': 'n',
   3668   'л': 'n',
   3669   'м': 'm',
   3670   'н': 'n',
   3671   'о': 'o',
   3672   'п': 'n',
   3673   'р': 'p',
   3674   'с': 'c',
   3675   'т': 'o',
   3676   'у': 'y',
   3677   'ф': 'b',
   3678   'х': 'x',
   3679   'ц': 'n',
   3680   'ч': 'n',
   3681   'ш': 'w',
   3682   'щ': 'w',
   3683   'ъ': 'a',
   3684   'ы': 'm',
   3685   'ь': 'a',
   3686   'э': 'e',
   3687   'ю': 'm',
   3688   'я': 'r'
   3689 };
   3690 
   3691 /**
   3692  * This function adds new font metrics to default metricMap
   3693  * It can also override existing metrics
   3694  */
   3695 function setFontMetrics(fontName, metrics) {
   3696   fontMetricsData[fontName] = metrics;
   3697 }
   3698 /**
   3699  * This function is a convenience function for looking up information in the
   3700  * metricMap table. It takes a character as a string, and a font.
   3701  *
   3702  * Note: the `width` property may be undefined if fontMetricsData.js wasn't
   3703  * built using `Make extended_metrics`.
   3704  */
   3705 
   3706 function getCharacterMetrics(character, font, mode) {
   3707   if (!fontMetricsData[font]) {
   3708     throw new Error("Font metrics not found for font: " + font + ".");
   3709   }
   3710 
   3711   var ch = character.charCodeAt(0);
   3712   var metrics = fontMetricsData[font][ch];
   3713 
   3714   if (!metrics && character[0] in extraCharacterMap) {
   3715     ch = extraCharacterMap[character[0]].charCodeAt(0);
   3716     metrics = fontMetricsData[font][ch];
   3717   }
   3718 
   3719   if (!metrics && mode === 'text') {
   3720     // We don't typically have font metrics for Asian scripts.
   3721     // But since we support them in text mode, we need to return
   3722     // some sort of metrics.
   3723     // So if the character is in a script we support but we
   3724     // don't have metrics for it, just use the metrics for
   3725     // the Latin capital letter M. This is close enough because
   3726     // we (currently) only care about the height of the glpyh
   3727     // not its width.
   3728     if (supportedCodepoint(ch)) {
   3729       metrics = fontMetricsData[font][77]; // 77 is the charcode for 'M'
   3730     }
   3731   }
   3732 
   3733   if (metrics) {
   3734     return {
   3735       depth: metrics[0],
   3736       height: metrics[1],
   3737       italic: metrics[2],
   3738       skew: metrics[3],
   3739       width: metrics[4]
   3740     };
   3741   }
   3742 }
   3743 var fontMetricsBySizeIndex = {};
   3744 /**
   3745  * Get the font metrics for a given size.
   3746  */
   3747 
   3748 function getGlobalMetrics(size) {
   3749   var sizeIndex;
   3750 
   3751   if (size >= 5) {
   3752     sizeIndex = 0;
   3753   } else if (size >= 3) {
   3754     sizeIndex = 1;
   3755   } else {
   3756     sizeIndex = 2;
   3757   }
   3758 
   3759   if (!fontMetricsBySizeIndex[sizeIndex]) {
   3760     var metrics = fontMetricsBySizeIndex[sizeIndex] = {
   3761       cssEmPerMu: sigmasAndXis.quad[sizeIndex] / 18
   3762     };
   3763 
   3764     for (var key in sigmasAndXis) {
   3765       if (sigmasAndXis.hasOwnProperty(key)) {
   3766         metrics[key] = sigmasAndXis[key][sizeIndex];
   3767       }
   3768     }
   3769   }
   3770 
   3771   return fontMetricsBySizeIndex[sizeIndex];
   3772 }
   3773 
   3774 /**
   3775  * This file holds a list of all no-argument functions and single-character
   3776  * symbols (like 'a' or ';').
   3777  *
   3778  * For each of the symbols, there are three properties they can have:
   3779  * - font (required): the font to be used for this symbol. Either "main" (the
   3780      normal font), or "ams" (the ams fonts).
   3781  * - group (required): the ParseNode group type the symbol should have (i.e.
   3782      "textord", "mathord", etc).
   3783      See https://github.com/KaTeX/KaTeX/wiki/Examining-TeX#group-types
   3784  * - replace: the character that this symbol or function should be
   3785  *   replaced with (i.e. "\phi" has a replace value of "\u03d5", the phi
   3786  *   character in the main font).
   3787  *
   3788  * The outermost map in the table indicates what mode the symbols should be
   3789  * accepted in (e.g. "math" or "text").
   3790  */
   3791 // Some of these have a "-token" suffix since these are also used as `ParseNode`
   3792 // types for raw text tokens, and we want to avoid conflicts with higher-level
   3793 // `ParseNode` types. These `ParseNode`s are constructed within `Parser` by
   3794 // looking up the `symbols` map.
   3795 var ATOMS = {
   3796   "bin": 1,
   3797   "close": 1,
   3798   "inner": 1,
   3799   "open": 1,
   3800   "punct": 1,
   3801   "rel": 1
   3802 };
   3803 var NON_ATOMS = {
   3804   "accent-token": 1,
   3805   "mathord": 1,
   3806   "op-token": 1,
   3807   "spacing": 1,
   3808   "textord": 1
   3809 };
   3810 var symbols = {
   3811   "math": {},
   3812   "text": {}
   3813 };
   3814 /** `acceptUnicodeChar = true` is only applicable if `replace` is set. */
   3815 
   3816 function defineSymbol(mode, font, group, replace, name, acceptUnicodeChar) {
   3817   symbols[mode][name] = {
   3818     font,
   3819     group,
   3820     replace
   3821   };
   3822 
   3823   if (acceptUnicodeChar && replace) {
   3824     symbols[mode][replace] = symbols[mode][name];
   3825   }
   3826 } // Some abbreviations for commonly used strings.
   3827 // This helps minify the code, and also spotting typos using jshint.
   3828 // modes:
   3829 
   3830 var math = "math";
   3831 var text$1 = "text"; // fonts:
   3832 
   3833 var main = "main";
   3834 var ams = "ams"; // groups:
   3835 
   3836 var accent = "accent-token";
   3837 var bin = "bin";
   3838 var close = "close";
   3839 var inner = "inner";
   3840 var mathord = "mathord";
   3841 var op = "op-token";
   3842 var open = "open";
   3843 var punct = "punct";
   3844 var rel = "rel";
   3845 var spacing = "spacing";
   3846 var textord = "textord"; // Now comes the symbol table
   3847 // Relation Symbols
   3848 
   3849 defineSymbol(math, main, rel, "\u2261", "\\equiv", true);
   3850 defineSymbol(math, main, rel, "\u227a", "\\prec", true);
   3851 defineSymbol(math, main, rel, "\u227b", "\\succ", true);
   3852 defineSymbol(math, main, rel, "\u223c", "\\sim", true);
   3853 defineSymbol(math, main, rel, "\u22a5", "\\perp");
   3854 defineSymbol(math, main, rel, "\u2aaf", "\\preceq", true);
   3855 defineSymbol(math, main, rel, "\u2ab0", "\\succeq", true);
   3856 defineSymbol(math, main, rel, "\u2243", "\\simeq", true);
   3857 defineSymbol(math, main, rel, "\u2223", "\\mid", true);
   3858 defineSymbol(math, main, rel, "\u226a", "\\ll", true);
   3859 defineSymbol(math, main, rel, "\u226b", "\\gg", true);
   3860 defineSymbol(math, main, rel, "\u224d", "\\asymp", true);
   3861 defineSymbol(math, main, rel, "\u2225", "\\parallel");
   3862 defineSymbol(math, main, rel, "\u22c8", "\\bowtie", true);
   3863 defineSymbol(math, main, rel, "\u2323", "\\smile", true);
   3864 defineSymbol(math, main, rel, "\u2291", "\\sqsubseteq", true);
   3865 defineSymbol(math, main, rel, "\u2292", "\\sqsupseteq", true);
   3866 defineSymbol(math, main, rel, "\u2250", "\\doteq", true);
   3867 defineSymbol(math, main, rel, "\u2322", "\\frown", true);
   3868 defineSymbol(math, main, rel, "\u220b", "\\ni", true);
   3869 defineSymbol(math, main, rel, "\u221d", "\\propto", true);
   3870 defineSymbol(math, main, rel, "\u22a2", "\\vdash", true);
   3871 defineSymbol(math, main, rel, "\u22a3", "\\dashv", true);
   3872 defineSymbol(math, main, rel, "\u220b", "\\owns"); // Punctuation
   3873 
   3874 defineSymbol(math, main, punct, "\u002e", "\\ldotp");
   3875 defineSymbol(math, main, punct, "\u22c5", "\\cdotp"); // Misc Symbols
   3876 
   3877 defineSymbol(math, main, textord, "\u0023", "\\#");
   3878 defineSymbol(text$1, main, textord, "\u0023", "\\#");
   3879 defineSymbol(math, main, textord, "\u0026", "\\&");
   3880 defineSymbol(text$1, main, textord, "\u0026", "\\&");
   3881 defineSymbol(math, main, textord, "\u2135", "\\aleph", true);
   3882 defineSymbol(math, main, textord, "\u2200", "\\forall", true);
   3883 defineSymbol(math, main, textord, "\u210f", "\\hbar", true);
   3884 defineSymbol(math, main, textord, "\u2203", "\\exists", true);
   3885 defineSymbol(math, main, textord, "\u2207", "\\nabla", true);
   3886 defineSymbol(math, main, textord, "\u266d", "\\flat", true);
   3887 defineSymbol(math, main, textord, "\u2113", "\\ell", true);
   3888 defineSymbol(math, main, textord, "\u266e", "\\natural", true);
   3889 defineSymbol(math, main, textord, "\u2663", "\\clubsuit", true);
   3890 defineSymbol(math, main, textord, "\u2118", "\\wp", true);
   3891 defineSymbol(math, main, textord, "\u266f", "\\sharp", true);
   3892 defineSymbol(math, main, textord, "\u2662", "\\diamondsuit", true);
   3893 defineSymbol(math, main, textord, "\u211c", "\\Re", true);
   3894 defineSymbol(math, main, textord, "\u2661", "\\heartsuit", true);
   3895 defineSymbol(math, main, textord, "\u2111", "\\Im", true);
   3896 defineSymbol(math, main, textord, "\u2660", "\\spadesuit", true);
   3897 defineSymbol(text$1, main, textord, "\u00a7", "\\S", true);
   3898 defineSymbol(text$1, main, textord, "\u00b6", "\\P", true); // Math and Text
   3899 
   3900 defineSymbol(math, main, textord, "\u2020", "\\dag");
   3901 defineSymbol(text$1, main, textord, "\u2020", "\\dag");
   3902 defineSymbol(text$1, main, textord, "\u2020", "\\textdagger");
   3903 defineSymbol(math, main, textord, "\u2021", "\\ddag");
   3904 defineSymbol(text$1, main, textord, "\u2021", "\\ddag");
   3905 defineSymbol(text$1, main, textord, "\u2021", "\\textdaggerdbl"); // Large Delimiters
   3906 
   3907 defineSymbol(math, main, close, "\u23b1", "\\rmoustache", true);
   3908 defineSymbol(math, main, open, "\u23b0", "\\lmoustache", true);
   3909 defineSymbol(math, main, close, "\u27ef", "\\rgroup", true);
   3910 defineSymbol(math, main, open, "\u27ee", "\\lgroup", true); // Binary Operators
   3911 
   3912 defineSymbol(math, main, bin, "\u2213", "\\mp", true);
   3913 defineSymbol(math, main, bin, "\u2296", "\\ominus", true);
   3914 defineSymbol(math, main, bin, "\u228e", "\\uplus", true);
   3915 defineSymbol(math, main, bin, "\u2293", "\\sqcap", true);
   3916 defineSymbol(math, main, bin, "\u2217", "\\ast");
   3917 defineSymbol(math, main, bin, "\u2294", "\\sqcup", true);
   3918 defineSymbol(math, main, bin, "\u25ef", "\\bigcirc", true);
   3919 defineSymbol(math, main, bin, "\u2219", "\\bullet");
   3920 defineSymbol(math, main, bin, "\u2021", "\\ddagger");
   3921 defineSymbol(math, main, bin, "\u2240", "\\wr", true);
   3922 defineSymbol(math, main, bin, "\u2a3f", "\\amalg");
   3923 defineSymbol(math, main, bin, "\u0026", "\\And"); // from amsmath
   3924 // Arrow Symbols
   3925 
   3926 defineSymbol(math, main, rel, "\u27f5", "\\longleftarrow", true);
   3927 defineSymbol(math, main, rel, "\u21d0", "\\Leftarrow", true);
   3928 defineSymbol(math, main, rel, "\u27f8", "\\Longleftarrow", true);
   3929 defineSymbol(math, main, rel, "\u27f6", "\\longrightarrow", true);
   3930 defineSymbol(math, main, rel, "\u21d2", "\\Rightarrow", true);
   3931 defineSymbol(math, main, rel, "\u27f9", "\\Longrightarrow", true);
   3932 defineSymbol(math, main, rel, "\u2194", "\\leftrightarrow", true);
   3933 defineSymbol(math, main, rel, "\u27f7", "\\longleftrightarrow", true);
   3934 defineSymbol(math, main, rel, "\u21d4", "\\Leftrightarrow", true);
   3935 defineSymbol(math, main, rel, "\u27fa", "\\Longleftrightarrow", true);
   3936 defineSymbol(math, main, rel, "\u21a6", "\\mapsto", true);
   3937 defineSymbol(math, main, rel, "\u27fc", "\\longmapsto", true);
   3938 defineSymbol(math, main, rel, "\u2197", "\\nearrow", true);
   3939 defineSymbol(math, main, rel, "\u21a9", "\\hookleftarrow", true);
   3940 defineSymbol(math, main, rel, "\u21aa", "\\hookrightarrow", true);
   3941 defineSymbol(math, main, rel, "\u2198", "\\searrow", true);
   3942 defineSymbol(math, main, rel, "\u21bc", "\\leftharpoonup", true);
   3943 defineSymbol(math, main, rel, "\u21c0", "\\rightharpoonup", true);
   3944 defineSymbol(math, main, rel, "\u2199", "\\swarrow", true);
   3945 defineSymbol(math, main, rel, "\u21bd", "\\leftharpoondown", true);
   3946 defineSymbol(math, main, rel, "\u21c1", "\\rightharpoondown", true);
   3947 defineSymbol(math, main, rel, "\u2196", "\\nwarrow", true);
   3948 defineSymbol(math, main, rel, "\u21cc", "\\rightleftharpoons", true); // AMS Negated Binary Relations
   3949 
   3950 defineSymbol(math, ams, rel, "\u226e", "\\nless", true); // Symbol names preceeded by "@" each have a corresponding macro.
   3951 
   3952 defineSymbol(math, ams, rel, "\ue010", "\\@nleqslant");
   3953 defineSymbol(math, ams, rel, "\ue011", "\\@nleqq");
   3954 defineSymbol(math, ams, rel, "\u2a87", "\\lneq", true);
   3955 defineSymbol(math, ams, rel, "\u2268", "\\lneqq", true);
   3956 defineSymbol(math, ams, rel, "\ue00c", "\\@lvertneqq");
   3957 defineSymbol(math, ams, rel, "\u22e6", "\\lnsim", true);
   3958 defineSymbol(math, ams, rel, "\u2a89", "\\lnapprox", true);
   3959 defineSymbol(math, ams, rel, "\u2280", "\\nprec", true); // unicode-math maps \u22e0 to \npreccurlyeq. We'll use the AMS synonym.
   3960 
   3961 defineSymbol(math, ams, rel, "\u22e0", "\\npreceq", true);
   3962 defineSymbol(math, ams, rel, "\u22e8", "\\precnsim", true);
   3963 defineSymbol(math, ams, rel, "\u2ab9", "\\precnapprox", true);
   3964 defineSymbol(math, ams, rel, "\u2241", "\\nsim", true);
   3965 defineSymbol(math, ams, rel, "\ue006", "\\@nshortmid");
   3966 defineSymbol(math, ams, rel, "\u2224", "\\nmid", true);
   3967 defineSymbol(math, ams, rel, "\u22ac", "\\nvdash", true);
   3968 defineSymbol(math, ams, rel, "\u22ad", "\\nvDash", true);
   3969 defineSymbol(math, ams, rel, "\u22ea", "\\ntriangleleft");
   3970 defineSymbol(math, ams, rel, "\u22ec", "\\ntrianglelefteq", true);
   3971 defineSymbol(math, ams, rel, "\u228a", "\\subsetneq", true);
   3972 defineSymbol(math, ams, rel, "\ue01a", "\\@varsubsetneq");
   3973 defineSymbol(math, ams, rel, "\u2acb", "\\subsetneqq", true);
   3974 defineSymbol(math, ams, rel, "\ue017", "\\@varsubsetneqq");
   3975 defineSymbol(math, ams, rel, "\u226f", "\\ngtr", true);
   3976 defineSymbol(math, ams, rel, "\ue00f", "\\@ngeqslant");
   3977 defineSymbol(math, ams, rel, "\ue00e", "\\@ngeqq");
   3978 defineSymbol(math, ams, rel, "\u2a88", "\\gneq", true);
   3979 defineSymbol(math, ams, rel, "\u2269", "\\gneqq", true);
   3980 defineSymbol(math, ams, rel, "\ue00d", "\\@gvertneqq");
   3981 defineSymbol(math, ams, rel, "\u22e7", "\\gnsim", true);
   3982 defineSymbol(math, ams, rel, "\u2a8a", "\\gnapprox", true);
   3983 defineSymbol(math, ams, rel, "\u2281", "\\nsucc", true); // unicode-math maps \u22e1 to \nsucccurlyeq. We'll use the AMS synonym.
   3984 
   3985 defineSymbol(math, ams, rel, "\u22e1", "\\nsucceq", true);
   3986 defineSymbol(math, ams, rel, "\u22e9", "\\succnsim", true);
   3987 defineSymbol(math, ams, rel, "\u2aba", "\\succnapprox", true); // unicode-math maps \u2246 to \simneqq. We'll use the AMS synonym.
   3988 
   3989 defineSymbol(math, ams, rel, "\u2246", "\\ncong", true);
   3990 defineSymbol(math, ams, rel, "\ue007", "\\@nshortparallel");
   3991 defineSymbol(math, ams, rel, "\u2226", "\\nparallel", true);
   3992 defineSymbol(math, ams, rel, "\u22af", "\\nVDash", true);
   3993 defineSymbol(math, ams, rel, "\u22eb", "\\ntriangleright");
   3994 defineSymbol(math, ams, rel, "\u22ed", "\\ntrianglerighteq", true);
   3995 defineSymbol(math, ams, rel, "\ue018", "\\@nsupseteqq");
   3996 defineSymbol(math, ams, rel, "\u228b", "\\supsetneq", true);
   3997 defineSymbol(math, ams, rel, "\ue01b", "\\@varsupsetneq");
   3998 defineSymbol(math, ams, rel, "\u2acc", "\\supsetneqq", true);
   3999 defineSymbol(math, ams, rel, "\ue019", "\\@varsupsetneqq");
   4000 defineSymbol(math, ams, rel, "\u22ae", "\\nVdash", true);
   4001 defineSymbol(math, ams, rel, "\u2ab5", "\\precneqq", true);
   4002 defineSymbol(math, ams, rel, "\u2ab6", "\\succneqq", true);
   4003 defineSymbol(math, ams, rel, "\ue016", "\\@nsubseteqq");
   4004 defineSymbol(math, ams, bin, "\u22b4", "\\unlhd");
   4005 defineSymbol(math, ams, bin, "\u22b5", "\\unrhd"); // AMS Negated Arrows
   4006 
   4007 defineSymbol(math, ams, rel, "\u219a", "\\nleftarrow", true);
   4008 defineSymbol(math, ams, rel, "\u219b", "\\nrightarrow", true);
   4009 defineSymbol(math, ams, rel, "\u21cd", "\\nLeftarrow", true);
   4010 defineSymbol(math, ams, rel, "\u21cf", "\\nRightarrow", true);
   4011 defineSymbol(math, ams, rel, "\u21ae", "\\nleftrightarrow", true);
   4012 defineSymbol(math, ams, rel, "\u21ce", "\\nLeftrightarrow", true); // AMS Misc
   4013 
   4014 defineSymbol(math, ams, rel, "\u25b3", "\\vartriangle");
   4015 defineSymbol(math, ams, textord, "\u210f", "\\hslash");
   4016 defineSymbol(math, ams, textord, "\u25bd", "\\triangledown");
   4017 defineSymbol(math, ams, textord, "\u25ca", "\\lozenge");
   4018 defineSymbol(math, ams, textord, "\u24c8", "\\circledS");
   4019 defineSymbol(math, ams, textord, "\u00ae", "\\circledR");
   4020 defineSymbol(text$1, ams, textord, "\u00ae", "\\circledR");
   4021 defineSymbol(math, ams, textord, "\u2221", "\\measuredangle", true);
   4022 defineSymbol(math, ams, textord, "\u2204", "\\nexists");
   4023 defineSymbol(math, ams, textord, "\u2127", "\\mho");
   4024 defineSymbol(math, ams, textord, "\u2132", "\\Finv", true);
   4025 defineSymbol(math, ams, textord, "\u2141", "\\Game", true);
   4026 defineSymbol(math, ams, textord, "\u2035", "\\backprime");
   4027 defineSymbol(math, ams, textord, "\u25b2", "\\blacktriangle");
   4028 defineSymbol(math, ams, textord, "\u25bc", "\\blacktriangledown");
   4029 defineSymbol(math, ams, textord, "\u25a0", "\\blacksquare");
   4030 defineSymbol(math, ams, textord, "\u29eb", "\\blacklozenge");
   4031 defineSymbol(math, ams, textord, "\u2605", "\\bigstar");
   4032 defineSymbol(math, ams, textord, "\u2222", "\\sphericalangle", true);
   4033 defineSymbol(math, ams, textord, "\u2201", "\\complement", true); // unicode-math maps U+F0 to \matheth. We map to AMS function \eth
   4034 
   4035 defineSymbol(math, ams, textord, "\u00f0", "\\eth", true);
   4036 defineSymbol(text$1, main, textord, "\u00f0", "\u00f0");
   4037 defineSymbol(math, ams, textord, "\u2571", "\\diagup");
   4038 defineSymbol(math, ams, textord, "\u2572", "\\diagdown");
   4039 defineSymbol(math, ams, textord, "\u25a1", "\\square");
   4040 defineSymbol(math, ams, textord, "\u25a1", "\\Box");
   4041 defineSymbol(math, ams, textord, "\u25ca", "\\Diamond"); // unicode-math maps U+A5 to \mathyen. We map to AMS function \yen
   4042 
   4043 defineSymbol(math, ams, textord, "\u00a5", "\\yen", true);
   4044 defineSymbol(text$1, ams, textord, "\u00a5", "\\yen", true);
   4045 defineSymbol(math, ams, textord, "\u2713", "\\checkmark", true);
   4046 defineSymbol(text$1, ams, textord, "\u2713", "\\checkmark"); // AMS Hebrew
   4047 
   4048 defineSymbol(math, ams, textord, "\u2136", "\\beth", true);
   4049 defineSymbol(math, ams, textord, "\u2138", "\\daleth", true);
   4050 defineSymbol(math, ams, textord, "\u2137", "\\gimel", true); // AMS Greek
   4051 
   4052 defineSymbol(math, ams, textord, "\u03dd", "\\digamma", true);
   4053 defineSymbol(math, ams, textord, "\u03f0", "\\varkappa"); // AMS Delimiters
   4054 
   4055 defineSymbol(math, ams, open, "\u250c", "\\@ulcorner", true);
   4056 defineSymbol(math, ams, close, "\u2510", "\\@urcorner", true);
   4057 defineSymbol(math, ams, open, "\u2514", "\\@llcorner", true);
   4058 defineSymbol(math, ams, close, "\u2518", "\\@lrcorner", true); // AMS Binary Relations
   4059 
   4060 defineSymbol(math, ams, rel, "\u2266", "\\leqq", true);
   4061 defineSymbol(math, ams, rel, "\u2a7d", "\\leqslant", true);
   4062 defineSymbol(math, ams, rel, "\u2a95", "\\eqslantless", true);
   4063 defineSymbol(math, ams, rel, "\u2272", "\\lesssim", true);
   4064 defineSymbol(math, ams, rel, "\u2a85", "\\lessapprox", true);
   4065 defineSymbol(math, ams, rel, "\u224a", "\\approxeq", true);
   4066 defineSymbol(math, ams, bin, "\u22d6", "\\lessdot");
   4067 defineSymbol(math, ams, rel, "\u22d8", "\\lll", true);
   4068 defineSymbol(math, ams, rel, "\u2276", "\\lessgtr", true);
   4069 defineSymbol(math, ams, rel, "\u22da", "\\lesseqgtr", true);
   4070 defineSymbol(math, ams, rel, "\u2a8b", "\\lesseqqgtr", true);
   4071 defineSymbol(math, ams, rel, "\u2251", "\\doteqdot");
   4072 defineSymbol(math, ams, rel, "\u2253", "\\risingdotseq", true);
   4073 defineSymbol(math, ams, rel, "\u2252", "\\fallingdotseq", true);
   4074 defineSymbol(math, ams, rel, "\u223d", "\\backsim", true);
   4075 defineSymbol(math, ams, rel, "\u22cd", "\\backsimeq", true);
   4076 defineSymbol(math, ams, rel, "\u2ac5", "\\subseteqq", true);
   4077 defineSymbol(math, ams, rel, "\u22d0", "\\Subset", true);
   4078 defineSymbol(math, ams, rel, "\u228f", "\\sqsubset", true);
   4079 defineSymbol(math, ams, rel, "\u227c", "\\preccurlyeq", true);
   4080 defineSymbol(math, ams, rel, "\u22de", "\\curlyeqprec", true);
   4081 defineSymbol(math, ams, rel, "\u227e", "\\precsim", true);
   4082 defineSymbol(math, ams, rel, "\u2ab7", "\\precapprox", true);
   4083 defineSymbol(math, ams, rel, "\u22b2", "\\vartriangleleft");
   4084 defineSymbol(math, ams, rel, "\u22b4", "\\trianglelefteq");
   4085 defineSymbol(math, ams, rel, "\u22a8", "\\vDash", true);
   4086 defineSymbol(math, ams, rel, "\u22aa", "\\Vvdash", true);
   4087 defineSymbol(math, ams, rel, "\u2323", "\\smallsmile");
   4088 defineSymbol(math, ams, rel, "\u2322", "\\smallfrown");
   4089 defineSymbol(math, ams, rel, "\u224f", "\\bumpeq", true);
   4090 defineSymbol(math, ams, rel, "\u224e", "\\Bumpeq", true);
   4091 defineSymbol(math, ams, rel, "\u2267", "\\geqq", true);
   4092 defineSymbol(math, ams, rel, "\u2a7e", "\\geqslant", true);
   4093 defineSymbol(math, ams, rel, "\u2a96", "\\eqslantgtr", true);
   4094 defineSymbol(math, ams, rel, "\u2273", "\\gtrsim", true);
   4095 defineSymbol(math, ams, rel, "\u2a86", "\\gtrapprox", true);
   4096 defineSymbol(math, ams, bin, "\u22d7", "\\gtrdot");
   4097 defineSymbol(math, ams, rel, "\u22d9", "\\ggg", true);
   4098 defineSymbol(math, ams, rel, "\u2277", "\\gtrless", true);
   4099 defineSymbol(math, ams, rel, "\u22db", "\\gtreqless", true);
   4100 defineSymbol(math, ams, rel, "\u2a8c", "\\gtreqqless", true);
   4101 defineSymbol(math, ams, rel, "\u2256", "\\eqcirc", true);
   4102 defineSymbol(math, ams, rel, "\u2257", "\\circeq", true);
   4103 defineSymbol(math, ams, rel, "\u225c", "\\triangleq", true);
   4104 defineSymbol(math, ams, rel, "\u223c", "\\thicksim");
   4105 defineSymbol(math, ams, rel, "\u2248", "\\thickapprox");
   4106 defineSymbol(math, ams, rel, "\u2ac6", "\\supseteqq", true);
   4107 defineSymbol(math, ams, rel, "\u22d1", "\\Supset", true);
   4108 defineSymbol(math, ams, rel, "\u2290", "\\sqsupset", true);
   4109 defineSymbol(math, ams, rel, "\u227d", "\\succcurlyeq", true);
   4110 defineSymbol(math, ams, rel, "\u22df", "\\curlyeqsucc", true);
   4111 defineSymbol(math, ams, rel, "\u227f", "\\succsim", true);
   4112 defineSymbol(math, ams, rel, "\u2ab8", "\\succapprox", true);
   4113 defineSymbol(math, ams, rel, "\u22b3", "\\vartriangleright");
   4114 defineSymbol(math, ams, rel, "\u22b5", "\\trianglerighteq");
   4115 defineSymbol(math, ams, rel, "\u22a9", "\\Vdash", true);
   4116 defineSymbol(math, ams, rel, "\u2223", "\\shortmid");
   4117 defineSymbol(math, ams, rel, "\u2225", "\\shortparallel");
   4118 defineSymbol(math, ams, rel, "\u226c", "\\between", true);
   4119 defineSymbol(math, ams, rel, "\u22d4", "\\pitchfork", true);
   4120 defineSymbol(math, ams, rel, "\u221d", "\\varpropto");
   4121 defineSymbol(math, ams, rel, "\u25c0", "\\blacktriangleleft"); // unicode-math says that \therefore is a mathord atom.
   4122 // We kept the amssymb atom type, which is rel.
   4123 
   4124 defineSymbol(math, ams, rel, "\u2234", "\\therefore", true);
   4125 defineSymbol(math, ams, rel, "\u220d", "\\backepsilon");
   4126 defineSymbol(math, ams, rel, "\u25b6", "\\blacktriangleright"); // unicode-math says that \because is a mathord atom.
   4127 // We kept the amssymb atom type, which is rel.
   4128 
   4129 defineSymbol(math, ams, rel, "\u2235", "\\because", true);
   4130 defineSymbol(math, ams, rel, "\u22d8", "\\llless");
   4131 defineSymbol(math, ams, rel, "\u22d9", "\\gggtr");
   4132 defineSymbol(math, ams, bin, "\u22b2", "\\lhd");
   4133 defineSymbol(math, ams, bin, "\u22b3", "\\rhd");
   4134 defineSymbol(math, ams, rel, "\u2242", "\\eqsim", true);
   4135 defineSymbol(math, main, rel, "\u22c8", "\\Join");
   4136 defineSymbol(math, ams, rel, "\u2251", "\\Doteq", true); // AMS Binary Operators
   4137 
   4138 defineSymbol(math, ams, bin, "\u2214", "\\dotplus", true);
   4139 defineSymbol(math, ams, bin, "\u2216", "\\smallsetminus");
   4140 defineSymbol(math, ams, bin, "\u22d2", "\\Cap", true);
   4141 defineSymbol(math, ams, bin, "\u22d3", "\\Cup", true);
   4142 defineSymbol(math, ams, bin, "\u2a5e", "\\doublebarwedge", true);
   4143 defineSymbol(math, ams, bin, "\u229f", "\\boxminus", true);
   4144 defineSymbol(math, ams, bin, "\u229e", "\\boxplus", true);
   4145 defineSymbol(math, ams, bin, "\u22c7", "\\divideontimes", true);
   4146 defineSymbol(math, ams, bin, "\u22c9", "\\ltimes", true);
   4147 defineSymbol(math, ams, bin, "\u22ca", "\\rtimes", true);
   4148 defineSymbol(math, ams, bin, "\u22cb", "\\leftthreetimes", true);
   4149 defineSymbol(math, ams, bin, "\u22cc", "\\rightthreetimes", true);
   4150 defineSymbol(math, ams, bin, "\u22cf", "\\curlywedge", true);
   4151 defineSymbol(math, ams, bin, "\u22ce", "\\curlyvee", true);
   4152 defineSymbol(math, ams, bin, "\u229d", "\\circleddash", true);
   4153 defineSymbol(math, ams, bin, "\u229b", "\\circledast", true);
   4154 defineSymbol(math, ams, bin, "\u22c5", "\\centerdot");
   4155 defineSymbol(math, ams, bin, "\u22ba", "\\intercal", true);
   4156 defineSymbol(math, ams, bin, "\u22d2", "\\doublecap");
   4157 defineSymbol(math, ams, bin, "\u22d3", "\\doublecup");
   4158 defineSymbol(math, ams, bin, "\u22a0", "\\boxtimes", true); // AMS Arrows
   4159 // Note: unicode-math maps \u21e2 to their own function \rightdasharrow.
   4160 // We'll map it to AMS function \dashrightarrow. It produces the same atom.
   4161 
   4162 defineSymbol(math, ams, rel, "\u21e2", "\\dashrightarrow", true); // unicode-math maps \u21e0 to \leftdasharrow. We'll use the AMS synonym.
   4163 
   4164 defineSymbol(math, ams, rel, "\u21e0", "\\dashleftarrow", true);
   4165 defineSymbol(math, ams, rel, "\u21c7", "\\leftleftarrows", true);
   4166 defineSymbol(math, ams, rel, "\u21c6", "\\leftrightarrows", true);
   4167 defineSymbol(math, ams, rel, "\u21da", "\\Lleftarrow", true);
   4168 defineSymbol(math, ams, rel, "\u219e", "\\twoheadleftarrow", true);
   4169 defineSymbol(math, ams, rel, "\u21a2", "\\leftarrowtail", true);
   4170 defineSymbol(math, ams, rel, "\u21ab", "\\looparrowleft", true);
   4171 defineSymbol(math, ams, rel, "\u21cb", "\\leftrightharpoons", true);
   4172 defineSymbol(math, ams, rel, "\u21b6", "\\curvearrowleft", true); // unicode-math maps \u21ba to \acwopencirclearrow. We'll use the AMS synonym.
   4173 
   4174 defineSymbol(math, ams, rel, "\u21ba", "\\circlearrowleft", true);
   4175 defineSymbol(math, ams, rel, "\u21b0", "\\Lsh", true);
   4176 defineSymbol(math, ams, rel, "\u21c8", "\\upuparrows", true);
   4177 defineSymbol(math, ams, rel, "\u21bf", "\\upharpoonleft", true);
   4178 defineSymbol(math, ams, rel, "\u21c3", "\\downharpoonleft", true);
   4179 defineSymbol(math, main, rel, "\u22b6", "\\origof", true); // not in font
   4180 
   4181 defineSymbol(math, main, rel, "\u22b7", "\\imageof", true); // not in font
   4182 
   4183 defineSymbol(math, ams, rel, "\u22b8", "\\multimap", true);
   4184 defineSymbol(math, ams, rel, "\u21ad", "\\leftrightsquigarrow", true);
   4185 defineSymbol(math, ams, rel, "\u21c9", "\\rightrightarrows", true);
   4186 defineSymbol(math, ams, rel, "\u21c4", "\\rightleftarrows", true);
   4187 defineSymbol(math, ams, rel, "\u21a0", "\\twoheadrightarrow", true);
   4188 defineSymbol(math, ams, rel, "\u21a3", "\\rightarrowtail", true);
   4189 defineSymbol(math, ams, rel, "\u21ac", "\\looparrowright", true);
   4190 defineSymbol(math, ams, rel, "\u21b7", "\\curvearrowright", true); // unicode-math maps \u21bb to \cwopencirclearrow. We'll use the AMS synonym.
   4191 
   4192 defineSymbol(math, ams, rel, "\u21bb", "\\circlearrowright", true);
   4193 defineSymbol(math, ams, rel, "\u21b1", "\\Rsh", true);
   4194 defineSymbol(math, ams, rel, "\u21ca", "\\downdownarrows", true);
   4195 defineSymbol(math, ams, rel, "\u21be", "\\upharpoonright", true);
   4196 defineSymbol(math, ams, rel, "\u21c2", "\\downharpoonright", true);
   4197 defineSymbol(math, ams, rel, "\u21dd", "\\rightsquigarrow", true);
   4198 defineSymbol(math, ams, rel, "\u21dd", "\\leadsto");
   4199 defineSymbol(math, ams, rel, "\u21db", "\\Rrightarrow", true);
   4200 defineSymbol(math, ams, rel, "\u21be", "\\restriction");
   4201 defineSymbol(math, main, textord, "\u2018", "`");
   4202 defineSymbol(math, main, textord, "$", "\\$");
   4203 defineSymbol(text$1, main, textord, "$", "\\$");
   4204 defineSymbol(text$1, main, textord, "$", "\\textdollar");
   4205 defineSymbol(math, main, textord, "%", "\\%");
   4206 defineSymbol(text$1, main, textord, "%", "\\%");
   4207 defineSymbol(math, main, textord, "_", "\\_");
   4208 defineSymbol(text$1, main, textord, "_", "\\_");
   4209 defineSymbol(text$1, main, textord, "_", "\\textunderscore");
   4210 defineSymbol(math, main, textord, "\u2220", "\\angle", true);
   4211 defineSymbol(math, main, textord, "\u221e", "\\infty", true);
   4212 defineSymbol(math, main, textord, "\u2032", "\\prime");
   4213 defineSymbol(math, main, textord, "\u25b3", "\\triangle");
   4214 defineSymbol(math, main, textord, "\u0393", "\\Gamma", true);
   4215 defineSymbol(math, main, textord, "\u0394", "\\Delta", true);
   4216 defineSymbol(math, main, textord, "\u0398", "\\Theta", true);
   4217 defineSymbol(math, main, textord, "\u039b", "\\Lambda", true);
   4218 defineSymbol(math, main, textord, "\u039e", "\\Xi", true);
   4219 defineSymbol(math, main, textord, "\u03a0", "\\Pi", true);
   4220 defineSymbol(math, main, textord, "\u03a3", "\\Sigma", true);
   4221 defineSymbol(math, main, textord, "\u03a5", "\\Upsilon", true);
   4222 defineSymbol(math, main, textord, "\u03a6", "\\Phi", true);
   4223 defineSymbol(math, main, textord, "\u03a8", "\\Psi", true);
   4224 defineSymbol(math, main, textord, "\u03a9", "\\Omega", true);
   4225 defineSymbol(math, main, textord, "A", "\u0391");
   4226 defineSymbol(math, main, textord, "B", "\u0392");
   4227 defineSymbol(math, main, textord, "E", "\u0395");
   4228 defineSymbol(math, main, textord, "Z", "\u0396");
   4229 defineSymbol(math, main, textord, "H", "\u0397");
   4230 defineSymbol(math, main, textord, "I", "\u0399");
   4231 defineSymbol(math, main, textord, "K", "\u039A");
   4232 defineSymbol(math, main, textord, "M", "\u039C");
   4233 defineSymbol(math, main, textord, "N", "\u039D");
   4234 defineSymbol(math, main, textord, "O", "\u039F");
   4235 defineSymbol(math, main, textord, "P", "\u03A1");
   4236 defineSymbol(math, main, textord, "T", "\u03A4");
   4237 defineSymbol(math, main, textord, "X", "\u03A7");
   4238 defineSymbol(math, main, textord, "\u00ac", "\\neg", true);
   4239 defineSymbol(math, main, textord, "\u00ac", "\\lnot");
   4240 defineSymbol(math, main, textord, "\u22a4", "\\top");
   4241 defineSymbol(math, main, textord, "\u22a5", "\\bot");
   4242 defineSymbol(math, main, textord, "\u2205", "\\emptyset");
   4243 defineSymbol(math, ams, textord, "\u2205", "\\varnothing");
   4244 defineSymbol(math, main, mathord, "\u03b1", "\\alpha", true);
   4245 defineSymbol(math, main, mathord, "\u03b2", "\\beta", true);
   4246 defineSymbol(math, main, mathord, "\u03b3", "\\gamma", true);
   4247 defineSymbol(math, main, mathord, "\u03b4", "\\delta", true);
   4248 defineSymbol(math, main, mathord, "\u03f5", "\\epsilon", true);
   4249 defineSymbol(math, main, mathord, "\u03b6", "\\zeta", true);
   4250 defineSymbol(math, main, mathord, "\u03b7", "\\eta", true);
   4251 defineSymbol(math, main, mathord, "\u03b8", "\\theta", true);
   4252 defineSymbol(math, main, mathord, "\u03b9", "\\iota", true);
   4253 defineSymbol(math, main, mathord, "\u03ba", "\\kappa", true);
   4254 defineSymbol(math, main, mathord, "\u03bb", "\\lambda", true);
   4255 defineSymbol(math, main, mathord, "\u03bc", "\\mu", true);
   4256 defineSymbol(math, main, mathord, "\u03bd", "\\nu", true);
   4257 defineSymbol(math, main, mathord, "\u03be", "\\xi", true);
   4258 defineSymbol(math, main, mathord, "\u03bf", "\\omicron", true);
   4259 defineSymbol(math, main, mathord, "\u03c0", "\\pi", true);
   4260 defineSymbol(math, main, mathord, "\u03c1", "\\rho", true);
   4261 defineSymbol(math, main, mathord, "\u03c3", "\\sigma", true);
   4262 defineSymbol(math, main, mathord, "\u03c4", "\\tau", true);
   4263 defineSymbol(math, main, mathord, "\u03c5", "\\upsilon", true);
   4264 defineSymbol(math, main, mathord, "\u03d5", "\\phi", true);
   4265 defineSymbol(math, main, mathord, "\u03c7", "\\chi", true);
   4266 defineSymbol(math, main, mathord, "\u03c8", "\\psi", true);
   4267 defineSymbol(math, main, mathord, "\u03c9", "\\omega", true);
   4268 defineSymbol(math, main, mathord, "\u03b5", "\\varepsilon", true);
   4269 defineSymbol(math, main, mathord, "\u03d1", "\\vartheta", true);
   4270 defineSymbol(math, main, mathord, "\u03d6", "\\varpi", true);
   4271 defineSymbol(math, main, mathord, "\u03f1", "\\varrho", true);
   4272 defineSymbol(math, main, mathord, "\u03c2", "\\varsigma", true);
   4273 defineSymbol(math, main, mathord, "\u03c6", "\\varphi", true);
   4274 defineSymbol(math, main, bin, "\u2217", "*");
   4275 defineSymbol(math, main, bin, "+", "+");
   4276 defineSymbol(math, main, bin, "\u2212", "-");
   4277 defineSymbol(math, main, bin, "\u22c5", "\\cdot", true);
   4278 defineSymbol(math, main, bin, "\u2218", "\\circ");
   4279 defineSymbol(math, main, bin, "\u00f7", "\\div", true);
   4280 defineSymbol(math, main, bin, "\u00b1", "\\pm", true);
   4281 defineSymbol(math, main, bin, "\u00d7", "\\times", true);
   4282 defineSymbol(math, main, bin, "\u2229", "\\cap", true);
   4283 defineSymbol(math, main, bin, "\u222a", "\\cup", true);
   4284 defineSymbol(math, main, bin, "\u2216", "\\setminus");
   4285 defineSymbol(math, main, bin, "\u2227", "\\land");
   4286 defineSymbol(math, main, bin, "\u2228", "\\lor");
   4287 defineSymbol(math, main, bin, "\u2227", "\\wedge", true);
   4288 defineSymbol(math, main, bin, "\u2228", "\\vee", true);
   4289 defineSymbol(math, main, textord, "\u221a", "\\surd");
   4290 defineSymbol(math, main, open, "\u27e8", "\\langle", true);
   4291 defineSymbol(math, main, open, "\u2223", "\\lvert");
   4292 defineSymbol(math, main, open, "\u2225", "\\lVert");
   4293 defineSymbol(math, main, close, "?", "?");
   4294 defineSymbol(math, main, close, "!", "!");
   4295 defineSymbol(math, main, close, "\u27e9", "\\rangle", true);
   4296 defineSymbol(math, main, close, "\u2223", "\\rvert");
   4297 defineSymbol(math, main, close, "\u2225", "\\rVert");
   4298 defineSymbol(math, main, rel, "=", "=");
   4299 defineSymbol(math, main, rel, ":", ":");
   4300 defineSymbol(math, main, rel, "\u2248", "\\approx", true);
   4301 defineSymbol(math, main, rel, "\u2245", "\\cong", true);
   4302 defineSymbol(math, main, rel, "\u2265", "\\ge");
   4303 defineSymbol(math, main, rel, "\u2265", "\\geq", true);
   4304 defineSymbol(math, main, rel, "\u2190", "\\gets");
   4305 defineSymbol(math, main, rel, ">", "\\gt", true);
   4306 defineSymbol(math, main, rel, "\u2208", "\\in", true);
   4307 defineSymbol(math, main, rel, "\ue020", "\\@not");
   4308 defineSymbol(math, main, rel, "\u2282", "\\subset", true);
   4309 defineSymbol(math, main, rel, "\u2283", "\\supset", true);
   4310 defineSymbol(math, main, rel, "\u2286", "\\subseteq", true);
   4311 defineSymbol(math, main, rel, "\u2287", "\\supseteq", true);
   4312 defineSymbol(math, ams, rel, "\u2288", "\\nsubseteq", true);
   4313 defineSymbol(math, ams, rel, "\u2289", "\\nsupseteq", true);
   4314 defineSymbol(math, main, rel, "\u22a8", "\\models");
   4315 defineSymbol(math, main, rel, "\u2190", "\\leftarrow", true);
   4316 defineSymbol(math, main, rel, "\u2264", "\\le");
   4317 defineSymbol(math, main, rel, "\u2264", "\\leq", true);
   4318 defineSymbol(math, main, rel, "<", "\\lt", true);
   4319 defineSymbol(math, main, rel, "\u2192", "\\rightarrow", true);
   4320 defineSymbol(math, main, rel, "\u2192", "\\to");
   4321 defineSymbol(math, ams, rel, "\u2271", "\\ngeq", true);
   4322 defineSymbol(math, ams, rel, "\u2270", "\\nleq", true);
   4323 defineSymbol(math, main, spacing, "\u00a0", "\\ ");
   4324 defineSymbol(math, main, spacing, "\u00a0", "~");
   4325 defineSymbol(math, main, spacing, "\u00a0", "\\space"); // Ref: LaTeX Source 2e: \DeclareRobustCommand{\nobreakspace}{%
   4326 
   4327 defineSymbol(math, main, spacing, "\u00a0", "\\nobreakspace");
   4328 defineSymbol(text$1, main, spacing, "\u00a0", "\\ ");
   4329 defineSymbol(text$1, main, spacing, "\u00a0", " ");
   4330 defineSymbol(text$1, main, spacing, "\u00a0", "~");
   4331 defineSymbol(text$1, main, spacing, "\u00a0", "\\space");
   4332 defineSymbol(text$1, main, spacing, "\u00a0", "\\nobreakspace");
   4333 defineSymbol(math, main, spacing, null, "\\nobreak");
   4334 defineSymbol(math, main, spacing, null, "\\allowbreak");
   4335 defineSymbol(math, main, punct, ",", ",");
   4336 defineSymbol(math, main, punct, ";", ";");
   4337 defineSymbol(math, ams, bin, "\u22bc", "\\barwedge", true);
   4338 defineSymbol(math, ams, bin, "\u22bb", "\\veebar", true);
   4339 defineSymbol(math, main, bin, "\u2299", "\\odot", true);
   4340 defineSymbol(math, main, bin, "\u2295", "\\oplus", true);
   4341 defineSymbol(math, main, bin, "\u2297", "\\otimes", true);
   4342 defineSymbol(math, main, textord, "\u2202", "\\partial", true);
   4343 defineSymbol(math, main, bin, "\u2298", "\\oslash", true);
   4344 defineSymbol(math, ams, bin, "\u229a", "\\circledcirc", true);
   4345 defineSymbol(math, ams, bin, "\u22a1", "\\boxdot", true);
   4346 defineSymbol(math, main, bin, "\u25b3", "\\bigtriangleup");
   4347 defineSymbol(math, main, bin, "\u25bd", "\\bigtriangledown");
   4348 defineSymbol(math, main, bin, "\u2020", "\\dagger");
   4349 defineSymbol(math, main, bin, "\u22c4", "\\diamond");
   4350 defineSymbol(math, main, bin, "\u22c6", "\\star");
   4351 defineSymbol(math, main, bin, "\u25c3", "\\triangleleft");
   4352 defineSymbol(math, main, bin, "\u25b9", "\\triangleright");
   4353 defineSymbol(math, main, open, "{", "\\{");
   4354 defineSymbol(text$1, main, textord, "{", "\\{");
   4355 defineSymbol(text$1, main, textord, "{", "\\textbraceleft");
   4356 defineSymbol(math, main, close, "}", "\\}");
   4357 defineSymbol(text$1, main, textord, "}", "\\}");
   4358 defineSymbol(text$1, main, textord, "}", "\\textbraceright");
   4359 defineSymbol(math, main, open, "{", "\\lbrace");
   4360 defineSymbol(math, main, close, "}", "\\rbrace");
   4361 defineSymbol(math, main, open, "[", "\\lbrack", true);
   4362 defineSymbol(text$1, main, textord, "[", "\\lbrack", true);
   4363 defineSymbol(math, main, close, "]", "\\rbrack", true);
   4364 defineSymbol(text$1, main, textord, "]", "\\rbrack", true);
   4365 defineSymbol(math, main, open, "(", "\\lparen", true);
   4366 defineSymbol(math, main, close, ")", "\\rparen", true);
   4367 defineSymbol(text$1, main, textord, "<", "\\textless", true); // in T1 fontenc
   4368 
   4369 defineSymbol(text$1, main, textord, ">", "\\textgreater", true); // in T1 fontenc
   4370 
   4371 defineSymbol(math, main, open, "\u230a", "\\lfloor", true);
   4372 defineSymbol(math, main, close, "\u230b", "\\rfloor", true);
   4373 defineSymbol(math, main, open, "\u2308", "\\lceil", true);
   4374 defineSymbol(math, main, close, "\u2309", "\\rceil", true);
   4375 defineSymbol(math, main, textord, "\\", "\\backslash");
   4376 defineSymbol(math, main, textord, "\u2223", "|");
   4377 defineSymbol(math, main, textord, "\u2223", "\\vert");
   4378 defineSymbol(text$1, main, textord, "|", "\\textbar", true); // in T1 fontenc
   4379 
   4380 defineSymbol(math, main, textord, "\u2225", "\\|");
   4381 defineSymbol(math, main, textord, "\u2225", "\\Vert");
   4382 defineSymbol(text$1, main, textord, "\u2225", "\\textbardbl");
   4383 defineSymbol(text$1, main, textord, "~", "\\textasciitilde");
   4384 defineSymbol(text$1, main, textord, "\\", "\\textbackslash");
   4385 defineSymbol(text$1, main, textord, "^", "\\textasciicircum");
   4386 defineSymbol(math, main, rel, "\u2191", "\\uparrow", true);
   4387 defineSymbol(math, main, rel, "\u21d1", "\\Uparrow", true);
   4388 defineSymbol(math, main, rel, "\u2193", "\\downarrow", true);
   4389 defineSymbol(math, main, rel, "\u21d3", "\\Downarrow", true);
   4390 defineSymbol(math, main, rel, "\u2195", "\\updownarrow", true);
   4391 defineSymbol(math, main, rel, "\u21d5", "\\Updownarrow", true);
   4392 defineSymbol(math, main, op, "\u2210", "\\coprod");
   4393 defineSymbol(math, main, op, "\u22c1", "\\bigvee");
   4394 defineSymbol(math, main, op, "\u22c0", "\\bigwedge");
   4395 defineSymbol(math, main, op, "\u2a04", "\\biguplus");
   4396 defineSymbol(math, main, op, "\u22c2", "\\bigcap");
   4397 defineSymbol(math, main, op, "\u22c3", "\\bigcup");
   4398 defineSymbol(math, main, op, "\u222b", "\\int");
   4399 defineSymbol(math, main, op, "\u222b", "\\intop");
   4400 defineSymbol(math, main, op, "\u222c", "\\iint");
   4401 defineSymbol(math, main, op, "\u222d", "\\iiint");
   4402 defineSymbol(math, main, op, "\u220f", "\\prod");
   4403 defineSymbol(math, main, op, "\u2211", "\\sum");
   4404 defineSymbol(math, main, op, "\u2a02", "\\bigotimes");
   4405 defineSymbol(math, main, op, "\u2a01", "\\bigoplus");
   4406 defineSymbol(math, main, op, "\u2a00", "\\bigodot");
   4407 defineSymbol(math, main, op, "\u222e", "\\oint");
   4408 defineSymbol(math, main, op, "\u222f", "\\oiint");
   4409 defineSymbol(math, main, op, "\u2230", "\\oiiint");
   4410 defineSymbol(math, main, op, "\u2a06", "\\bigsqcup");
   4411 defineSymbol(math, main, op, "\u222b", "\\smallint");
   4412 defineSymbol(text$1, main, inner, "\u2026", "\\textellipsis");
   4413 defineSymbol(math, main, inner, "\u2026", "\\mathellipsis");
   4414 defineSymbol(text$1, main, inner, "\u2026", "\\ldots", true);
   4415 defineSymbol(math, main, inner, "\u2026", "\\ldots", true);
   4416 defineSymbol(math, main, inner, "\u22ef", "\\@cdots", true);
   4417 defineSymbol(math, main, inner, "\u22f1", "\\ddots", true);
   4418 defineSymbol(math, main, textord, "\u22ee", "\\varvdots"); // \vdots is a macro
   4419 
   4420 defineSymbol(math, main, accent, "\u02ca", "\\acute");
   4421 defineSymbol(math, main, accent, "\u02cb", "\\grave");
   4422 defineSymbol(math, main, accent, "\u00a8", "\\ddot");
   4423 defineSymbol(math, main, accent, "\u007e", "\\tilde");
   4424 defineSymbol(math, main, accent, "\u02c9", "\\bar");
   4425 defineSymbol(math, main, accent, "\u02d8", "\\breve");
   4426 defineSymbol(math, main, accent, "\u02c7", "\\check");
   4427 defineSymbol(math, main, accent, "\u005e", "\\hat");
   4428 defineSymbol(math, main, accent, "\u20d7", "\\vec");
   4429 defineSymbol(math, main, accent, "\u02d9", "\\dot");
   4430 defineSymbol(math, main, accent, "\u02da", "\\mathring"); // \imath and \jmath should be invariant to \mathrm, \mathbf, etc., so use PUA
   4431 
   4432 defineSymbol(math, main, mathord, "\ue131", "\\@imath");
   4433 defineSymbol(math, main, mathord, "\ue237", "\\@jmath");
   4434 defineSymbol(math, main, textord, "\u0131", "\u0131");
   4435 defineSymbol(math, main, textord, "\u0237", "\u0237");
   4436 defineSymbol(text$1, main, textord, "\u0131", "\\i", true);
   4437 defineSymbol(text$1, main, textord, "\u0237", "\\j", true);
   4438 defineSymbol(text$1, main, textord, "\u00df", "\\ss", true);
   4439 defineSymbol(text$1, main, textord, "\u00e6", "\\ae", true);
   4440 defineSymbol(text$1, main, textord, "\u0153", "\\oe", true);
   4441 defineSymbol(text$1, main, textord, "\u00f8", "\\o", true);
   4442 defineSymbol(text$1, main, textord, "\u00c6", "\\AE", true);
   4443 defineSymbol(text$1, main, textord, "\u0152", "\\OE", true);
   4444 defineSymbol(text$1, main, textord, "\u00d8", "\\O", true);
   4445 defineSymbol(text$1, main, accent, "\u02ca", "\\'"); // acute
   4446 
   4447 defineSymbol(text$1, main, accent, "\u02cb", "\\`"); // grave
   4448 
   4449 defineSymbol(text$1, main, accent, "\u02c6", "\\^"); // circumflex
   4450 
   4451 defineSymbol(text$1, main, accent, "\u02dc", "\\~"); // tilde
   4452 
   4453 defineSymbol(text$1, main, accent, "\u02c9", "\\="); // macron
   4454 
   4455 defineSymbol(text$1, main, accent, "\u02d8", "\\u"); // breve
   4456 
   4457 defineSymbol(text$1, main, accent, "\u02d9", "\\."); // dot above
   4458 
   4459 defineSymbol(text$1, main, accent, "\u02da", "\\r"); // ring above
   4460 
   4461 defineSymbol(text$1, main, accent, "\u02c7", "\\v"); // caron
   4462 
   4463 defineSymbol(text$1, main, accent, "\u00a8", '\\"'); // diaresis
   4464 
   4465 defineSymbol(text$1, main, accent, "\u02dd", "\\H"); // double acute
   4466 
   4467 defineSymbol(text$1, main, accent, "\u25ef", "\\textcircled"); // \bigcirc glyph
   4468 // These ligatures are detected and created in Parser.js's `formLigatures`.
   4469 
   4470 var ligatures = {
   4471   "--": true,
   4472   "---": true,
   4473   "``": true,
   4474   "''": true
   4475 };
   4476 defineSymbol(text$1, main, textord, "\u2013", "--", true);
   4477 defineSymbol(text$1, main, textord, "\u2013", "\\textendash");
   4478 defineSymbol(text$1, main, textord, "\u2014", "---", true);
   4479 defineSymbol(text$1, main, textord, "\u2014", "\\textemdash");
   4480 defineSymbol(text$1, main, textord, "\u2018", "`", true);
   4481 defineSymbol(text$1, main, textord, "\u2018", "\\textquoteleft");
   4482 defineSymbol(text$1, main, textord, "\u2019", "'", true);
   4483 defineSymbol(text$1, main, textord, "\u2019", "\\textquoteright");
   4484 defineSymbol(text$1, main, textord, "\u201c", "``", true);
   4485 defineSymbol(text$1, main, textord, "\u201c", "\\textquotedblleft");
   4486 defineSymbol(text$1, main, textord, "\u201d", "''", true);
   4487 defineSymbol(text$1, main, textord, "\u201d", "\\textquotedblright"); //  \degree from gensymb package
   4488 
   4489 defineSymbol(math, main, textord, "\u00b0", "\\degree", true);
   4490 defineSymbol(text$1, main, textord, "\u00b0", "\\degree"); // \textdegree from inputenc package
   4491 
   4492 defineSymbol(text$1, main, textord, "\u00b0", "\\textdegree", true); // TODO: In LaTeX, \pounds can generate a different character in text and math
   4493 // mode, but among our fonts, only Main-Regular defines this character "163".
   4494 
   4495 defineSymbol(math, main, textord, "\u00a3", "\\pounds");
   4496 defineSymbol(math, main, textord, "\u00a3", "\\mathsterling", true);
   4497 defineSymbol(text$1, main, textord, "\u00a3", "\\pounds");
   4498 defineSymbol(text$1, main, textord, "\u00a3", "\\textsterling", true);
   4499 defineSymbol(math, ams, textord, "\u2720", "\\maltese");
   4500 defineSymbol(text$1, ams, textord, "\u2720", "\\maltese"); // There are lots of symbols which are the same, so we add them in afterwards.
   4501 // All of these are textords in math mode
   4502 
   4503 var mathTextSymbols = "0123456789/@.\"";
   4504 
   4505 for (var i = 0; i < mathTextSymbols.length; i++) {
   4506   var ch = mathTextSymbols.charAt(i);
   4507   defineSymbol(math, main, textord, ch, ch);
   4508 } // All of these are textords in text mode
   4509 
   4510 
   4511 var textSymbols = "0123456789!@*()-=+\";:?/.,";
   4512 
   4513 for (var _i = 0; _i < textSymbols.length; _i++) {
   4514   var _ch = textSymbols.charAt(_i);
   4515 
   4516   defineSymbol(text$1, main, textord, _ch, _ch);
   4517 } // All of these are textords in text mode, and mathords in math mode
   4518 
   4519 
   4520 var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
   4521 
   4522 for (var _i2 = 0; _i2 < letters.length; _i2++) {
   4523   var _ch2 = letters.charAt(_i2);
   4524 
   4525   defineSymbol(math, main, mathord, _ch2, _ch2);
   4526   defineSymbol(text$1, main, textord, _ch2, _ch2);
   4527 } // Blackboard bold and script letters in Unicode range
   4528 
   4529 
   4530 defineSymbol(math, ams, textord, "C", "\u2102"); // blackboard bold
   4531 
   4532 defineSymbol(text$1, ams, textord, "C", "\u2102");
   4533 defineSymbol(math, ams, textord, "H", "\u210D");
   4534 defineSymbol(text$1, ams, textord, "H", "\u210D");
   4535 defineSymbol(math, ams, textord, "N", "\u2115");
   4536 defineSymbol(text$1, ams, textord, "N", "\u2115");
   4537 defineSymbol(math, ams, textord, "P", "\u2119");
   4538 defineSymbol(text$1, ams, textord, "P", "\u2119");
   4539 defineSymbol(math, ams, textord, "Q", "\u211A");
   4540 defineSymbol(text$1, ams, textord, "Q", "\u211A");
   4541 defineSymbol(math, ams, textord, "R", "\u211D");
   4542 defineSymbol(text$1, ams, textord, "R", "\u211D");
   4543 defineSymbol(math, ams, textord, "Z", "\u2124");
   4544 defineSymbol(text$1, ams, textord, "Z", "\u2124");
   4545 defineSymbol(math, main, mathord, "h", "\u210E"); // italic h, Planck constant
   4546 
   4547 defineSymbol(text$1, main, mathord, "h", "\u210E"); // The next loop loads wide (surrogate pair) characters.
   4548 // We support some letters in the Unicode range U+1D400 to U+1D7FF,
   4549 // Mathematical Alphanumeric Symbols.
   4550 // Some editors do not deal well with wide characters. So don't write the
   4551 // string into this file. Instead, create the string from the surrogate pair.
   4552 
   4553 var wideChar = "";
   4554 
   4555 for (var _i3 = 0; _i3 < letters.length; _i3++) {
   4556   var _ch3 = letters.charAt(_i3); // The hex numbers in the next line are a surrogate pair.
   4557   // 0xD835 is the high surrogate for all letters in the range we support.
   4558   // 0xDC00 is the low surrogate for bold A.
   4559 
   4560 
   4561   wideChar = String.fromCharCode(0xD835, 0xDC00 + _i3); // A-Z a-z bold
   4562 
   4563   defineSymbol(math, main, mathord, _ch3, wideChar);
   4564   defineSymbol(text$1, main, textord, _ch3, wideChar);
   4565   wideChar = String.fromCharCode(0xD835, 0xDC34 + _i3); // A-Z a-z italic
   4566 
   4567   defineSymbol(math, main, mathord, _ch3, wideChar);
   4568   defineSymbol(text$1, main, textord, _ch3, wideChar);
   4569   wideChar = String.fromCharCode(0xD835, 0xDC68 + _i3); // A-Z a-z bold italic
   4570 
   4571   defineSymbol(math, main, mathord, _ch3, wideChar);
   4572   defineSymbol(text$1, main, textord, _ch3, wideChar);
   4573   wideChar = String.fromCharCode(0xD835, 0xDD04 + _i3); // A-Z a-z Fractur
   4574 
   4575   defineSymbol(math, main, mathord, _ch3, wideChar);
   4576   defineSymbol(text$1, main, textord, _ch3, wideChar);
   4577   wideChar = String.fromCharCode(0xD835, 0xDDA0 + _i3); // A-Z a-z sans-serif
   4578 
   4579   defineSymbol(math, main, mathord, _ch3, wideChar);
   4580   defineSymbol(text$1, main, textord, _ch3, wideChar);
   4581   wideChar = String.fromCharCode(0xD835, 0xDDD4 + _i3); // A-Z a-z sans bold
   4582 
   4583   defineSymbol(math, main, mathord, _ch3, wideChar);
   4584   defineSymbol(text$1, main, textord, _ch3, wideChar);
   4585   wideChar = String.fromCharCode(0xD835, 0xDE08 + _i3); // A-Z a-z sans italic
   4586 
   4587   defineSymbol(math, main, mathord, _ch3, wideChar);
   4588   defineSymbol(text$1, main, textord, _ch3, wideChar);
   4589   wideChar = String.fromCharCode(0xD835, 0xDE70 + _i3); // A-Z a-z monospace
   4590 
   4591   defineSymbol(math, main, mathord, _ch3, wideChar);
   4592   defineSymbol(text$1, main, textord, _ch3, wideChar);
   4593 
   4594   if (_i3 < 26) {
   4595     // KaTeX fonts have only capital letters for blackboard bold and script.
   4596     // See exception for k below.
   4597     wideChar = String.fromCharCode(0xD835, 0xDD38 + _i3); // A-Z double struck
   4598 
   4599     defineSymbol(math, main, mathord, _ch3, wideChar);
   4600     defineSymbol(text$1, main, textord, _ch3, wideChar);
   4601     wideChar = String.fromCharCode(0xD835, 0xDC9C + _i3); // A-Z script
   4602 
   4603     defineSymbol(math, main, mathord, _ch3, wideChar);
   4604     defineSymbol(text$1, main, textord, _ch3, wideChar);
   4605   } // TODO: Add bold script when it is supported by a KaTeX font.
   4606 
   4607 } // "k" is the only double struck lower case letter in the KaTeX fonts.
   4608 
   4609 
   4610 wideChar = String.fromCharCode(0xD835, 0xDD5C); // k double struck
   4611 
   4612 defineSymbol(math, main, mathord, "k", wideChar);
   4613 defineSymbol(text$1, main, textord, "k", wideChar); // Next, some wide character numerals
   4614 
   4615 for (var _i4 = 0; _i4 < 10; _i4++) {
   4616   var _ch4 = _i4.toString();
   4617 
   4618   wideChar = String.fromCharCode(0xD835, 0xDFCE + _i4); // 0-9 bold
   4619 
   4620   defineSymbol(math, main, mathord, _ch4, wideChar);
   4621   defineSymbol(text$1, main, textord, _ch4, wideChar);
   4622   wideChar = String.fromCharCode(0xD835, 0xDFE2 + _i4); // 0-9 sans serif
   4623 
   4624   defineSymbol(math, main, mathord, _ch4, wideChar);
   4625   defineSymbol(text$1, main, textord, _ch4, wideChar);
   4626   wideChar = String.fromCharCode(0xD835, 0xDFEC + _i4); // 0-9 bold sans
   4627 
   4628   defineSymbol(math, main, mathord, _ch4, wideChar);
   4629   defineSymbol(text$1, main, textord, _ch4, wideChar);
   4630   wideChar = String.fromCharCode(0xD835, 0xDFF6 + _i4); // 0-9 monospace
   4631 
   4632   defineSymbol(math, main, mathord, _ch4, wideChar);
   4633   defineSymbol(text$1, main, textord, _ch4, wideChar);
   4634 } // We add these Latin-1 letters as symbols for backwards-compatibility,
   4635 // but they are not actually in the font, nor are they supported by the
   4636 // Unicode accent mechanism, so they fall back to Times font and look ugly.
   4637 // TODO(edemaine): Fix this.
   4638 
   4639 
   4640 var extraLatin = "\u00c7\u00d0\u00de\u00e7\u00fe";
   4641 
   4642 for (var _i5 = 0; _i5 < extraLatin.length; _i5++) {
   4643   var _ch5 = extraLatin.charAt(_i5);
   4644 
   4645   defineSymbol(math, main, mathord, _ch5, _ch5);
   4646   defineSymbol(text$1, main, textord, _ch5, _ch5);
   4647 }
   4648 
   4649 /**
   4650  * This file provides support for Unicode range U+1D400 to U+1D7FF,
   4651  * Mathematical Alphanumeric Symbols.
   4652  *
   4653  * Function wideCharacterFont takes a wide character as input and returns
   4654  * the font information necessary to render it properly.
   4655  */
   4656 /**
   4657  * Data below is from https://www.unicode.org/charts/PDF/U1D400.pdf
   4658  * That document sorts characters into groups by font type, say bold or italic.
   4659  *
   4660  * In the arrays below, each subarray consists three elements:
   4661  *      * The CSS class of that group when in math mode.
   4662  *      * The CSS class of that group when in text mode.
   4663  *      * The font name, so that KaTeX can get font metrics.
   4664  */
   4665 
   4666 var wideLatinLetterData = [["mathbf", "textbf", "Main-Bold"], // A-Z bold upright
   4667 ["mathbf", "textbf", "Main-Bold"], // a-z bold upright
   4668 ["mathnormal", "textit", "Math-Italic"], // A-Z italic
   4669 ["mathnormal", "textit", "Math-Italic"], // a-z italic
   4670 ["boldsymbol", "boldsymbol", "Main-BoldItalic"], // A-Z bold italic
   4671 ["boldsymbol", "boldsymbol", "Main-BoldItalic"], // a-z bold italic
   4672 // Map fancy A-Z letters to script, not calligraphic.
   4673 // This aligns with unicode-math and math fonts (except Cambria Math).
   4674 ["mathscr", "textscr", "Script-Regular"], // A-Z script
   4675 ["", "", ""], // a-z script.  No font
   4676 ["", "", ""], // A-Z bold script. No font
   4677 ["", "", ""], // a-z bold script. No font
   4678 ["mathfrak", "textfrak", "Fraktur-Regular"], // A-Z Fraktur
   4679 ["mathfrak", "textfrak", "Fraktur-Regular"], // a-z Fraktur
   4680 ["mathbb", "textbb", "AMS-Regular"], // A-Z double-struck
   4681 ["mathbb", "textbb", "AMS-Regular"], // k double-struck
   4682 ["", "", ""], // A-Z bold Fraktur No font metrics
   4683 ["", "", ""], // a-z bold Fraktur.   No font.
   4684 ["mathsf", "textsf", "SansSerif-Regular"], // A-Z sans-serif
   4685 ["mathsf", "textsf", "SansSerif-Regular"], // a-z sans-serif
   4686 ["mathboldsf", "textboldsf", "SansSerif-Bold"], // A-Z bold sans-serif
   4687 ["mathboldsf", "textboldsf", "SansSerif-Bold"], // a-z bold sans-serif
   4688 ["mathitsf", "textitsf", "SansSerif-Italic"], // A-Z italic sans-serif
   4689 ["mathitsf", "textitsf", "SansSerif-Italic"], // a-z italic sans-serif
   4690 ["", "", ""], // A-Z bold italic sans. No font
   4691 ["", "", ""], // a-z bold italic sans. No font
   4692 ["mathtt", "texttt", "Typewriter-Regular"], // A-Z monospace
   4693 ["mathtt", "texttt", "Typewriter-Regular"] // a-z monospace
   4694 ];
   4695 var wideNumeralData = [["mathbf", "textbf", "Main-Bold"], // 0-9 bold
   4696 ["", "", ""], // 0-9 double-struck. No KaTeX font.
   4697 ["mathsf", "textsf", "SansSerif-Regular"], // 0-9 sans-serif
   4698 ["mathboldsf", "textboldsf", "SansSerif-Bold"], // 0-9 bold sans-serif
   4699 ["mathtt", "texttt", "Typewriter-Regular"] // 0-9 monospace
   4700 ];
   4701 var wideCharacterFont = function wideCharacterFont(wideChar, mode) {
   4702   // IE doesn't support codePointAt(). So work with the surrogate pair.
   4703   var H = wideChar.charCodeAt(0); // high surrogate
   4704 
   4705   var L = wideChar.charCodeAt(1); // low surrogate
   4706 
   4707   var codePoint = (H - 0xD800) * 0x400 + (L - 0xDC00) + 0x10000;
   4708   var j = mode === "math" ? 0 : 1; // column index for CSS class.
   4709 
   4710   if (0x1D400 <= codePoint && codePoint < 0x1D6A4) {
   4711     // wideLatinLetterData contains exactly 26 chars on each row.
   4712     // So we can calculate the relevant row. No traverse necessary.
   4713     var i = Math.floor((codePoint - 0x1D400) / 26);
   4714     return [wideLatinLetterData[i][2], wideLatinLetterData[i][j]];
   4715   } else if (0x1D7CE <= codePoint && codePoint <= 0x1D7FF) {
   4716     // Numerals, ten per row.
   4717     var _i = Math.floor((codePoint - 0x1D7CE) / 10);
   4718 
   4719     return [wideNumeralData[_i][2], wideNumeralData[_i][j]];
   4720   } else if (codePoint === 0x1D6A5 || codePoint === 0x1D6A6) {
   4721     // dotless i or j
   4722     return [wideLatinLetterData[0][2], wideLatinLetterData[0][j]];
   4723   } else if (0x1D6A6 < codePoint && codePoint < 0x1D7CE) {
   4724     // Greek letters. Not supported, yet.
   4725     return ["", ""];
   4726   } else {
   4727     // We don't support any wide characters outside 1D400–1D7FF.
   4728     throw new ParseError("Unsupported character: " + wideChar);
   4729   }
   4730 };
   4731 
   4732 /**
   4733  * This file contains information about the options that the Parser carries
   4734  * around with it while parsing. Data is held in an `Options` object, and when
   4735  * recursing, a new `Options` object can be created with the `.with*` and
   4736  * `.reset` functions.
   4737  */
   4738 var sizeStyleMap = [// Each element contains [textsize, scriptsize, scriptscriptsize].
   4739 // The size mappings are taken from TeX with \normalsize=10pt.
   4740 [1, 1, 1], // size1: [5, 5, 5]              \tiny
   4741 [2, 1, 1], // size2: [6, 5, 5]
   4742 [3, 1, 1], // size3: [7, 5, 5]              \scriptsize
   4743 [4, 2, 1], // size4: [8, 6, 5]              \footnotesize
   4744 [5, 2, 1], // size5: [9, 6, 5]              \small
   4745 [6, 3, 1], // size6: [10, 7, 5]             \normalsize
   4746 [7, 4, 2], // size7: [12, 8, 6]             \large
   4747 [8, 6, 3], // size8: [14.4, 10, 7]          \Large
   4748 [9, 7, 6], // size9: [17.28, 12, 10]        \LARGE
   4749 [10, 8, 7], // size10: [20.74, 14.4, 12]     \huge
   4750 [11, 10, 9] // size11: [24.88, 20.74, 17.28] \HUGE
   4751 ];
   4752 var sizeMultipliers = [// fontMetrics.js:getGlobalMetrics also uses size indexes, so if
   4753 // you change size indexes, change that function.
   4754 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.2, 1.44, 1.728, 2.074, 2.488];
   4755 
   4756 var sizeAtStyle = function sizeAtStyle(size, style) {
   4757   return style.size < 2 ? size : sizeStyleMap[size - 1][style.size - 1];
   4758 }; // In these types, "" (empty string) means "no change".
   4759 
   4760 
   4761 /**
   4762  * This is the main options class. It contains the current style, size, color,
   4763  * and font.
   4764  *
   4765  * Options objects should not be modified. To create a new Options with
   4766  * different properties, call a `.having*` method.
   4767  */
   4768 class Options {
   4769   // A font family applies to a group of fonts (i.e. SansSerif), while a font
   4770   // represents a specific font (i.e. SansSerif Bold).
   4771   // See: https://tex.stackexchange.com/questions/22350/difference-between-textrm-and-mathrm
   4772 
   4773   /**
   4774    * The base size index.
   4775    */
   4776   constructor(data) {
   4777     this.style = void 0;
   4778     this.color = void 0;
   4779     this.size = void 0;
   4780     this.textSize = void 0;
   4781     this.phantom = void 0;
   4782     this.font = void 0;
   4783     this.fontFamily = void 0;
   4784     this.fontWeight = void 0;
   4785     this.fontShape = void 0;
   4786     this.sizeMultiplier = void 0;
   4787     this.maxSize = void 0;
   4788     this.minRuleThickness = void 0;
   4789     this._fontMetrics = void 0;
   4790     this.style = data.style;
   4791     this.color = data.color;
   4792     this.size = data.size || Options.BASESIZE;
   4793     this.textSize = data.textSize || this.size;
   4794     this.phantom = !!data.phantom;
   4795     this.font = data.font || "";
   4796     this.fontFamily = data.fontFamily || "";
   4797     this.fontWeight = data.fontWeight || '';
   4798     this.fontShape = data.fontShape || '';
   4799     this.sizeMultiplier = sizeMultipliers[this.size - 1];
   4800     this.maxSize = data.maxSize;
   4801     this.minRuleThickness = data.minRuleThickness;
   4802     this._fontMetrics = undefined;
   4803   }
   4804   /**
   4805    * Returns a new options object with the same properties as "this".  Properties
   4806    * from "extension" will be copied to the new options object.
   4807    */
   4808 
   4809 
   4810   extend(extension) {
   4811     var data = {
   4812       style: this.style,
   4813       size: this.size,
   4814       textSize: this.textSize,
   4815       color: this.color,
   4816       phantom: this.phantom,
   4817       font: this.font,
   4818       fontFamily: this.fontFamily,
   4819       fontWeight: this.fontWeight,
   4820       fontShape: this.fontShape,
   4821       maxSize: this.maxSize,
   4822       minRuleThickness: this.minRuleThickness
   4823     };
   4824 
   4825     for (var key in extension) {
   4826       if (extension.hasOwnProperty(key)) {
   4827         data[key] = extension[key];
   4828       }
   4829     }
   4830 
   4831     return new Options(data);
   4832   }
   4833   /**
   4834    * Return an options object with the given style. If `this.style === style`,
   4835    * returns `this`.
   4836    */
   4837 
   4838 
   4839   havingStyle(style) {
   4840     if (this.style === style) {
   4841       return this;
   4842     } else {
   4843       return this.extend({
   4844         style: style,
   4845         size: sizeAtStyle(this.textSize, style)
   4846       });
   4847     }
   4848   }
   4849   /**
   4850    * Return an options object with a cramped version of the current style. If
   4851    * the current style is cramped, returns `this`.
   4852    */
   4853 
   4854 
   4855   havingCrampedStyle() {
   4856     return this.havingStyle(this.style.cramp());
   4857   }
   4858   /**
   4859    * Return an options object with the given size and in at least `\textstyle`.
   4860    * Returns `this` if appropriate.
   4861    */
   4862 
   4863 
   4864   havingSize(size) {
   4865     if (this.size === size && this.textSize === size) {
   4866       return this;
   4867     } else {
   4868       return this.extend({
   4869         style: this.style.text(),
   4870         size: size,
   4871         textSize: size,
   4872         sizeMultiplier: sizeMultipliers[size - 1]
   4873       });
   4874     }
   4875   }
   4876   /**
   4877    * Like `this.havingSize(BASESIZE).havingStyle(style)`. If `style` is omitted,
   4878    * changes to at least `\textstyle`.
   4879    */
   4880 
   4881 
   4882   havingBaseStyle(style) {
   4883     style = style || this.style.text();
   4884     var wantSize = sizeAtStyle(Options.BASESIZE, style);
   4885 
   4886     if (this.size === wantSize && this.textSize === Options.BASESIZE && this.style === style) {
   4887       return this;
   4888     } else {
   4889       return this.extend({
   4890         style: style,
   4891         size: wantSize
   4892       });
   4893     }
   4894   }
   4895   /**
   4896    * Remove the effect of sizing changes such as \Huge.
   4897    * Keep the effect of the current style, such as \scriptstyle.
   4898    */
   4899 
   4900 
   4901   havingBaseSizing() {
   4902     var size;
   4903 
   4904     switch (this.style.id) {
   4905       case 4:
   4906       case 5:
   4907         size = 3; // normalsize in scriptstyle
   4908 
   4909         break;
   4910 
   4911       case 6:
   4912       case 7:
   4913         size = 1; // normalsize in scriptscriptstyle
   4914 
   4915         break;
   4916 
   4917       default:
   4918         size = 6;
   4919       // normalsize in textstyle or displaystyle
   4920     }
   4921 
   4922     return this.extend({
   4923       style: this.style.text(),
   4924       size: size
   4925     });
   4926   }
   4927   /**
   4928    * Create a new options object with the given color.
   4929    */
   4930 
   4931 
   4932   withColor(color) {
   4933     return this.extend({
   4934       color: color
   4935     });
   4936   }
   4937   /**
   4938    * Create a new options object with "phantom" set to true.
   4939    */
   4940 
   4941 
   4942   withPhantom() {
   4943     return this.extend({
   4944       phantom: true
   4945     });
   4946   }
   4947   /**
   4948    * Creates a new options object with the given math font or old text font.
   4949    * @type {[type]}
   4950    */
   4951 
   4952 
   4953   withFont(font) {
   4954     return this.extend({
   4955       font
   4956     });
   4957   }
   4958   /**
   4959    * Create a new options objects with the given fontFamily.
   4960    */
   4961 
   4962 
   4963   withTextFontFamily(fontFamily) {
   4964     return this.extend({
   4965       fontFamily,
   4966       font: ""
   4967     });
   4968   }
   4969   /**
   4970    * Creates a new options object with the given font weight
   4971    */
   4972 
   4973 
   4974   withTextFontWeight(fontWeight) {
   4975     return this.extend({
   4976       fontWeight,
   4977       font: ""
   4978     });
   4979   }
   4980   /**
   4981    * Creates a new options object with the given font weight
   4982    */
   4983 
   4984 
   4985   withTextFontShape(fontShape) {
   4986     return this.extend({
   4987       fontShape,
   4988       font: ""
   4989     });
   4990   }
   4991   /**
   4992    * Return the CSS sizing classes required to switch from enclosing options
   4993    * `oldOptions` to `this`. Returns an array of classes.
   4994    */
   4995 
   4996 
   4997   sizingClasses(oldOptions) {
   4998     if (oldOptions.size !== this.size) {
   4999       return ["sizing", "reset-size" + oldOptions.size, "size" + this.size];
   5000     } else {
   5001       return [];
   5002     }
   5003   }
   5004   /**
   5005    * Return the CSS sizing classes required to switch to the base size. Like
   5006    * `this.havingSize(BASESIZE).sizingClasses(this)`.
   5007    */
   5008 
   5009 
   5010   baseSizingClasses() {
   5011     if (this.size !== Options.BASESIZE) {
   5012       return ["sizing", "reset-size" + this.size, "size" + Options.BASESIZE];
   5013     } else {
   5014       return [];
   5015     }
   5016   }
   5017   /**
   5018    * Return the font metrics for this size.
   5019    */
   5020 
   5021 
   5022   fontMetrics() {
   5023     if (!this._fontMetrics) {
   5024       this._fontMetrics = getGlobalMetrics(this.size);
   5025     }
   5026 
   5027     return this._fontMetrics;
   5028   }
   5029   /**
   5030    * Gets the CSS color of the current options object
   5031    */
   5032 
   5033 
   5034   getColor() {
   5035     if (this.phantom) {
   5036       return "transparent";
   5037     } else {
   5038       return this.color;
   5039     }
   5040   }
   5041 
   5042 }
   5043 
   5044 Options.BASESIZE = 6;
   5045 
   5046 /**
   5047  * This file does conversion between units.  In particular, it provides
   5048  * calculateSize to convert other units into ems.
   5049  */
   5050 // Thus, multiplying a length by this number converts the length from units
   5051 // into pts.  Dividing the result by ptPerEm gives the number of ems
   5052 // *assuming* a font size of ptPerEm (normal size, normal style).
   5053 
   5054 var ptPerUnit = {
   5055   // https://en.wikibooks.org/wiki/LaTeX/Lengths and
   5056   // https://tex.stackexchange.com/a/8263
   5057   "pt": 1,
   5058   // TeX point
   5059   "mm": 7227 / 2540,
   5060   // millimeter
   5061   "cm": 7227 / 254,
   5062   // centimeter
   5063   "in": 72.27,
   5064   // inch
   5065   "bp": 803 / 800,
   5066   // big (PostScript) points
   5067   "pc": 12,
   5068   // pica
   5069   "dd": 1238 / 1157,
   5070   // didot
   5071   "cc": 14856 / 1157,
   5072   // cicero (12 didot)
   5073   "nd": 685 / 642,
   5074   // new didot
   5075   "nc": 1370 / 107,
   5076   // new cicero (12 new didot)
   5077   "sp": 1 / 65536,
   5078   // scaled point (TeX's internal smallest unit)
   5079   // https://tex.stackexchange.com/a/41371
   5080   "px": 803 / 800 // \pdfpxdimen defaults to 1 bp in pdfTeX and LuaTeX
   5081 
   5082 }; // Dictionary of relative units, for fast validity testing.
   5083 
   5084 var relativeUnit = {
   5085   "ex": true,
   5086   "em": true,
   5087   "mu": true
   5088 };
   5089 
   5090 /**
   5091  * Determine whether the specified unit (either a string defining the unit
   5092  * or a "size" parse node containing a unit field) is valid.
   5093  */
   5094 var validUnit = function validUnit(unit) {
   5095   if (typeof unit !== "string") {
   5096     unit = unit.unit;
   5097   }
   5098 
   5099   return unit in ptPerUnit || unit in relativeUnit || unit === "ex";
   5100 };
   5101 /*
   5102  * Convert a "size" parse node (with numeric "number" and string "unit" fields,
   5103  * as parsed by functions.js argType "size") into a CSS em value for the
   5104  * current style/scale.  `options` gives the current options.
   5105  */
   5106 
   5107 var calculateSize = function calculateSize(sizeValue, options) {
   5108   var scale;
   5109 
   5110   if (sizeValue.unit in ptPerUnit) {
   5111     // Absolute units
   5112     scale = ptPerUnit[sizeValue.unit] // Convert unit to pt
   5113     / options.fontMetrics().ptPerEm // Convert pt to CSS em
   5114     / options.sizeMultiplier; // Unscale to make absolute units
   5115   } else if (sizeValue.unit === "mu") {
   5116     // `mu` units scale with scriptstyle/scriptscriptstyle.
   5117     scale = options.fontMetrics().cssEmPerMu;
   5118   } else {
   5119     // Other relative units always refer to the *textstyle* font
   5120     // in the current size.
   5121     var unitOptions;
   5122 
   5123     if (options.style.isTight()) {
   5124       // isTight() means current style is script/scriptscript.
   5125       unitOptions = options.havingStyle(options.style.text());
   5126     } else {
   5127       unitOptions = options;
   5128     } // TODO: In TeX these units are relative to the quad of the current
   5129     // *text* font, e.g. cmr10. KaTeX instead uses values from the
   5130     // comparably-sized *Computer Modern symbol* font. At 10pt, these
   5131     // match. At 7pt and 5pt, they differ: cmr7=1.138894, cmsy7=1.170641;
   5132     // cmr5=1.361133, cmsy5=1.472241. Consider $\scriptsize a\kern1emb$.
   5133     // TeX \showlists shows a kern of 1.13889 * fontsize;
   5134     // KaTeX shows a kern of 1.171 * fontsize.
   5135 
   5136 
   5137     if (sizeValue.unit === "ex") {
   5138       scale = unitOptions.fontMetrics().xHeight;
   5139     } else if (sizeValue.unit === "em") {
   5140       scale = unitOptions.fontMetrics().quad;
   5141     } else {
   5142       throw new ParseError("Invalid unit: '" + sizeValue.unit + "'");
   5143     }
   5144 
   5145     if (unitOptions !== options) {
   5146       scale *= unitOptions.sizeMultiplier / options.sizeMultiplier;
   5147     }
   5148   }
   5149 
   5150   return Math.min(sizeValue.number * scale, options.maxSize);
   5151 };
   5152 
   5153 /* eslint no-console:0 */
   5154 
   5155 /**
   5156  * Looks up the given symbol in fontMetrics, after applying any symbol
   5157  * replacements defined in symbol.js
   5158  */
   5159 var lookupSymbol = function lookupSymbol(value, // TODO(#963): Use a union type for this.
   5160 fontName, mode) {
   5161   // Replace the value with its replaced value from symbol.js
   5162   if (symbols[mode][value] && symbols[mode][value].replace) {
   5163     value = symbols[mode][value].replace;
   5164   }
   5165 
   5166   return {
   5167     value: value,
   5168     metrics: getCharacterMetrics(value, fontName, mode)
   5169   };
   5170 };
   5171 /**
   5172  * Makes a symbolNode after translation via the list of symbols in symbols.js.
   5173  * Correctly pulls out metrics for the character, and optionally takes a list of
   5174  * classes to be attached to the node.
   5175  *
   5176  * TODO: make argument order closer to makeSpan
   5177  * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which
   5178  * should if present come first in `classes`.
   5179  * TODO(#953): Make `options` mandatory and always pass it in.
   5180  */
   5181 
   5182 
   5183 var makeSymbol = function makeSymbol(value, fontName, mode, options, classes) {
   5184   var lookup = lookupSymbol(value, fontName, mode);
   5185   var metrics = lookup.metrics;
   5186   value = lookup.value;
   5187   var symbolNode;
   5188 
   5189   if (metrics) {
   5190     var italic = metrics.italic;
   5191 
   5192     if (mode === "text" || options && options.font === "mathit") {
   5193       italic = 0;
   5194     }
   5195 
   5196     symbolNode = new SymbolNode(value, metrics.height, metrics.depth, italic, metrics.skew, metrics.width, classes);
   5197   } else {
   5198     // TODO(emily): Figure out a good way to only print this in development
   5199     typeof console !== "undefined" && console.warn("No character metrics " + ("for '" + value + "' in style '" + fontName + "' and mode '" + mode + "'"));
   5200     symbolNode = new SymbolNode(value, 0, 0, 0, 0, 0, classes);
   5201   }
   5202 
   5203   if (options) {
   5204     symbolNode.maxFontSize = options.sizeMultiplier;
   5205 
   5206     if (options.style.isTight()) {
   5207       symbolNode.classes.push("mtight");
   5208     }
   5209 
   5210     var color = options.getColor();
   5211 
   5212     if (color) {
   5213       symbolNode.style.color = color;
   5214     }
   5215   }
   5216 
   5217   return symbolNode;
   5218 };
   5219 /**
   5220  * Makes a symbol in Main-Regular or AMS-Regular.
   5221  * Used for rel, bin, open, close, inner, and punct.
   5222  */
   5223 
   5224 
   5225 var mathsym = function mathsym(value, mode, options, classes) {
   5226   if (classes === void 0) {
   5227     classes = [];
   5228   }
   5229 
   5230   // Decide what font to render the symbol in by its entry in the symbols
   5231   // table.
   5232   // Have a special case for when the value = \ because the \ is used as a
   5233   // textord in unsupported command errors but cannot be parsed as a regular
   5234   // text ordinal and is therefore not present as a symbol in the symbols
   5235   // table for text, as well as a special case for boldsymbol because it
   5236   // can be used for bold + and -
   5237   if (options.font === "boldsymbol" && lookupSymbol(value, "Main-Bold", mode).metrics) {
   5238     return makeSymbol(value, "Main-Bold", mode, options, classes.concat(["mathbf"]));
   5239   } else if (value === "\\" || symbols[mode][value].font === "main") {
   5240     return makeSymbol(value, "Main-Regular", mode, options, classes);
   5241   } else {
   5242     return makeSymbol(value, "AMS-Regular", mode, options, classes.concat(["amsrm"]));
   5243   }
   5244 };
   5245 /**
   5246  * Determines which of the two font names (Main-Bold and Math-BoldItalic) and
   5247  * corresponding style tags (mathbf or boldsymbol) to use for font "boldsymbol",
   5248  * depending on the symbol.  Use this function instead of fontMap for font
   5249  * "boldsymbol".
   5250  */
   5251 
   5252 
   5253 var boldsymbol = function boldsymbol(value, mode, options, classes, type) {
   5254   if (type !== "textord" && lookupSymbol(value, "Math-BoldItalic", mode).metrics) {
   5255     return {
   5256       fontName: "Math-BoldItalic",
   5257       fontClass: "boldsymbol"
   5258     };
   5259   } else {
   5260     // Some glyphs do not exist in Math-BoldItalic so we need to use
   5261     // Main-Bold instead.
   5262     return {
   5263       fontName: "Main-Bold",
   5264       fontClass: "mathbf"
   5265     };
   5266   }
   5267 };
   5268 /**
   5269  * Makes either a mathord or textord in the correct font and color.
   5270  */
   5271 
   5272 
   5273 var makeOrd = function makeOrd(group, options, type) {
   5274   var mode = group.mode;
   5275   var text = group.text;
   5276   var classes = ["mord"]; // Math mode or Old font (i.e. \rm)
   5277 
   5278   var isFont = mode === "math" || mode === "text" && options.font;
   5279   var fontOrFamily = isFont ? options.font : options.fontFamily;
   5280 
   5281   if (text.charCodeAt(0) === 0xD835) {
   5282     // surrogate pairs get special treatment
   5283     var [wideFontName, wideFontClass] = wideCharacterFont(text, mode);
   5284     return makeSymbol(text, wideFontName, mode, options, classes.concat(wideFontClass));
   5285   } else if (fontOrFamily) {
   5286     var fontName;
   5287     var fontClasses;
   5288 
   5289     if (fontOrFamily === "boldsymbol") {
   5290       var fontData = boldsymbol(text, mode, options, classes, type);
   5291       fontName = fontData.fontName;
   5292       fontClasses = [fontData.fontClass];
   5293     } else if (isFont) {
   5294       fontName = fontMap[fontOrFamily].fontName;
   5295       fontClasses = [fontOrFamily];
   5296     } else {
   5297       fontName = retrieveTextFontName(fontOrFamily, options.fontWeight, options.fontShape);
   5298       fontClasses = [fontOrFamily, options.fontWeight, options.fontShape];
   5299     }
   5300 
   5301     if (lookupSymbol(text, fontName, mode).metrics) {
   5302       return makeSymbol(text, fontName, mode, options, classes.concat(fontClasses));
   5303     } else if (ligatures.hasOwnProperty(text) && fontName.substr(0, 10) === "Typewriter") {
   5304       // Deconstruct ligatures in monospace fonts (\texttt, \tt).
   5305       var parts = [];
   5306 
   5307       for (var i = 0; i < text.length; i++) {
   5308         parts.push(makeSymbol(text[i], fontName, mode, options, classes.concat(fontClasses)));
   5309       }
   5310 
   5311       return makeFragment(parts);
   5312     }
   5313   } // Makes a symbol in the default font for mathords and textords.
   5314 
   5315 
   5316   if (type === "mathord") {
   5317     return makeSymbol(text, "Math-Italic", mode, options, classes.concat(["mathnormal"]));
   5318   } else if (type === "textord") {
   5319     var font = symbols[mode][text] && symbols[mode][text].font;
   5320 
   5321     if (font === "ams") {
   5322       var _fontName = retrieveTextFontName("amsrm", options.fontWeight, options.fontShape);
   5323 
   5324       return makeSymbol(text, _fontName, mode, options, classes.concat("amsrm", options.fontWeight, options.fontShape));
   5325     } else if (font === "main" || !font) {
   5326       var _fontName2 = retrieveTextFontName("textrm", options.fontWeight, options.fontShape);
   5327 
   5328       return makeSymbol(text, _fontName2, mode, options, classes.concat(options.fontWeight, options.fontShape));
   5329     } else {
   5330       // fonts added by plugins
   5331       var _fontName3 = retrieveTextFontName(font, options.fontWeight, options.fontShape); // We add font name as a css class
   5332 
   5333 
   5334       return makeSymbol(text, _fontName3, mode, options, classes.concat(_fontName3, options.fontWeight, options.fontShape));
   5335     }
   5336   } else {
   5337     throw new Error("unexpected type: " + type + " in makeOrd");
   5338   }
   5339 };
   5340 /**
   5341  * Returns true if subsequent symbolNodes have the same classes, skew, maxFont,
   5342  * and styles.
   5343  */
   5344 
   5345 
   5346 var canCombine = (prev, next) => {
   5347   if (createClass(prev.classes) !== createClass(next.classes) || prev.skew !== next.skew || prev.maxFontSize !== next.maxFontSize) {
   5348     return false;
   5349   } // If prev and next both are just "mbin"s or "mord"s we don't combine them
   5350   // so that the proper spacing can be preserved.
   5351 
   5352 
   5353   if (prev.classes.length === 1) {
   5354     var cls = prev.classes[0];
   5355 
   5356     if (cls === "mbin" || cls === "mord") {
   5357       return false;
   5358     }
   5359   }
   5360 
   5361   for (var style in prev.style) {
   5362     if (prev.style.hasOwnProperty(style) && prev.style[style] !== next.style[style]) {
   5363       return false;
   5364     }
   5365   }
   5366 
   5367   for (var _style in next.style) {
   5368     if (next.style.hasOwnProperty(_style) && prev.style[_style] !== next.style[_style]) {
   5369       return false;
   5370     }
   5371   }
   5372 
   5373   return true;
   5374 };
   5375 /**
   5376  * Combine consecutive domTree.symbolNodes into a single symbolNode.
   5377  * Note: this function mutates the argument.
   5378  */
   5379 
   5380 
   5381 var tryCombineChars = chars => {
   5382   for (var i = 0; i < chars.length - 1; i++) {
   5383     var prev = chars[i];
   5384     var next = chars[i + 1];
   5385 
   5386     if (prev instanceof SymbolNode && next instanceof SymbolNode && canCombine(prev, next)) {
   5387       prev.text += next.text;
   5388       prev.height = Math.max(prev.height, next.height);
   5389       prev.depth = Math.max(prev.depth, next.depth); // Use the last character's italic correction since we use
   5390       // it to add padding to the right of the span created from
   5391       // the combined characters.
   5392 
   5393       prev.italic = next.italic;
   5394       chars.splice(i + 1, 1);
   5395       i--;
   5396     }
   5397   }
   5398 
   5399   return chars;
   5400 };
   5401 /**
   5402  * Calculate the height, depth, and maxFontSize of an element based on its
   5403  * children.
   5404  */
   5405 
   5406 
   5407 var sizeElementFromChildren = function sizeElementFromChildren(elem) {
   5408   var height = 0;
   5409   var depth = 0;
   5410   var maxFontSize = 0;
   5411 
   5412   for (var i = 0; i < elem.children.length; i++) {
   5413     var child = elem.children[i];
   5414 
   5415     if (child.height > height) {
   5416       height = child.height;
   5417     }
   5418 
   5419     if (child.depth > depth) {
   5420       depth = child.depth;
   5421     }
   5422 
   5423     if (child.maxFontSize > maxFontSize) {
   5424       maxFontSize = child.maxFontSize;
   5425     }
   5426   }
   5427 
   5428   elem.height = height;
   5429   elem.depth = depth;
   5430   elem.maxFontSize = maxFontSize;
   5431 };
   5432 /**
   5433  * Makes a span with the given list of classes, list of children, and options.
   5434  *
   5435  * TODO(#953): Ensure that `options` is always provided (currently some call
   5436  * sites don't pass it) and make the type below mandatory.
   5437  * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which
   5438  * should if present come first in `classes`.
   5439  */
   5440 
   5441 
   5442 var makeSpan = function makeSpan(classes, children, options, style) {
   5443   var span = new Span(classes, children, options, style);
   5444   sizeElementFromChildren(span);
   5445   return span;
   5446 }; // SVG one is simpler -- doesn't require height, depth, max-font setting.
   5447 // This is also a separate method for typesafety.
   5448 
   5449 
   5450 var makeSvgSpan = (classes, children, options, style) => new Span(classes, children, options, style);
   5451 
   5452 var makeLineSpan = function makeLineSpan(className, options, thickness) {
   5453   var line = makeSpan([className], [], options);
   5454   line.height = Math.max(thickness || options.fontMetrics().defaultRuleThickness, options.minRuleThickness);
   5455   line.style.borderBottomWidth = line.height + "em";
   5456   line.maxFontSize = 1.0;
   5457   return line;
   5458 };
   5459 /**
   5460  * Makes an anchor with the given href, list of classes, list of children,
   5461  * and options.
   5462  */
   5463 
   5464 
   5465 var makeAnchor = function makeAnchor(href, classes, children, options) {
   5466   var anchor = new Anchor(href, classes, children, options);
   5467   sizeElementFromChildren(anchor);
   5468   return anchor;
   5469 };
   5470 /**
   5471  * Makes a document fragment with the given list of children.
   5472  */
   5473 
   5474 
   5475 var makeFragment = function makeFragment(children) {
   5476   var fragment = new DocumentFragment(children);
   5477   sizeElementFromChildren(fragment);
   5478   return fragment;
   5479 };
   5480 /**
   5481  * Wraps group in a span if it's a document fragment, allowing to apply classes
   5482  * and styles
   5483  */
   5484 
   5485 
   5486 var wrapFragment = function wrapFragment(group, options) {
   5487   if (group instanceof DocumentFragment) {
   5488     return makeSpan([], [group], options);
   5489   }
   5490 
   5491   return group;
   5492 }; // These are exact object types to catch typos in the names of the optional fields.
   5493 
   5494 
   5495 // Computes the updated `children` list and the overall depth.
   5496 //
   5497 // This helper function for makeVList makes it easier to enforce type safety by
   5498 // allowing early exits (returns) in the logic.
   5499 var getVListChildrenAndDepth = function getVListChildrenAndDepth(params) {
   5500   if (params.positionType === "individualShift") {
   5501     var oldChildren = params.children;
   5502     var children = [oldChildren[0]]; // Add in kerns to the list of params.children to get each element to be
   5503     // shifted to the correct specified shift
   5504 
   5505     var _depth = -oldChildren[0].shift - oldChildren[0].elem.depth;
   5506 
   5507     var currPos = _depth;
   5508 
   5509     for (var i = 1; i < oldChildren.length; i++) {
   5510       var diff = -oldChildren[i].shift - currPos - oldChildren[i].elem.depth;
   5511       var size = diff - (oldChildren[i - 1].elem.height + oldChildren[i - 1].elem.depth);
   5512       currPos = currPos + diff;
   5513       children.push({
   5514         type: "kern",
   5515         size
   5516       });
   5517       children.push(oldChildren[i]);
   5518     }
   5519 
   5520     return {
   5521       children,
   5522       depth: _depth
   5523     };
   5524   }
   5525 
   5526   var depth;
   5527 
   5528   if (params.positionType === "top") {
   5529     // We always start at the bottom, so calculate the bottom by adding up
   5530     // all the sizes
   5531     var bottom = params.positionData;
   5532 
   5533     for (var _i = 0; _i < params.children.length; _i++) {
   5534       var child = params.children[_i];
   5535       bottom -= child.type === "kern" ? child.size : child.elem.height + child.elem.depth;
   5536     }
   5537 
   5538     depth = bottom;
   5539   } else if (params.positionType === "bottom") {
   5540     depth = -params.positionData;
   5541   } else {
   5542     var firstChild = params.children[0];
   5543 
   5544     if (firstChild.type !== "elem") {
   5545       throw new Error('First child must have type "elem".');
   5546     }
   5547 
   5548     if (params.positionType === "shift") {
   5549       depth = -firstChild.elem.depth - params.positionData;
   5550     } else if (params.positionType === "firstBaseline") {
   5551       depth = -firstChild.elem.depth;
   5552     } else {
   5553       throw new Error("Invalid positionType " + params.positionType + ".");
   5554     }
   5555   }
   5556 
   5557   return {
   5558     children: params.children,
   5559     depth
   5560   };
   5561 };
   5562 /**
   5563  * Makes a vertical list by stacking elements and kerns on top of each other.
   5564  * Allows for many different ways of specifying the positioning method.
   5565  *
   5566  * See VListParam documentation above.
   5567  */
   5568 
   5569 
   5570 var makeVList = function makeVList(params, options) {
   5571   var {
   5572     children,
   5573     depth
   5574   } = getVListChildrenAndDepth(params); // Create a strut that is taller than any list item. The strut is added to
   5575   // each item, where it will determine the item's baseline. Since it has
   5576   // `overflow:hidden`, the strut's top edge will sit on the item's line box's
   5577   // top edge and the strut's bottom edge will sit on the item's baseline,
   5578   // with no additional line-height spacing. This allows the item baseline to
   5579   // be positioned precisely without worrying about font ascent and
   5580   // line-height.
   5581 
   5582   var pstrutSize = 0;
   5583 
   5584   for (var i = 0; i < children.length; i++) {
   5585     var child = children[i];
   5586 
   5587     if (child.type === "elem") {
   5588       var elem = child.elem;
   5589       pstrutSize = Math.max(pstrutSize, elem.maxFontSize, elem.height);
   5590     }
   5591   }
   5592 
   5593   pstrutSize += 2;
   5594   var pstrut = makeSpan(["pstrut"], []);
   5595   pstrut.style.height = pstrutSize + "em"; // Create a new list of actual children at the correct offsets
   5596 
   5597   var realChildren = [];
   5598   var minPos = depth;
   5599   var maxPos = depth;
   5600   var currPos = depth;
   5601 
   5602   for (var _i2 = 0; _i2 < children.length; _i2++) {
   5603     var _child = children[_i2];
   5604 
   5605     if (_child.type === "kern") {
   5606       currPos += _child.size;
   5607     } else {
   5608       var _elem = _child.elem;
   5609       var classes = _child.wrapperClasses || [];
   5610       var style = _child.wrapperStyle || {};
   5611       var childWrap = makeSpan(classes, [pstrut, _elem], undefined, style);
   5612       childWrap.style.top = -pstrutSize - currPos - _elem.depth + "em";
   5613 
   5614       if (_child.marginLeft) {
   5615         childWrap.style.marginLeft = _child.marginLeft;
   5616       }
   5617 
   5618       if (_child.marginRight) {
   5619         childWrap.style.marginRight = _child.marginRight;
   5620       }
   5621 
   5622       realChildren.push(childWrap);
   5623       currPos += _elem.height + _elem.depth;
   5624     }
   5625 
   5626     minPos = Math.min(minPos, currPos);
   5627     maxPos = Math.max(maxPos, currPos);
   5628   } // The vlist contents go in a table-cell with `vertical-align:bottom`.
   5629   // This cell's bottom edge will determine the containing table's baseline
   5630   // without overly expanding the containing line-box.
   5631 
   5632 
   5633   var vlist = makeSpan(["vlist"], realChildren);
   5634   vlist.style.height = maxPos + "em"; // A second row is used if necessary to represent the vlist's depth.
   5635 
   5636   var rows;
   5637 
   5638   if (minPos < 0) {
   5639     // We will define depth in an empty span with display: table-cell.
   5640     // It should render with the height that we define. But Chrome, in
   5641     // contenteditable mode only, treats that span as if it contains some
   5642     // text content. And that min-height over-rides our desired height.
   5643     // So we put another empty span inside the depth strut span.
   5644     var emptySpan = makeSpan([], []);
   5645     var depthStrut = makeSpan(["vlist"], [emptySpan]);
   5646     depthStrut.style.height = -minPos + "em"; // Safari wants the first row to have inline content; otherwise it
   5647     // puts the bottom of the *second* row on the baseline.
   5648 
   5649     var topStrut = makeSpan(["vlist-s"], [new SymbolNode("\u200b")]);
   5650     rows = [makeSpan(["vlist-r"], [vlist, topStrut]), makeSpan(["vlist-r"], [depthStrut])];
   5651   } else {
   5652     rows = [makeSpan(["vlist-r"], [vlist])];
   5653   }
   5654 
   5655   var vtable = makeSpan(["vlist-t"], rows);
   5656 
   5657   if (rows.length === 2) {
   5658     vtable.classes.push("vlist-t2");
   5659   }
   5660 
   5661   vtable.height = maxPos;
   5662   vtable.depth = -minPos;
   5663   return vtable;
   5664 }; // Glue is a concept from TeX which is a flexible space between elements in
   5665 // either a vertical or horizontal list. In KaTeX, at least for now, it's
   5666 // static space between elements in a horizontal layout.
   5667 
   5668 
   5669 var makeGlue = (measurement, options) => {
   5670   // Make an empty span for the space
   5671   var rule = makeSpan(["mspace"], [], options);
   5672   var size = calculateSize(measurement, options);
   5673   rule.style.marginRight = size + "em";
   5674   return rule;
   5675 }; // Takes font options, and returns the appropriate fontLookup name
   5676 
   5677 
   5678 var retrieveTextFontName = function retrieveTextFontName(fontFamily, fontWeight, fontShape) {
   5679   var baseFontName = "";
   5680 
   5681   switch (fontFamily) {
   5682     case "amsrm":
   5683       baseFontName = "AMS";
   5684       break;
   5685 
   5686     case "textrm":
   5687       baseFontName = "Main";
   5688       break;
   5689 
   5690     case "textsf":
   5691       baseFontName = "SansSerif";
   5692       break;
   5693 
   5694     case "texttt":
   5695       baseFontName = "Typewriter";
   5696       break;
   5697 
   5698     default:
   5699       baseFontName = fontFamily;
   5700     // use fonts added by a plugin
   5701   }
   5702 
   5703   var fontStylesName;
   5704 
   5705   if (fontWeight === "textbf" && fontShape === "textit") {
   5706     fontStylesName = "BoldItalic";
   5707   } else if (fontWeight === "textbf") {
   5708     fontStylesName = "Bold";
   5709   } else if (fontWeight === "textit") {
   5710     fontStylesName = "Italic";
   5711   } else {
   5712     fontStylesName = "Regular";
   5713   }
   5714 
   5715   return baseFontName + "-" + fontStylesName;
   5716 };
   5717 /**
   5718  * Maps TeX font commands to objects containing:
   5719  * - variant: string used for "mathvariant" attribute in buildMathML.js
   5720  * - fontName: the "style" parameter to fontMetrics.getCharacterMetrics
   5721  */
   5722 // A map between tex font commands an MathML mathvariant attribute values
   5723 
   5724 
   5725 var fontMap = {
   5726   // styles
   5727   "mathbf": {
   5728     variant: "bold",
   5729     fontName: "Main-Bold"
   5730   },
   5731   "mathrm": {
   5732     variant: "normal",
   5733     fontName: "Main-Regular"
   5734   },
   5735   "textit": {
   5736     variant: "italic",
   5737     fontName: "Main-Italic"
   5738   },
   5739   "mathit": {
   5740     variant: "italic",
   5741     fontName: "Main-Italic"
   5742   },
   5743   "mathnormal": {
   5744     variant: "italic",
   5745     fontName: "Math-Italic"
   5746   },
   5747   // "boldsymbol" is missing because they require the use of multiple fonts:
   5748   // Math-BoldItalic and Main-Bold.  This is handled by a special case in
   5749   // makeOrd which ends up calling boldsymbol.
   5750   // families
   5751   "mathbb": {
   5752     variant: "double-struck",
   5753     fontName: "AMS-Regular"
   5754   },
   5755   "mathcal": {
   5756     variant: "script",
   5757     fontName: "Caligraphic-Regular"
   5758   },
   5759   "mathfrak": {
   5760     variant: "fraktur",
   5761     fontName: "Fraktur-Regular"
   5762   },
   5763   "mathscr": {
   5764     variant: "script",
   5765     fontName: "Script-Regular"
   5766   },
   5767   "mathsf": {
   5768     variant: "sans-serif",
   5769     fontName: "SansSerif-Regular"
   5770   },
   5771   "mathtt": {
   5772     variant: "monospace",
   5773     fontName: "Typewriter-Regular"
   5774   }
   5775 };
   5776 var svgData = {
   5777   //   path, width, height
   5778   vec: ["vec", 0.471, 0.714],
   5779   // values from the font glyph
   5780   oiintSize1: ["oiintSize1", 0.957, 0.499],
   5781   // oval to overlay the integrand
   5782   oiintSize2: ["oiintSize2", 1.472, 0.659],
   5783   oiiintSize1: ["oiiintSize1", 1.304, 0.499],
   5784   oiiintSize2: ["oiiintSize2", 1.98, 0.659]
   5785 };
   5786 
   5787 var staticSvg = function staticSvg(value, options) {
   5788   // Create a span with inline SVG for the element.
   5789   var [pathName, width, height] = svgData[value];
   5790   var path = new PathNode(pathName);
   5791   var svgNode = new SvgNode([path], {
   5792     "width": width + "em",
   5793     "height": height + "em",
   5794     // Override CSS rule `.katex svg { width: 100% }`
   5795     "style": "width:" + width + "em",
   5796     "viewBox": "0 0 " + 1000 * width + " " + 1000 * height,
   5797     "preserveAspectRatio": "xMinYMin"
   5798   });
   5799   var span = makeSvgSpan(["overlay"], [svgNode], options);
   5800   span.height = height;
   5801   span.style.height = height + "em";
   5802   span.style.width = width + "em";
   5803   return span;
   5804 };
   5805 
   5806 var buildCommon = {
   5807   fontMap,
   5808   makeSymbol,
   5809   mathsym,
   5810   makeSpan,
   5811   makeSvgSpan,
   5812   makeLineSpan,
   5813   makeAnchor,
   5814   makeFragment,
   5815   wrapFragment,
   5816   makeVList,
   5817   makeOrd,
   5818   makeGlue,
   5819   staticSvg,
   5820   svgData,
   5821   tryCombineChars
   5822 };
   5823 
   5824 /**
   5825  * Describes spaces between different classes of atoms.
   5826  */
   5827 var thinspace = {
   5828   number: 3,
   5829   unit: "mu"
   5830 };
   5831 var mediumspace = {
   5832   number: 4,
   5833   unit: "mu"
   5834 };
   5835 var thickspace = {
   5836   number: 5,
   5837   unit: "mu"
   5838 }; // Making the type below exact with all optional fields doesn't work due to
   5839 // - https://github.com/facebook/flow/issues/4582
   5840 // - https://github.com/facebook/flow/issues/5688
   5841 // However, since *all* fields are optional, $Shape<> works as suggested in 5688
   5842 // above.
   5843 
   5844 // Spacing relationships for display and text styles
   5845 var spacings = {
   5846   mord: {
   5847     mop: thinspace,
   5848     mbin: mediumspace,
   5849     mrel: thickspace,
   5850     minner: thinspace
   5851   },
   5852   mop: {
   5853     mord: thinspace,
   5854     mop: thinspace,
   5855     mrel: thickspace,
   5856     minner: thinspace
   5857   },
   5858   mbin: {
   5859     mord: mediumspace,
   5860     mop: mediumspace,
   5861     mopen: mediumspace,
   5862     minner: mediumspace
   5863   },
   5864   mrel: {
   5865     mord: thickspace,
   5866     mop: thickspace,
   5867     mopen: thickspace,
   5868     minner: thickspace
   5869   },
   5870   mopen: {},
   5871   mclose: {
   5872     mop: thinspace,
   5873     mbin: mediumspace,
   5874     mrel: thickspace,
   5875     minner: thinspace
   5876   },
   5877   mpunct: {
   5878     mord: thinspace,
   5879     mop: thinspace,
   5880     mrel: thickspace,
   5881     mopen: thinspace,
   5882     mclose: thinspace,
   5883     mpunct: thinspace,
   5884     minner: thinspace
   5885   },
   5886   minner: {
   5887     mord: thinspace,
   5888     mop: thinspace,
   5889     mbin: mediumspace,
   5890     mrel: thickspace,
   5891     mopen: thinspace,
   5892     mpunct: thinspace,
   5893     minner: thinspace
   5894   }
   5895 }; // Spacing relationships for script and scriptscript styles
   5896 
   5897 var tightSpacings = {
   5898   mord: {
   5899     mop: thinspace
   5900   },
   5901   mop: {
   5902     mord: thinspace,
   5903     mop: thinspace
   5904   },
   5905   mbin: {},
   5906   mrel: {},
   5907   mopen: {},
   5908   mclose: {
   5909     mop: thinspace
   5910   },
   5911   mpunct: {},
   5912   minner: {
   5913     mop: thinspace
   5914   }
   5915 };
   5916 
   5917 /** Context provided to function handlers for error messages. */
   5918 // Note: reverse the order of the return type union will cause a flow error.
   5919 // See https://github.com/facebook/flow/issues/3663.
   5920 // More general version of `HtmlBuilder` for nodes (e.g. \sum, accent types)
   5921 // whose presence impacts super/subscripting. In this case, ParseNode<"supsub">
   5922 // delegates its HTML building to the HtmlBuilder corresponding to these nodes.
   5923 
   5924 /**
   5925  * Final function spec for use at parse time.
   5926  * This is almost identical to `FunctionPropSpec`, except it
   5927  * 1. includes the function handler, and
   5928  * 2. requires all arguments except argTypes.
   5929  * It is generated by `defineFunction()` below.
   5930  */
   5931 
   5932 /**
   5933  * All registered functions.
   5934  * `functions.js` just exports this same dictionary again and makes it public.
   5935  * `Parser.js` requires this dictionary.
   5936  */
   5937 var _functions = {};
   5938 /**
   5939  * All HTML builders. Should be only used in the `define*` and the `build*ML`
   5940  * functions.
   5941  */
   5942 
   5943 var _htmlGroupBuilders = {};
   5944 /**
   5945  * All MathML builders. Should be only used in the `define*` and the `build*ML`
   5946  * functions.
   5947  */
   5948 
   5949 var _mathmlGroupBuilders = {};
   5950 function defineFunction(_ref) {
   5951   var {
   5952     type,
   5953     names,
   5954     props,
   5955     handler,
   5956     htmlBuilder,
   5957     mathmlBuilder
   5958   } = _ref;
   5959   // Set default values of functions
   5960   var data = {
   5961     type,
   5962     numArgs: props.numArgs,
   5963     argTypes: props.argTypes,
   5964     allowedInArgument: !!props.allowedInArgument,
   5965     allowedInText: !!props.allowedInText,
   5966     allowedInMath: props.allowedInMath === undefined ? true : props.allowedInMath,
   5967     numOptionalArgs: props.numOptionalArgs || 0,
   5968     infix: !!props.infix,
   5969     primitive: !!props.primitive,
   5970     handler: handler
   5971   };
   5972 
   5973   for (var i = 0; i < names.length; ++i) {
   5974     _functions[names[i]] = data;
   5975   }
   5976 
   5977   if (type) {
   5978     if (htmlBuilder) {
   5979       _htmlGroupBuilders[type] = htmlBuilder;
   5980     }
   5981 
   5982     if (mathmlBuilder) {
   5983       _mathmlGroupBuilders[type] = mathmlBuilder;
   5984     }
   5985   }
   5986 }
   5987 /**
   5988  * Use this to register only the HTML and MathML builders for a function (e.g.
   5989  * if the function's ParseNode is generated in Parser.js rather than via a
   5990  * stand-alone handler provided to `defineFunction`).
   5991  */
   5992 
   5993 function defineFunctionBuilders(_ref2) {
   5994   var {
   5995     type,
   5996     htmlBuilder,
   5997     mathmlBuilder
   5998   } = _ref2;
   5999   defineFunction({
   6000     type,
   6001     names: [],
   6002     props: {
   6003       numArgs: 0
   6004     },
   6005 
   6006     handler() {
   6007       throw new Error('Should never be called.');
   6008     },
   6009 
   6010     htmlBuilder,
   6011     mathmlBuilder
   6012   });
   6013 }
   6014 var normalizeArgument = function normalizeArgument(arg) {
   6015   return arg.type === "ordgroup" && arg.body.length === 1 ? arg.body[0] : arg;
   6016 }; // Since the corresponding buildHTML/buildMathML function expects a
   6017 // list of elements, we normalize for different kinds of arguments
   6018 
   6019 var ordargument = function ordargument(arg) {
   6020   return arg.type === "ordgroup" ? arg.body : [arg];
   6021 };
   6022 
   6023 /**
   6024  * This file does the main work of building a domTree structure from a parse
   6025  * tree. The entry point is the `buildHTML` function, which takes a parse tree.
   6026  * Then, the buildExpression, buildGroup, and various groupBuilders functions
   6027  * are called, to produce a final HTML tree.
   6028  */
   6029 var makeSpan$1 = buildCommon.makeSpan; // Binary atoms (first class `mbin`) change into ordinary atoms (`mord`)
   6030 // depending on their surroundings. See TeXbook pg. 442-446, Rules 5 and 6,
   6031 // and the text before Rule 19.
   6032 
   6033 var binLeftCanceller = ["leftmost", "mbin", "mopen", "mrel", "mop", "mpunct"];
   6034 var binRightCanceller = ["rightmost", "mrel", "mclose", "mpunct"];
   6035 var styleMap = {
   6036   "display": Style$1.DISPLAY,
   6037   "text": Style$1.TEXT,
   6038   "script": Style$1.SCRIPT,
   6039   "scriptscript": Style$1.SCRIPTSCRIPT
   6040 };
   6041 var DomEnum = {
   6042   mord: "mord",
   6043   mop: "mop",
   6044   mbin: "mbin",
   6045   mrel: "mrel",
   6046   mopen: "mopen",
   6047   mclose: "mclose",
   6048   mpunct: "mpunct",
   6049   minner: "minner"
   6050 };
   6051 
   6052 /**
   6053  * Take a list of nodes, build them in order, and return a list of the built
   6054  * nodes. documentFragments are flattened into their contents, so the
   6055  * returned list contains no fragments. `isRealGroup` is true if `expression`
   6056  * is a real group (no atoms will be added on either side), as opposed to
   6057  * a partial group (e.g. one created by \color). `surrounding` is an array
   6058  * consisting type of nodes that will be added to the left and right.
   6059  */
   6060 var buildExpression = function buildExpression(expression, options, isRealGroup, surrounding) {
   6061   if (surrounding === void 0) {
   6062     surrounding = [null, null];
   6063   }
   6064 
   6065   // Parse expressions into `groups`.
   6066   var groups = [];
   6067 
   6068   for (var i = 0; i < expression.length; i++) {
   6069     var output = buildGroup(expression[i], options);
   6070 
   6071     if (output instanceof DocumentFragment) {
   6072       var children = output.children;
   6073       groups.push(...children);
   6074     } else {
   6075       groups.push(output);
   6076     }
   6077   } // Combine consecutive domTree.symbolNodes into a single symbolNode.
   6078 
   6079 
   6080   buildCommon.tryCombineChars(groups); // If `expression` is a partial group, let the parent handle spacings
   6081   // to avoid processing groups multiple times.
   6082 
   6083   if (!isRealGroup) {
   6084     return groups;
   6085   }
   6086 
   6087   var glueOptions = options;
   6088 
   6089   if (expression.length === 1) {
   6090     var node = expression[0];
   6091 
   6092     if (node.type === "sizing") {
   6093       glueOptions = options.havingSize(node.size);
   6094     } else if (node.type === "styling") {
   6095       glueOptions = options.havingStyle(styleMap[node.style]);
   6096     }
   6097   } // Dummy spans for determining spacings between surrounding atoms.
   6098   // If `expression` has no atoms on the left or right, class "leftmost"
   6099   // or "rightmost", respectively, is used to indicate it.
   6100 
   6101 
   6102   var dummyPrev = makeSpan$1([surrounding[0] || "leftmost"], [], options);
   6103   var dummyNext = makeSpan$1([surrounding[1] || "rightmost"], [], options); // TODO: These code assumes that a node's math class is the first element
   6104   // of its `classes` array. A later cleanup should ensure this, for
   6105   // instance by changing the signature of `makeSpan`.
   6106   // Before determining what spaces to insert, perform bin cancellation.
   6107   // Binary operators change to ordinary symbols in some contexts.
   6108 
   6109   var isRoot = isRealGroup === "root";
   6110   traverseNonSpaceNodes(groups, (node, prev) => {
   6111     var prevType = prev.classes[0];
   6112     var type = node.classes[0];
   6113 
   6114     if (prevType === "mbin" && utils.contains(binRightCanceller, type)) {
   6115       prev.classes[0] = "mord";
   6116     } else if (type === "mbin" && utils.contains(binLeftCanceller, prevType)) {
   6117       node.classes[0] = "mord";
   6118     }
   6119   }, {
   6120     node: dummyPrev
   6121   }, dummyNext, isRoot);
   6122   traverseNonSpaceNodes(groups, (node, prev) => {
   6123     var prevType = getTypeOfDomTree(prev);
   6124     var type = getTypeOfDomTree(node); // 'mtight' indicates that the node is script or scriptscript style.
   6125 
   6126     var space = prevType && type ? node.hasClass("mtight") ? tightSpacings[prevType][type] : spacings[prevType][type] : null;
   6127 
   6128     if (space) {
   6129       // Insert glue (spacing) after the `prev`.
   6130       return buildCommon.makeGlue(space, glueOptions);
   6131     }
   6132   }, {
   6133     node: dummyPrev
   6134   }, dummyNext, isRoot);
   6135   return groups;
   6136 }; // Depth-first traverse non-space `nodes`, calling `callback` with the current and
   6137 // previous node as arguments, optionally returning a node to insert after the
   6138 // previous node. `prev` is an object with the previous node and `insertAfter`
   6139 // function to insert after it. `next` is a node that will be added to the right.
   6140 // Used for bin cancellation and inserting spacings.
   6141 
   6142 var traverseNonSpaceNodes = function traverseNonSpaceNodes(nodes, callback, prev, next, isRoot) {
   6143   if (next) {
   6144     // temporarily append the right node, if exists
   6145     nodes.push(next);
   6146   }
   6147 
   6148   var i = 0;
   6149 
   6150   for (; i < nodes.length; i++) {
   6151     var node = nodes[i];
   6152     var partialGroup = checkPartialGroup(node);
   6153 
   6154     if (partialGroup) {
   6155       // Recursive DFS
   6156       // $FlowFixMe: make nodes a $ReadOnlyArray by returning a new array
   6157       traverseNonSpaceNodes(partialGroup.children, callback, prev, null, isRoot);
   6158       continue;
   6159     } // Ignore explicit spaces (e.g., \;, \,) when determining what implicit
   6160     // spacing should go between atoms of different classes
   6161 
   6162 
   6163     var nonspace = !node.hasClass("mspace");
   6164 
   6165     if (nonspace) {
   6166       var result = callback(node, prev.node);
   6167 
   6168       if (result) {
   6169         if (prev.insertAfter) {
   6170           prev.insertAfter(result);
   6171         } else {
   6172           // insert at front
   6173           nodes.unshift(result);
   6174           i++;
   6175         }
   6176       }
   6177     }
   6178 
   6179     if (nonspace) {
   6180       prev.node = node;
   6181     } else if (isRoot && node.hasClass("newline")) {
   6182       prev.node = makeSpan$1(["leftmost"]); // treat like beginning of line
   6183     }
   6184 
   6185     prev.insertAfter = (index => n => {
   6186       nodes.splice(index + 1, 0, n);
   6187       i++;
   6188     })(i);
   6189   }
   6190 
   6191   if (next) {
   6192     nodes.pop();
   6193   }
   6194 }; // Check if given node is a partial group, i.e., does not affect spacing around.
   6195 
   6196 
   6197 var checkPartialGroup = function checkPartialGroup(node) {
   6198   if (node instanceof DocumentFragment || node instanceof Anchor || node instanceof Span && node.hasClass("enclosing")) {
   6199     return node;
   6200   }
   6201 
   6202   return null;
   6203 }; // Return the outermost node of a domTree.
   6204 
   6205 
   6206 var getOutermostNode = function getOutermostNode(node, side) {
   6207   var partialGroup = checkPartialGroup(node);
   6208 
   6209   if (partialGroup) {
   6210     var children = partialGroup.children;
   6211 
   6212     if (children.length) {
   6213       if (side === "right") {
   6214         return getOutermostNode(children[children.length - 1], "right");
   6215       } else if (side === "left") {
   6216         return getOutermostNode(children[0], "left");
   6217       }
   6218     }
   6219   }
   6220 
   6221   return node;
   6222 }; // Return math atom class (mclass) of a domTree.
   6223 // If `side` is given, it will get the type of the outermost node at given side.
   6224 
   6225 
   6226 var getTypeOfDomTree = function getTypeOfDomTree(node, side) {
   6227   if (!node) {
   6228     return null;
   6229   }
   6230 
   6231   if (side) {
   6232     node = getOutermostNode(node, side);
   6233   } // This makes a lot of assumptions as to where the type of atom
   6234   // appears.  We should do a better job of enforcing this.
   6235 
   6236 
   6237   return DomEnum[node.classes[0]] || null;
   6238 };
   6239 var makeNullDelimiter = function makeNullDelimiter(options, classes) {
   6240   var moreClasses = ["nulldelimiter"].concat(options.baseSizingClasses());
   6241   return makeSpan$1(classes.concat(moreClasses));
   6242 };
   6243 /**
   6244  * buildGroup is the function that takes a group and calls the correct groupType
   6245  * function for it. It also handles the interaction of size and style changes
   6246  * between parents and children.
   6247  */
   6248 
   6249 var buildGroup = function buildGroup(group, options, baseOptions) {
   6250   if (!group) {
   6251     return makeSpan$1();
   6252   }
   6253 
   6254   if (_htmlGroupBuilders[group.type]) {
   6255     // Call the groupBuilders function
   6256     // $FlowFixMe
   6257     var groupNode = _htmlGroupBuilders[group.type](group, options); // If the size changed between the parent and the current group, account
   6258     // for that size difference.
   6259 
   6260     if (baseOptions && options.size !== baseOptions.size) {
   6261       groupNode = makeSpan$1(options.sizingClasses(baseOptions), [groupNode], options);
   6262       var multiplier = options.sizeMultiplier / baseOptions.sizeMultiplier;
   6263       groupNode.height *= multiplier;
   6264       groupNode.depth *= multiplier;
   6265     }
   6266 
   6267     return groupNode;
   6268   } else {
   6269     throw new ParseError("Got group of unknown type: '" + group.type + "'");
   6270   }
   6271 };
   6272 /**
   6273  * Combine an array of HTML DOM nodes (e.g., the output of `buildExpression`)
   6274  * into an unbreakable HTML node of class .base, with proper struts to
   6275  * guarantee correct vertical extent.  `buildHTML` calls this repeatedly to
   6276  * make up the entire expression as a sequence of unbreakable units.
   6277  */
   6278 
   6279 function buildHTMLUnbreakable(children, options) {
   6280   // Compute height and depth of this chunk.
   6281   var body = makeSpan$1(["base"], children, options); // Add strut, which ensures that the top of the HTML element falls at
   6282   // the height of the expression, and the bottom of the HTML element
   6283   // falls at the depth of the expression.
   6284 
   6285   var strut = makeSpan$1(["strut"]);
   6286   strut.style.height = body.height + body.depth + "em";
   6287   strut.style.verticalAlign = -body.depth + "em";
   6288   body.children.unshift(strut);
   6289   return body;
   6290 }
   6291 /**
   6292  * Take an entire parse tree, and build it into an appropriate set of HTML
   6293  * nodes.
   6294  */
   6295 
   6296 
   6297 function buildHTML(tree, options) {
   6298   // Strip off outer tag wrapper for processing below.
   6299   var tag = null;
   6300 
   6301   if (tree.length === 1 && tree[0].type === "tag") {
   6302     tag = tree[0].tag;
   6303     tree = tree[0].body;
   6304   } // Build the expression contained in the tree
   6305 
   6306 
   6307   var expression = buildExpression(tree, options, "root");
   6308   var eqnNum;
   6309 
   6310   if (expression.length === 2 && expression[1].hasClass("tag")) {
   6311     // An environment with automatic equation numbers, e.g. {gather}.
   6312     eqnNum = expression.pop();
   6313   }
   6314 
   6315   var children = []; // Create one base node for each chunk between potential line breaks.
   6316   // The TeXBook [p.173] says "A formula will be broken only after a
   6317   // relation symbol like $=$ or $<$ or $\rightarrow$, or after a binary
   6318   // operation symbol like $+$ or $-$ or $\times$, where the relation or
   6319   // binary operation is on the ``outer level'' of the formula (i.e., not
   6320   // enclosed in {...} and not part of an \over construction)."
   6321 
   6322   var parts = [];
   6323 
   6324   for (var i = 0; i < expression.length; i++) {
   6325     parts.push(expression[i]);
   6326 
   6327     if (expression[i].hasClass("mbin") || expression[i].hasClass("mrel") || expression[i].hasClass("allowbreak")) {
   6328       // Put any post-operator glue on same line as operator.
   6329       // Watch for \nobreak along the way, and stop at \newline.
   6330       var nobreak = false;
   6331 
   6332       while (i < expression.length - 1 && expression[i + 1].hasClass("mspace") && !expression[i + 1].hasClass("newline")) {
   6333         i++;
   6334         parts.push(expression[i]);
   6335 
   6336         if (expression[i].hasClass("nobreak")) {
   6337           nobreak = true;
   6338         }
   6339       } // Don't allow break if \nobreak among the post-operator glue.
   6340 
   6341 
   6342       if (!nobreak) {
   6343         children.push(buildHTMLUnbreakable(parts, options));
   6344         parts = [];
   6345       }
   6346     } else if (expression[i].hasClass("newline")) {
   6347       // Write the line except the newline
   6348       parts.pop();
   6349 
   6350       if (parts.length > 0) {
   6351         children.push(buildHTMLUnbreakable(parts, options));
   6352         parts = [];
   6353       } // Put the newline at the top level
   6354 
   6355 
   6356       children.push(expression[i]);
   6357     }
   6358   }
   6359 
   6360   if (parts.length > 0) {
   6361     children.push(buildHTMLUnbreakable(parts, options));
   6362   } // Now, if there was a tag, build it too and append it as a final child.
   6363 
   6364 
   6365   var tagChild;
   6366 
   6367   if (tag) {
   6368     tagChild = buildHTMLUnbreakable(buildExpression(tag, options, true));
   6369     tagChild.classes = ["tag"];
   6370     children.push(tagChild);
   6371   } else if (eqnNum) {
   6372     children.push(eqnNum);
   6373   }
   6374 
   6375   var htmlNode = makeSpan$1(["katex-html"], children);
   6376   htmlNode.setAttribute("aria-hidden", "true"); // Adjust the strut of the tag to be the maximum height of all children
   6377   // (the height of the enclosing htmlNode) for proper vertical alignment.
   6378 
   6379   if (tagChild) {
   6380     var strut = tagChild.children[0];
   6381     strut.style.height = htmlNode.height + htmlNode.depth + "em";
   6382     strut.style.verticalAlign = -htmlNode.depth + "em";
   6383   }
   6384 
   6385   return htmlNode;
   6386 }
   6387 
   6388 /**
   6389  * These objects store data about MathML nodes. This is the MathML equivalent
   6390  * of the types in domTree.js. Since MathML handles its own rendering, and
   6391  * since we're mainly using MathML to improve accessibility, we don't manage
   6392  * any of the styling state that the plain DOM nodes do.
   6393  *
   6394  * The `toNode` and `toMarkup` functions work simlarly to how they do in
   6395  * domTree.js, creating namespaced DOM nodes and HTML text markup respectively.
   6396  */
   6397 function newDocumentFragment(children) {
   6398   return new DocumentFragment(children);
   6399 }
   6400 /**
   6401  * This node represents a general purpose MathML node of any type. The
   6402  * constructor requires the type of node to create (for example, `"mo"` or
   6403  * `"mspace"`, corresponding to `<mo>` and `<mspace>` tags).
   6404  */
   6405 
   6406 class MathNode {
   6407   constructor(type, children, classes) {
   6408     this.type = void 0;
   6409     this.attributes = void 0;
   6410     this.children = void 0;
   6411     this.classes = void 0;
   6412     this.type = type;
   6413     this.attributes = {};
   6414     this.children = children || [];
   6415     this.classes = classes || [];
   6416   }
   6417   /**
   6418    * Sets an attribute on a MathML node. MathML depends on attributes to convey a
   6419    * semantic content, so this is used heavily.
   6420    */
   6421 
   6422 
   6423   setAttribute(name, value) {
   6424     this.attributes[name] = value;
   6425   }
   6426   /**
   6427    * Gets an attribute on a MathML node.
   6428    */
   6429 
   6430 
   6431   getAttribute(name) {
   6432     return this.attributes[name];
   6433   }
   6434   /**
   6435    * Converts the math node into a MathML-namespaced DOM element.
   6436    */
   6437 
   6438 
   6439   toNode() {
   6440     var node = document.createElementNS("http://www.w3.org/1998/Math/MathML", this.type);
   6441 
   6442     for (var attr in this.attributes) {
   6443       if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
   6444         node.setAttribute(attr, this.attributes[attr]);
   6445       }
   6446     }
   6447 
   6448     if (this.classes.length > 0) {
   6449       node.className = createClass(this.classes);
   6450     }
   6451 
   6452     for (var i = 0; i < this.children.length; i++) {
   6453       node.appendChild(this.children[i].toNode());
   6454     }
   6455 
   6456     return node;
   6457   }
   6458   /**
   6459    * Converts the math node into an HTML markup string.
   6460    */
   6461 
   6462 
   6463   toMarkup() {
   6464     var markup = "<" + this.type; // Add the attributes
   6465 
   6466     for (var attr in this.attributes) {
   6467       if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
   6468         markup += " " + attr + "=\"";
   6469         markup += utils.escape(this.attributes[attr]);
   6470         markup += "\"";
   6471       }
   6472     }
   6473 
   6474     if (this.classes.length > 0) {
   6475       markup += " class =\"" + utils.escape(createClass(this.classes)) + "\"";
   6476     }
   6477 
   6478     markup += ">";
   6479 
   6480     for (var i = 0; i < this.children.length; i++) {
   6481       markup += this.children[i].toMarkup();
   6482     }
   6483 
   6484     markup += "</" + this.type + ">";
   6485     return markup;
   6486   }
   6487   /**
   6488    * Converts the math node into a string, similar to innerText, but escaped.
   6489    */
   6490 
   6491 
   6492   toText() {
   6493     return this.children.map(child => child.toText()).join("");
   6494   }
   6495 
   6496 }
   6497 /**
   6498  * This node represents a piece of text.
   6499  */
   6500 
   6501 class TextNode {
   6502   constructor(text) {
   6503     this.text = void 0;
   6504     this.text = text;
   6505   }
   6506   /**
   6507    * Converts the text node into a DOM text node.
   6508    */
   6509 
   6510 
   6511   toNode() {
   6512     return document.createTextNode(this.text);
   6513   }
   6514   /**
   6515    * Converts the text node into escaped HTML markup
   6516    * (representing the text itself).
   6517    */
   6518 
   6519 
   6520   toMarkup() {
   6521     return utils.escape(this.toText());
   6522   }
   6523   /**
   6524    * Converts the text node into a string
   6525    * (representing the text iteself).
   6526    */
   6527 
   6528 
   6529   toText() {
   6530     return this.text;
   6531   }
   6532 
   6533 }
   6534 /**
   6535  * This node represents a space, but may render as <mspace.../> or as text,
   6536  * depending on the width.
   6537  */
   6538 
   6539 class SpaceNode {
   6540   /**
   6541    * Create a Space node with width given in CSS ems.
   6542    */
   6543   constructor(width) {
   6544     this.width = void 0;
   6545     this.character = void 0;
   6546     this.width = width; // See https://www.w3.org/TR/2000/WD-MathML2-20000328/chapter6.html
   6547     // for a table of space-like characters.  We use Unicode
   6548     // representations instead of &LongNames; as it's not clear how to
   6549     // make the latter via document.createTextNode.
   6550 
   6551     if (width >= 0.05555 && width <= 0.05556) {
   6552       this.character = "\u200a"; // &VeryThinSpace;
   6553     } else if (width >= 0.1666 && width <= 0.1667) {
   6554       this.character = "\u2009"; // &ThinSpace;
   6555     } else if (width >= 0.2222 && width <= 0.2223) {
   6556       this.character = "\u2005"; // &MediumSpace;
   6557     } else if (width >= 0.2777 && width <= 0.2778) {
   6558       this.character = "\u2005\u200a"; // &ThickSpace;
   6559     } else if (width >= -0.05556 && width <= -0.05555) {
   6560       this.character = "\u200a\u2063"; // &NegativeVeryThinSpace;
   6561     } else if (width >= -0.1667 && width <= -0.1666) {
   6562       this.character = "\u2009\u2063"; // &NegativeThinSpace;
   6563     } else if (width >= -0.2223 && width <= -0.2222) {
   6564       this.character = "\u205f\u2063"; // &NegativeMediumSpace;
   6565     } else if (width >= -0.2778 && width <= -0.2777) {
   6566       this.character = "\u2005\u2063"; // &NegativeThickSpace;
   6567     } else {
   6568       this.character = null;
   6569     }
   6570   }
   6571   /**
   6572    * Converts the math node into a MathML-namespaced DOM element.
   6573    */
   6574 
   6575 
   6576   toNode() {
   6577     if (this.character) {
   6578       return document.createTextNode(this.character);
   6579     } else {
   6580       var node = document.createElementNS("http://www.w3.org/1998/Math/MathML", "mspace");
   6581       node.setAttribute("width", this.width + "em");
   6582       return node;
   6583     }
   6584   }
   6585   /**
   6586    * Converts the math node into an HTML markup string.
   6587    */
   6588 
   6589 
   6590   toMarkup() {
   6591     if (this.character) {
   6592       return "<mtext>" + this.character + "</mtext>";
   6593     } else {
   6594       return "<mspace width=\"" + this.width + "em\"/>";
   6595     }
   6596   }
   6597   /**
   6598    * Converts the math node into a string, similar to innerText.
   6599    */
   6600 
   6601 
   6602   toText() {
   6603     if (this.character) {
   6604       return this.character;
   6605     } else {
   6606       return " ";
   6607     }
   6608   }
   6609 
   6610 }
   6611 
   6612 var mathMLTree = {
   6613   MathNode,
   6614   TextNode,
   6615   SpaceNode,
   6616   newDocumentFragment
   6617 };
   6618 
   6619 /**
   6620  * This file converts a parse tree into a cooresponding MathML tree. The main
   6621  * entry point is the `buildMathML` function, which takes a parse tree from the
   6622  * parser.
   6623  */
   6624 
   6625 /**
   6626  * Takes a symbol and converts it into a MathML text node after performing
   6627  * optional replacement from symbols.js.
   6628  */
   6629 var makeText = function makeText(text, mode, options) {
   6630   if (symbols[mode][text] && symbols[mode][text].replace && text.charCodeAt(0) !== 0xD835 && !(ligatures.hasOwnProperty(text) && options && (options.fontFamily && options.fontFamily.substr(4, 2) === "tt" || options.font && options.font.substr(4, 2) === "tt"))) {
   6631     text = symbols[mode][text].replace;
   6632   }
   6633 
   6634   return new mathMLTree.TextNode(text);
   6635 };
   6636 /**
   6637  * Wrap the given array of nodes in an <mrow> node if needed, i.e.,
   6638  * unless the array has length 1.  Always returns a single node.
   6639  */
   6640 
   6641 var makeRow = function makeRow(body) {
   6642   if (body.length === 1) {
   6643     return body[0];
   6644   } else {
   6645     return new mathMLTree.MathNode("mrow", body);
   6646   }
   6647 };
   6648 /**
   6649  * Returns the math variant as a string or null if none is required.
   6650  */
   6651 
   6652 var getVariant = function getVariant(group, options) {
   6653   // Handle \text... font specifiers as best we can.
   6654   // MathML has a limited list of allowable mathvariant specifiers; see
   6655   // https://www.w3.org/TR/MathML3/chapter3.html#presm.commatt
   6656   if (options.fontFamily === "texttt") {
   6657     return "monospace";
   6658   } else if (options.fontFamily === "textsf") {
   6659     if (options.fontShape === "textit" && options.fontWeight === "textbf") {
   6660       return "sans-serif-bold-italic";
   6661     } else if (options.fontShape === "textit") {
   6662       return "sans-serif-italic";
   6663     } else if (options.fontWeight === "textbf") {
   6664       return "bold-sans-serif";
   6665     } else {
   6666       return "sans-serif";
   6667     }
   6668   } else if (options.fontShape === "textit" && options.fontWeight === "textbf") {
   6669     return "bold-italic";
   6670   } else if (options.fontShape === "textit") {
   6671     return "italic";
   6672   } else if (options.fontWeight === "textbf") {
   6673     return "bold";
   6674   }
   6675 
   6676   var font = options.font;
   6677 
   6678   if (!font || font === "mathnormal") {
   6679     return null;
   6680   }
   6681 
   6682   var mode = group.mode;
   6683 
   6684   if (font === "mathit") {
   6685     return "italic";
   6686   } else if (font === "boldsymbol") {
   6687     return group.type === "textord" ? "bold" : "bold-italic";
   6688   } else if (font === "mathbf") {
   6689     return "bold";
   6690   } else if (font === "mathbb") {
   6691     return "double-struck";
   6692   } else if (font === "mathfrak") {
   6693     return "fraktur";
   6694   } else if (font === "mathscr" || font === "mathcal") {
   6695     // MathML makes no distinction between script and caligrahpic
   6696     return "script";
   6697   } else if (font === "mathsf") {
   6698     return "sans-serif";
   6699   } else if (font === "mathtt") {
   6700     return "monospace";
   6701   }
   6702 
   6703   var text = group.text;
   6704 
   6705   if (utils.contains(["\\imath", "\\jmath"], text)) {
   6706     return null;
   6707   }
   6708 
   6709   if (symbols[mode][text] && symbols[mode][text].replace) {
   6710     text = symbols[mode][text].replace;
   6711   }
   6712 
   6713   var fontName = buildCommon.fontMap[font].fontName;
   6714 
   6715   if (getCharacterMetrics(text, fontName, mode)) {
   6716     return buildCommon.fontMap[font].variant;
   6717   }
   6718 
   6719   return null;
   6720 };
   6721 /**
   6722  * Takes a list of nodes, builds them, and returns a list of the generated
   6723  * MathML nodes.  Also combine consecutive <mtext> outputs into a single
   6724  * <mtext> tag.
   6725  */
   6726 
   6727 var buildExpression$1 = function buildExpression(expression, options, isOrdgroup) {
   6728   if (expression.length === 1) {
   6729     var group = buildGroup$1(expression[0], options);
   6730 
   6731     if (isOrdgroup && group instanceof MathNode && group.type === "mo") {
   6732       // When TeX writers want to suppress spacing on an operator,
   6733       // they often put the operator by itself inside braces.
   6734       group.setAttribute("lspace", "0em");
   6735       group.setAttribute("rspace", "0em");
   6736     }
   6737 
   6738     return [group];
   6739   }
   6740 
   6741   var groups = [];
   6742   var lastGroup;
   6743 
   6744   for (var i = 0; i < expression.length; i++) {
   6745     var _group = buildGroup$1(expression[i], options);
   6746 
   6747     if (_group instanceof MathNode && lastGroup instanceof MathNode) {
   6748       // Concatenate adjacent <mtext>s
   6749       if (_group.type === 'mtext' && lastGroup.type === 'mtext' && _group.getAttribute('mathvariant') === lastGroup.getAttribute('mathvariant')) {
   6750         lastGroup.children.push(..._group.children);
   6751         continue; // Concatenate adjacent <mn>s
   6752       } else if (_group.type === 'mn' && lastGroup.type === 'mn') {
   6753         lastGroup.children.push(..._group.children);
   6754         continue; // Concatenate <mn>...</mn> followed by <mi>.</mi>
   6755       } else if (_group.type === 'mi' && _group.children.length === 1 && lastGroup.type === 'mn') {
   6756         var child = _group.children[0];
   6757 
   6758         if (child instanceof TextNode && child.text === '.') {
   6759           lastGroup.children.push(..._group.children);
   6760           continue;
   6761         }
   6762       } else if (lastGroup.type === 'mi' && lastGroup.children.length === 1) {
   6763         var lastChild = lastGroup.children[0];
   6764 
   6765         if (lastChild instanceof TextNode && lastChild.text === '\u0338' && (_group.type === 'mo' || _group.type === 'mi' || _group.type === 'mn')) {
   6766           var _child = _group.children[0];
   6767 
   6768           if (_child instanceof TextNode && _child.text.length > 0) {
   6769             // Overlay with combining character long solidus
   6770             _child.text = _child.text.slice(0, 1) + "\u0338" + _child.text.slice(1);
   6771             groups.pop();
   6772           }
   6773         }
   6774       }
   6775     }
   6776 
   6777     groups.push(_group);
   6778     lastGroup = _group;
   6779   }
   6780 
   6781   return groups;
   6782 };
   6783 /**
   6784  * Equivalent to buildExpression, but wraps the elements in an <mrow>
   6785  * if there's more than one.  Returns a single node instead of an array.
   6786  */
   6787 
   6788 var buildExpressionRow = function buildExpressionRow(expression, options, isOrdgroup) {
   6789   return makeRow(buildExpression$1(expression, options, isOrdgroup));
   6790 };
   6791 /**
   6792  * Takes a group from the parser and calls the appropriate groupBuilders function
   6793  * on it to produce a MathML node.
   6794  */
   6795 
   6796 var buildGroup$1 = function buildGroup(group, options) {
   6797   if (!group) {
   6798     return new mathMLTree.MathNode("mrow");
   6799   }
   6800 
   6801   if (_mathmlGroupBuilders[group.type]) {
   6802     // Call the groupBuilders function
   6803     // $FlowFixMe
   6804     var result = _mathmlGroupBuilders[group.type](group, options); // $FlowFixMe
   6805 
   6806     return result;
   6807   } else {
   6808     throw new ParseError("Got group of unknown type: '" + group.type + "'");
   6809   }
   6810 };
   6811 /**
   6812  * Takes a full parse tree and settings and builds a MathML representation of
   6813  * it. In particular, we put the elements from building the parse tree into a
   6814  * <semantics> tag so we can also include that TeX source as an annotation.
   6815  *
   6816  * Note that we actually return a domTree element with a `<math>` inside it so
   6817  * we can do appropriate styling.
   6818  */
   6819 
   6820 function buildMathML(tree, texExpression, options, isDisplayMode, forMathmlOnly) {
   6821   var expression = buildExpression$1(tree, options); // TODO: Make a pass thru the MathML similar to buildHTML.traverseNonSpaceNodes
   6822   // and add spacing nodes. This is necessary only adjacent to math operators
   6823   // like \sin or \lim or to subsup elements that contain math operators.
   6824   // MathML takes care of the other spacing issues.
   6825   // Wrap up the expression in an mrow so it is presented in the semantics
   6826   // tag correctly, unless it's a single <mrow> or <mtable>.
   6827 
   6828   var wrapper;
   6829 
   6830   if (expression.length === 1 && expression[0] instanceof MathNode && utils.contains(["mrow", "mtable"], expression[0].type)) {
   6831     wrapper = expression[0];
   6832   } else {
   6833     wrapper = new mathMLTree.MathNode("mrow", expression);
   6834   } // Build a TeX annotation of the source
   6835 
   6836 
   6837   var annotation = new mathMLTree.MathNode("annotation", [new mathMLTree.TextNode(texExpression)]);
   6838   annotation.setAttribute("encoding", "application/x-tex");
   6839   var semantics = new mathMLTree.MathNode("semantics", [wrapper, annotation]);
   6840   var math = new mathMLTree.MathNode("math", [semantics]);
   6841   math.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML");
   6842 
   6843   if (isDisplayMode) {
   6844     math.setAttribute("display", "block");
   6845   } // You can't style <math> nodes, so we wrap the node in a span.
   6846   // NOTE: The span class is not typed to have <math> nodes as children, and
   6847   // we don't want to make the children type more generic since the children
   6848   // of span are expected to have more fields in `buildHtml` contexts.
   6849 
   6850 
   6851   var wrapperClass = forMathmlOnly ? "katex" : "katex-mathml"; // $FlowFixMe
   6852 
   6853   return buildCommon.makeSpan([wrapperClass], [math]);
   6854 }
   6855 
   6856 var optionsFromSettings = function optionsFromSettings(settings) {
   6857   return new Options({
   6858     style: settings.displayMode ? Style$1.DISPLAY : Style$1.TEXT,
   6859     maxSize: settings.maxSize,
   6860     minRuleThickness: settings.minRuleThickness
   6861   });
   6862 };
   6863 
   6864 var displayWrap = function displayWrap(node, settings) {
   6865   if (settings.displayMode) {
   6866     var classes = ["katex-display"];
   6867 
   6868     if (settings.leqno) {
   6869       classes.push("leqno");
   6870     }
   6871 
   6872     if (settings.fleqn) {
   6873       classes.push("fleqn");
   6874     }
   6875 
   6876     node = buildCommon.makeSpan(classes, [node]);
   6877   }
   6878 
   6879   return node;
   6880 };
   6881 
   6882 var buildTree = function buildTree(tree, expression, settings) {
   6883   var options = optionsFromSettings(settings);
   6884   var katexNode;
   6885 
   6886   if (settings.output === "mathml") {
   6887     return buildMathML(tree, expression, options, settings.displayMode, true);
   6888   } else if (settings.output === "html") {
   6889     var htmlNode = buildHTML(tree, options);
   6890     katexNode = buildCommon.makeSpan(["katex"], [htmlNode]);
   6891   } else {
   6892     var mathMLNode = buildMathML(tree, expression, options, settings.displayMode, false);
   6893 
   6894     var _htmlNode = buildHTML(tree, options);
   6895 
   6896     katexNode = buildCommon.makeSpan(["katex"], [mathMLNode, _htmlNode]);
   6897   }
   6898 
   6899   return displayWrap(katexNode, settings);
   6900 };
   6901 var buildHTMLTree = function buildHTMLTree(tree, expression, settings) {
   6902   var options = optionsFromSettings(settings);
   6903   var htmlNode = buildHTML(tree, options);
   6904   var katexNode = buildCommon.makeSpan(["katex"], [htmlNode]);
   6905   return displayWrap(katexNode, settings);
   6906 };
   6907 
   6908 /**
   6909  * This file provides support to buildMathML.js and buildHTML.js
   6910  * for stretchy wide elements rendered from SVG files
   6911  * and other CSS trickery.
   6912  */
   6913 var stretchyCodePoint = {
   6914   widehat: "^",
   6915   widecheck: "ˇ",
   6916   widetilde: "~",
   6917   utilde: "~",
   6918   overleftarrow: "\u2190",
   6919   underleftarrow: "\u2190",
   6920   xleftarrow: "\u2190",
   6921   overrightarrow: "\u2192",
   6922   underrightarrow: "\u2192",
   6923   xrightarrow: "\u2192",
   6924   underbrace: "\u23df",
   6925   overbrace: "\u23de",
   6926   overgroup: "\u23e0",
   6927   undergroup: "\u23e1",
   6928   overleftrightarrow: "\u2194",
   6929   underleftrightarrow: "\u2194",
   6930   xleftrightarrow: "\u2194",
   6931   Overrightarrow: "\u21d2",
   6932   xRightarrow: "\u21d2",
   6933   overleftharpoon: "\u21bc",
   6934   xleftharpoonup: "\u21bc",
   6935   overrightharpoon: "\u21c0",
   6936   xrightharpoonup: "\u21c0",
   6937   xLeftarrow: "\u21d0",
   6938   xLeftrightarrow: "\u21d4",
   6939   xhookleftarrow: "\u21a9",
   6940   xhookrightarrow: "\u21aa",
   6941   xmapsto: "\u21a6",
   6942   xrightharpoondown: "\u21c1",
   6943   xleftharpoondown: "\u21bd",
   6944   xrightleftharpoons: "\u21cc",
   6945   xleftrightharpoons: "\u21cb",
   6946   xtwoheadleftarrow: "\u219e",
   6947   xtwoheadrightarrow: "\u21a0",
   6948   xlongequal: "=",
   6949   xtofrom: "\u21c4",
   6950   xrightleftarrows: "\u21c4",
   6951   xrightequilibrium: "\u21cc",
   6952   // Not a perfect match.
   6953   xleftequilibrium: "\u21cb",
   6954   // None better available.
   6955   "\\\\cdrightarrow": "\u2192",
   6956   "\\\\cdleftarrow": "\u2190",
   6957   "\\\\cdlongequal": "="
   6958 };
   6959 
   6960 var mathMLnode = function mathMLnode(label) {
   6961   var node = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode(stretchyCodePoint[label])]);
   6962   node.setAttribute("stretchy", "true");
   6963   return node;
   6964 }; // Many of the KaTeX SVG images have been adapted from glyphs in KaTeX fonts.
   6965 // Copyright (c) 2009-2010, Design Science, Inc. (<www.mathjax.org>)
   6966 // Copyright (c) 2014-2017 Khan Academy (<www.khanacademy.org>)
   6967 // Licensed under the SIL Open Font License, Version 1.1.
   6968 // See \nhttp://scripts.sil.org/OFL
   6969 // Very Long SVGs
   6970 //    Many of the KaTeX stretchy wide elements use a long SVG image and an
   6971 //    overflow: hidden tactic to achieve a stretchy image while avoiding
   6972 //    distortion of arrowheads or brace corners.
   6973 //    The SVG typically contains a very long (400 em) arrow.
   6974 //    The SVG is in a container span that has overflow: hidden, so the span
   6975 //    acts like a window that exposes only part of the  SVG.
   6976 //    The SVG always has a longer, thinner aspect ratio than the container span.
   6977 //    After the SVG fills 100% of the height of the container span,
   6978 //    there is a long arrow shaft left over. That left-over shaft is not shown.
   6979 //    Instead, it is sliced off because the span's CSS has overflow: hidden.
   6980 //    Thus, the reader sees an arrow that matches the subject matter width
   6981 //    without distortion.
   6982 //    Some functions, such as \cancel, need to vary their aspect ratio. These
   6983 //    functions do not get the overflow SVG treatment.
   6984 // Second Brush Stroke
   6985 //    Low resolution monitors struggle to display images in fine detail.
   6986 //    So browsers apply anti-aliasing. A long straight arrow shaft therefore
   6987 //    will sometimes appear as if it has a blurred edge.
   6988 //    To mitigate this, these SVG files contain a second "brush-stroke" on the
   6989 //    arrow shafts. That is, a second long thin rectangular SVG path has been
   6990 //    written directly on top of each arrow shaft. This reinforcement causes
   6991 //    some of the screen pixels to display as black instead of the anti-aliased
   6992 //    gray pixel that a  single path would generate. So we get arrow shafts
   6993 //    whose edges appear to be sharper.
   6994 // In the katexImagesData object just below, the dimensions all
   6995 // correspond to path geometry inside the relevant SVG.
   6996 // For example, \overrightarrow uses the same arrowhead as glyph U+2192
   6997 // from the KaTeX Main font. The scaling factor is 1000.
   6998 // That is, inside the font, that arrowhead is 522 units tall, which
   6999 // corresponds to 0.522 em inside the document.
   7000 
   7001 
   7002 var katexImagesData = {
   7003   //   path(s), minWidth, height, align
   7004   overrightarrow: [["rightarrow"], 0.888, 522, "xMaxYMin"],
   7005   overleftarrow: [["leftarrow"], 0.888, 522, "xMinYMin"],
   7006   underrightarrow: [["rightarrow"], 0.888, 522, "xMaxYMin"],
   7007   underleftarrow: [["leftarrow"], 0.888, 522, "xMinYMin"],
   7008   xrightarrow: [["rightarrow"], 1.469, 522, "xMaxYMin"],
   7009   "\\cdrightarrow": [["rightarrow"], 3.0, 522, "xMaxYMin"],
   7010   // CD minwwidth2.5pc
   7011   xleftarrow: [["leftarrow"], 1.469, 522, "xMinYMin"],
   7012   "\\cdleftarrow": [["leftarrow"], 3.0, 522, "xMinYMin"],
   7013   Overrightarrow: [["doublerightarrow"], 0.888, 560, "xMaxYMin"],
   7014   xRightarrow: [["doublerightarrow"], 1.526, 560, "xMaxYMin"],
   7015   xLeftarrow: [["doubleleftarrow"], 1.526, 560, "xMinYMin"],
   7016   overleftharpoon: [["leftharpoon"], 0.888, 522, "xMinYMin"],
   7017   xleftharpoonup: [["leftharpoon"], 0.888, 522, "xMinYMin"],
   7018   xleftharpoondown: [["leftharpoondown"], 0.888, 522, "xMinYMin"],
   7019   overrightharpoon: [["rightharpoon"], 0.888, 522, "xMaxYMin"],
   7020   xrightharpoonup: [["rightharpoon"], 0.888, 522, "xMaxYMin"],
   7021   xrightharpoondown: [["rightharpoondown"], 0.888, 522, "xMaxYMin"],
   7022   xlongequal: [["longequal"], 0.888, 334, "xMinYMin"],
   7023   "\\cdlongequal": [["longequal"], 3.0, 334, "xMinYMin"],
   7024   xtwoheadleftarrow: [["twoheadleftarrow"], 0.888, 334, "xMinYMin"],
   7025   xtwoheadrightarrow: [["twoheadrightarrow"], 0.888, 334, "xMaxYMin"],
   7026   overleftrightarrow: [["leftarrow", "rightarrow"], 0.888, 522],
   7027   overbrace: [["leftbrace", "midbrace", "rightbrace"], 1.6, 548],
   7028   underbrace: [["leftbraceunder", "midbraceunder", "rightbraceunder"], 1.6, 548],
   7029   underleftrightarrow: [["leftarrow", "rightarrow"], 0.888, 522],
   7030   xleftrightarrow: [["leftarrow", "rightarrow"], 1.75, 522],
   7031   xLeftrightarrow: [["doubleleftarrow", "doublerightarrow"], 1.75, 560],
   7032   xrightleftharpoons: [["leftharpoondownplus", "rightharpoonplus"], 1.75, 716],
   7033   xleftrightharpoons: [["leftharpoonplus", "rightharpoondownplus"], 1.75, 716],
   7034   xhookleftarrow: [["leftarrow", "righthook"], 1.08, 522],
   7035   xhookrightarrow: [["lefthook", "rightarrow"], 1.08, 522],
   7036   overlinesegment: [["leftlinesegment", "rightlinesegment"], 0.888, 522],
   7037   underlinesegment: [["leftlinesegment", "rightlinesegment"], 0.888, 522],
   7038   overgroup: [["leftgroup", "rightgroup"], 0.888, 342],
   7039   undergroup: [["leftgroupunder", "rightgroupunder"], 0.888, 342],
   7040   xmapsto: [["leftmapsto", "rightarrow"], 1.5, 522],
   7041   xtofrom: [["leftToFrom", "rightToFrom"], 1.75, 528],
   7042   // The next three arrows are from the mhchem package.
   7043   // In mhchem.sty, min-length is 2.0em. But these arrows might appear in the
   7044   // document as \xrightarrow or \xrightleftharpoons. Those have
   7045   // min-length = 1.75em, so we set min-length on these next three to match.
   7046   xrightleftarrows: [["baraboveleftarrow", "rightarrowabovebar"], 1.75, 901],
   7047   xrightequilibrium: [["baraboveshortleftharpoon", "rightharpoonaboveshortbar"], 1.75, 716],
   7048   xleftequilibrium: [["shortbaraboveleftharpoon", "shortrightharpoonabovebar"], 1.75, 716]
   7049 };
   7050 
   7051 var groupLength = function groupLength(arg) {
   7052   if (arg.type === "ordgroup") {
   7053     return arg.body.length;
   7054   } else {
   7055     return 1;
   7056   }
   7057 };
   7058 
   7059 var svgSpan = function svgSpan(group, options) {
   7060   // Create a span with inline SVG for the element.
   7061   function buildSvgSpan_() {
   7062     var viewBoxWidth = 400000; // default
   7063 
   7064     var label = group.label.substr(1);
   7065 
   7066     if (utils.contains(["widehat", "widecheck", "widetilde", "utilde"], label)) {
   7067       // Each type in the `if` statement corresponds to one of the ParseNode
   7068       // types below. This narrowing is required to access `grp.base`.
   7069       // $FlowFixMe
   7070       var grp = group; // There are four SVG images available for each function.
   7071       // Choose a taller image when there are more characters.
   7072 
   7073       var numChars = groupLength(grp.base);
   7074       var viewBoxHeight;
   7075       var pathName;
   7076 
   7077       var _height;
   7078 
   7079       if (numChars > 5) {
   7080         if (label === "widehat" || label === "widecheck") {
   7081           viewBoxHeight = 420;
   7082           viewBoxWidth = 2364;
   7083           _height = 0.42;
   7084           pathName = label + "4";
   7085         } else {
   7086           viewBoxHeight = 312;
   7087           viewBoxWidth = 2340;
   7088           _height = 0.34;
   7089           pathName = "tilde4";
   7090         }
   7091       } else {
   7092         var imgIndex = [1, 1, 2, 2, 3, 3][numChars];
   7093 
   7094         if (label === "widehat" || label === "widecheck") {
   7095           viewBoxWidth = [0, 1062, 2364, 2364, 2364][imgIndex];
   7096           viewBoxHeight = [0, 239, 300, 360, 420][imgIndex];
   7097           _height = [0, 0.24, 0.3, 0.3, 0.36, 0.42][imgIndex];
   7098           pathName = label + imgIndex;
   7099         } else {
   7100           viewBoxWidth = [0, 600, 1033, 2339, 2340][imgIndex];
   7101           viewBoxHeight = [0, 260, 286, 306, 312][imgIndex];
   7102           _height = [0, 0.26, 0.286, 0.3, 0.306, 0.34][imgIndex];
   7103           pathName = "tilde" + imgIndex;
   7104         }
   7105       }
   7106 
   7107       var path = new PathNode(pathName);
   7108       var svgNode = new SvgNode([path], {
   7109         "width": "100%",
   7110         "height": _height + "em",
   7111         "viewBox": "0 0 " + viewBoxWidth + " " + viewBoxHeight,
   7112         "preserveAspectRatio": "none"
   7113       });
   7114       return {
   7115         span: buildCommon.makeSvgSpan([], [svgNode], options),
   7116         minWidth: 0,
   7117         height: _height
   7118       };
   7119     } else {
   7120       var spans = [];
   7121       var data = katexImagesData[label];
   7122       var [paths, _minWidth, _viewBoxHeight] = data;
   7123 
   7124       var _height2 = _viewBoxHeight / 1000;
   7125 
   7126       var numSvgChildren = paths.length;
   7127       var widthClasses;
   7128       var aligns;
   7129 
   7130       if (numSvgChildren === 1) {
   7131         // $FlowFixMe: All these cases must be of the 4-tuple type.
   7132         var align1 = data[3];
   7133         widthClasses = ["hide-tail"];
   7134         aligns = [align1];
   7135       } else if (numSvgChildren === 2) {
   7136         widthClasses = ["halfarrow-left", "halfarrow-right"];
   7137         aligns = ["xMinYMin", "xMaxYMin"];
   7138       } else if (numSvgChildren === 3) {
   7139         widthClasses = ["brace-left", "brace-center", "brace-right"];
   7140         aligns = ["xMinYMin", "xMidYMin", "xMaxYMin"];
   7141       } else {
   7142         throw new Error("Correct katexImagesData or update code here to support\n                    " + numSvgChildren + " children.");
   7143       }
   7144 
   7145       for (var i = 0; i < numSvgChildren; i++) {
   7146         var _path = new PathNode(paths[i]);
   7147 
   7148         var _svgNode = new SvgNode([_path], {
   7149           "width": "400em",
   7150           "height": _height2 + "em",
   7151           "viewBox": "0 0 " + viewBoxWidth + " " + _viewBoxHeight,
   7152           "preserveAspectRatio": aligns[i] + " slice"
   7153         });
   7154 
   7155         var _span = buildCommon.makeSvgSpan([widthClasses[i]], [_svgNode], options);
   7156 
   7157         if (numSvgChildren === 1) {
   7158           return {
   7159             span: _span,
   7160             minWidth: _minWidth,
   7161             height: _height2
   7162           };
   7163         } else {
   7164           _span.style.height = _height2 + "em";
   7165           spans.push(_span);
   7166         }
   7167       }
   7168 
   7169       return {
   7170         span: buildCommon.makeSpan(["stretchy"], spans, options),
   7171         minWidth: _minWidth,
   7172         height: _height2
   7173       };
   7174     }
   7175   } // buildSvgSpan_()
   7176 
   7177 
   7178   var {
   7179     span,
   7180     minWidth,
   7181     height
   7182   } = buildSvgSpan_(); // Note that we are returning span.depth = 0.
   7183   // Any adjustments relative to the baseline must be done in buildHTML.
   7184 
   7185   span.height = height;
   7186   span.style.height = height + "em";
   7187 
   7188   if (minWidth > 0) {
   7189     span.style.minWidth = minWidth + "em";
   7190   }
   7191 
   7192   return span;
   7193 };
   7194 
   7195 var encloseSpan = function encloseSpan(inner, label, topPad, bottomPad, options) {
   7196   // Return an image span for \cancel, \bcancel, \xcancel, \fbox, or \angl
   7197   var img;
   7198   var totalHeight = inner.height + inner.depth + topPad + bottomPad;
   7199 
   7200   if (/fbox|color|angl/.test(label)) {
   7201     img = buildCommon.makeSpan(["stretchy", label], [], options);
   7202 
   7203     if (label === "fbox") {
   7204       var color = options.color && options.getColor();
   7205 
   7206       if (color) {
   7207         img.style.borderColor = color;
   7208       }
   7209     }
   7210   } else {
   7211     // \cancel, \bcancel, or \xcancel
   7212     // Since \cancel's SVG is inline and it omits the viewBox attribute,
   7213     // its stroke-width will not vary with span area.
   7214     var lines = [];
   7215 
   7216     if (/^[bx]cancel$/.test(label)) {
   7217       lines.push(new LineNode({
   7218         "x1": "0",
   7219         "y1": "0",
   7220         "x2": "100%",
   7221         "y2": "100%",
   7222         "stroke-width": "0.046em"
   7223       }));
   7224     }
   7225 
   7226     if (/^x?cancel$/.test(label)) {
   7227       lines.push(new LineNode({
   7228         "x1": "0",
   7229         "y1": "100%",
   7230         "x2": "100%",
   7231         "y2": "0",
   7232         "stroke-width": "0.046em"
   7233       }));
   7234     }
   7235 
   7236     var svgNode = new SvgNode(lines, {
   7237       "width": "100%",
   7238       "height": totalHeight + "em"
   7239     });
   7240     img = buildCommon.makeSvgSpan([], [svgNode], options);
   7241   }
   7242 
   7243   img.height = totalHeight;
   7244   img.style.height = totalHeight + "em";
   7245   return img;
   7246 };
   7247 
   7248 var stretchy = {
   7249   encloseSpan,
   7250   mathMLnode,
   7251   svgSpan
   7252 };
   7253 
   7254 /**
   7255  * Asserts that the node is of the given type and returns it with stricter
   7256  * typing. Throws if the node's type does not match.
   7257  */
   7258 function assertNodeType(node, type) {
   7259   if (!node || node.type !== type) {
   7260     throw new Error("Expected node of type " + type + ", but got " + (node ? "node of type " + node.type : String(node)));
   7261   } // $FlowFixMe, >=0.125
   7262 
   7263 
   7264   return node;
   7265 }
   7266 /**
   7267  * Returns the node more strictly typed iff it is of the given type. Otherwise,
   7268  * returns null.
   7269  */
   7270 
   7271 function assertSymbolNodeType(node) {
   7272   var typedNode = checkSymbolNodeType(node);
   7273 
   7274   if (!typedNode) {
   7275     throw new Error("Expected node of symbol group type, but got " + (node ? "node of type " + node.type : String(node)));
   7276   }
   7277 
   7278   return typedNode;
   7279 }
   7280 /**
   7281  * Returns the node more strictly typed iff it is of the given type. Otherwise,
   7282  * returns null.
   7283  */
   7284 
   7285 function checkSymbolNodeType(node) {
   7286   if (node && (node.type === "atom" || NON_ATOMS.hasOwnProperty(node.type))) {
   7287     // $FlowFixMe
   7288     return node;
   7289   }
   7290 
   7291   return null;
   7292 }
   7293 
   7294 // NOTE: Unlike most `htmlBuilder`s, this one handles not only "accent", but
   7295 // also "supsub" since an accent can affect super/subscripting.
   7296 var htmlBuilder = (grp, options) => {
   7297   // Accents are handled in the TeXbook pg. 443, rule 12.
   7298   var base;
   7299   var group;
   7300   var supSubGroup;
   7301 
   7302   if (grp && grp.type === "supsub") {
   7303     // If our base is a character box, and we have superscripts and
   7304     // subscripts, the supsub will defer to us. In particular, we want
   7305     // to attach the superscripts and subscripts to the inner body (so
   7306     // that the position of the superscripts and subscripts won't be
   7307     // affected by the height of the accent). We accomplish this by
   7308     // sticking the base of the accent into the base of the supsub, and
   7309     // rendering that, while keeping track of where the accent is.
   7310     // The real accent group is the base of the supsub group
   7311     group = assertNodeType(grp.base, "accent"); // The character box is the base of the accent group
   7312 
   7313     base = group.base; // Stick the character box into the base of the supsub group
   7314 
   7315     grp.base = base; // Rerender the supsub group with its new base, and store that
   7316     // result.
   7317 
   7318     supSubGroup = assertSpan(buildGroup(grp, options)); // reset original base
   7319 
   7320     grp.base = group;
   7321   } else {
   7322     group = assertNodeType(grp, "accent");
   7323     base = group.base;
   7324   } // Build the base group
   7325 
   7326 
   7327   var body = buildGroup(base, options.havingCrampedStyle()); // Does the accent need to shift for the skew of a character?
   7328 
   7329   var mustShift = group.isShifty && utils.isCharacterBox(base); // Calculate the skew of the accent. This is based on the line "If the
   7330   // nucleus is not a single character, let s = 0; otherwise set s to the
   7331   // kern amount for the nucleus followed by the \skewchar of its font."
   7332   // Note that our skew metrics are just the kern between each character
   7333   // and the skewchar.
   7334 
   7335   var skew = 0;
   7336 
   7337   if (mustShift) {
   7338     // If the base is a character box, then we want the skew of the
   7339     // innermost character. To do that, we find the innermost character:
   7340     var baseChar = utils.getBaseElem(base); // Then, we render its group to get the symbol inside it
   7341 
   7342     var baseGroup = buildGroup(baseChar, options.havingCrampedStyle()); // Finally, we pull the skew off of the symbol.
   7343 
   7344     skew = assertSymbolDomNode(baseGroup).skew; // Note that we now throw away baseGroup, because the layers we
   7345     // removed with getBaseElem might contain things like \color which
   7346     // we can't get rid of.
   7347     // TODO(emily): Find a better way to get the skew
   7348   } // calculate the amount of space between the body and the accent
   7349 
   7350 
   7351   var clearance = Math.min(body.height, options.fontMetrics().xHeight); // Build the accent
   7352 
   7353   var accentBody;
   7354 
   7355   if (!group.isStretchy) {
   7356     var accent;
   7357     var width;
   7358 
   7359     if (group.label === "\\vec") {
   7360       // Before version 0.9, \vec used the combining font glyph U+20D7.
   7361       // But browsers, especially Safari, are not consistent in how they
   7362       // render combining characters when not preceded by a character.
   7363       // So now we use an SVG.
   7364       // If Safari reforms, we should consider reverting to the glyph.
   7365       accent = buildCommon.staticSvg("vec", options);
   7366       width = buildCommon.svgData.vec[1];
   7367     } else {
   7368       accent = buildCommon.makeOrd({
   7369         mode: group.mode,
   7370         text: group.label
   7371       }, options, "textord");
   7372       accent = assertSymbolDomNode(accent); // Remove the italic correction of the accent, because it only serves to
   7373       // shift the accent over to a place we don't want.
   7374 
   7375       accent.italic = 0;
   7376       width = accent.width;
   7377     }
   7378 
   7379     accentBody = buildCommon.makeSpan(["accent-body"], [accent]); // "Full" accents expand the width of the resulting symbol to be
   7380     // at least the width of the accent, and overlap directly onto the
   7381     // character without any vertical offset.
   7382 
   7383     var accentFull = group.label === "\\textcircled";
   7384 
   7385     if (accentFull) {
   7386       accentBody.classes.push('accent-full');
   7387       clearance = body.height;
   7388     } // Shift the accent over by the skew.
   7389 
   7390 
   7391     var left = skew; // CSS defines `.katex .accent .accent-body:not(.accent-full) { width: 0 }`
   7392     // so that the accent doesn't contribute to the bounding box.
   7393     // We need to shift the character by its width (effectively half
   7394     // its width) to compensate.
   7395 
   7396     if (!accentFull) {
   7397       left -= width / 2;
   7398     }
   7399 
   7400     accentBody.style.left = left + "em"; // \textcircled uses the \bigcirc glyph, so it needs some
   7401     // vertical adjustment to match LaTeX.
   7402 
   7403     if (group.label === "\\textcircled") {
   7404       accentBody.style.top = ".2em";
   7405     }
   7406 
   7407     accentBody = buildCommon.makeVList({
   7408       positionType: "firstBaseline",
   7409       children: [{
   7410         type: "elem",
   7411         elem: body
   7412       }, {
   7413         type: "kern",
   7414         size: -clearance
   7415       }, {
   7416         type: "elem",
   7417         elem: accentBody
   7418       }]
   7419     }, options);
   7420   } else {
   7421     accentBody = stretchy.svgSpan(group, options);
   7422     accentBody = buildCommon.makeVList({
   7423       positionType: "firstBaseline",
   7424       children: [{
   7425         type: "elem",
   7426         elem: body
   7427       }, {
   7428         type: "elem",
   7429         elem: accentBody,
   7430         wrapperClasses: ["svg-align"],
   7431         wrapperStyle: skew > 0 ? {
   7432           width: "calc(100% - " + 2 * skew + "em)",
   7433           marginLeft: 2 * skew + "em"
   7434         } : undefined
   7435       }]
   7436     }, options);
   7437   }
   7438 
   7439   var accentWrap = buildCommon.makeSpan(["mord", "accent"], [accentBody], options);
   7440 
   7441   if (supSubGroup) {
   7442     // Here, we replace the "base" child of the supsub with our newly
   7443     // generated accent.
   7444     supSubGroup.children[0] = accentWrap; // Since we don't rerun the height calculation after replacing the
   7445     // accent, we manually recalculate height.
   7446 
   7447     supSubGroup.height = Math.max(accentWrap.height, supSubGroup.height); // Accents should always be ords, even when their innards are not.
   7448 
   7449     supSubGroup.classes[0] = "mord";
   7450     return supSubGroup;
   7451   } else {
   7452     return accentWrap;
   7453   }
   7454 };
   7455 
   7456 var mathmlBuilder = (group, options) => {
   7457   var accentNode = group.isStretchy ? stretchy.mathMLnode(group.label) : new mathMLTree.MathNode("mo", [makeText(group.label, group.mode)]);
   7458   var node = new mathMLTree.MathNode("mover", [buildGroup$1(group.base, options), accentNode]);
   7459   node.setAttribute("accent", "true");
   7460   return node;
   7461 };
   7462 
   7463 var NON_STRETCHY_ACCENT_REGEX = new RegExp(["\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve", "\\check", "\\hat", "\\vec", "\\dot", "\\mathring"].map(accent => "\\" + accent).join("|")); // Accents
   7464 
   7465 defineFunction({
   7466   type: "accent",
   7467   names: ["\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve", "\\check", "\\hat", "\\vec", "\\dot", "\\mathring", "\\widecheck", "\\widehat", "\\widetilde", "\\overrightarrow", "\\overleftarrow", "\\Overrightarrow", "\\overleftrightarrow", "\\overgroup", "\\overlinesegment", "\\overleftharpoon", "\\overrightharpoon"],
   7468   props: {
   7469     numArgs: 1
   7470   },
   7471   handler: (context, args) => {
   7472     var base = normalizeArgument(args[0]);
   7473     var isStretchy = !NON_STRETCHY_ACCENT_REGEX.test(context.funcName);
   7474     var isShifty = !isStretchy || context.funcName === "\\widehat" || context.funcName === "\\widetilde" || context.funcName === "\\widecheck";
   7475     return {
   7476       type: "accent",
   7477       mode: context.parser.mode,
   7478       label: context.funcName,
   7479       isStretchy: isStretchy,
   7480       isShifty: isShifty,
   7481       base: base
   7482     };
   7483   },
   7484   htmlBuilder,
   7485   mathmlBuilder
   7486 }); // Text-mode accents
   7487 
   7488 defineFunction({
   7489   type: "accent",
   7490   names: ["\\'", "\\`", "\\^", "\\~", "\\=", "\\u", "\\.", '\\"', "\\r", "\\H", "\\v", "\\textcircled"],
   7491   props: {
   7492     numArgs: 1,
   7493     allowedInText: true,
   7494     allowedInMath: false,
   7495     argTypes: ["primitive"]
   7496   },
   7497   handler: (context, args) => {
   7498     var base = args[0];
   7499     return {
   7500       type: "accent",
   7501       mode: context.parser.mode,
   7502       label: context.funcName,
   7503       isStretchy: false,
   7504       isShifty: true,
   7505       base: base
   7506     };
   7507   },
   7508   htmlBuilder,
   7509   mathmlBuilder
   7510 });
   7511 
   7512 // Horizontal overlap functions
   7513 defineFunction({
   7514   type: "accentUnder",
   7515   names: ["\\underleftarrow", "\\underrightarrow", "\\underleftrightarrow", "\\undergroup", "\\underlinesegment", "\\utilde"],
   7516   props: {
   7517     numArgs: 1
   7518   },
   7519   handler: (_ref, args) => {
   7520     var {
   7521       parser,
   7522       funcName
   7523     } = _ref;
   7524     var base = args[0];
   7525     return {
   7526       type: "accentUnder",
   7527       mode: parser.mode,
   7528       label: funcName,
   7529       base: base
   7530     };
   7531   },
   7532   htmlBuilder: (group, options) => {
   7533     // Treat under accents much like underlines.
   7534     var innerGroup = buildGroup(group.base, options);
   7535     var accentBody = stretchy.svgSpan(group, options);
   7536     var kern = group.label === "\\utilde" ? 0.12 : 0; // Generate the vlist, with the appropriate kerns
   7537 
   7538     var vlist = buildCommon.makeVList({
   7539       positionType: "top",
   7540       positionData: innerGroup.height,
   7541       children: [{
   7542         type: "elem",
   7543         elem: accentBody,
   7544         wrapperClasses: ["svg-align"]
   7545       }, {
   7546         type: "kern",
   7547         size: kern
   7548       }, {
   7549         type: "elem",
   7550         elem: innerGroup
   7551       }]
   7552     }, options);
   7553     return buildCommon.makeSpan(["mord", "accentunder"], [vlist], options);
   7554   },
   7555   mathmlBuilder: (group, options) => {
   7556     var accentNode = stretchy.mathMLnode(group.label);
   7557     var node = new mathMLTree.MathNode("munder", [buildGroup$1(group.base, options), accentNode]);
   7558     node.setAttribute("accentunder", "true");
   7559     return node;
   7560   }
   7561 });
   7562 
   7563 // Helper function
   7564 var paddedNode = group => {
   7565   var node = new mathMLTree.MathNode("mpadded", group ? [group] : []);
   7566   node.setAttribute("width", "+0.6em");
   7567   node.setAttribute("lspace", "0.3em");
   7568   return node;
   7569 }; // Stretchy arrows with an optional argument
   7570 
   7571 
   7572 defineFunction({
   7573   type: "xArrow",
   7574   names: ["\\xleftarrow", "\\xrightarrow", "\\xLeftarrow", "\\xRightarrow", "\\xleftrightarrow", "\\xLeftrightarrow", "\\xhookleftarrow", "\\xhookrightarrow", "\\xmapsto", "\\xrightharpoondown", "\\xrightharpoonup", "\\xleftharpoondown", "\\xleftharpoonup", "\\xrightleftharpoons", "\\xleftrightharpoons", "\\xlongequal", "\\xtwoheadrightarrow", "\\xtwoheadleftarrow", "\\xtofrom", // The next 3 functions are here to support the mhchem extension.
   7575   // Direct use of these functions is discouraged and may break someday.
   7576   "\\xrightleftarrows", "\\xrightequilibrium", "\\xleftequilibrium", // The next 3 functions are here only to support the {CD} environment.
   7577   "\\\\cdrightarrow", "\\\\cdleftarrow", "\\\\cdlongequal"],
   7578   props: {
   7579     numArgs: 1,
   7580     numOptionalArgs: 1
   7581   },
   7582 
   7583   handler(_ref, args, optArgs) {
   7584     var {
   7585       parser,
   7586       funcName
   7587     } = _ref;
   7588     return {
   7589       type: "xArrow",
   7590       mode: parser.mode,
   7591       label: funcName,
   7592       body: args[0],
   7593       below: optArgs[0]
   7594     };
   7595   },
   7596 
   7597   // Flow is unable to correctly infer the type of `group`, even though it's
   7598   // unamibiguously determined from the passed-in `type` above.
   7599   htmlBuilder(group, options) {
   7600     var style = options.style; // Build the argument groups in the appropriate style.
   7601     // Ref: amsmath.dtx:   \hbox{$\scriptstyle\mkern#3mu{#6}\mkern#4mu$}%
   7602     // Some groups can return document fragments.  Handle those by wrapping
   7603     // them in a span.
   7604 
   7605     var newOptions = options.havingStyle(style.sup());
   7606     var upperGroup = buildCommon.wrapFragment(buildGroup(group.body, newOptions, options), options);
   7607     var arrowPrefix = group.label.slice(0, 2) === "\\x" ? "x" : "cd";
   7608     upperGroup.classes.push(arrowPrefix + "-arrow-pad");
   7609     var lowerGroup;
   7610 
   7611     if (group.below) {
   7612       // Build the lower group
   7613       newOptions = options.havingStyle(style.sub());
   7614       lowerGroup = buildCommon.wrapFragment(buildGroup(group.below, newOptions, options), options);
   7615       lowerGroup.classes.push(arrowPrefix + "-arrow-pad");
   7616     }
   7617 
   7618     var arrowBody = stretchy.svgSpan(group, options); // Re shift: Note that stretchy.svgSpan returned arrowBody.depth = 0.
   7619     // The point we want on the math axis is at 0.5 * arrowBody.height.
   7620 
   7621     var arrowShift = -options.fontMetrics().axisHeight + 0.5 * arrowBody.height; // 2 mu kern. Ref: amsmath.dtx: #7\if0#2\else\mkern#2mu\fi
   7622 
   7623     var upperShift = -options.fontMetrics().axisHeight - 0.5 * arrowBody.height - 0.111; // 0.111 em = 2 mu
   7624 
   7625     if (upperGroup.depth > 0.25 || group.label === "\\xleftequilibrium") {
   7626       upperShift -= upperGroup.depth; // shift up if depth encroaches
   7627     } // Generate the vlist
   7628 
   7629 
   7630     var vlist;
   7631 
   7632     if (lowerGroup) {
   7633       var lowerShift = -options.fontMetrics().axisHeight + lowerGroup.height + 0.5 * arrowBody.height + 0.111;
   7634       vlist = buildCommon.makeVList({
   7635         positionType: "individualShift",
   7636         children: [{
   7637           type: "elem",
   7638           elem: upperGroup,
   7639           shift: upperShift
   7640         }, {
   7641           type: "elem",
   7642           elem: arrowBody,
   7643           shift: arrowShift
   7644         }, {
   7645           type: "elem",
   7646           elem: lowerGroup,
   7647           shift: lowerShift
   7648         }]
   7649       }, options);
   7650     } else {
   7651       vlist = buildCommon.makeVList({
   7652         positionType: "individualShift",
   7653         children: [{
   7654           type: "elem",
   7655           elem: upperGroup,
   7656           shift: upperShift
   7657         }, {
   7658           type: "elem",
   7659           elem: arrowBody,
   7660           shift: arrowShift
   7661         }]
   7662       }, options);
   7663     } // $FlowFixMe: Replace this with passing "svg-align" into makeVList.
   7664 
   7665 
   7666     vlist.children[0].children[0].children[1].classes.push("svg-align");
   7667     return buildCommon.makeSpan(["mrel", "x-arrow"], [vlist], options);
   7668   },
   7669 
   7670   mathmlBuilder(group, options) {
   7671     var arrowNode = stretchy.mathMLnode(group.label);
   7672     arrowNode.setAttribute("minsize", group.label.charAt(0) === "x" ? "1.75em" : "3.0em");
   7673     var node;
   7674 
   7675     if (group.body) {
   7676       var upperNode = paddedNode(buildGroup$1(group.body, options));
   7677 
   7678       if (group.below) {
   7679         var lowerNode = paddedNode(buildGroup$1(group.below, options));
   7680         node = new mathMLTree.MathNode("munderover", [arrowNode, lowerNode, upperNode]);
   7681       } else {
   7682         node = new mathMLTree.MathNode("mover", [arrowNode, upperNode]);
   7683       }
   7684     } else if (group.below) {
   7685       var _lowerNode = paddedNode(buildGroup$1(group.below, options));
   7686 
   7687       node = new mathMLTree.MathNode("munder", [arrowNode, _lowerNode]);
   7688     } else {
   7689       // This should never happen.
   7690       // Parser.js throws an error if there is no argument.
   7691       node = paddedNode();
   7692       node = new mathMLTree.MathNode("mover", [arrowNode, node]);
   7693     }
   7694 
   7695     return node;
   7696   }
   7697 
   7698 });
   7699 
   7700 var cdArrowFunctionName = {
   7701   ">": "\\\\cdrightarrow",
   7702   "<": "\\\\cdleftarrow",
   7703   "=": "\\\\cdlongequal",
   7704   "A": "\\uparrow",
   7705   "V": "\\downarrow",
   7706   "|": "\\Vert",
   7707   ".": "no arrow"
   7708 };
   7709 
   7710 var newCell = () => {
   7711   // Create an empty cell, to be filled below with parse nodes.
   7712   // The parseTree from this module must be constructed like the
   7713   // one created by parseArray(), so an empty CD cell must
   7714   // be a ParseNode<"styling">. And CD is always displaystyle.
   7715   // So these values are fixed and flow can do implicit typing.
   7716   return {
   7717     type: "styling",
   7718     body: [],
   7719     mode: "math",
   7720     style: "display"
   7721   };
   7722 };
   7723 
   7724 var isStartOfArrow = node => {
   7725   return node.type === "textord" && node.text === "@";
   7726 };
   7727 
   7728 var isLabelEnd = (node, endChar) => {
   7729   return (node.type === "mathord" || node.type === "atom") && node.text === endChar;
   7730 };
   7731 
   7732 function cdArrow(arrowChar, labels, parser) {
   7733   // Return a parse tree of an arrow and its labels.
   7734   // This acts in a way similar to a macro expansion.
   7735   var funcName = cdArrowFunctionName[arrowChar];
   7736 
   7737   switch (funcName) {
   7738     case "\\\\cdrightarrow":
   7739     case "\\\\cdleftarrow":
   7740       return parser.callFunction(funcName, [labels[0]], [labels[1]]);
   7741 
   7742     case "\\uparrow":
   7743     case "\\downarrow":
   7744       {
   7745         var leftLabel = parser.callFunction("\\\\cdleft", [labels[0]], []);
   7746         var bareArrow = {
   7747           type: "atom",
   7748           text: funcName,
   7749           mode: "math",
   7750           family: "rel"
   7751         };
   7752         var sizedArrow = parser.callFunction("\\Big", [bareArrow], []);
   7753         var rightLabel = parser.callFunction("\\\\cdright", [labels[1]], []);
   7754         var arrowGroup = {
   7755           type: "ordgroup",
   7756           mode: "math",
   7757           body: [leftLabel, sizedArrow, rightLabel]
   7758         };
   7759         return parser.callFunction("\\\\cdparent", [arrowGroup], []);
   7760       }
   7761 
   7762     case "\\\\cdlongequal":
   7763       return parser.callFunction("\\\\cdlongequal", [], []);
   7764 
   7765     case "\\Vert":
   7766       {
   7767         var arrow = {
   7768           type: "textord",
   7769           text: "\\Vert",
   7770           mode: "math"
   7771         };
   7772         return parser.callFunction("\\Big", [arrow], []);
   7773       }
   7774 
   7775     default:
   7776       return {
   7777         type: "textord",
   7778         text: " ",
   7779         mode: "math"
   7780       };
   7781   }
   7782 }
   7783 
   7784 function parseCD(parser) {
   7785   // Get the array's parse nodes with \\ temporarily mapped to \cr.
   7786   var parsedRows = [];
   7787   parser.gullet.beginGroup();
   7788   parser.gullet.macros.set("\\cr", "\\\\\\relax");
   7789   parser.gullet.beginGroup();
   7790 
   7791   while (true) {
   7792     // eslint-disable-line no-constant-condition
   7793     // Get the parse nodes for the next row.
   7794     parsedRows.push(parser.parseExpression(false, "\\\\"));
   7795     parser.gullet.endGroup();
   7796     parser.gullet.beginGroup();
   7797     var next = parser.fetch().text;
   7798 
   7799     if (next === "&" || next === "\\\\") {
   7800       parser.consume();
   7801     } else if (next === "\\end") {
   7802       if (parsedRows[parsedRows.length - 1].length === 0) {
   7803         parsedRows.pop(); // final row ended in \\
   7804       }
   7805 
   7806       break;
   7807     } else {
   7808       throw new ParseError("Expected \\\\ or \\cr or \\end", parser.nextToken);
   7809     }
   7810   }
   7811 
   7812   var row = [];
   7813   var body = [row]; // Loop thru the parse nodes. Collect them into cells and arrows.
   7814 
   7815   for (var i = 0; i < parsedRows.length; i++) {
   7816     // Start a new row.
   7817     var rowNodes = parsedRows[i]; // Create the first cell.
   7818 
   7819     var cell = newCell();
   7820 
   7821     for (var j = 0; j < rowNodes.length; j++) {
   7822       if (!isStartOfArrow(rowNodes[j])) {
   7823         // If a parseNode is not an arrow, it goes into a cell.
   7824         cell.body.push(rowNodes[j]);
   7825       } else {
   7826         // Parse node j is an "@", the start of an arrow.
   7827         // Before starting on the arrow, push the cell into `row`.
   7828         row.push(cell); // Now collect parseNodes into an arrow.
   7829         // The character after "@" defines the arrow type.
   7830 
   7831         j += 1;
   7832         var arrowChar = assertSymbolNodeType(rowNodes[j]).text; // Create two empty label nodes. We may or may not use them.
   7833 
   7834         var labels = new Array(2);
   7835         labels[0] = {
   7836           type: "ordgroup",
   7837           mode: "math",
   7838           body: []
   7839         };
   7840         labels[1] = {
   7841           type: "ordgroup",
   7842           mode: "math",
   7843           body: []
   7844         }; // Process the arrow.
   7845 
   7846         if ("=|.".indexOf(arrowChar) > -1) ; else if ("<>AV".indexOf(arrowChar) > -1) {
   7847           // Four arrows, `@>>>`, `@<<<`, `@AAA`, and `@VVV`, each take
   7848           // two optional labels. E.g. the right-point arrow syntax is
   7849           // really:  @>{optional label}>{optional label}>
   7850           // Collect parseNodes into labels.
   7851           for (var labelNum = 0; labelNum < 2; labelNum++) {
   7852             var inLabel = true;
   7853 
   7854             for (var k = j + 1; k < rowNodes.length; k++) {
   7855               if (isLabelEnd(rowNodes[k], arrowChar)) {
   7856                 inLabel = false;
   7857                 j = k;
   7858                 break;
   7859               }
   7860 
   7861               if (isStartOfArrow(rowNodes[k])) {
   7862                 throw new ParseError("Missing a " + arrowChar + " character to complete a CD arrow.", rowNodes[k]);
   7863               }
   7864 
   7865               labels[labelNum].body.push(rowNodes[k]);
   7866             }
   7867 
   7868             if (inLabel) {
   7869               // isLabelEnd never returned a true.
   7870               throw new ParseError("Missing a " + arrowChar + " character to complete a CD arrow.", rowNodes[j]);
   7871             }
   7872           }
   7873         } else {
   7874           throw new ParseError("Expected one of \"<>AV=|.\" after @", rowNodes[j]);
   7875         } // Now join the arrow to its labels.
   7876 
   7877 
   7878         var arrow = cdArrow(arrowChar, labels, parser); // Wrap the arrow in  ParseNode<"styling">.
   7879         // This is done to match parseArray() behavior.
   7880 
   7881         var wrappedArrow = {
   7882           type: "styling",
   7883           body: [arrow],
   7884           mode: "math",
   7885           style: "display" // CD is always displaystyle.
   7886 
   7887         };
   7888         row.push(wrappedArrow); // In CD's syntax, cells are implicit. That is, everything that
   7889         // is not an arrow gets collected into a cell. So create an empty
   7890         // cell now. It will collect upcoming parseNodes.
   7891 
   7892         cell = newCell();
   7893       }
   7894     }
   7895 
   7896     if (i % 2 === 0) {
   7897       // Even-numbered rows consist of: cell, arrow, cell, arrow, ... cell
   7898       // The last cell is not yet pushed into `row`, so:
   7899       row.push(cell);
   7900     } else {
   7901       // Odd-numbered rows consist of: vert arrow, empty cell, ... vert arrow
   7902       // Remove the empty cell that was placed at the beginning of `row`.
   7903       row.shift();
   7904     }
   7905 
   7906     row = [];
   7907     body.push(row);
   7908   } // End row group
   7909 
   7910 
   7911   parser.gullet.endGroup(); // End array group defining \\
   7912 
   7913   parser.gullet.endGroup(); // define column separation.
   7914 
   7915   var cols = new Array(body[0].length).fill({
   7916     type: "align",
   7917     align: "c",
   7918     pregap: 0.25,
   7919     // CD package sets \enskip between columns.
   7920     postgap: 0.25 // So pre and post each get half an \enskip, i.e. 0.25em.
   7921 
   7922   });
   7923   return {
   7924     type: "array",
   7925     mode: "math",
   7926     body,
   7927     arraystretch: 1,
   7928     addJot: true,
   7929     rowGaps: [null],
   7930     cols,
   7931     colSeparationType: "CD",
   7932     hLinesBeforeRow: new Array(body.length + 1).fill([])
   7933   };
   7934 } // The functions below are not available for general use.
   7935 // They are here only for internal use by the {CD} environment in placing labels
   7936 // next to vertical arrows.
   7937 // We don't need any such functions for horizontal arrows because we can reuse
   7938 // the functionality that already exists for extensible arrows.
   7939 
   7940 defineFunction({
   7941   type: "cdlabel",
   7942   names: ["\\\\cdleft", "\\\\cdright"],
   7943   props: {
   7944     numArgs: 1
   7945   },
   7946 
   7947   handler(_ref, args) {
   7948     var {
   7949       parser,
   7950       funcName
   7951     } = _ref;
   7952     return {
   7953       type: "cdlabel",
   7954       mode: parser.mode,
   7955       side: funcName.slice(4),
   7956       label: args[0]
   7957     };
   7958   },
   7959 
   7960   htmlBuilder(group, options) {
   7961     var newOptions = options.havingStyle(options.style.sup());
   7962     var label = buildCommon.wrapFragment(buildGroup(group.label, newOptions, options), options);
   7963     label.classes.push("cd-label-" + group.side);
   7964     label.style.bottom = 0.8 - label.depth + "em"; // Zero out label height & depth, so vertical align of arrow is set
   7965     // by the arrow height, not by the label.
   7966 
   7967     label.height = 0;
   7968     label.depth = 0;
   7969     return label;
   7970   },
   7971 
   7972   mathmlBuilder(group, options) {
   7973     var label = new mathMLTree.MathNode("mrow", [buildGroup$1(group.label, options)]);
   7974     label = new mathMLTree.MathNode("mpadded", [label]);
   7975     label.setAttribute("width", "0");
   7976 
   7977     if (group.side === "left") {
   7978       label.setAttribute("lspace", "-1width");
   7979     } // We have to guess at vertical alignment. We know the arrow is 1.8em tall,
   7980     // But we don't know the height or depth of the label.
   7981 
   7982 
   7983     label.setAttribute("voffset", "0.7em");
   7984     label = new mathMLTree.MathNode("mstyle", [label]);
   7985     label.setAttribute("displaystyle", "false");
   7986     label.setAttribute("scriptlevel", "1");
   7987     return label;
   7988   }
   7989 
   7990 });
   7991 defineFunction({
   7992   type: "cdlabelparent",
   7993   names: ["\\\\cdparent"],
   7994   props: {
   7995     numArgs: 1
   7996   },
   7997 
   7998   handler(_ref2, args) {
   7999     var {
   8000       parser
   8001     } = _ref2;
   8002     return {
   8003       type: "cdlabelparent",
   8004       mode: parser.mode,
   8005       fragment: args[0]
   8006     };
   8007   },
   8008 
   8009   htmlBuilder(group, options) {
   8010     // Wrap the vertical arrow and its labels.
   8011     // The parent gets position: relative. The child gets position: absolute.
   8012     // So CSS can locate the label correctly.
   8013     var parent = buildCommon.wrapFragment(buildGroup(group.fragment, options), options);
   8014     parent.classes.push("cd-vert-arrow");
   8015     return parent;
   8016   },
   8017 
   8018   mathmlBuilder(group, options) {
   8019     return new mathMLTree.MathNode("mrow", [buildGroup$1(group.fragment, options)]);
   8020   }
   8021 
   8022 });
   8023 
   8024 // {123} and converts into symbol with code 123.  It is used by the *macro*
   8025 // \char defined in macros.js.
   8026 
   8027 defineFunction({
   8028   type: "textord",
   8029   names: ["\\@char"],
   8030   props: {
   8031     numArgs: 1,
   8032     allowedInText: true
   8033   },
   8034 
   8035   handler(_ref, args) {
   8036     var {
   8037       parser
   8038     } = _ref;
   8039     var arg = assertNodeType(args[0], "ordgroup");
   8040     var group = arg.body;
   8041     var number = "";
   8042 
   8043     for (var i = 0; i < group.length; i++) {
   8044       var node = assertNodeType(group[i], "textord");
   8045       number += node.text;
   8046     }
   8047 
   8048     var code = parseInt(number);
   8049 
   8050     if (isNaN(code)) {
   8051       throw new ParseError("\\@char has non-numeric argument " + number);
   8052     }
   8053 
   8054     return {
   8055       type: "textord",
   8056       mode: parser.mode,
   8057       text: String.fromCharCode(code)
   8058     };
   8059   }
   8060 
   8061 });
   8062 
   8063 var htmlBuilder$1 = (group, options) => {
   8064   var elements = buildExpression(group.body, options.withColor(group.color), false); // \color isn't supposed to affect the type of the elements it contains.
   8065   // To accomplish this, we wrap the results in a fragment, so the inner
   8066   // elements will be able to directly interact with their neighbors. For
   8067   // example, `\color{red}{2 +} 3` has the same spacing as `2 + 3`
   8068 
   8069   return buildCommon.makeFragment(elements);
   8070 };
   8071 
   8072 var mathmlBuilder$1 = (group, options) => {
   8073   var inner = buildExpression$1(group.body, options.withColor(group.color));
   8074   var node = new mathMLTree.MathNode("mstyle", inner);
   8075   node.setAttribute("mathcolor", group.color);
   8076   return node;
   8077 };
   8078 
   8079 defineFunction({
   8080   type: "color",
   8081   names: ["\\textcolor"],
   8082   props: {
   8083     numArgs: 2,
   8084     allowedInText: true,
   8085     argTypes: ["color", "original"]
   8086   },
   8087 
   8088   handler(_ref, args) {
   8089     var {
   8090       parser
   8091     } = _ref;
   8092     var color = assertNodeType(args[0], "color-token").color;
   8093     var body = args[1];
   8094     return {
   8095       type: "color",
   8096       mode: parser.mode,
   8097       color,
   8098       body: ordargument(body)
   8099     };
   8100   },
   8101 
   8102   htmlBuilder: htmlBuilder$1,
   8103   mathmlBuilder: mathmlBuilder$1
   8104 });
   8105 defineFunction({
   8106   type: "color",
   8107   names: ["\\color"],
   8108   props: {
   8109     numArgs: 1,
   8110     allowedInText: true,
   8111     argTypes: ["color"]
   8112   },
   8113 
   8114   handler(_ref2, args) {
   8115     var {
   8116       parser,
   8117       breakOnTokenText
   8118     } = _ref2;
   8119     var color = assertNodeType(args[0], "color-token").color; // Set macro \current@color in current namespace to store the current
   8120     // color, mimicking the behavior of color.sty.
   8121     // This is currently used just to correctly color a \right
   8122     // that follows a \color command.
   8123 
   8124     parser.gullet.macros.set("\\current@color", color); // Parse out the implicit body that should be colored.
   8125 
   8126     var body = parser.parseExpression(true, breakOnTokenText);
   8127     return {
   8128       type: "color",
   8129       mode: parser.mode,
   8130       color,
   8131       body
   8132     };
   8133   },
   8134 
   8135   htmlBuilder: htmlBuilder$1,
   8136   mathmlBuilder: mathmlBuilder$1
   8137 });
   8138 
   8139 // Row breaks within tabular environments, and line breaks at top level
   8140 
   8141 defineFunction({
   8142   type: "cr",
   8143   names: ["\\\\"],
   8144   props: {
   8145     numArgs: 0,
   8146     numOptionalArgs: 1,
   8147     argTypes: ["size"],
   8148     allowedInText: true
   8149   },
   8150 
   8151   handler(_ref, args, optArgs) {
   8152     var {
   8153       parser
   8154     } = _ref;
   8155     var size = optArgs[0];
   8156     var newLine = !parser.settings.displayMode || !parser.settings.useStrictBehavior("newLineInDisplayMode", "In LaTeX, \\\\ or \\newline " + "does nothing in display mode");
   8157     return {
   8158       type: "cr",
   8159       mode: parser.mode,
   8160       newLine,
   8161       size: size && assertNodeType(size, "size").value
   8162     };
   8163   },
   8164 
   8165   // The following builders are called only at the top level,
   8166   // not within tabular/array environments.
   8167   htmlBuilder(group, options) {
   8168     var span = buildCommon.makeSpan(["mspace"], [], options);
   8169 
   8170     if (group.newLine) {
   8171       span.classes.push("newline");
   8172 
   8173       if (group.size) {
   8174         span.style.marginTop = calculateSize(group.size, options) + "em";
   8175       }
   8176     }
   8177 
   8178     return span;
   8179   },
   8180 
   8181   mathmlBuilder(group, options) {
   8182     var node = new mathMLTree.MathNode("mspace");
   8183 
   8184     if (group.newLine) {
   8185       node.setAttribute("linebreak", "newline");
   8186 
   8187       if (group.size) {
   8188         node.setAttribute("height", calculateSize(group.size, options) + "em");
   8189       }
   8190     }
   8191 
   8192     return node;
   8193   }
   8194 
   8195 });
   8196 
   8197 var globalMap = {
   8198   "\\global": "\\global",
   8199   "\\long": "\\\\globallong",
   8200   "\\\\globallong": "\\\\globallong",
   8201   "\\def": "\\gdef",
   8202   "\\gdef": "\\gdef",
   8203   "\\edef": "\\xdef",
   8204   "\\xdef": "\\xdef",
   8205   "\\let": "\\\\globallet",
   8206   "\\futurelet": "\\\\globalfuture"
   8207 };
   8208 
   8209 var checkControlSequence = tok => {
   8210   var name = tok.text;
   8211 
   8212   if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) {
   8213     throw new ParseError("Expected a control sequence", tok);
   8214   }
   8215 
   8216   return name;
   8217 };
   8218 
   8219 var getRHS = parser => {
   8220   var tok = parser.gullet.popToken();
   8221 
   8222   if (tok.text === "=") {
   8223     // consume optional equals
   8224     tok = parser.gullet.popToken();
   8225 
   8226     if (tok.text === " ") {
   8227       // consume one optional space
   8228       tok = parser.gullet.popToken();
   8229     }
   8230   }
   8231 
   8232   return tok;
   8233 };
   8234 
   8235 var letCommand = (parser, name, tok, global) => {
   8236   var macro = parser.gullet.macros.get(tok.text);
   8237 
   8238   if (macro == null) {
   8239     // don't expand it later even if a macro with the same name is defined
   8240     // e.g., \let\foo=\frac \def\frac{\relax} \frac12
   8241     tok.noexpand = true;
   8242     macro = {
   8243       tokens: [tok],
   8244       numArgs: 0,
   8245       // reproduce the same behavior in expansion
   8246       unexpandable: !parser.gullet.isExpandable(tok.text)
   8247     };
   8248   }
   8249 
   8250   parser.gullet.macros.set(name, macro, global);
   8251 }; // <assignment> -> <non-macro assignment>|<macro assignment>
   8252 // <non-macro assignment> -> <simple assignment>|\global<non-macro assignment>
   8253 // <macro assignment> -> <definition>|<prefix><macro assignment>
   8254 // <prefix> -> \global|\long|\outer
   8255 
   8256 
   8257 defineFunction({
   8258   type: "internal",
   8259   names: ["\\global", "\\long", "\\\\globallong" // can’t be entered directly
   8260   ],
   8261   props: {
   8262     numArgs: 0,
   8263     allowedInText: true
   8264   },
   8265 
   8266   handler(_ref) {
   8267     var {
   8268       parser,
   8269       funcName
   8270     } = _ref;
   8271     parser.consumeSpaces();
   8272     var token = parser.fetch();
   8273 
   8274     if (globalMap[token.text]) {
   8275       // KaTeX doesn't have \par, so ignore \long
   8276       if (funcName === "\\global" || funcName === "\\\\globallong") {
   8277         token.text = globalMap[token.text];
   8278       }
   8279 
   8280       return assertNodeType(parser.parseFunction(), "internal");
   8281     }
   8282 
   8283     throw new ParseError("Invalid token after macro prefix", token);
   8284   }
   8285 
   8286 }); // Basic support for macro definitions: \def, \gdef, \edef, \xdef
   8287 // <definition> -> <def><control sequence><definition text>
   8288 // <def> -> \def|\gdef|\edef|\xdef
   8289 // <definition text> -> <parameter text><left brace><balanced text><right brace>
   8290 
   8291 defineFunction({
   8292   type: "internal",
   8293   names: ["\\def", "\\gdef", "\\edef", "\\xdef"],
   8294   props: {
   8295     numArgs: 0,
   8296     allowedInText: true,
   8297     primitive: true
   8298   },
   8299 
   8300   handler(_ref2) {
   8301     var {
   8302       parser,
   8303       funcName
   8304     } = _ref2;
   8305     var tok = parser.gullet.popToken();
   8306     var name = tok.text;
   8307 
   8308     if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) {
   8309       throw new ParseError("Expected a control sequence", tok);
   8310     }
   8311 
   8312     var numArgs = 0;
   8313     var insert;
   8314     var delimiters = [[]]; // <parameter text> contains no braces
   8315 
   8316     while (parser.gullet.future().text !== "{") {
   8317       tok = parser.gullet.popToken();
   8318 
   8319       if (tok.text === "#") {
   8320         // If the very last character of the <parameter text> is #, so that
   8321         // this # is immediately followed by {, TeX will behave as if the {
   8322         // had been inserted at the right end of both the parameter text
   8323         // and the replacement text.
   8324         if (parser.gullet.future().text === "{") {
   8325           insert = parser.gullet.future();
   8326           delimiters[numArgs].push("{");
   8327           break;
   8328         } // A parameter, the first appearance of # must be followed by 1,
   8329         // the next by 2, and so on; up to nine #’s are allowed
   8330 
   8331 
   8332         tok = parser.gullet.popToken();
   8333 
   8334         if (!/^[1-9]$/.test(tok.text)) {
   8335           throw new ParseError("Invalid argument number \"" + tok.text + "\"");
   8336         }
   8337 
   8338         if (parseInt(tok.text) !== numArgs + 1) {
   8339           throw new ParseError("Argument number \"" + tok.text + "\" out of order");
   8340         }
   8341 
   8342         numArgs++;
   8343         delimiters.push([]);
   8344       } else if (tok.text === "EOF") {
   8345         throw new ParseError("Expected a macro definition");
   8346       } else {
   8347         delimiters[numArgs].push(tok.text);
   8348       }
   8349     } // replacement text, enclosed in '{' and '}' and properly nested
   8350 
   8351 
   8352     var {
   8353       tokens
   8354     } = parser.gullet.consumeArg();
   8355 
   8356     if (insert) {
   8357       tokens.unshift(insert);
   8358     }
   8359 
   8360     if (funcName === "\\edef" || funcName === "\\xdef") {
   8361       tokens = parser.gullet.expandTokens(tokens);
   8362       tokens.reverse(); // to fit in with stack order
   8363     } // Final arg is the expansion of the macro
   8364 
   8365 
   8366     parser.gullet.macros.set(name, {
   8367       tokens,
   8368       numArgs,
   8369       delimiters
   8370     }, funcName === globalMap[funcName]);
   8371     return {
   8372       type: "internal",
   8373       mode: parser.mode
   8374     };
   8375   }
   8376 
   8377 }); // <simple assignment> -> <let assignment>
   8378 // <let assignment> -> \futurelet<control sequence><token><token>
   8379 //     | \let<control sequence><equals><one optional space><token>
   8380 // <equals> -> <optional spaces>|<optional spaces>=
   8381 
   8382 defineFunction({
   8383   type: "internal",
   8384   names: ["\\let", "\\\\globallet" // can’t be entered directly
   8385   ],
   8386   props: {
   8387     numArgs: 0,
   8388     allowedInText: true,
   8389     primitive: true
   8390   },
   8391 
   8392   handler(_ref3) {
   8393     var {
   8394       parser,
   8395       funcName
   8396     } = _ref3;
   8397     var name = checkControlSequence(parser.gullet.popToken());
   8398     parser.gullet.consumeSpaces();
   8399     var tok = getRHS(parser);
   8400     letCommand(parser, name, tok, funcName === "\\\\globallet");
   8401     return {
   8402       type: "internal",
   8403       mode: parser.mode
   8404     };
   8405   }
   8406 
   8407 }); // ref: https://www.tug.org/TUGboat/tb09-3/tb22bechtolsheim.pdf
   8408 
   8409 defineFunction({
   8410   type: "internal",
   8411   names: ["\\futurelet", "\\\\globalfuture" // can’t be entered directly
   8412   ],
   8413   props: {
   8414     numArgs: 0,
   8415     allowedInText: true,
   8416     primitive: true
   8417   },
   8418 
   8419   handler(_ref4) {
   8420     var {
   8421       parser,
   8422       funcName
   8423     } = _ref4;
   8424     var name = checkControlSequence(parser.gullet.popToken());
   8425     var middle = parser.gullet.popToken();
   8426     var tok = parser.gullet.popToken();
   8427     letCommand(parser, name, tok, funcName === "\\\\globalfuture");
   8428     parser.gullet.pushToken(tok);
   8429     parser.gullet.pushToken(middle);
   8430     return {
   8431       type: "internal",
   8432       mode: parser.mode
   8433     };
   8434   }
   8435 
   8436 });
   8437 
   8438 /**
   8439  * This file deals with creating delimiters of various sizes. The TeXbook
   8440  * discusses these routines on page 441-442, in the "Another subroutine sets box
   8441  * x to a specified variable delimiter" paragraph.
   8442  *
   8443  * There are three main routines here. `makeSmallDelim` makes a delimiter in the
   8444  * normal font, but in either text, script, or scriptscript style.
   8445  * `makeLargeDelim` makes a delimiter in textstyle, but in one of the Size1,
   8446  * Size2, Size3, or Size4 fonts. `makeStackedDelim` makes a delimiter out of
   8447  * smaller pieces that are stacked on top of one another.
   8448  *
   8449  * The functions take a parameter `center`, which determines if the delimiter
   8450  * should be centered around the axis.
   8451  *
   8452  * Then, there are three exposed functions. `sizedDelim` makes a delimiter in
   8453  * one of the given sizes. This is used for things like `\bigl`.
   8454  * `customSizedDelim` makes a delimiter with a given total height+depth. It is
   8455  * called in places like `\sqrt`. `leftRightDelim` makes an appropriate
   8456  * delimiter which surrounds an expression of a given height an depth. It is
   8457  * used in `\left` and `\right`.
   8458  */
   8459 
   8460 /**
   8461  * Get the metrics for a given symbol and font, after transformation (i.e.
   8462  * after following replacement from symbols.js)
   8463  */
   8464 var getMetrics = function getMetrics(symbol, font, mode) {
   8465   var replace = symbols.math[symbol] && symbols.math[symbol].replace;
   8466   var metrics = getCharacterMetrics(replace || symbol, font, mode);
   8467 
   8468   if (!metrics) {
   8469     throw new Error("Unsupported symbol " + symbol + " and font size " + font + ".");
   8470   }
   8471 
   8472   return metrics;
   8473 };
   8474 /**
   8475  * Puts a delimiter span in a given style, and adds appropriate height, depth,
   8476  * and maxFontSizes.
   8477  */
   8478 
   8479 
   8480 var styleWrap = function styleWrap(delim, toStyle, options, classes) {
   8481   var newOptions = options.havingBaseStyle(toStyle);
   8482   var span = buildCommon.makeSpan(classes.concat(newOptions.sizingClasses(options)), [delim], options);
   8483   var delimSizeMultiplier = newOptions.sizeMultiplier / options.sizeMultiplier;
   8484   span.height *= delimSizeMultiplier;
   8485   span.depth *= delimSizeMultiplier;
   8486   span.maxFontSize = newOptions.sizeMultiplier;
   8487   return span;
   8488 };
   8489 
   8490 var centerSpan = function centerSpan(span, options, style) {
   8491   var newOptions = options.havingBaseStyle(style);
   8492   var shift = (1 - options.sizeMultiplier / newOptions.sizeMultiplier) * options.fontMetrics().axisHeight;
   8493   span.classes.push("delimcenter");
   8494   span.style.top = shift + "em";
   8495   span.height -= shift;
   8496   span.depth += shift;
   8497 };
   8498 /**
   8499  * Makes a small delimiter. This is a delimiter that comes in the Main-Regular
   8500  * font, but is restyled to either be in textstyle, scriptstyle, or
   8501  * scriptscriptstyle.
   8502  */
   8503 
   8504 
   8505 var makeSmallDelim = function makeSmallDelim(delim, style, center, options, mode, classes) {
   8506   var text = buildCommon.makeSymbol(delim, "Main-Regular", mode, options);
   8507   var span = styleWrap(text, style, options, classes);
   8508 
   8509   if (center) {
   8510     centerSpan(span, options, style);
   8511   }
   8512 
   8513   return span;
   8514 };
   8515 /**
   8516  * Builds a symbol in the given font size (note size is an integer)
   8517  */
   8518 
   8519 
   8520 var mathrmSize = function mathrmSize(value, size, mode, options) {
   8521   return buildCommon.makeSymbol(value, "Size" + size + "-Regular", mode, options);
   8522 };
   8523 /**
   8524  * Makes a large delimiter. This is a delimiter that comes in the Size1, Size2,
   8525  * Size3, or Size4 fonts. It is always rendered in textstyle.
   8526  */
   8527 
   8528 
   8529 var makeLargeDelim = function makeLargeDelim(delim, size, center, options, mode, classes) {
   8530   var inner = mathrmSize(delim, size, mode, options);
   8531   var span = styleWrap(buildCommon.makeSpan(["delimsizing", "size" + size], [inner], options), Style$1.TEXT, options, classes);
   8532 
   8533   if (center) {
   8534     centerSpan(span, options, Style$1.TEXT);
   8535   }
   8536 
   8537   return span;
   8538 };
   8539 /**
   8540  * Make a span from a font glyph with the given offset and in the given font.
   8541  * This is used in makeStackedDelim to make the stacking pieces for the delimiter.
   8542  */
   8543 
   8544 
   8545 var makeGlyphSpan = function makeGlyphSpan(symbol, font, mode) {
   8546   var sizeClass; // Apply the correct CSS class to choose the right font.
   8547 
   8548   if (font === "Size1-Regular") {
   8549     sizeClass = "delim-size1";
   8550   } else
   8551     /* if (font === "Size4-Regular") */
   8552     {
   8553       sizeClass = "delim-size4";
   8554     }
   8555 
   8556   var corner = buildCommon.makeSpan(["delimsizinginner", sizeClass], [buildCommon.makeSpan([], [buildCommon.makeSymbol(symbol, font, mode)])]); // Since this will be passed into `makeVList` in the end, wrap the element
   8557   // in the appropriate tag that VList uses.
   8558 
   8559   return {
   8560     type: "elem",
   8561     elem: corner
   8562   };
   8563 };
   8564 
   8565 var makeInner = function makeInner(ch, height, options) {
   8566   // Create a span with inline SVG for the inner part of a tall stacked delimiter.
   8567   var width = fontMetricsData['Size4-Regular'][ch.charCodeAt(0)] ? fontMetricsData['Size4-Regular'][ch.charCodeAt(0)][4].toFixed(3) : fontMetricsData['Size1-Regular'][ch.charCodeAt(0)][4].toFixed(3);
   8568   var path = new PathNode("inner", innerPath(ch, Math.round(1000 * height)));
   8569   var svgNode = new SvgNode([path], {
   8570     "width": width + "em",
   8571     "height": height + "em",
   8572     // Override CSS rule `.katex svg { width: 100% }`
   8573     "style": "width:" + width + "em",
   8574     "viewBox": "0 0 " + 1000 * width + " " + Math.round(1000 * height),
   8575     "preserveAspectRatio": "xMinYMin"
   8576   });
   8577   var span = buildCommon.makeSvgSpan([], [svgNode], options);
   8578   span.height = height;
   8579   span.style.height = height + "em";
   8580   span.style.width = width + "em";
   8581   return {
   8582     type: "elem",
   8583     elem: span
   8584   };
   8585 }; // Helpers for makeStackedDelim
   8586 
   8587 
   8588 var lapInEms = 0.008;
   8589 var lap = {
   8590   type: "kern",
   8591   size: -1 * lapInEms
   8592 };
   8593 var verts = ["|", "\\lvert", "\\rvert", "\\vert"];
   8594 var doubleVerts = ["\\|", "\\lVert", "\\rVert", "\\Vert"];
   8595 /**
   8596  * Make a stacked delimiter out of a given delimiter, with the total height at
   8597  * least `heightTotal`. This routine is mentioned on page 442 of the TeXbook.
   8598  */
   8599 
   8600 var makeStackedDelim = function makeStackedDelim(delim, heightTotal, center, options, mode, classes) {
   8601   // There are four parts, the top, an optional middle, a repeated part, and a
   8602   // bottom.
   8603   var top;
   8604   var middle;
   8605   var repeat;
   8606   var bottom;
   8607   top = repeat = bottom = delim;
   8608   middle = null; // Also keep track of what font the delimiters are in
   8609 
   8610   var font = "Size1-Regular"; // We set the parts and font based on the symbol. Note that we use
   8611   // '\u23d0' instead of '|' and '\u2016' instead of '\\|' for the
   8612   // repeats of the arrows
   8613 
   8614   if (delim === "\\uparrow") {
   8615     repeat = bottom = "\u23d0";
   8616   } else if (delim === "\\Uparrow") {
   8617     repeat = bottom = "\u2016";
   8618   } else if (delim === "\\downarrow") {
   8619     top = repeat = "\u23d0";
   8620   } else if (delim === "\\Downarrow") {
   8621     top = repeat = "\u2016";
   8622   } else if (delim === "\\updownarrow") {
   8623     top = "\\uparrow";
   8624     repeat = "\u23d0";
   8625     bottom = "\\downarrow";
   8626   } else if (delim === "\\Updownarrow") {
   8627     top = "\\Uparrow";
   8628     repeat = "\u2016";
   8629     bottom = "\\Downarrow";
   8630   } else if (utils.contains(verts, delim)) {
   8631     repeat = "\u2223";
   8632   } else if (utils.contains(doubleVerts, delim)) {
   8633     repeat = "\u2225";
   8634   } else if (delim === "[" || delim === "\\lbrack") {
   8635     top = "\u23a1";
   8636     repeat = "\u23a2";
   8637     bottom = "\u23a3";
   8638     font = "Size4-Regular";
   8639   } else if (delim === "]" || delim === "\\rbrack") {
   8640     top = "\u23a4";
   8641     repeat = "\u23a5";
   8642     bottom = "\u23a6";
   8643     font = "Size4-Regular";
   8644   } else if (delim === "\\lfloor" || delim === "\u230a") {
   8645     repeat = top = "\u23a2";
   8646     bottom = "\u23a3";
   8647     font = "Size4-Regular";
   8648   } else if (delim === "\\lceil" || delim === "\u2308") {
   8649     top = "\u23a1";
   8650     repeat = bottom = "\u23a2";
   8651     font = "Size4-Regular";
   8652   } else if (delim === "\\rfloor" || delim === "\u230b") {
   8653     repeat = top = "\u23a5";
   8654     bottom = "\u23a6";
   8655     font = "Size4-Regular";
   8656   } else if (delim === "\\rceil" || delim === "\u2309") {
   8657     top = "\u23a4";
   8658     repeat = bottom = "\u23a5";
   8659     font = "Size4-Regular";
   8660   } else if (delim === "(" || delim === "\\lparen") {
   8661     top = "\u239b";
   8662     repeat = "\u239c";
   8663     bottom = "\u239d";
   8664     font = "Size4-Regular";
   8665   } else if (delim === ")" || delim === "\\rparen") {
   8666     top = "\u239e";
   8667     repeat = "\u239f";
   8668     bottom = "\u23a0";
   8669     font = "Size4-Regular";
   8670   } else if (delim === "\\{" || delim === "\\lbrace") {
   8671     top = "\u23a7";
   8672     middle = "\u23a8";
   8673     bottom = "\u23a9";
   8674     repeat = "\u23aa";
   8675     font = "Size4-Regular";
   8676   } else if (delim === "\\}" || delim === "\\rbrace") {
   8677     top = "\u23ab";
   8678     middle = "\u23ac";
   8679     bottom = "\u23ad";
   8680     repeat = "\u23aa";
   8681     font = "Size4-Regular";
   8682   } else if (delim === "\\lgroup" || delim === "\u27ee") {
   8683     top = "\u23a7";
   8684     bottom = "\u23a9";
   8685     repeat = "\u23aa";
   8686     font = "Size4-Regular";
   8687   } else if (delim === "\\rgroup" || delim === "\u27ef") {
   8688     top = "\u23ab";
   8689     bottom = "\u23ad";
   8690     repeat = "\u23aa";
   8691     font = "Size4-Regular";
   8692   } else if (delim === "\\lmoustache" || delim === "\u23b0") {
   8693     top = "\u23a7";
   8694     bottom = "\u23ad";
   8695     repeat = "\u23aa";
   8696     font = "Size4-Regular";
   8697   } else if (delim === "\\rmoustache" || delim === "\u23b1") {
   8698     top = "\u23ab";
   8699     bottom = "\u23a9";
   8700     repeat = "\u23aa";
   8701     font = "Size4-Regular";
   8702   } // Get the metrics of the four sections
   8703 
   8704 
   8705   var topMetrics = getMetrics(top, font, mode);
   8706   var topHeightTotal = topMetrics.height + topMetrics.depth;
   8707   var repeatMetrics = getMetrics(repeat, font, mode);
   8708   var repeatHeightTotal = repeatMetrics.height + repeatMetrics.depth;
   8709   var bottomMetrics = getMetrics(bottom, font, mode);
   8710   var bottomHeightTotal = bottomMetrics.height + bottomMetrics.depth;
   8711   var middleHeightTotal = 0;
   8712   var middleFactor = 1;
   8713 
   8714   if (middle !== null) {
   8715     var middleMetrics = getMetrics(middle, font, mode);
   8716     middleHeightTotal = middleMetrics.height + middleMetrics.depth;
   8717     middleFactor = 2; // repeat symmetrically above and below middle
   8718   } // Calcuate the minimal height that the delimiter can have.
   8719   // It is at least the size of the top, bottom, and optional middle combined.
   8720 
   8721 
   8722   var minHeight = topHeightTotal + bottomHeightTotal + middleHeightTotal; // Compute the number of copies of the repeat symbol we will need
   8723 
   8724   var repeatCount = Math.max(0, Math.ceil((heightTotal - minHeight) / (middleFactor * repeatHeightTotal))); // Compute the total height of the delimiter including all the symbols
   8725 
   8726   var realHeightTotal = minHeight + repeatCount * middleFactor * repeatHeightTotal; // The center of the delimiter is placed at the center of the axis. Note
   8727   // that in this context, "center" means that the delimiter should be
   8728   // centered around the axis in the current style, while normally it is
   8729   // centered around the axis in textstyle.
   8730 
   8731   var axisHeight = options.fontMetrics().axisHeight;
   8732 
   8733   if (center) {
   8734     axisHeight *= options.sizeMultiplier;
   8735   } // Calculate the depth
   8736 
   8737 
   8738   var depth = realHeightTotal / 2 - axisHeight; // Now, we start building the pieces that will go into the vlist
   8739   // Keep a list of the pieces of the stacked delimiter
   8740 
   8741   var stack = []; // Add the bottom symbol
   8742 
   8743   stack.push(makeGlyphSpan(bottom, font, mode));
   8744   stack.push(lap); // overlap
   8745 
   8746   if (middle === null) {
   8747     // The middle section will be an SVG. Make it an extra 0.016em tall.
   8748     // We'll overlap by 0.008em at top and bottom.
   8749     var innerHeight = realHeightTotal - topHeightTotal - bottomHeightTotal + 2 * lapInEms;
   8750     stack.push(makeInner(repeat, innerHeight, options));
   8751   } else {
   8752     // When there is a middle bit, we need the middle part and two repeated
   8753     // sections
   8754     var _innerHeight = (realHeightTotal - topHeightTotal - bottomHeightTotal - middleHeightTotal) / 2 + 2 * lapInEms;
   8755 
   8756     stack.push(makeInner(repeat, _innerHeight, options)); // Now insert the middle of the brace.
   8757 
   8758     stack.push(lap);
   8759     stack.push(makeGlyphSpan(middle, font, mode));
   8760     stack.push(lap);
   8761     stack.push(makeInner(repeat, _innerHeight, options));
   8762   } // Add the top symbol
   8763 
   8764 
   8765   stack.push(lap);
   8766   stack.push(makeGlyphSpan(top, font, mode)); // Finally, build the vlist
   8767 
   8768   var newOptions = options.havingBaseStyle(Style$1.TEXT);
   8769   var inner = buildCommon.makeVList({
   8770     positionType: "bottom",
   8771     positionData: depth,
   8772     children: stack
   8773   }, newOptions);
   8774   return styleWrap(buildCommon.makeSpan(["delimsizing", "mult"], [inner], newOptions), Style$1.TEXT, options, classes);
   8775 }; // All surds have 0.08em padding above the viniculum inside the SVG.
   8776 // That keeps browser span height rounding error from pinching the line.
   8777 
   8778 
   8779 var vbPad = 80; // padding above the surd, measured inside the viewBox.
   8780 
   8781 var emPad = 0.08; // padding, in ems, measured in the document.
   8782 
   8783 var sqrtSvg = function sqrtSvg(sqrtName, height, viewBoxHeight, extraViniculum, options) {
   8784   var path = sqrtPath(sqrtName, extraViniculum, viewBoxHeight);
   8785   var pathNode = new PathNode(sqrtName, path);
   8786   var svg = new SvgNode([pathNode], {
   8787     // Note: 1000:1 ratio of viewBox to document em width.
   8788     "width": "400em",
   8789     "height": height + "em",
   8790     "viewBox": "0 0 400000 " + viewBoxHeight,
   8791     "preserveAspectRatio": "xMinYMin slice"
   8792   });
   8793   return buildCommon.makeSvgSpan(["hide-tail"], [svg], options);
   8794 };
   8795 /**
   8796  * Make a sqrt image of the given height,
   8797  */
   8798 
   8799 
   8800 var makeSqrtImage = function makeSqrtImage(height, options) {
   8801   // Define a newOptions that removes the effect of size changes such as \Huge.
   8802   // We don't pick different a height surd for \Huge. For it, we scale up.
   8803   var newOptions = options.havingBaseSizing(); // Pick the desired surd glyph from a sequence of surds.
   8804 
   8805   var delim = traverseSequence("\\surd", height * newOptions.sizeMultiplier, stackLargeDelimiterSequence, newOptions);
   8806   var sizeMultiplier = newOptions.sizeMultiplier; // default
   8807   // The standard sqrt SVGs each have a 0.04em thick viniculum.
   8808   // If Settings.minRuleThickness is larger than that, we add extraViniculum.
   8809 
   8810   var extraViniculum = Math.max(0, options.minRuleThickness - options.fontMetrics().sqrtRuleThickness); // Create a span containing an SVG image of a sqrt symbol.
   8811 
   8812   var span;
   8813   var spanHeight = 0;
   8814   var texHeight = 0;
   8815   var viewBoxHeight = 0;
   8816   var advanceWidth; // We create viewBoxes with 80 units of "padding" above each surd.
   8817   // Then browser rounding error on the parent span height will not
   8818   // encroach on the ink of the viniculum. But that padding is not
   8819   // included in the TeX-like `height` used for calculation of
   8820   // vertical alignment. So texHeight = span.height < span.style.height.
   8821 
   8822   if (delim.type === "small") {
   8823     // Get an SVG that is derived from glyph U+221A in font KaTeX-Main.
   8824     // 1000 unit normal glyph height.
   8825     viewBoxHeight = 1000 + 1000 * extraViniculum + vbPad;
   8826 
   8827     if (height < 1.0) {
   8828       sizeMultiplier = 1.0; // mimic a \textfont radical
   8829     } else if (height < 1.4) {
   8830       sizeMultiplier = 0.7; // mimic a \scriptfont radical
   8831     }
   8832 
   8833     spanHeight = (1.0 + extraViniculum + emPad) / sizeMultiplier;
   8834     texHeight = (1.00 + extraViniculum) / sizeMultiplier;
   8835     span = sqrtSvg("sqrtMain", spanHeight, viewBoxHeight, extraViniculum, options);
   8836     span.style.minWidth = "0.853em";
   8837     advanceWidth = 0.833 / sizeMultiplier; // from the font.
   8838   } else if (delim.type === "large") {
   8839     // These SVGs come from fonts: KaTeX_Size1, _Size2, etc.
   8840     viewBoxHeight = (1000 + vbPad) * sizeToMaxHeight[delim.size];
   8841     texHeight = (sizeToMaxHeight[delim.size] + extraViniculum) / sizeMultiplier;
   8842     spanHeight = (sizeToMaxHeight[delim.size] + extraViniculum + emPad) / sizeMultiplier;
   8843     span = sqrtSvg("sqrtSize" + delim.size, spanHeight, viewBoxHeight, extraViniculum, options);
   8844     span.style.minWidth = "1.02em";
   8845     advanceWidth = 1.0 / sizeMultiplier; // 1.0 from the font.
   8846   } else {
   8847     // Tall sqrt. In TeX, this would be stacked using multiple glyphs.
   8848     // We'll use a single SVG to accomplish the same thing.
   8849     spanHeight = height + extraViniculum + emPad;
   8850     texHeight = height + extraViniculum;
   8851     viewBoxHeight = Math.floor(1000 * height + extraViniculum) + vbPad;
   8852     span = sqrtSvg("sqrtTall", spanHeight, viewBoxHeight, extraViniculum, options);
   8853     span.style.minWidth = "0.742em";
   8854     advanceWidth = 1.056;
   8855   }
   8856 
   8857   span.height = texHeight;
   8858   span.style.height = spanHeight + "em";
   8859   return {
   8860     span,
   8861     advanceWidth,
   8862     // Calculate the actual line width.
   8863     // This actually should depend on the chosen font -- e.g. \boldmath
   8864     // should use the thicker surd symbols from e.g. KaTeX_Main-Bold, and
   8865     // have thicker rules.
   8866     ruleWidth: (options.fontMetrics().sqrtRuleThickness + extraViniculum) * sizeMultiplier
   8867   };
   8868 }; // There are three kinds of delimiters, delimiters that stack when they become
   8869 // too large
   8870 
   8871 
   8872 var stackLargeDelimiters = ["(", "\\lparen", ")", "\\rparen", "[", "\\lbrack", "]", "\\rbrack", "\\{", "\\lbrace", "\\}", "\\rbrace", "\\lfloor", "\\rfloor", "\u230a", "\u230b", "\\lceil", "\\rceil", "\u2308", "\u2309", "\\surd"]; // delimiters that always stack
   8873 
   8874 var stackAlwaysDelimiters = ["\\uparrow", "\\downarrow", "\\updownarrow", "\\Uparrow", "\\Downarrow", "\\Updownarrow", "|", "\\|", "\\vert", "\\Vert", "\\lvert", "\\rvert", "\\lVert", "\\rVert", "\\lgroup", "\\rgroup", "\u27ee", "\u27ef", "\\lmoustache", "\\rmoustache", "\u23b0", "\u23b1"]; // and delimiters that never stack
   8875 
   8876 var stackNeverDelimiters = ["<", ">", "\\langle", "\\rangle", "/", "\\backslash", "\\lt", "\\gt"]; // Metrics of the different sizes. Found by looking at TeX's output of
   8877 // $\bigl| // \Bigl| \biggl| \Biggl| \showlists$
   8878 // Used to create stacked delimiters of appropriate sizes in makeSizedDelim.
   8879 
   8880 var sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0];
   8881 /**
   8882  * Used to create a delimiter of a specific size, where `size` is 1, 2, 3, or 4.
   8883  */
   8884 
   8885 var makeSizedDelim = function makeSizedDelim(delim, size, options, mode, classes) {
   8886   // < and > turn into \langle and \rangle in delimiters
   8887   if (delim === "<" || delim === "\\lt" || delim === "\u27e8") {
   8888     delim = "\\langle";
   8889   } else if (delim === ">" || delim === "\\gt" || delim === "\u27e9") {
   8890     delim = "\\rangle";
   8891   } // Sized delimiters are never centered.
   8892 
   8893 
   8894   if (utils.contains(stackLargeDelimiters, delim) || utils.contains(stackNeverDelimiters, delim)) {
   8895     return makeLargeDelim(delim, size, false, options, mode, classes);
   8896   } else if (utils.contains(stackAlwaysDelimiters, delim)) {
   8897     return makeStackedDelim(delim, sizeToMaxHeight[size], false, options, mode, classes);
   8898   } else {
   8899     throw new ParseError("Illegal delimiter: '" + delim + "'");
   8900   }
   8901 };
   8902 /**
   8903  * There are three different sequences of delimiter sizes that the delimiters
   8904  * follow depending on the kind of delimiter. This is used when creating custom
   8905  * sized delimiters to decide whether to create a small, large, or stacked
   8906  * delimiter.
   8907  *
   8908  * In real TeX, these sequences aren't explicitly defined, but are instead
   8909  * defined inside the font metrics. Since there are only three sequences that
   8910  * are possible for the delimiters that TeX defines, it is easier to just encode
   8911  * them explicitly here.
   8912  */
   8913 
   8914 
   8915 // Delimiters that never stack try small delimiters and large delimiters only
   8916 var stackNeverDelimiterSequence = [{
   8917   type: "small",
   8918   style: Style$1.SCRIPTSCRIPT
   8919 }, {
   8920   type: "small",
   8921   style: Style$1.SCRIPT
   8922 }, {
   8923   type: "small",
   8924   style: Style$1.TEXT
   8925 }, {
   8926   type: "large",
   8927   size: 1
   8928 }, {
   8929   type: "large",
   8930   size: 2
   8931 }, {
   8932   type: "large",
   8933   size: 3
   8934 }, {
   8935   type: "large",
   8936   size: 4
   8937 }]; // Delimiters that always stack try the small delimiters first, then stack
   8938 
   8939 var stackAlwaysDelimiterSequence = [{
   8940   type: "small",
   8941   style: Style$1.SCRIPTSCRIPT
   8942 }, {
   8943   type: "small",
   8944   style: Style$1.SCRIPT
   8945 }, {
   8946   type: "small",
   8947   style: Style$1.TEXT
   8948 }, {
   8949   type: "stack"
   8950 }]; // Delimiters that stack when large try the small and then large delimiters, and
   8951 // stack afterwards
   8952 
   8953 var stackLargeDelimiterSequence = [{
   8954   type: "small",
   8955   style: Style$1.SCRIPTSCRIPT
   8956 }, {
   8957   type: "small",
   8958   style: Style$1.SCRIPT
   8959 }, {
   8960   type: "small",
   8961   style: Style$1.TEXT
   8962 }, {
   8963   type: "large",
   8964   size: 1
   8965 }, {
   8966   type: "large",
   8967   size: 2
   8968 }, {
   8969   type: "large",
   8970   size: 3
   8971 }, {
   8972   type: "large",
   8973   size: 4
   8974 }, {
   8975   type: "stack"
   8976 }];
   8977 /**
   8978  * Get the font used in a delimiter based on what kind of delimiter it is.
   8979  * TODO(#963) Use more specific font family return type once that is introduced.
   8980  */
   8981 
   8982 var delimTypeToFont = function delimTypeToFont(type) {
   8983   if (type.type === "small") {
   8984     return "Main-Regular";
   8985   } else if (type.type === "large") {
   8986     return "Size" + type.size + "-Regular";
   8987   } else if (type.type === "stack") {
   8988     return "Size4-Regular";
   8989   } else {
   8990     throw new Error("Add support for delim type '" + type.type + "' here.");
   8991   }
   8992 };
   8993 /**
   8994  * Traverse a sequence of types of delimiters to decide what kind of delimiter
   8995  * should be used to create a delimiter of the given height+depth.
   8996  */
   8997 
   8998 
   8999 var traverseSequence = function traverseSequence(delim, height, sequence, options) {
   9000   // Here, we choose the index we should start at in the sequences. In smaller
   9001   // sizes (which correspond to larger numbers in style.size) we start earlier
   9002   // in the sequence. Thus, scriptscript starts at index 3-3=0, script starts
   9003   // at index 3-2=1, text starts at 3-1=2, and display starts at min(2,3-0)=2
   9004   var start = Math.min(2, 3 - options.style.size);
   9005 
   9006   for (var i = start; i < sequence.length; i++) {
   9007     if (sequence[i].type === "stack") {
   9008       // This is always the last delimiter, so we just break the loop now.
   9009       break;
   9010     }
   9011 
   9012     var metrics = getMetrics(delim, delimTypeToFont(sequence[i]), "math");
   9013     var heightDepth = metrics.height + metrics.depth; // Small delimiters are scaled down versions of the same font, so we
   9014     // account for the style change size.
   9015 
   9016     if (sequence[i].type === "small") {
   9017       var newOptions = options.havingBaseStyle(sequence[i].style);
   9018       heightDepth *= newOptions.sizeMultiplier;
   9019     } // Check if the delimiter at this size works for the given height.
   9020 
   9021 
   9022     if (heightDepth > height) {
   9023       return sequence[i];
   9024     }
   9025   } // If we reached the end of the sequence, return the last sequence element.
   9026 
   9027 
   9028   return sequence[sequence.length - 1];
   9029 };
   9030 /**
   9031  * Make a delimiter of a given height+depth, with optional centering. Here, we
   9032  * traverse the sequences, and create a delimiter that the sequence tells us to.
   9033  */
   9034 
   9035 
   9036 var makeCustomSizedDelim = function makeCustomSizedDelim(delim, height, center, options, mode, classes) {
   9037   if (delim === "<" || delim === "\\lt" || delim === "\u27e8") {
   9038     delim = "\\langle";
   9039   } else if (delim === ">" || delim === "\\gt" || delim === "\u27e9") {
   9040     delim = "\\rangle";
   9041   } // Decide what sequence to use
   9042 
   9043 
   9044   var sequence;
   9045 
   9046   if (utils.contains(stackNeverDelimiters, delim)) {
   9047     sequence = stackNeverDelimiterSequence;
   9048   } else if (utils.contains(stackLargeDelimiters, delim)) {
   9049     sequence = stackLargeDelimiterSequence;
   9050   } else {
   9051     sequence = stackAlwaysDelimiterSequence;
   9052   } // Look through the sequence
   9053 
   9054 
   9055   var delimType = traverseSequence(delim, height, sequence, options); // Get the delimiter from font glyphs.
   9056   // Depending on the sequence element we decided on, call the
   9057   // appropriate function.
   9058 
   9059   if (delimType.type === "small") {
   9060     return makeSmallDelim(delim, delimType.style, center, options, mode, classes);
   9061   } else if (delimType.type === "large") {
   9062     return makeLargeDelim(delim, delimType.size, center, options, mode, classes);
   9063   } else
   9064     /* if (delimType.type === "stack") */
   9065     {
   9066       return makeStackedDelim(delim, height, center, options, mode, classes);
   9067     }
   9068 };
   9069 /**
   9070  * Make a delimiter for use with `\left` and `\right`, given a height and depth
   9071  * of an expression that the delimiters surround.
   9072  */
   9073 
   9074 
   9075 var makeLeftRightDelim = function makeLeftRightDelim(delim, height, depth, options, mode, classes) {
   9076   // We always center \left/\right delimiters, so the axis is always shifted
   9077   var axisHeight = options.fontMetrics().axisHeight * options.sizeMultiplier; // Taken from TeX source, tex.web, function make_left_right
   9078 
   9079   var delimiterFactor = 901;
   9080   var delimiterExtend = 5.0 / options.fontMetrics().ptPerEm;
   9081   var maxDistFromAxis = Math.max(height - axisHeight, depth + axisHeight);
   9082   var totalHeight = Math.max( // In real TeX, calculations are done using integral values which are
   9083   // 65536 per pt, or 655360 per em. So, the division here truncates in
   9084   // TeX but doesn't here, producing different results. If we wanted to
   9085   // exactly match TeX's calculation, we could do
   9086   //   Math.floor(655360 * maxDistFromAxis / 500) *
   9087   //    delimiterFactor / 655360
   9088   // (To see the difference, compare
   9089   //    x^{x^{\left(\rule{0.1em}{0.68em}\right)}}
   9090   // in TeX and KaTeX)
   9091   maxDistFromAxis / 500 * delimiterFactor, 2 * maxDistFromAxis - delimiterExtend); // Finally, we defer to `makeCustomSizedDelim` with our calculated total
   9092   // height
   9093 
   9094   return makeCustomSizedDelim(delim, totalHeight, true, options, mode, classes);
   9095 };
   9096 
   9097 var delimiter = {
   9098   sqrtImage: makeSqrtImage,
   9099   sizedDelim: makeSizedDelim,
   9100   sizeToMaxHeight: sizeToMaxHeight,
   9101   customSizedDelim: makeCustomSizedDelim,
   9102   leftRightDelim: makeLeftRightDelim
   9103 };
   9104 
   9105 // Extra data needed for the delimiter handler down below
   9106 var delimiterSizes = {
   9107   "\\bigl": {
   9108     mclass: "mopen",
   9109     size: 1
   9110   },
   9111   "\\Bigl": {
   9112     mclass: "mopen",
   9113     size: 2
   9114   },
   9115   "\\biggl": {
   9116     mclass: "mopen",
   9117     size: 3
   9118   },
   9119   "\\Biggl": {
   9120     mclass: "mopen",
   9121     size: 4
   9122   },
   9123   "\\bigr": {
   9124     mclass: "mclose",
   9125     size: 1
   9126   },
   9127   "\\Bigr": {
   9128     mclass: "mclose",
   9129     size: 2
   9130   },
   9131   "\\biggr": {
   9132     mclass: "mclose",
   9133     size: 3
   9134   },
   9135   "\\Biggr": {
   9136     mclass: "mclose",
   9137     size: 4
   9138   },
   9139   "\\bigm": {
   9140     mclass: "mrel",
   9141     size: 1
   9142   },
   9143   "\\Bigm": {
   9144     mclass: "mrel",
   9145     size: 2
   9146   },
   9147   "\\biggm": {
   9148     mclass: "mrel",
   9149     size: 3
   9150   },
   9151   "\\Biggm": {
   9152     mclass: "mrel",
   9153     size: 4
   9154   },
   9155   "\\big": {
   9156     mclass: "mord",
   9157     size: 1
   9158   },
   9159   "\\Big": {
   9160     mclass: "mord",
   9161     size: 2
   9162   },
   9163   "\\bigg": {
   9164     mclass: "mord",
   9165     size: 3
   9166   },
   9167   "\\Bigg": {
   9168     mclass: "mord",
   9169     size: 4
   9170   }
   9171 };
   9172 var delimiters = ["(", "\\lparen", ")", "\\rparen", "[", "\\lbrack", "]", "\\rbrack", "\\{", "\\lbrace", "\\}", "\\rbrace", "\\lfloor", "\\rfloor", "\u230a", "\u230b", "\\lceil", "\\rceil", "\u2308", "\u2309", "<", ">", "\\langle", "\u27e8", "\\rangle", "\u27e9", "\\lt", "\\gt", "\\lvert", "\\rvert", "\\lVert", "\\rVert", "\\lgroup", "\\rgroup", "\u27ee", "\u27ef", "\\lmoustache", "\\rmoustache", "\u23b0", "\u23b1", "/", "\\backslash", "|", "\\vert", "\\|", "\\Vert", "\\uparrow", "\\Uparrow", "\\downarrow", "\\Downarrow", "\\updownarrow", "\\Updownarrow", "."];
   9173 
   9174 // Delimiter functions
   9175 function checkDelimiter(delim, context) {
   9176   var symDelim = checkSymbolNodeType(delim);
   9177 
   9178   if (symDelim && utils.contains(delimiters, symDelim.text)) {
   9179     return symDelim;
   9180   } else if (symDelim) {
   9181     throw new ParseError("Invalid delimiter '" + symDelim.text + "' after '" + context.funcName + "'", delim);
   9182   } else {
   9183     throw new ParseError("Invalid delimiter type '" + delim.type + "'", delim);
   9184   }
   9185 }
   9186 
   9187 defineFunction({
   9188   type: "delimsizing",
   9189   names: ["\\bigl", "\\Bigl", "\\biggl", "\\Biggl", "\\bigr", "\\Bigr", "\\biggr", "\\Biggr", "\\bigm", "\\Bigm", "\\biggm", "\\Biggm", "\\big", "\\Big", "\\bigg", "\\Bigg"],
   9190   props: {
   9191     numArgs: 1,
   9192     argTypes: ["primitive"]
   9193   },
   9194   handler: (context, args) => {
   9195     var delim = checkDelimiter(args[0], context);
   9196     return {
   9197       type: "delimsizing",
   9198       mode: context.parser.mode,
   9199       size: delimiterSizes[context.funcName].size,
   9200       mclass: delimiterSizes[context.funcName].mclass,
   9201       delim: delim.text
   9202     };
   9203   },
   9204   htmlBuilder: (group, options) => {
   9205     if (group.delim === ".") {
   9206       // Empty delimiters still count as elements, even though they don't
   9207       // show anything.
   9208       return buildCommon.makeSpan([group.mclass]);
   9209     } // Use delimiter.sizedDelim to generate the delimiter.
   9210 
   9211 
   9212     return delimiter.sizedDelim(group.delim, group.size, options, group.mode, [group.mclass]);
   9213   },
   9214   mathmlBuilder: group => {
   9215     var children = [];
   9216 
   9217     if (group.delim !== ".") {
   9218       children.push(makeText(group.delim, group.mode));
   9219     }
   9220 
   9221     var node = new mathMLTree.MathNode("mo", children);
   9222 
   9223     if (group.mclass === "mopen" || group.mclass === "mclose") {
   9224       // Only some of the delimsizing functions act as fences, and they
   9225       // return "mopen" or "mclose" mclass.
   9226       node.setAttribute("fence", "true");
   9227     } else {
   9228       // Explicitly disable fencing if it's not a fence, to override the
   9229       // defaults.
   9230       node.setAttribute("fence", "false");
   9231     }
   9232 
   9233     node.setAttribute("stretchy", "true");
   9234     node.setAttribute("minsize", delimiter.sizeToMaxHeight[group.size] + "em");
   9235     node.setAttribute("maxsize", delimiter.sizeToMaxHeight[group.size] + "em");
   9236     return node;
   9237   }
   9238 });
   9239 
   9240 function assertParsed(group) {
   9241   if (!group.body) {
   9242     throw new Error("Bug: The leftright ParseNode wasn't fully parsed.");
   9243   }
   9244 }
   9245 
   9246 defineFunction({
   9247   type: "leftright-right",
   9248   names: ["\\right"],
   9249   props: {
   9250     numArgs: 1,
   9251     primitive: true
   9252   },
   9253   handler: (context, args) => {
   9254     // \left case below triggers parsing of \right in
   9255     //   `const right = parser.parseFunction();`
   9256     // uses this return value.
   9257     var color = context.parser.gullet.macros.get("\\current@color");
   9258 
   9259     if (color && typeof color !== "string") {
   9260       throw new ParseError("\\current@color set to non-string in \\right");
   9261     }
   9262 
   9263     return {
   9264       type: "leftright-right",
   9265       mode: context.parser.mode,
   9266       delim: checkDelimiter(args[0], context).text,
   9267       color // undefined if not set via \color
   9268 
   9269     };
   9270   }
   9271 });
   9272 defineFunction({
   9273   type: "leftright",
   9274   names: ["\\left"],
   9275   props: {
   9276     numArgs: 1,
   9277     primitive: true
   9278   },
   9279   handler: (context, args) => {
   9280     var delim = checkDelimiter(args[0], context);
   9281     var parser = context.parser; // Parse out the implicit body
   9282 
   9283     ++parser.leftrightDepth; // parseExpression stops before '\\right'
   9284 
   9285     var body = parser.parseExpression(false);
   9286     --parser.leftrightDepth; // Check the next token
   9287 
   9288     parser.expect("\\right", false);
   9289     var right = assertNodeType(parser.parseFunction(), "leftright-right");
   9290     return {
   9291       type: "leftright",
   9292       mode: parser.mode,
   9293       body,
   9294       left: delim.text,
   9295       right: right.delim,
   9296       rightColor: right.color
   9297     };
   9298   },
   9299   htmlBuilder: (group, options) => {
   9300     assertParsed(group); // Build the inner expression
   9301 
   9302     var inner = buildExpression(group.body, options, true, ["mopen", "mclose"]);
   9303     var innerHeight = 0;
   9304     var innerDepth = 0;
   9305     var hadMiddle = false; // Calculate its height and depth
   9306 
   9307     for (var i = 0; i < inner.length; i++) {
   9308       // Property `isMiddle` not defined on `span`. See comment in
   9309       // "middle"'s htmlBuilder.
   9310       // $FlowFixMe
   9311       if (inner[i].isMiddle) {
   9312         hadMiddle = true;
   9313       } else {
   9314         innerHeight = Math.max(inner[i].height, innerHeight);
   9315         innerDepth = Math.max(inner[i].depth, innerDepth);
   9316       }
   9317     } // The size of delimiters is the same, regardless of what style we are
   9318     // in. Thus, to correctly calculate the size of delimiter we need around
   9319     // a group, we scale down the inner size based on the size.
   9320 
   9321 
   9322     innerHeight *= options.sizeMultiplier;
   9323     innerDepth *= options.sizeMultiplier;
   9324     var leftDelim;
   9325 
   9326     if (group.left === ".") {
   9327       // Empty delimiters in \left and \right make null delimiter spaces.
   9328       leftDelim = makeNullDelimiter(options, ["mopen"]);
   9329     } else {
   9330       // Otherwise, use leftRightDelim to generate the correct sized
   9331       // delimiter.
   9332       leftDelim = delimiter.leftRightDelim(group.left, innerHeight, innerDepth, options, group.mode, ["mopen"]);
   9333     } // Add it to the beginning of the expression
   9334 
   9335 
   9336     inner.unshift(leftDelim); // Handle middle delimiters
   9337 
   9338     if (hadMiddle) {
   9339       for (var _i = 1; _i < inner.length; _i++) {
   9340         var middleDelim = inner[_i]; // Property `isMiddle` not defined on `span`. See comment in
   9341         // "middle"'s htmlBuilder.
   9342         // $FlowFixMe
   9343 
   9344         var isMiddle = middleDelim.isMiddle;
   9345 
   9346         if (isMiddle) {
   9347           // Apply the options that were active when \middle was called
   9348           inner[_i] = delimiter.leftRightDelim(isMiddle.delim, innerHeight, innerDepth, isMiddle.options, group.mode, []);
   9349         }
   9350       }
   9351     }
   9352 
   9353     var rightDelim; // Same for the right delimiter, but using color specified by \color
   9354 
   9355     if (group.right === ".") {
   9356       rightDelim = makeNullDelimiter(options, ["mclose"]);
   9357     } else {
   9358       var colorOptions = group.rightColor ? options.withColor(group.rightColor) : options;
   9359       rightDelim = delimiter.leftRightDelim(group.right, innerHeight, innerDepth, colorOptions, group.mode, ["mclose"]);
   9360     } // Add it to the end of the expression.
   9361 
   9362 
   9363     inner.push(rightDelim);
   9364     return buildCommon.makeSpan(["minner"], inner, options);
   9365   },
   9366   mathmlBuilder: (group, options) => {
   9367     assertParsed(group);
   9368     var inner = buildExpression$1(group.body, options);
   9369 
   9370     if (group.left !== ".") {
   9371       var leftNode = new mathMLTree.MathNode("mo", [makeText(group.left, group.mode)]);
   9372       leftNode.setAttribute("fence", "true");
   9373       inner.unshift(leftNode);
   9374     }
   9375 
   9376     if (group.right !== ".") {
   9377       var rightNode = new mathMLTree.MathNode("mo", [makeText(group.right, group.mode)]);
   9378       rightNode.setAttribute("fence", "true");
   9379 
   9380       if (group.rightColor) {
   9381         rightNode.setAttribute("mathcolor", group.rightColor);
   9382       }
   9383 
   9384       inner.push(rightNode);
   9385     }
   9386 
   9387     return makeRow(inner);
   9388   }
   9389 });
   9390 defineFunction({
   9391   type: "middle",
   9392   names: ["\\middle"],
   9393   props: {
   9394     numArgs: 1,
   9395     primitive: true
   9396   },
   9397   handler: (context, args) => {
   9398     var delim = checkDelimiter(args[0], context);
   9399 
   9400     if (!context.parser.leftrightDepth) {
   9401       throw new ParseError("\\middle without preceding \\left", delim);
   9402     }
   9403 
   9404     return {
   9405       type: "middle",
   9406       mode: context.parser.mode,
   9407       delim: delim.text
   9408     };
   9409   },
   9410   htmlBuilder: (group, options) => {
   9411     var middleDelim;
   9412 
   9413     if (group.delim === ".") {
   9414       middleDelim = makeNullDelimiter(options, []);
   9415     } else {
   9416       middleDelim = delimiter.sizedDelim(group.delim, 1, options, group.mode, []);
   9417       var isMiddle = {
   9418         delim: group.delim,
   9419         options
   9420       }; // Property `isMiddle` not defined on `span`. It is only used in
   9421       // this file above.
   9422       // TODO: Fix this violation of the `span` type and possibly rename
   9423       // things since `isMiddle` sounds like a boolean, but is a struct.
   9424       // $FlowFixMe
   9425 
   9426       middleDelim.isMiddle = isMiddle;
   9427     }
   9428 
   9429     return middleDelim;
   9430   },
   9431   mathmlBuilder: (group, options) => {
   9432     // A Firefox \middle will strech a character vertically only if it
   9433     // is in the fence part of the operator dictionary at:
   9434     // https://www.w3.org/TR/MathML3/appendixc.html.
   9435     // So we need to avoid U+2223 and use plain "|" instead.
   9436     var textNode = group.delim === "\\vert" || group.delim === "|" ? makeText("|", "text") : makeText(group.delim, group.mode);
   9437     var middleNode = new mathMLTree.MathNode("mo", [textNode]);
   9438     middleNode.setAttribute("fence", "true"); // MathML gives 5/18em spacing to each <mo> element.
   9439     // \middle should get delimiter spacing instead.
   9440 
   9441     middleNode.setAttribute("lspace", "0.05em");
   9442     middleNode.setAttribute("rspace", "0.05em");
   9443     return middleNode;
   9444   }
   9445 });
   9446 
   9447 var htmlBuilder$2 = (group, options) => {
   9448   // \cancel, \bcancel, \xcancel, \sout, \fbox, \colorbox, \fcolorbox, \phase
   9449   // Some groups can return document fragments.  Handle those by wrapping
   9450   // them in a span.
   9451   var inner = buildCommon.wrapFragment(buildGroup(group.body, options), options);
   9452   var label = group.label.substr(1);
   9453   var scale = options.sizeMultiplier;
   9454   var img;
   9455   var imgShift = 0; // In the LaTeX cancel package, line geometry is slightly different
   9456   // depending on whether the subject is wider than it is tall, or vice versa.
   9457   // We don't know the width of a group, so as a proxy, we test if
   9458   // the subject is a single character. This captures most of the
   9459   // subjects that should get the "tall" treatment.
   9460 
   9461   var isSingleChar = utils.isCharacterBox(group.body);
   9462 
   9463   if (label === "sout") {
   9464     img = buildCommon.makeSpan(["stretchy", "sout"]);
   9465     img.height = options.fontMetrics().defaultRuleThickness / scale;
   9466     imgShift = -0.5 * options.fontMetrics().xHeight;
   9467   } else if (label === "phase") {
   9468     // Set a couple of dimensions from the steinmetz package.
   9469     var lineWeight = calculateSize({
   9470       number: 0.6,
   9471       unit: "pt"
   9472     }, options);
   9473     var clearance = calculateSize({
   9474       number: 0.35,
   9475       unit: "ex"
   9476     }, options); // Prevent size changes like \Huge from affecting line thickness
   9477 
   9478     var newOptions = options.havingBaseSizing();
   9479     scale = scale / newOptions.sizeMultiplier;
   9480     var angleHeight = inner.height + inner.depth + lineWeight + clearance; // Reserve a left pad for the angle.
   9481 
   9482     inner.style.paddingLeft = angleHeight / 2 + lineWeight + "em"; // Create an SVG
   9483 
   9484     var viewBoxHeight = Math.floor(1000 * angleHeight * scale);
   9485     var path = phasePath(viewBoxHeight);
   9486     var svgNode = new SvgNode([new PathNode("phase", path)], {
   9487       "width": "400em",
   9488       "height": viewBoxHeight / 1000 + "em",
   9489       "viewBox": "0 0 400000 " + viewBoxHeight,
   9490       "preserveAspectRatio": "xMinYMin slice"
   9491     }); // Wrap it in a span with overflow: hidden.
   9492 
   9493     img = buildCommon.makeSvgSpan(["hide-tail"], [svgNode], options);
   9494     img.style.height = angleHeight + "em";
   9495     imgShift = inner.depth + lineWeight + clearance;
   9496   } else {
   9497     // Add horizontal padding
   9498     if (/cancel/.test(label)) {
   9499       if (!isSingleChar) {
   9500         inner.classes.push("cancel-pad");
   9501       }
   9502     } else if (label === "angl") {
   9503       inner.classes.push("anglpad");
   9504     } else {
   9505       inner.classes.push("boxpad");
   9506     } // Add vertical padding
   9507 
   9508 
   9509     var topPad = 0;
   9510     var bottomPad = 0;
   9511     var ruleThickness = 0; // ref: cancel package: \advance\totalheight2\p@ % "+2"
   9512 
   9513     if (/box/.test(label)) {
   9514       ruleThickness = Math.max(options.fontMetrics().fboxrule, // default
   9515       options.minRuleThickness // User override.
   9516       );
   9517       topPad = options.fontMetrics().fboxsep + (label === "colorbox" ? 0 : ruleThickness);
   9518       bottomPad = topPad;
   9519     } else if (label === "angl") {
   9520       ruleThickness = Math.max(options.fontMetrics().defaultRuleThickness, options.minRuleThickness);
   9521       topPad = 4 * ruleThickness; // gap = 3 × line, plus the line itself.
   9522 
   9523       bottomPad = Math.max(0, 0.25 - inner.depth);
   9524     } else {
   9525       topPad = isSingleChar ? 0.2 : 0;
   9526       bottomPad = topPad;
   9527     }
   9528 
   9529     img = stretchy.encloseSpan(inner, label, topPad, bottomPad, options);
   9530 
   9531     if (/fbox|boxed|fcolorbox/.test(label)) {
   9532       img.style.borderStyle = "solid";
   9533       img.style.borderWidth = ruleThickness + "em";
   9534     } else if (label === "angl" && ruleThickness !== 0.049) {
   9535       img.style.borderTopWidth = ruleThickness + "em";
   9536       img.style.borderRightWidth = ruleThickness + "em";
   9537     }
   9538 
   9539     imgShift = inner.depth + bottomPad;
   9540 
   9541     if (group.backgroundColor) {
   9542       img.style.backgroundColor = group.backgroundColor;
   9543 
   9544       if (group.borderColor) {
   9545         img.style.borderColor = group.borderColor;
   9546       }
   9547     }
   9548   }
   9549 
   9550   var vlist;
   9551 
   9552   if (group.backgroundColor) {
   9553     vlist = buildCommon.makeVList({
   9554       positionType: "individualShift",
   9555       children: [// Put the color background behind inner;
   9556       {
   9557         type: "elem",
   9558         elem: img,
   9559         shift: imgShift
   9560       }, {
   9561         type: "elem",
   9562         elem: inner,
   9563         shift: 0
   9564       }]
   9565     }, options);
   9566   } else {
   9567     var classes = /cancel|phase/.test(label) ? ["svg-align"] : [];
   9568     vlist = buildCommon.makeVList({
   9569       positionType: "individualShift",
   9570       children: [// Write the \cancel stroke on top of inner.
   9571       {
   9572         type: "elem",
   9573         elem: inner,
   9574         shift: 0
   9575       }, {
   9576         type: "elem",
   9577         elem: img,
   9578         shift: imgShift,
   9579         wrapperClasses: classes
   9580       }]
   9581     }, options);
   9582   }
   9583 
   9584   if (/cancel/.test(label)) {
   9585     // The cancel package documentation says that cancel lines add their height
   9586     // to the expression, but tests show that isn't how it actually works.
   9587     vlist.height = inner.height;
   9588     vlist.depth = inner.depth;
   9589   }
   9590 
   9591   if (/cancel/.test(label) && !isSingleChar) {
   9592     // cancel does not create horiz space for its line extension.
   9593     return buildCommon.makeSpan(["mord", "cancel-lap"], [vlist], options);
   9594   } else {
   9595     return buildCommon.makeSpan(["mord"], [vlist], options);
   9596   }
   9597 };
   9598 
   9599 var mathmlBuilder$2 = (group, options) => {
   9600   var fboxsep = 0;
   9601   var node = new mathMLTree.MathNode(group.label.indexOf("colorbox") > -1 ? "mpadded" : "menclose", [buildGroup$1(group.body, options)]);
   9602 
   9603   switch (group.label) {
   9604     case "\\cancel":
   9605       node.setAttribute("notation", "updiagonalstrike");
   9606       break;
   9607 
   9608     case "\\bcancel":
   9609       node.setAttribute("notation", "downdiagonalstrike");
   9610       break;
   9611 
   9612     case "\\phase":
   9613       node.setAttribute("notation", "phasorangle");
   9614       break;
   9615 
   9616     case "\\sout":
   9617       node.setAttribute("notation", "horizontalstrike");
   9618       break;
   9619 
   9620     case "\\fbox":
   9621       node.setAttribute("notation", "box");
   9622       break;
   9623 
   9624     case "\\angl":
   9625       node.setAttribute("notation", "actuarial");
   9626       break;
   9627 
   9628     case "\\fcolorbox":
   9629     case "\\colorbox":
   9630       // <menclose> doesn't have a good notation option. So use <mpadded>
   9631       // instead. Set some attributes that come included with <menclose>.
   9632       fboxsep = options.fontMetrics().fboxsep * options.fontMetrics().ptPerEm;
   9633       node.setAttribute("width", "+" + 2 * fboxsep + "pt");
   9634       node.setAttribute("height", "+" + 2 * fboxsep + "pt");
   9635       node.setAttribute("lspace", fboxsep + "pt"); //
   9636 
   9637       node.setAttribute("voffset", fboxsep + "pt");
   9638 
   9639       if (group.label === "\\fcolorbox") {
   9640         var thk = Math.max(options.fontMetrics().fboxrule, // default
   9641         options.minRuleThickness // user override
   9642         );
   9643         node.setAttribute("style", "border: " + thk + "em solid " + String(group.borderColor));
   9644       }
   9645 
   9646       break;
   9647 
   9648     case "\\xcancel":
   9649       node.setAttribute("notation", "updiagonalstrike downdiagonalstrike");
   9650       break;
   9651   }
   9652 
   9653   if (group.backgroundColor) {
   9654     node.setAttribute("mathbackground", group.backgroundColor);
   9655   }
   9656 
   9657   return node;
   9658 };
   9659 
   9660 defineFunction({
   9661   type: "enclose",
   9662   names: ["\\colorbox"],
   9663   props: {
   9664     numArgs: 2,
   9665     allowedInText: true,
   9666     argTypes: ["color", "text"]
   9667   },
   9668 
   9669   handler(_ref, args, optArgs) {
   9670     var {
   9671       parser,
   9672       funcName
   9673     } = _ref;
   9674     var color = assertNodeType(args[0], "color-token").color;
   9675     var body = args[1];
   9676     return {
   9677       type: "enclose",
   9678       mode: parser.mode,
   9679       label: funcName,
   9680       backgroundColor: color,
   9681       body
   9682     };
   9683   },
   9684 
   9685   htmlBuilder: htmlBuilder$2,
   9686   mathmlBuilder: mathmlBuilder$2
   9687 });
   9688 defineFunction({
   9689   type: "enclose",
   9690   names: ["\\fcolorbox"],
   9691   props: {
   9692     numArgs: 3,
   9693     allowedInText: true,
   9694     argTypes: ["color", "color", "text"]
   9695   },
   9696 
   9697   handler(_ref2, args, optArgs) {
   9698     var {
   9699       parser,
   9700       funcName
   9701     } = _ref2;
   9702     var borderColor = assertNodeType(args[0], "color-token").color;
   9703     var backgroundColor = assertNodeType(args[1], "color-token").color;
   9704     var body = args[2];
   9705     return {
   9706       type: "enclose",
   9707       mode: parser.mode,
   9708       label: funcName,
   9709       backgroundColor,
   9710       borderColor,
   9711       body
   9712     };
   9713   },
   9714 
   9715   htmlBuilder: htmlBuilder$2,
   9716   mathmlBuilder: mathmlBuilder$2
   9717 });
   9718 defineFunction({
   9719   type: "enclose",
   9720   names: ["\\fbox"],
   9721   props: {
   9722     numArgs: 1,
   9723     argTypes: ["hbox"],
   9724     allowedInText: true
   9725   },
   9726 
   9727   handler(_ref3, args) {
   9728     var {
   9729       parser
   9730     } = _ref3;
   9731     return {
   9732       type: "enclose",
   9733       mode: parser.mode,
   9734       label: "\\fbox",
   9735       body: args[0]
   9736     };
   9737   }
   9738 
   9739 });
   9740 defineFunction({
   9741   type: "enclose",
   9742   names: ["\\cancel", "\\bcancel", "\\xcancel", "\\sout", "\\phase"],
   9743   props: {
   9744     numArgs: 1
   9745   },
   9746 
   9747   handler(_ref4, args) {
   9748     var {
   9749       parser,
   9750       funcName
   9751     } = _ref4;
   9752     var body = args[0];
   9753     return {
   9754       type: "enclose",
   9755       mode: parser.mode,
   9756       label: funcName,
   9757       body
   9758     };
   9759   },
   9760 
   9761   htmlBuilder: htmlBuilder$2,
   9762   mathmlBuilder: mathmlBuilder$2
   9763 });
   9764 defineFunction({
   9765   type: "enclose",
   9766   names: ["\\angl"],
   9767   props: {
   9768     numArgs: 1,
   9769     argTypes: ["hbox"],
   9770     allowedInText: false
   9771   },
   9772 
   9773   handler(_ref5, args) {
   9774     var {
   9775       parser
   9776     } = _ref5;
   9777     return {
   9778       type: "enclose",
   9779       mode: parser.mode,
   9780       label: "\\angl",
   9781       body: args[0]
   9782     };
   9783   }
   9784 
   9785 });
   9786 
   9787 /**
   9788  * All registered environments.
   9789  * `environments.js` exports this same dictionary again and makes it public.
   9790  * `Parser.js` requires this dictionary via `environments.js`.
   9791  */
   9792 var _environments = {};
   9793 function defineEnvironment(_ref) {
   9794   var {
   9795     type,
   9796     names,
   9797     props,
   9798     handler,
   9799     htmlBuilder,
   9800     mathmlBuilder
   9801   } = _ref;
   9802   // Set default values of environments.
   9803   var data = {
   9804     type,
   9805     numArgs: props.numArgs || 0,
   9806     allowedInText: false,
   9807     numOptionalArgs: 0,
   9808     handler
   9809   };
   9810 
   9811   for (var i = 0; i < names.length; ++i) {
   9812     // TODO: The value type of _environments should be a type union of all
   9813     // possible `EnvSpec<>` possibilities instead of `EnvSpec<*>`, which is
   9814     // an existential type.
   9815     _environments[names[i]] = data;
   9816   }
   9817 
   9818   if (htmlBuilder) {
   9819     _htmlGroupBuilders[type] = htmlBuilder;
   9820   }
   9821 
   9822   if (mathmlBuilder) {
   9823     _mathmlGroupBuilders[type] = mathmlBuilder;
   9824   }
   9825 }
   9826 
   9827 // Helper functions
   9828 function getHLines(parser) {
   9829   // Return an array. The array length = number of hlines.
   9830   // Each element in the array tells if the line is dashed.
   9831   var hlineInfo = [];
   9832   parser.consumeSpaces();
   9833   var nxt = parser.fetch().text;
   9834 
   9835   while (nxt === "\\hline" || nxt === "\\hdashline") {
   9836     parser.consume();
   9837     hlineInfo.push(nxt === "\\hdashline");
   9838     parser.consumeSpaces();
   9839     nxt = parser.fetch().text;
   9840   }
   9841 
   9842   return hlineInfo;
   9843 }
   9844 
   9845 var validateAmsEnvironmentContext = context => {
   9846   var settings = context.parser.settings;
   9847 
   9848   if (!settings.displayMode) {
   9849     throw new ParseError("{" + context.envName + "} can be used only in" + " display mode.");
   9850   }
   9851 };
   9852 /**
   9853  * Parse the body of the environment, with rows delimited by \\ and
   9854  * columns delimited by &, and create a nested list in row-major order
   9855  * with one group per cell.  If given an optional argument style
   9856  * ("text", "display", etc.), then each cell is cast into that style.
   9857  */
   9858 
   9859 
   9860 function parseArray(parser, _ref, style) {
   9861   var {
   9862     hskipBeforeAndAfter,
   9863     addJot,
   9864     cols,
   9865     arraystretch,
   9866     colSeparationType,
   9867     addEqnNum,
   9868     singleRow,
   9869     maxNumCols,
   9870     leqno
   9871   } = _ref;
   9872   parser.gullet.beginGroup();
   9873 
   9874   if (!singleRow) {
   9875     // \cr is equivalent to \\ without the optional size argument (see below)
   9876     // TODO: provide helpful error when \cr is used outside array environment
   9877     parser.gullet.macros.set("\\cr", "\\\\\\relax");
   9878   } // Get current arraystretch if it's not set by the environment
   9879 
   9880 
   9881   if (!arraystretch) {
   9882     var stretch = parser.gullet.expandMacroAsText("\\arraystretch");
   9883 
   9884     if (stretch == null) {
   9885       // Default \arraystretch from lttab.dtx
   9886       arraystretch = 1;
   9887     } else {
   9888       arraystretch = parseFloat(stretch);
   9889 
   9890       if (!arraystretch || arraystretch < 0) {
   9891         throw new ParseError("Invalid \\arraystretch: " + stretch);
   9892       }
   9893     }
   9894   } // Start group for first cell
   9895 
   9896 
   9897   parser.gullet.beginGroup();
   9898   var row = [];
   9899   var body = [row];
   9900   var rowGaps = [];
   9901   var hLinesBeforeRow = []; // Test for \hline at the top of the array.
   9902 
   9903   hLinesBeforeRow.push(getHLines(parser));
   9904 
   9905   while (true) {
   9906     // eslint-disable-line no-constant-condition
   9907     // Parse each cell in its own group (namespace)
   9908     var cell = parser.parseExpression(false, singleRow ? "\\end" : "\\\\");
   9909     parser.gullet.endGroup();
   9910     parser.gullet.beginGroup();
   9911     cell = {
   9912       type: "ordgroup",
   9913       mode: parser.mode,
   9914       body: cell
   9915     };
   9916 
   9917     if (style) {
   9918       cell = {
   9919         type: "styling",
   9920         mode: parser.mode,
   9921         style,
   9922         body: [cell]
   9923       };
   9924     }
   9925 
   9926     row.push(cell);
   9927     var next = parser.fetch().text;
   9928 
   9929     if (next === "&") {
   9930       if (maxNumCols && row.length === maxNumCols) {
   9931         if (singleRow || colSeparationType) {
   9932           // {equation} or {split}
   9933           throw new ParseError("Too many tab characters: &", parser.nextToken);
   9934         } else {
   9935           // {array} environment
   9936           parser.settings.reportNonstrict("textEnv", "Too few columns " + "specified in the {array} column argument.");
   9937         }
   9938       }
   9939 
   9940       parser.consume();
   9941     } else if (next === "\\end") {
   9942       // Arrays terminate newlines with `\crcr` which consumes a `\cr` if
   9943       // the last line is empty.
   9944       // NOTE: Currently, `cell` is the last item added into `row`.
   9945       if (row.length === 1 && cell.type === "styling" && cell.body[0].body.length === 0) {
   9946         body.pop();
   9947       }
   9948 
   9949       if (hLinesBeforeRow.length < body.length + 1) {
   9950         hLinesBeforeRow.push([]);
   9951       }
   9952 
   9953       break;
   9954     } else if (next === "\\\\") {
   9955       parser.consume();
   9956       var size = void 0; // \def\Let@{\let\\\math@cr}
   9957       // \def\math@cr{...\math@cr@}
   9958       // \def\math@cr@{\new@ifnextchar[\math@cr@@{\math@cr@@[\z@]}}
   9959       // \def\math@cr@@[#1]{...\math@cr@@@...}
   9960       // \def\math@cr@@@{\cr}
   9961 
   9962       if (parser.gullet.future().text !== " ") {
   9963         size = parser.parseSizeGroup(true);
   9964       }
   9965 
   9966       rowGaps.push(size ? size.value : null); // check for \hline(s) following the row separator
   9967 
   9968       hLinesBeforeRow.push(getHLines(parser));
   9969       row = [];
   9970       body.push(row);
   9971     } else {
   9972       throw new ParseError("Expected & or \\\\ or \\cr or \\end", parser.nextToken);
   9973     }
   9974   } // End cell group
   9975 
   9976 
   9977   parser.gullet.endGroup(); // End array group defining \cr
   9978 
   9979   parser.gullet.endGroup();
   9980   return {
   9981     type: "array",
   9982     mode: parser.mode,
   9983     addJot,
   9984     arraystretch,
   9985     body,
   9986     cols,
   9987     rowGaps,
   9988     hskipBeforeAndAfter,
   9989     hLinesBeforeRow,
   9990     colSeparationType,
   9991     addEqnNum,
   9992     leqno
   9993   };
   9994 } // Decides on a style for cells in an array according to whether the given
   9995 // environment name starts with the letter 'd'.
   9996 
   9997 
   9998 function dCellStyle(envName) {
   9999   if (envName.substr(0, 1) === "d") {
  10000     return "display";
  10001   } else {
  10002     return "text";
  10003   }
  10004 }
  10005 
  10006 var htmlBuilder$3 = function htmlBuilder(group, options) {
  10007   var r;
  10008   var c;
  10009   var nr = group.body.length;
  10010   var hLinesBeforeRow = group.hLinesBeforeRow;
  10011   var nc = 0;
  10012   var body = new Array(nr);
  10013   var hlines = [];
  10014   var ruleThickness = Math.max( // From LaTeX \showthe\arrayrulewidth. Equals 0.04 em.
  10015   options.fontMetrics().arrayRuleWidth, options.minRuleThickness // User override.
  10016   ); // Horizontal spacing
  10017 
  10018   var pt = 1 / options.fontMetrics().ptPerEm;
  10019   var arraycolsep = 5 * pt; // default value, i.e. \arraycolsep in article.cls
  10020 
  10021   if (group.colSeparationType && group.colSeparationType === "small") {
  10022     // We're in a {smallmatrix}. Default column space is \thickspace,
  10023     // i.e. 5/18em = 0.2778em, per amsmath.dtx for {smallmatrix}.
  10024     // But that needs adjustment because LaTeX applies \scriptstyle to the
  10025     // entire array, including the colspace, but this function applies
  10026     // \scriptstyle only inside each element.
  10027     var localMultiplier = options.havingStyle(Style$1.SCRIPT).sizeMultiplier;
  10028     arraycolsep = 0.2778 * (localMultiplier / options.sizeMultiplier);
  10029   } // Vertical spacing
  10030 
  10031 
  10032   var baselineskip = group.colSeparationType === "CD" ? calculateSize({
  10033     number: 3,
  10034     unit: "ex"
  10035   }, options) : 12 * pt; // see size10.clo
  10036   // Default \jot from ltmath.dtx
  10037   // TODO(edemaine): allow overriding \jot via \setlength (#687)
  10038 
  10039   var jot = 3 * pt;
  10040   var arrayskip = group.arraystretch * baselineskip;
  10041   var arstrutHeight = 0.7 * arrayskip; // \strutbox in ltfsstrc.dtx and
  10042 
  10043   var arstrutDepth = 0.3 * arrayskip; // \@arstrutbox in lttab.dtx
  10044 
  10045   var totalHeight = 0; // Set a position for \hline(s) at the top of the array, if any.
  10046 
  10047   function setHLinePos(hlinesInGap) {
  10048     for (var i = 0; i < hlinesInGap.length; ++i) {
  10049       if (i > 0) {
  10050         totalHeight += 0.25;
  10051       }
  10052 
  10053       hlines.push({
  10054         pos: totalHeight,
  10055         isDashed: hlinesInGap[i]
  10056       });
  10057     }
  10058   }
  10059 
  10060   setHLinePos(hLinesBeforeRow[0]);
  10061 
  10062   for (r = 0; r < group.body.length; ++r) {
  10063     var inrow = group.body[r];
  10064     var height = arstrutHeight; // \@array adds an \@arstrut
  10065 
  10066     var depth = arstrutDepth; // to each tow (via the template)
  10067 
  10068     if (nc < inrow.length) {
  10069       nc = inrow.length;
  10070     }
  10071 
  10072     var outrow = new Array(inrow.length);
  10073 
  10074     for (c = 0; c < inrow.length; ++c) {
  10075       var elt = buildGroup(inrow[c], options);
  10076 
  10077       if (depth < elt.depth) {
  10078         depth = elt.depth;
  10079       }
  10080 
  10081       if (height < elt.height) {
  10082         height = elt.height;
  10083       }
  10084 
  10085       outrow[c] = elt;
  10086     }
  10087 
  10088     var rowGap = group.rowGaps[r];
  10089     var gap = 0;
  10090 
  10091     if (rowGap) {
  10092       gap = calculateSize(rowGap, options);
  10093 
  10094       if (gap > 0) {
  10095         // \@argarraycr
  10096         gap += arstrutDepth;
  10097 
  10098         if (depth < gap) {
  10099           depth = gap; // \@xargarraycr
  10100         }
  10101 
  10102         gap = 0;
  10103       }
  10104     } // In AMS multiline environments such as aligned and gathered, rows
  10105     // correspond to lines that have additional \jot added to the
  10106     // \baselineskip via \openup.
  10107 
  10108 
  10109     if (group.addJot) {
  10110       depth += jot;
  10111     }
  10112 
  10113     outrow.height = height;
  10114     outrow.depth = depth;
  10115     totalHeight += height;
  10116     outrow.pos = totalHeight;
  10117     totalHeight += depth + gap; // \@yargarraycr
  10118 
  10119     body[r] = outrow; // Set a position for \hline(s), if any.
  10120 
  10121     setHLinePos(hLinesBeforeRow[r + 1]);
  10122   }
  10123 
  10124   var offset = totalHeight / 2 + options.fontMetrics().axisHeight;
  10125   var colDescriptions = group.cols || [];
  10126   var cols = [];
  10127   var colSep;
  10128   var colDescrNum;
  10129   var eqnNumSpans = [];
  10130 
  10131   if (group.addEqnNum) {
  10132     // An environment with automatic equation numbers.
  10133     // Create node(s) that will trigger CSS counter increment.
  10134     for (r = 0; r < nr; ++r) {
  10135       var rw = body[r];
  10136       var shift = rw.pos - offset;
  10137       var eqnTag = buildCommon.makeSpan(["eqn-num"], [], options);
  10138       eqnTag.depth = rw.depth;
  10139       eqnTag.height = rw.height;
  10140       eqnNumSpans.push({
  10141         type: "elem",
  10142         elem: eqnTag,
  10143         shift
  10144       });
  10145     }
  10146   }
  10147 
  10148   for (c = 0, colDescrNum = 0; // Continue while either there are more columns or more column
  10149   // descriptions, so trailing separators don't get lost.
  10150   c < nc || colDescrNum < colDescriptions.length; ++c, ++colDescrNum) {
  10151     var colDescr = colDescriptions[colDescrNum] || {};
  10152     var firstSeparator = true;
  10153 
  10154     while (colDescr.type === "separator") {
  10155       // If there is more than one separator in a row, add a space
  10156       // between them.
  10157       if (!firstSeparator) {
  10158         colSep = buildCommon.makeSpan(["arraycolsep"], []);
  10159         colSep.style.width = options.fontMetrics().doubleRuleSep + "em";
  10160         cols.push(colSep);
  10161       }
  10162 
  10163       if (colDescr.separator === "|" || colDescr.separator === ":") {
  10164         var lineType = colDescr.separator === "|" ? "solid" : "dashed";
  10165         var separator = buildCommon.makeSpan(["vertical-separator"], [], options);
  10166         separator.style.height = totalHeight + "em";
  10167         separator.style.borderRightWidth = ruleThickness + "em";
  10168         separator.style.borderRightStyle = lineType;
  10169         separator.style.margin = "0 -" + ruleThickness / 2 + "em";
  10170         separator.style.verticalAlign = -(totalHeight - offset) + "em";
  10171         cols.push(separator);
  10172       } else {
  10173         throw new ParseError("Invalid separator type: " + colDescr.separator);
  10174       }
  10175 
  10176       colDescrNum++;
  10177       colDescr = colDescriptions[colDescrNum] || {};
  10178       firstSeparator = false;
  10179     }
  10180 
  10181     if (c >= nc) {
  10182       continue;
  10183     }
  10184 
  10185     var sepwidth = void 0;
  10186 
  10187     if (c > 0 || group.hskipBeforeAndAfter) {
  10188       sepwidth = utils.deflt(colDescr.pregap, arraycolsep);
  10189 
  10190       if (sepwidth !== 0) {
  10191         colSep = buildCommon.makeSpan(["arraycolsep"], []);
  10192         colSep.style.width = sepwidth + "em";
  10193         cols.push(colSep);
  10194       }
  10195     }
  10196 
  10197     var col = [];
  10198 
  10199     for (r = 0; r < nr; ++r) {
  10200       var row = body[r];
  10201       var elem = row[c];
  10202 
  10203       if (!elem) {
  10204         continue;
  10205       }
  10206 
  10207       var _shift = row.pos - offset;
  10208 
  10209       elem.depth = row.depth;
  10210       elem.height = row.height;
  10211       col.push({
  10212         type: "elem",
  10213         elem: elem,
  10214         shift: _shift
  10215       });
  10216     }
  10217 
  10218     col = buildCommon.makeVList({
  10219       positionType: "individualShift",
  10220       children: col
  10221     }, options);
  10222     col = buildCommon.makeSpan(["col-align-" + (colDescr.align || "c")], [col]);
  10223     cols.push(col);
  10224 
  10225     if (c < nc - 1 || group.hskipBeforeAndAfter) {
  10226       sepwidth = utils.deflt(colDescr.postgap, arraycolsep);
  10227 
  10228       if (sepwidth !== 0) {
  10229         colSep = buildCommon.makeSpan(["arraycolsep"], []);
  10230         colSep.style.width = sepwidth + "em";
  10231         cols.push(colSep);
  10232       }
  10233     }
  10234   }
  10235 
  10236   body = buildCommon.makeSpan(["mtable"], cols); // Add \hline(s), if any.
  10237 
  10238   if (hlines.length > 0) {
  10239     var line = buildCommon.makeLineSpan("hline", options, ruleThickness);
  10240     var dashes = buildCommon.makeLineSpan("hdashline", options, ruleThickness);
  10241     var vListElems = [{
  10242       type: "elem",
  10243       elem: body,
  10244       shift: 0
  10245     }];
  10246 
  10247     while (hlines.length > 0) {
  10248       var hline = hlines.pop();
  10249       var lineShift = hline.pos - offset;
  10250 
  10251       if (hline.isDashed) {
  10252         vListElems.push({
  10253           type: "elem",
  10254           elem: dashes,
  10255           shift: lineShift
  10256         });
  10257       } else {
  10258         vListElems.push({
  10259           type: "elem",
  10260           elem: line,
  10261           shift: lineShift
  10262         });
  10263       }
  10264     }
  10265 
  10266     body = buildCommon.makeVList({
  10267       positionType: "individualShift",
  10268       children: vListElems
  10269     }, options);
  10270   }
  10271 
  10272   if (!group.addEqnNum) {
  10273     return buildCommon.makeSpan(["mord"], [body], options);
  10274   } else {
  10275     var eqnNumCol = buildCommon.makeVList({
  10276       positionType: "individualShift",
  10277       children: eqnNumSpans
  10278     }, options);
  10279     eqnNumCol = buildCommon.makeSpan(["tag"], [eqnNumCol], options);
  10280     return buildCommon.makeFragment([body, eqnNumCol]);
  10281   }
  10282 };
  10283 
  10284 var alignMap = {
  10285   c: "center ",
  10286   l: "left ",
  10287   r: "right "
  10288 };
  10289 
  10290 var mathmlBuilder$3 = function mathmlBuilder(group, options) {
  10291   var tbl = [];
  10292   var glue = new mathMLTree.MathNode("mtd", [], ["mtr-glue"]);
  10293   var tag = new mathMLTree.MathNode("mtd", [], ["mml-eqn-num"]);
  10294 
  10295   for (var i = 0; i < group.body.length; i++) {
  10296     var rw = group.body[i];
  10297     var row = [];
  10298 
  10299     for (var j = 0; j < rw.length; j++) {
  10300       row.push(new mathMLTree.MathNode("mtd", [buildGroup$1(rw[j], options)]));
  10301     }
  10302 
  10303     if (group.addEqnNum) {
  10304       row.unshift(glue);
  10305       row.push(glue);
  10306 
  10307       if (group.leqno) {
  10308         row.unshift(tag);
  10309       } else {
  10310         row.push(tag);
  10311       }
  10312     }
  10313 
  10314     tbl.push(new mathMLTree.MathNode("mtr", row));
  10315   }
  10316 
  10317   var table = new mathMLTree.MathNode("mtable", tbl); // Set column alignment, row spacing, column spacing, and
  10318   // array lines by setting attributes on the table element.
  10319   // Set the row spacing. In MathML, we specify a gap distance.
  10320   // We do not use rowGap[] because MathML automatically increases
  10321   // cell height with the height/depth of the element content.
  10322   // LaTeX \arraystretch multiplies the row baseline-to-baseline distance.
  10323   // We simulate this by adding (arraystretch - 1)em to the gap. This
  10324   // does a reasonable job of adjusting arrays containing 1 em tall content.
  10325   // The 0.16 and 0.09 values are found emprically. They produce an array
  10326   // similar to LaTeX and in which content does not interfere with \hines.
  10327 
  10328   var gap = group.arraystretch === 0.5 ? 0.1 // {smallmatrix}, {subarray}
  10329   : 0.16 + group.arraystretch - 1 + (group.addJot ? 0.09 : 0);
  10330   table.setAttribute("rowspacing", gap.toFixed(4) + "em"); // MathML table lines go only between cells.
  10331   // To place a line on an edge we'll use <menclose>, if necessary.
  10332 
  10333   var menclose = "";
  10334   var align = "";
  10335 
  10336   if (group.cols && group.cols.length > 0) {
  10337     // Find column alignment, column spacing, and  vertical lines.
  10338     var cols = group.cols;
  10339     var columnLines = "";
  10340     var prevTypeWasAlign = false;
  10341     var iStart = 0;
  10342     var iEnd = cols.length;
  10343 
  10344     if (cols[0].type === "separator") {
  10345       menclose += "top ";
  10346       iStart = 1;
  10347     }
  10348 
  10349     if (cols[cols.length - 1].type === "separator") {
  10350       menclose += "bottom ";
  10351       iEnd -= 1;
  10352     }
  10353 
  10354     for (var _i = iStart; _i < iEnd; _i++) {
  10355       if (cols[_i].type === "align") {
  10356         align += alignMap[cols[_i].align];
  10357 
  10358         if (prevTypeWasAlign) {
  10359           columnLines += "none ";
  10360         }
  10361 
  10362         prevTypeWasAlign = true;
  10363       } else if (cols[_i].type === "separator") {
  10364         // MathML accepts only single lines between cells.
  10365         // So we read only the first of consecutive separators.
  10366         if (prevTypeWasAlign) {
  10367           columnLines += cols[_i].separator === "|" ? "solid " : "dashed ";
  10368           prevTypeWasAlign = false;
  10369         }
  10370       }
  10371     }
  10372 
  10373     table.setAttribute("columnalign", align.trim());
  10374 
  10375     if (/[sd]/.test(columnLines)) {
  10376       table.setAttribute("columnlines", columnLines.trim());
  10377     }
  10378   } // Set column spacing.
  10379 
  10380 
  10381   if (group.colSeparationType === "align") {
  10382     var _cols = group.cols || [];
  10383 
  10384     var spacing = "";
  10385 
  10386     for (var _i2 = 1; _i2 < _cols.length; _i2++) {
  10387       spacing += _i2 % 2 ? "0em " : "1em ";
  10388     }
  10389 
  10390     table.setAttribute("columnspacing", spacing.trim());
  10391   } else if (group.colSeparationType === "alignat" || group.colSeparationType === "gather") {
  10392     table.setAttribute("columnspacing", "0em");
  10393   } else if (group.colSeparationType === "small") {
  10394     table.setAttribute("columnspacing", "0.2778em");
  10395   } else if (group.colSeparationType === "CD") {
  10396     table.setAttribute("columnspacing", "0.5em");
  10397   } else {
  10398     table.setAttribute("columnspacing", "1em");
  10399   } // Address \hline and \hdashline
  10400 
  10401 
  10402   var rowLines = "";
  10403   var hlines = group.hLinesBeforeRow;
  10404   menclose += hlines[0].length > 0 ? "left " : "";
  10405   menclose += hlines[hlines.length - 1].length > 0 ? "right " : "";
  10406 
  10407   for (var _i3 = 1; _i3 < hlines.length - 1; _i3++) {
  10408     rowLines += hlines[_i3].length === 0 ? "none " // MathML accepts only a single line between rows. Read one element.
  10409     : hlines[_i3][0] ? "dashed " : "solid ";
  10410   }
  10411 
  10412   if (/[sd]/.test(rowLines)) {
  10413     table.setAttribute("rowlines", rowLines.trim());
  10414   }
  10415 
  10416   if (menclose !== "") {
  10417     table = new mathMLTree.MathNode("menclose", [table]);
  10418     table.setAttribute("notation", menclose.trim());
  10419   }
  10420 
  10421   if (group.arraystretch && group.arraystretch < 1) {
  10422     // A small array. Wrap in scriptstyle so row gap is not too large.
  10423     table = new mathMLTree.MathNode("mstyle", [table]);
  10424     table.setAttribute("scriptlevel", "1");
  10425   }
  10426 
  10427   return table;
  10428 }; // Convenience function for align, align*, aligned, alignat, alignat*, alignedat.
  10429 
  10430 
  10431 var alignedHandler = function alignedHandler(context, args) {
  10432   if (context.envName.indexOf("ed") === -1) {
  10433     validateAmsEnvironmentContext(context);
  10434   }
  10435 
  10436   var cols = [];
  10437   var separationType = context.envName.indexOf("at") > -1 ? "alignat" : "align";
  10438   var res = parseArray(context.parser, {
  10439     cols,
  10440     addJot: true,
  10441     addEqnNum: context.envName === "align" || context.envName === "alignat",
  10442     colSeparationType: separationType,
  10443     maxNumCols: context.envName === "split" ? 2 : undefined,
  10444     leqno: context.parser.settings.leqno
  10445   }, "display"); // Determining number of columns.
  10446   // 1. If the first argument is given, we use it as a number of columns,
  10447   //    and makes sure that each row doesn't exceed that number.
  10448   // 2. Otherwise, just count number of columns = maximum number
  10449   //    of cells in each row ("aligned" mode -- isAligned will be true).
  10450   //
  10451   // At the same time, prepend empty group {} at beginning of every second
  10452   // cell in each row (starting with second cell) so that operators become
  10453   // binary.  This behavior is implemented in amsmath's \start@aligned.
  10454 
  10455   var numMaths;
  10456   var numCols = 0;
  10457   var emptyGroup = {
  10458     type: "ordgroup",
  10459     mode: context.mode,
  10460     body: []
  10461   };
  10462 
  10463   if (args[0] && args[0].type === "ordgroup") {
  10464     var arg0 = "";
  10465 
  10466     for (var i = 0; i < args[0].body.length; i++) {
  10467       var textord = assertNodeType(args[0].body[i], "textord");
  10468       arg0 += textord.text;
  10469     }
  10470 
  10471     numMaths = Number(arg0);
  10472     numCols = numMaths * 2;
  10473   }
  10474 
  10475   var isAligned = !numCols;
  10476   res.body.forEach(function (row) {
  10477     for (var _i4 = 1; _i4 < row.length; _i4 += 2) {
  10478       // Modify ordgroup node within styling node
  10479       var styling = assertNodeType(row[_i4], "styling");
  10480       var ordgroup = assertNodeType(styling.body[0], "ordgroup");
  10481       ordgroup.body.unshift(emptyGroup);
  10482     }
  10483 
  10484     if (!isAligned) {
  10485       // Case 1
  10486       var curMaths = row.length / 2;
  10487 
  10488       if (numMaths < curMaths) {
  10489         throw new ParseError("Too many math in a row: " + ("expected " + numMaths + ", but got " + curMaths), row[0]);
  10490       }
  10491     } else if (numCols < row.length) {
  10492       // Case 2
  10493       numCols = row.length;
  10494     }
  10495   }); // Adjusting alignment.
  10496   // In aligned mode, we add one \qquad between columns;
  10497   // otherwise we add nothing.
  10498 
  10499   for (var _i5 = 0; _i5 < numCols; ++_i5) {
  10500     var align = "r";
  10501     var pregap = 0;
  10502 
  10503     if (_i5 % 2 === 1) {
  10504       align = "l";
  10505     } else if (_i5 > 0 && isAligned) {
  10506       // "aligned" mode.
  10507       pregap = 1; // add one \quad
  10508     }
  10509 
  10510     cols[_i5] = {
  10511       type: "align",
  10512       align: align,
  10513       pregap: pregap,
  10514       postgap: 0
  10515     };
  10516   }
  10517 
  10518   res.colSeparationType = isAligned ? "align" : "alignat";
  10519   return res;
  10520 }; // Arrays are part of LaTeX, defined in lttab.dtx so its documentation
  10521 // is part of the source2e.pdf file of LaTeX2e source documentation.
  10522 // {darray} is an {array} environment where cells are set in \displaystyle,
  10523 // as defined in nccmath.sty.
  10524 
  10525 
  10526 defineEnvironment({
  10527   type: "array",
  10528   names: ["array", "darray"],
  10529   props: {
  10530     numArgs: 1
  10531   },
  10532 
  10533   handler(context, args) {
  10534     // Since no types are specified above, the two possibilities are
  10535     // - The argument is wrapped in {} or [], in which case Parser's
  10536     //   parseGroup() returns an "ordgroup" wrapping some symbol node.
  10537     // - The argument is a bare symbol node.
  10538     var symNode = checkSymbolNodeType(args[0]);
  10539     var colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body;
  10540     var cols = colalign.map(function (nde) {
  10541       var node = assertSymbolNodeType(nde);
  10542       var ca = node.text;
  10543 
  10544       if ("lcr".indexOf(ca) !== -1) {
  10545         return {
  10546           type: "align",
  10547           align: ca
  10548         };
  10549       } else if (ca === "|") {
  10550         return {
  10551           type: "separator",
  10552           separator: "|"
  10553         };
  10554       } else if (ca === ":") {
  10555         return {
  10556           type: "separator",
  10557           separator: ":"
  10558         };
  10559       }
  10560 
  10561       throw new ParseError("Unknown column alignment: " + ca, nde);
  10562     });
  10563     var res = {
  10564       cols,
  10565       hskipBeforeAndAfter: true,
  10566       // \@preamble in lttab.dtx
  10567       maxNumCols: cols.length
  10568     };
  10569     return parseArray(context.parser, res, dCellStyle(context.envName));
  10570   },
  10571 
  10572   htmlBuilder: htmlBuilder$3,
  10573   mathmlBuilder: mathmlBuilder$3
  10574 }); // The matrix environments of amsmath builds on the array environment
  10575 // of LaTeX, which is discussed above.
  10576 // The mathtools package adds starred versions of the same environments.
  10577 // These have an optional argument to choose left|center|right justification.
  10578 
  10579 defineEnvironment({
  10580   type: "array",
  10581   names: ["matrix", "pmatrix", "bmatrix", "Bmatrix", "vmatrix", "Vmatrix", "matrix*", "pmatrix*", "bmatrix*", "Bmatrix*", "vmatrix*", "Vmatrix*"],
  10582   props: {
  10583     numArgs: 0
  10584   },
  10585 
  10586   handler(context) {
  10587     var delimiters = {
  10588       "matrix": null,
  10589       "pmatrix": ["(", ")"],
  10590       "bmatrix": ["[", "]"],
  10591       "Bmatrix": ["\\{", "\\}"],
  10592       "vmatrix": ["|", "|"],
  10593       "Vmatrix": ["\\Vert", "\\Vert"]
  10594     }[context.envName.replace("*", "")]; // \hskip -\arraycolsep in amsmath
  10595 
  10596     var colAlign = "c";
  10597     var payload = {
  10598       hskipBeforeAndAfter: false,
  10599       cols: [{
  10600         type: "align",
  10601         align: colAlign
  10602       }]
  10603     };
  10604 
  10605     if (context.envName.charAt(context.envName.length - 1) === "*") {
  10606       // It's one of the mathtools starred functions.
  10607       // Parse the optional alignment argument.
  10608       var parser = context.parser;
  10609       parser.consumeSpaces();
  10610 
  10611       if (parser.fetch().text === "[") {
  10612         parser.consume();
  10613         parser.consumeSpaces();
  10614         colAlign = parser.fetch().text;
  10615 
  10616         if ("lcr".indexOf(colAlign) === -1) {
  10617           throw new ParseError("Expected l or c or r", parser.nextToken);
  10618         }
  10619 
  10620         parser.consume();
  10621         parser.consumeSpaces();
  10622         parser.expect("]");
  10623         parser.consume();
  10624         payload.cols = [{
  10625           type: "align",
  10626           align: colAlign
  10627         }];
  10628       }
  10629     }
  10630 
  10631     var res = parseArray(context.parser, payload, dCellStyle(context.envName)); // Populate cols with the correct number of column alignment specs.
  10632 
  10633     res.cols = new Array(res.body[0].length).fill({
  10634       type: "align",
  10635       align: colAlign
  10636     });
  10637     return delimiters ? {
  10638       type: "leftright",
  10639       mode: context.mode,
  10640       body: [res],
  10641       left: delimiters[0],
  10642       right: delimiters[1],
  10643       rightColor: undefined // \right uninfluenced by \color in array
  10644 
  10645     } : res;
  10646   },
  10647 
  10648   htmlBuilder: htmlBuilder$3,
  10649   mathmlBuilder: mathmlBuilder$3
  10650 });
  10651 defineEnvironment({
  10652   type: "array",
  10653   names: ["smallmatrix"],
  10654   props: {
  10655     numArgs: 0
  10656   },
  10657 
  10658   handler(context) {
  10659     var payload = {
  10660       arraystretch: 0.5
  10661     };
  10662     var res = parseArray(context.parser, payload, "script");
  10663     res.colSeparationType = "small";
  10664     return res;
  10665   },
  10666 
  10667   htmlBuilder: htmlBuilder$3,
  10668   mathmlBuilder: mathmlBuilder$3
  10669 });
  10670 defineEnvironment({
  10671   type: "array",
  10672   names: ["subarray"],
  10673   props: {
  10674     numArgs: 1
  10675   },
  10676 
  10677   handler(context, args) {
  10678     // Parsing of {subarray} is similar to {array}
  10679     var symNode = checkSymbolNodeType(args[0]);
  10680     var colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body;
  10681     var cols = colalign.map(function (nde) {
  10682       var node = assertSymbolNodeType(nde);
  10683       var ca = node.text; // {subarray} only recognizes "l" & "c"
  10684 
  10685       if ("lc".indexOf(ca) !== -1) {
  10686         return {
  10687           type: "align",
  10688           align: ca
  10689         };
  10690       }
  10691 
  10692       throw new ParseError("Unknown column alignment: " + ca, nde);
  10693     });
  10694 
  10695     if (cols.length > 1) {
  10696       throw new ParseError("{subarray} can contain only one column");
  10697     }
  10698 
  10699     var res = {
  10700       cols,
  10701       hskipBeforeAndAfter: false,
  10702       arraystretch: 0.5
  10703     };
  10704     res = parseArray(context.parser, res, "script");
  10705 
  10706     if (res.body.length > 0 && res.body[0].length > 1) {
  10707       throw new ParseError("{subarray} can contain only one column");
  10708     }
  10709 
  10710     return res;
  10711   },
  10712 
  10713   htmlBuilder: htmlBuilder$3,
  10714   mathmlBuilder: mathmlBuilder$3
  10715 }); // A cases environment (in amsmath.sty) is almost equivalent to
  10716 // \def\arraystretch{1.2}%
  10717 // \left\{\begin{array}{@{}l@{\quad}l@{}} … \end{array}\right.
  10718 // {dcases} is a {cases} environment where cells are set in \displaystyle,
  10719 // as defined in mathtools.sty.
  10720 // {rcases} is another mathtools environment. It's brace is on the right side.
  10721 
  10722 defineEnvironment({
  10723   type: "array",
  10724   names: ["cases", "dcases", "rcases", "drcases"],
  10725   props: {
  10726     numArgs: 0
  10727   },
  10728 
  10729   handler(context) {
  10730     var payload = {
  10731       arraystretch: 1.2,
  10732       cols: [{
  10733         type: "align",
  10734         align: "l",
  10735         pregap: 0,
  10736         // TODO(kevinb) get the current style.
  10737         // For now we use the metrics for TEXT style which is what we were
  10738         // doing before.  Before attempting to get the current style we
  10739         // should look at TeX's behavior especially for \over and matrices.
  10740         postgap: 1.0
  10741         /* 1em quad */
  10742 
  10743       }, {
  10744         type: "align",
  10745         align: "l",
  10746         pregap: 0,
  10747         postgap: 0
  10748       }]
  10749     };
  10750     var res = parseArray(context.parser, payload, dCellStyle(context.envName));
  10751     return {
  10752       type: "leftright",
  10753       mode: context.mode,
  10754       body: [res],
  10755       left: context.envName.indexOf("r") > -1 ? "." : "\\{",
  10756       right: context.envName.indexOf("r") > -1 ? "\\}" : ".",
  10757       rightColor: undefined
  10758     };
  10759   },
  10760 
  10761   htmlBuilder: htmlBuilder$3,
  10762   mathmlBuilder: mathmlBuilder$3
  10763 }); // In the align environment, one uses ampersands, &, to specify number of
  10764 // columns in each row, and to locate spacing between each column.
  10765 // align gets automatic numbering. align* and aligned do not.
  10766 // The alignedat environment can be used in math mode.
  10767 // Note that we assume \nomallineskiplimit to be zero,
  10768 // so that \strut@ is the same as \strut.
  10769 
  10770 defineEnvironment({
  10771   type: "array",
  10772   names: ["align", "align*", "aligned", "split"],
  10773   props: {
  10774     numArgs: 0
  10775   },
  10776   handler: alignedHandler,
  10777   htmlBuilder: htmlBuilder$3,
  10778   mathmlBuilder: mathmlBuilder$3
  10779 }); // A gathered environment is like an array environment with one centered
  10780 // column, but where rows are considered lines so get \jot line spacing
  10781 // and contents are set in \displaystyle.
  10782 
  10783 defineEnvironment({
  10784   type: "array",
  10785   names: ["gathered", "gather", "gather*"],
  10786   props: {
  10787     numArgs: 0
  10788   },
  10789 
  10790   handler(context) {
  10791     if (utils.contains(["gather", "gather*"], context.envName)) {
  10792       validateAmsEnvironmentContext(context);
  10793     }
  10794 
  10795     var res = {
  10796       cols: [{
  10797         type: "align",
  10798         align: "c"
  10799       }],
  10800       addJot: true,
  10801       colSeparationType: "gather",
  10802       addEqnNum: context.envName === "gather",
  10803       leqno: context.parser.settings.leqno
  10804     };
  10805     return parseArray(context.parser, res, "display");
  10806   },
  10807 
  10808   htmlBuilder: htmlBuilder$3,
  10809   mathmlBuilder: mathmlBuilder$3
  10810 }); // alignat environment is like an align environment, but one must explicitly
  10811 // specify maximum number of columns in each row, and can adjust spacing between
  10812 // each columns.
  10813 
  10814 defineEnvironment({
  10815   type: "array",
  10816   names: ["alignat", "alignat*", "alignedat"],
  10817   props: {
  10818     numArgs: 1
  10819   },
  10820   handler: alignedHandler,
  10821   htmlBuilder: htmlBuilder$3,
  10822   mathmlBuilder: mathmlBuilder$3
  10823 });
  10824 defineEnvironment({
  10825   type: "array",
  10826   names: ["equation", "equation*"],
  10827   props: {
  10828     numArgs: 0
  10829   },
  10830 
  10831   handler(context) {
  10832     validateAmsEnvironmentContext(context);
  10833     var res = {
  10834       addEqnNum: context.envName === "equation",
  10835       singleRow: true,
  10836       maxNumCols: 1,
  10837       leqno: context.parser.settings.leqno
  10838     };
  10839     return parseArray(context.parser, res, "display");
  10840   },
  10841 
  10842   htmlBuilder: htmlBuilder$3,
  10843   mathmlBuilder: mathmlBuilder$3
  10844 });
  10845 defineEnvironment({
  10846   type: "array",
  10847   names: ["CD"],
  10848   props: {
  10849     numArgs: 0
  10850   },
  10851 
  10852   handler(context) {
  10853     validateAmsEnvironmentContext(context);
  10854     return parseCD(context.parser);
  10855   },
  10856 
  10857   htmlBuilder: htmlBuilder$3,
  10858   mathmlBuilder: mathmlBuilder$3
  10859 }); // Catch \hline outside array environment
  10860 
  10861 defineFunction({
  10862   type: "text",
  10863   // Doesn't matter what this is.
  10864   names: ["\\hline", "\\hdashline"],
  10865   props: {
  10866     numArgs: 0,
  10867     allowedInText: true,
  10868     allowedInMath: true
  10869   },
  10870 
  10871   handler(context, args) {
  10872     throw new ParseError(context.funcName + " valid only within array environment");
  10873   }
  10874 
  10875 });
  10876 
  10877 var environments = _environments;
  10878 
  10879 // defineEnvironment definitions.
  10880 
  10881 defineFunction({
  10882   type: "environment",
  10883   names: ["\\begin", "\\end"],
  10884   props: {
  10885     numArgs: 1,
  10886     argTypes: ["text"]
  10887   },
  10888 
  10889   handler(_ref, args) {
  10890     var {
  10891       parser,
  10892       funcName
  10893     } = _ref;
  10894     var nameGroup = args[0];
  10895 
  10896     if (nameGroup.type !== "ordgroup") {
  10897       throw new ParseError("Invalid environment name", nameGroup);
  10898     }
  10899 
  10900     var envName = "";
  10901 
  10902     for (var i = 0; i < nameGroup.body.length; ++i) {
  10903       envName += assertNodeType(nameGroup.body[i], "textord").text;
  10904     }
  10905 
  10906     if (funcName === "\\begin") {
  10907       // begin...end is similar to left...right
  10908       if (!environments.hasOwnProperty(envName)) {
  10909         throw new ParseError("No such environment: " + envName, nameGroup);
  10910       } // Build the environment object. Arguments and other information will
  10911       // be made available to the begin and end methods using properties.
  10912 
  10913 
  10914       var env = environments[envName];
  10915       var {
  10916         args: _args,
  10917         optArgs
  10918       } = parser.parseArguments("\\begin{" + envName + "}", env);
  10919       var context = {
  10920         mode: parser.mode,
  10921         envName,
  10922         parser
  10923       };
  10924       var result = env.handler(context, _args, optArgs);
  10925       parser.expect("\\end", false);
  10926       var endNameToken = parser.nextToken;
  10927       var end = assertNodeType(parser.parseFunction(), "environment");
  10928 
  10929       if (end.name !== envName) {
  10930         throw new ParseError("Mismatch: \\begin{" + envName + "} matched by \\end{" + end.name + "}", endNameToken);
  10931       } // $FlowFixMe, "environment" handler returns an environment ParseNode
  10932 
  10933 
  10934       return result;
  10935     }
  10936 
  10937     return {
  10938       type: "environment",
  10939       mode: parser.mode,
  10940       name: envName,
  10941       nameGroup
  10942     };
  10943   }
  10944 
  10945 });
  10946 
  10947 var makeSpan$2 = buildCommon.makeSpan;
  10948 
  10949 function htmlBuilder$4(group, options) {
  10950   var elements = buildExpression(group.body, options, true);
  10951   return makeSpan$2([group.mclass], elements, options);
  10952 }
  10953 
  10954 function mathmlBuilder$4(group, options) {
  10955   var node;
  10956   var inner = buildExpression$1(group.body, options);
  10957 
  10958   if (group.mclass === "minner") {
  10959     return mathMLTree.newDocumentFragment(inner);
  10960   } else if (group.mclass === "mord") {
  10961     if (group.isCharacterBox) {
  10962       node = inner[0];
  10963       node.type = "mi";
  10964     } else {
  10965       node = new mathMLTree.MathNode("mi", inner);
  10966     }
  10967   } else {
  10968     if (group.isCharacterBox) {
  10969       node = inner[0];
  10970       node.type = "mo";
  10971     } else {
  10972       node = new mathMLTree.MathNode("mo", inner);
  10973     } // Set spacing based on what is the most likely adjacent atom type.
  10974     // See TeXbook p170.
  10975 
  10976 
  10977     if (group.mclass === "mbin") {
  10978       node.attributes.lspace = "0.22em"; // medium space
  10979 
  10980       node.attributes.rspace = "0.22em";
  10981     } else if (group.mclass === "mpunct") {
  10982       node.attributes.lspace = "0em";
  10983       node.attributes.rspace = "0.17em"; // thinspace
  10984     } else if (group.mclass === "mopen" || group.mclass === "mclose") {
  10985       node.attributes.lspace = "0em";
  10986       node.attributes.rspace = "0em";
  10987     } // MathML <mo> default space is 5/18 em, so <mrel> needs no action.
  10988     // Ref: https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mo
  10989 
  10990   }
  10991 
  10992   return node;
  10993 } // Math class commands except \mathop
  10994 
  10995 
  10996 defineFunction({
  10997   type: "mclass",
  10998   names: ["\\mathord", "\\mathbin", "\\mathrel", "\\mathopen", "\\mathclose", "\\mathpunct", "\\mathinner"],
  10999   props: {
  11000     numArgs: 1,
  11001     primitive: true
  11002   },
  11003 
  11004   handler(_ref, args) {
  11005     var {
  11006       parser,
  11007       funcName
  11008     } = _ref;
  11009     var body = args[0];
  11010     return {
  11011       type: "mclass",
  11012       mode: parser.mode,
  11013       mclass: "m" + funcName.substr(5),
  11014       // TODO(kevinb): don't prefix with 'm'
  11015       body: ordargument(body),
  11016       isCharacterBox: utils.isCharacterBox(body)
  11017     };
  11018   },
  11019 
  11020   htmlBuilder: htmlBuilder$4,
  11021   mathmlBuilder: mathmlBuilder$4
  11022 });
  11023 var binrelClass = arg => {
  11024   // \binrel@ spacing varies with (bin|rel|ord) of the atom in the argument.
  11025   // (by rendering separately and with {}s before and after, and measuring
  11026   // the change in spacing).  We'll do roughly the same by detecting the
  11027   // atom type directly.
  11028   var atom = arg.type === "ordgroup" && arg.body.length ? arg.body[0] : arg;
  11029 
  11030   if (atom.type === "atom" && (atom.family === "bin" || atom.family === "rel")) {
  11031     return "m" + atom.family;
  11032   } else {
  11033     return "mord";
  11034   }
  11035 }; // \@binrel{x}{y} renders like y but as mbin/mrel/mord if x is mbin/mrel/mord.
  11036 // This is equivalent to \binrel@{x}\binrel@@{y} in AMSTeX.
  11037 
  11038 defineFunction({
  11039   type: "mclass",
  11040   names: ["\\@binrel"],
  11041   props: {
  11042     numArgs: 2
  11043   },
  11044 
  11045   handler(_ref2, args) {
  11046     var {
  11047       parser
  11048     } = _ref2;
  11049     return {
  11050       type: "mclass",
  11051       mode: parser.mode,
  11052       mclass: binrelClass(args[0]),
  11053       body: ordargument(args[1]),
  11054       isCharacterBox: utils.isCharacterBox(args[1])
  11055     };
  11056   }
  11057 
  11058 }); // Build a relation or stacked op by placing one symbol on top of another
  11059 
  11060 defineFunction({
  11061   type: "mclass",
  11062   names: ["\\stackrel", "\\overset", "\\underset"],
  11063   props: {
  11064     numArgs: 2
  11065   },
  11066 
  11067   handler(_ref3, args) {
  11068     var {
  11069       parser,
  11070       funcName
  11071     } = _ref3;
  11072     var baseArg = args[1];
  11073     var shiftedArg = args[0];
  11074     var mclass;
  11075 
  11076     if (funcName !== "\\stackrel") {
  11077       // LaTeX applies \binrel spacing to \overset and \underset.
  11078       mclass = binrelClass(baseArg);
  11079     } else {
  11080       mclass = "mrel"; // for \stackrel
  11081     }
  11082 
  11083     var baseOp = {
  11084       type: "op",
  11085       mode: baseArg.mode,
  11086       limits: true,
  11087       alwaysHandleSupSub: true,
  11088       parentIsSupSub: false,
  11089       symbol: false,
  11090       suppressBaseShift: funcName !== "\\stackrel",
  11091       body: ordargument(baseArg)
  11092     };
  11093     var supsub = {
  11094       type: "supsub",
  11095       mode: shiftedArg.mode,
  11096       base: baseOp,
  11097       sup: funcName === "\\underset" ? null : shiftedArg,
  11098       sub: funcName === "\\underset" ? shiftedArg : null
  11099     };
  11100     return {
  11101       type: "mclass",
  11102       mode: parser.mode,
  11103       mclass,
  11104       body: [supsub],
  11105       isCharacterBox: utils.isCharacterBox(supsub)
  11106     };
  11107   },
  11108 
  11109   htmlBuilder: htmlBuilder$4,
  11110   mathmlBuilder: mathmlBuilder$4
  11111 });
  11112 
  11113 // TODO(kevinb): implement \\sl and \\sc
  11114 
  11115 var htmlBuilder$5 = (group, options) => {
  11116   var font = group.font;
  11117   var newOptions = options.withFont(font);
  11118   return buildGroup(group.body, newOptions);
  11119 };
  11120 
  11121 var mathmlBuilder$5 = (group, options) => {
  11122   var font = group.font;
  11123   var newOptions = options.withFont(font);
  11124   return buildGroup$1(group.body, newOptions);
  11125 };
  11126 
  11127 var fontAliases = {
  11128   "\\Bbb": "\\mathbb",
  11129   "\\bold": "\\mathbf",
  11130   "\\frak": "\\mathfrak",
  11131   "\\bm": "\\boldsymbol"
  11132 };
  11133 defineFunction({
  11134   type: "font",
  11135   names: [// styles, except \boldsymbol defined below
  11136   "\\mathrm", "\\mathit", "\\mathbf", "\\mathnormal", // families
  11137   "\\mathbb", "\\mathcal", "\\mathfrak", "\\mathscr", "\\mathsf", "\\mathtt", // aliases, except \bm defined below
  11138   "\\Bbb", "\\bold", "\\frak"],
  11139   props: {
  11140     numArgs: 1,
  11141     allowedInArgument: true
  11142   },
  11143   handler: (_ref, args) => {
  11144     var {
  11145       parser,
  11146       funcName
  11147     } = _ref;
  11148     var body = normalizeArgument(args[0]);
  11149     var func = funcName;
  11150 
  11151     if (func in fontAliases) {
  11152       func = fontAliases[func];
  11153     }
  11154 
  11155     return {
  11156       type: "font",
  11157       mode: parser.mode,
  11158       font: func.slice(1),
  11159       body
  11160     };
  11161   },
  11162   htmlBuilder: htmlBuilder$5,
  11163   mathmlBuilder: mathmlBuilder$5
  11164 });
  11165 defineFunction({
  11166   type: "mclass",
  11167   names: ["\\boldsymbol", "\\bm"],
  11168   props: {
  11169     numArgs: 1
  11170   },
  11171   handler: (_ref2, args) => {
  11172     var {
  11173       parser
  11174     } = _ref2;
  11175     var body = args[0];
  11176     var isCharacterBox = utils.isCharacterBox(body); // amsbsy.sty's \boldsymbol uses \binrel spacing to inherit the
  11177     // argument's bin|rel|ord status
  11178 
  11179     return {
  11180       type: "mclass",
  11181       mode: parser.mode,
  11182       mclass: binrelClass(body),
  11183       body: [{
  11184         type: "font",
  11185         mode: parser.mode,
  11186         font: "boldsymbol",
  11187         body
  11188       }],
  11189       isCharacterBox: isCharacterBox
  11190     };
  11191   }
  11192 }); // Old font changing functions
  11193 
  11194 defineFunction({
  11195   type: "font",
  11196   names: ["\\rm", "\\sf", "\\tt", "\\bf", "\\it", "\\cal"],
  11197   props: {
  11198     numArgs: 0,
  11199     allowedInText: true
  11200   },
  11201   handler: (_ref3, args) => {
  11202     var {
  11203       parser,
  11204       funcName,
  11205       breakOnTokenText
  11206     } = _ref3;
  11207     var {
  11208       mode
  11209     } = parser;
  11210     var body = parser.parseExpression(true, breakOnTokenText);
  11211     var style = "math" + funcName.slice(1);
  11212     return {
  11213       type: "font",
  11214       mode: mode,
  11215       font: style,
  11216       body: {
  11217         type: "ordgroup",
  11218         mode: parser.mode,
  11219         body
  11220       }
  11221     };
  11222   },
  11223   htmlBuilder: htmlBuilder$5,
  11224   mathmlBuilder: mathmlBuilder$5
  11225 });
  11226 
  11227 var adjustStyle = (size, originalStyle) => {
  11228   // Figure out what style this fraction should be in based on the
  11229   // function used
  11230   var style = originalStyle;
  11231 
  11232   if (size === "display") {
  11233     // Get display style as a default.
  11234     // If incoming style is sub/sup, use style.text() to get correct size.
  11235     style = style.id >= Style$1.SCRIPT.id ? style.text() : Style$1.DISPLAY;
  11236   } else if (size === "text" && style.size === Style$1.DISPLAY.size) {
  11237     // We're in a \tfrac but incoming style is displaystyle, so:
  11238     style = Style$1.TEXT;
  11239   } else if (size === "script") {
  11240     style = Style$1.SCRIPT;
  11241   } else if (size === "scriptscript") {
  11242     style = Style$1.SCRIPTSCRIPT;
  11243   }
  11244 
  11245   return style;
  11246 };
  11247 
  11248 var htmlBuilder$6 = (group, options) => {
  11249   // Fractions are handled in the TeXbook on pages 444-445, rules 15(a-e).
  11250   var style = adjustStyle(group.size, options.style);
  11251   var nstyle = style.fracNum();
  11252   var dstyle = style.fracDen();
  11253   var newOptions;
  11254   newOptions = options.havingStyle(nstyle);
  11255   var numerm = buildGroup(group.numer, newOptions, options);
  11256 
  11257   if (group.continued) {
  11258     // \cfrac inserts a \strut into the numerator.
  11259     // Get \strut dimensions from TeXbook page 353.
  11260     var hStrut = 8.5 / options.fontMetrics().ptPerEm;
  11261     var dStrut = 3.5 / options.fontMetrics().ptPerEm;
  11262     numerm.height = numerm.height < hStrut ? hStrut : numerm.height;
  11263     numerm.depth = numerm.depth < dStrut ? dStrut : numerm.depth;
  11264   }
  11265 
  11266   newOptions = options.havingStyle(dstyle);
  11267   var denomm = buildGroup(group.denom, newOptions, options);
  11268   var rule;
  11269   var ruleWidth;
  11270   var ruleSpacing;
  11271 
  11272   if (group.hasBarLine) {
  11273     if (group.barSize) {
  11274       ruleWidth = calculateSize(group.barSize, options);
  11275       rule = buildCommon.makeLineSpan("frac-line", options, ruleWidth);
  11276     } else {
  11277       rule = buildCommon.makeLineSpan("frac-line", options);
  11278     }
  11279 
  11280     ruleWidth = rule.height;
  11281     ruleSpacing = rule.height;
  11282   } else {
  11283     rule = null;
  11284     ruleWidth = 0;
  11285     ruleSpacing = options.fontMetrics().defaultRuleThickness;
  11286   } // Rule 15b
  11287 
  11288 
  11289   var numShift;
  11290   var clearance;
  11291   var denomShift;
  11292 
  11293   if (style.size === Style$1.DISPLAY.size || group.size === "display") {
  11294     numShift = options.fontMetrics().num1;
  11295 
  11296     if (ruleWidth > 0) {
  11297       clearance = 3 * ruleSpacing;
  11298     } else {
  11299       clearance = 7 * ruleSpacing;
  11300     }
  11301 
  11302     denomShift = options.fontMetrics().denom1;
  11303   } else {
  11304     if (ruleWidth > 0) {
  11305       numShift = options.fontMetrics().num2;
  11306       clearance = ruleSpacing;
  11307     } else {
  11308       numShift = options.fontMetrics().num3;
  11309       clearance = 3 * ruleSpacing;
  11310     }
  11311 
  11312     denomShift = options.fontMetrics().denom2;
  11313   }
  11314 
  11315   var frac;
  11316 
  11317   if (!rule) {
  11318     // Rule 15c
  11319     var candidateClearance = numShift - numerm.depth - (denomm.height - denomShift);
  11320 
  11321     if (candidateClearance < clearance) {
  11322       numShift += 0.5 * (clearance - candidateClearance);
  11323       denomShift += 0.5 * (clearance - candidateClearance);
  11324     }
  11325 
  11326     frac = buildCommon.makeVList({
  11327       positionType: "individualShift",
  11328       children: [{
  11329         type: "elem",
  11330         elem: denomm,
  11331         shift: denomShift
  11332       }, {
  11333         type: "elem",
  11334         elem: numerm,
  11335         shift: -numShift
  11336       }]
  11337     }, options);
  11338   } else {
  11339     // Rule 15d
  11340     var axisHeight = options.fontMetrics().axisHeight;
  11341 
  11342     if (numShift - numerm.depth - (axisHeight + 0.5 * ruleWidth) < clearance) {
  11343       numShift += clearance - (numShift - numerm.depth - (axisHeight + 0.5 * ruleWidth));
  11344     }
  11345 
  11346     if (axisHeight - 0.5 * ruleWidth - (denomm.height - denomShift) < clearance) {
  11347       denomShift += clearance - (axisHeight - 0.5 * ruleWidth - (denomm.height - denomShift));
  11348     }
  11349 
  11350     var midShift = -(axisHeight - 0.5 * ruleWidth);
  11351     frac = buildCommon.makeVList({
  11352       positionType: "individualShift",
  11353       children: [{
  11354         type: "elem",
  11355         elem: denomm,
  11356         shift: denomShift
  11357       }, {
  11358         type: "elem",
  11359         elem: rule,
  11360         shift: midShift
  11361       }, {
  11362         type: "elem",
  11363         elem: numerm,
  11364         shift: -numShift
  11365       }]
  11366     }, options);
  11367   } // Since we manually change the style sometimes (with \dfrac or \tfrac),
  11368   // account for the possible size change here.
  11369 
  11370 
  11371   newOptions = options.havingStyle(style);
  11372   frac.height *= newOptions.sizeMultiplier / options.sizeMultiplier;
  11373   frac.depth *= newOptions.sizeMultiplier / options.sizeMultiplier; // Rule 15e
  11374 
  11375   var delimSize;
  11376 
  11377   if (style.size === Style$1.DISPLAY.size) {
  11378     delimSize = options.fontMetrics().delim1;
  11379   } else {
  11380     delimSize = options.fontMetrics().delim2;
  11381   }
  11382 
  11383   var leftDelim;
  11384   var rightDelim;
  11385 
  11386   if (group.leftDelim == null) {
  11387     leftDelim = makeNullDelimiter(options, ["mopen"]);
  11388   } else {
  11389     leftDelim = delimiter.customSizedDelim(group.leftDelim, delimSize, true, options.havingStyle(style), group.mode, ["mopen"]);
  11390   }
  11391 
  11392   if (group.continued) {
  11393     rightDelim = buildCommon.makeSpan([]); // zero width for \cfrac
  11394   } else if (group.rightDelim == null) {
  11395     rightDelim = makeNullDelimiter(options, ["mclose"]);
  11396   } else {
  11397     rightDelim = delimiter.customSizedDelim(group.rightDelim, delimSize, true, options.havingStyle(style), group.mode, ["mclose"]);
  11398   }
  11399 
  11400   return buildCommon.makeSpan(["mord"].concat(newOptions.sizingClasses(options)), [leftDelim, buildCommon.makeSpan(["mfrac"], [frac]), rightDelim], options);
  11401 };
  11402 
  11403 var mathmlBuilder$6 = (group, options) => {
  11404   var node = new mathMLTree.MathNode("mfrac", [buildGroup$1(group.numer, options), buildGroup$1(group.denom, options)]);
  11405 
  11406   if (!group.hasBarLine) {
  11407     node.setAttribute("linethickness", "0px");
  11408   } else if (group.barSize) {
  11409     var ruleWidth = calculateSize(group.barSize, options);
  11410     node.setAttribute("linethickness", ruleWidth + "em");
  11411   }
  11412 
  11413   var style = adjustStyle(group.size, options.style);
  11414 
  11415   if (style.size !== options.style.size) {
  11416     node = new mathMLTree.MathNode("mstyle", [node]);
  11417     var isDisplay = style.size === Style$1.DISPLAY.size ? "true" : "false";
  11418     node.setAttribute("displaystyle", isDisplay);
  11419     node.setAttribute("scriptlevel", "0");
  11420   }
  11421 
  11422   if (group.leftDelim != null || group.rightDelim != null) {
  11423     var withDelims = [];
  11424 
  11425     if (group.leftDelim != null) {
  11426       var leftOp = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode(group.leftDelim.replace("\\", ""))]);
  11427       leftOp.setAttribute("fence", "true");
  11428       withDelims.push(leftOp);
  11429     }
  11430 
  11431     withDelims.push(node);
  11432 
  11433     if (group.rightDelim != null) {
  11434       var rightOp = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode(group.rightDelim.replace("\\", ""))]);
  11435       rightOp.setAttribute("fence", "true");
  11436       withDelims.push(rightOp);
  11437     }
  11438 
  11439     return makeRow(withDelims);
  11440   }
  11441 
  11442   return node;
  11443 };
  11444 
  11445 defineFunction({
  11446   type: "genfrac",
  11447   names: ["\\dfrac", "\\frac", "\\tfrac", "\\dbinom", "\\binom", "\\tbinom", "\\\\atopfrac", // can’t be entered directly
  11448   "\\\\bracefrac", "\\\\brackfrac" // ditto
  11449   ],
  11450   props: {
  11451     numArgs: 2,
  11452     allowedInArgument: true
  11453   },
  11454   handler: (_ref, args) => {
  11455     var {
  11456       parser,
  11457       funcName
  11458     } = _ref;
  11459     var numer = args[0];
  11460     var denom = args[1];
  11461     var hasBarLine;
  11462     var leftDelim = null;
  11463     var rightDelim = null;
  11464     var size = "auto";
  11465 
  11466     switch (funcName) {
  11467       case "\\dfrac":
  11468       case "\\frac":
  11469       case "\\tfrac":
  11470         hasBarLine = true;
  11471         break;
  11472 
  11473       case "\\\\atopfrac":
  11474         hasBarLine = false;
  11475         break;
  11476 
  11477       case "\\dbinom":
  11478       case "\\binom":
  11479       case "\\tbinom":
  11480         hasBarLine = false;
  11481         leftDelim = "(";
  11482         rightDelim = ")";
  11483         break;
  11484 
  11485       case "\\\\bracefrac":
  11486         hasBarLine = false;
  11487         leftDelim = "\\{";
  11488         rightDelim = "\\}";
  11489         break;
  11490 
  11491       case "\\\\brackfrac":
  11492         hasBarLine = false;
  11493         leftDelim = "[";
  11494         rightDelim = "]";
  11495         break;
  11496 
  11497       default:
  11498         throw new Error("Unrecognized genfrac command");
  11499     }
  11500 
  11501     switch (funcName) {
  11502       case "\\dfrac":
  11503       case "\\dbinom":
  11504         size = "display";
  11505         break;
  11506 
  11507       case "\\tfrac":
  11508       case "\\tbinom":
  11509         size = "text";
  11510         break;
  11511     }
  11512 
  11513     return {
  11514       type: "genfrac",
  11515       mode: parser.mode,
  11516       continued: false,
  11517       numer,
  11518       denom,
  11519       hasBarLine,
  11520       leftDelim,
  11521       rightDelim,
  11522       size,
  11523       barSize: null
  11524     };
  11525   },
  11526   htmlBuilder: htmlBuilder$6,
  11527   mathmlBuilder: mathmlBuilder$6
  11528 });
  11529 defineFunction({
  11530   type: "genfrac",
  11531   names: ["\\cfrac"],
  11532   props: {
  11533     numArgs: 2
  11534   },
  11535   handler: (_ref2, args) => {
  11536     var {
  11537       parser,
  11538       funcName
  11539     } = _ref2;
  11540     var numer = args[0];
  11541     var denom = args[1];
  11542     return {
  11543       type: "genfrac",
  11544       mode: parser.mode,
  11545       continued: true,
  11546       numer,
  11547       denom,
  11548       hasBarLine: true,
  11549       leftDelim: null,
  11550       rightDelim: null,
  11551       size: "display",
  11552       barSize: null
  11553     };
  11554   }
  11555 }); // Infix generalized fractions -- these are not rendered directly, but replaced
  11556 // immediately by one of the variants above.
  11557 
  11558 defineFunction({
  11559   type: "infix",
  11560   names: ["\\over", "\\choose", "\\atop", "\\brace", "\\brack"],
  11561   props: {
  11562     numArgs: 0,
  11563     infix: true
  11564   },
  11565 
  11566   handler(_ref3) {
  11567     var {
  11568       parser,
  11569       funcName,
  11570       token
  11571     } = _ref3;
  11572     var replaceWith;
  11573 
  11574     switch (funcName) {
  11575       case "\\over":
  11576         replaceWith = "\\frac";
  11577         break;
  11578 
  11579       case "\\choose":
  11580         replaceWith = "\\binom";
  11581         break;
  11582 
  11583       case "\\atop":
  11584         replaceWith = "\\\\atopfrac";
  11585         break;
  11586 
  11587       case "\\brace":
  11588         replaceWith = "\\\\bracefrac";
  11589         break;
  11590 
  11591       case "\\brack":
  11592         replaceWith = "\\\\brackfrac";
  11593         break;
  11594 
  11595       default:
  11596         throw new Error("Unrecognized infix genfrac command");
  11597     }
  11598 
  11599     return {
  11600       type: "infix",
  11601       mode: parser.mode,
  11602       replaceWith,
  11603       token
  11604     };
  11605   }
  11606 
  11607 });
  11608 var stylArray = ["display", "text", "script", "scriptscript"];
  11609 
  11610 var delimFromValue = function delimFromValue(delimString) {
  11611   var delim = null;
  11612 
  11613   if (delimString.length > 0) {
  11614     delim = delimString;
  11615     delim = delim === "." ? null : delim;
  11616   }
  11617 
  11618   return delim;
  11619 };
  11620 
  11621 defineFunction({
  11622   type: "genfrac",
  11623   names: ["\\genfrac"],
  11624   props: {
  11625     numArgs: 6,
  11626     allowedInArgument: true,
  11627     argTypes: ["math", "math", "size", "text", "math", "math"]
  11628   },
  11629 
  11630   handler(_ref4, args) {
  11631     var {
  11632       parser
  11633     } = _ref4;
  11634     var numer = args[4];
  11635     var denom = args[5]; // Look into the parse nodes to get the desired delimiters.
  11636 
  11637     var leftNode = normalizeArgument(args[0]);
  11638     var leftDelim = leftNode.type === "atom" && leftNode.family === "open" ? delimFromValue(leftNode.text) : null;
  11639     var rightNode = normalizeArgument(args[1]);
  11640     var rightDelim = rightNode.type === "atom" && rightNode.family === "close" ? delimFromValue(rightNode.text) : null;
  11641     var barNode = assertNodeType(args[2], "size");
  11642     var hasBarLine;
  11643     var barSize = null;
  11644 
  11645     if (barNode.isBlank) {
  11646       // \genfrac acts differently than \above.
  11647       // \genfrac treats an empty size group as a signal to use a
  11648       // standard bar size. \above would see size = 0 and omit the bar.
  11649       hasBarLine = true;
  11650     } else {
  11651       barSize = barNode.value;
  11652       hasBarLine = barSize.number > 0;
  11653     } // Find out if we want displaystyle, textstyle, etc.
  11654 
  11655 
  11656     var size = "auto";
  11657     var styl = args[3];
  11658 
  11659     if (styl.type === "ordgroup") {
  11660       if (styl.body.length > 0) {
  11661         var textOrd = assertNodeType(styl.body[0], "textord");
  11662         size = stylArray[Number(textOrd.text)];
  11663       }
  11664     } else {
  11665       styl = assertNodeType(styl, "textord");
  11666       size = stylArray[Number(styl.text)];
  11667     }
  11668 
  11669     return {
  11670       type: "genfrac",
  11671       mode: parser.mode,
  11672       numer,
  11673       denom,
  11674       continued: false,
  11675       hasBarLine,
  11676       barSize,
  11677       leftDelim,
  11678       rightDelim,
  11679       size
  11680     };
  11681   },
  11682 
  11683   htmlBuilder: htmlBuilder$6,
  11684   mathmlBuilder: mathmlBuilder$6
  11685 }); // \above is an infix fraction that also defines a fraction bar size.
  11686 
  11687 defineFunction({
  11688   type: "infix",
  11689   names: ["\\above"],
  11690   props: {
  11691     numArgs: 1,
  11692     argTypes: ["size"],
  11693     infix: true
  11694   },
  11695 
  11696   handler(_ref5, args) {
  11697     var {
  11698       parser,
  11699       funcName,
  11700       token
  11701     } = _ref5;
  11702     return {
  11703       type: "infix",
  11704       mode: parser.mode,
  11705       replaceWith: "\\\\abovefrac",
  11706       size: assertNodeType(args[0], "size").value,
  11707       token
  11708     };
  11709   }
  11710 
  11711 });
  11712 defineFunction({
  11713   type: "genfrac",
  11714   names: ["\\\\abovefrac"],
  11715   props: {
  11716     numArgs: 3,
  11717     argTypes: ["math", "size", "math"]
  11718   },
  11719   handler: (_ref6, args) => {
  11720     var {
  11721       parser,
  11722       funcName
  11723     } = _ref6;
  11724     var numer = args[0];
  11725     var barSize = assert(assertNodeType(args[1], "infix").size);
  11726     var denom = args[2];
  11727     var hasBarLine = barSize.number > 0;
  11728     return {
  11729       type: "genfrac",
  11730       mode: parser.mode,
  11731       numer,
  11732       denom,
  11733       continued: false,
  11734       hasBarLine,
  11735       barSize,
  11736       leftDelim: null,
  11737       rightDelim: null,
  11738       size: "auto"
  11739     };
  11740   },
  11741   htmlBuilder: htmlBuilder$6,
  11742   mathmlBuilder: mathmlBuilder$6
  11743 });
  11744 
  11745 // NOTE: Unlike most `htmlBuilder`s, this one handles not only "horizBrace", but
  11746 // also "supsub" since an over/underbrace can affect super/subscripting.
  11747 var htmlBuilder$7 = (grp, options) => {
  11748   var style = options.style; // Pull out the `ParseNode<"horizBrace">` if `grp` is a "supsub" node.
  11749 
  11750   var supSubGroup;
  11751   var group;
  11752 
  11753   if (grp.type === "supsub") {
  11754     // Ref: LaTeX source2e: }}}}\limits}
  11755     // i.e. LaTeX treats the brace similar to an op and passes it
  11756     // with \limits, so we need to assign supsub style.
  11757     supSubGroup = grp.sup ? buildGroup(grp.sup, options.havingStyle(style.sup()), options) : buildGroup(grp.sub, options.havingStyle(style.sub()), options);
  11758     group = assertNodeType(grp.base, "horizBrace");
  11759   } else {
  11760     group = assertNodeType(grp, "horizBrace");
  11761   } // Build the base group
  11762 
  11763 
  11764   var body = buildGroup(group.base, options.havingBaseStyle(Style$1.DISPLAY)); // Create the stretchy element
  11765 
  11766   var braceBody = stretchy.svgSpan(group, options); // Generate the vlist, with the appropriate kerns        ┏━━━━━━━━┓
  11767   // This first vlist contains the content and the brace:   equation
  11768 
  11769   var vlist;
  11770 
  11771   if (group.isOver) {
  11772     vlist = buildCommon.makeVList({
  11773       positionType: "firstBaseline",
  11774       children: [{
  11775         type: "elem",
  11776         elem: body
  11777       }, {
  11778         type: "kern",
  11779         size: 0.1
  11780       }, {
  11781         type: "elem",
  11782         elem: braceBody
  11783       }]
  11784     }, options); // $FlowFixMe: Replace this with passing "svg-align" into makeVList.
  11785 
  11786     vlist.children[0].children[0].children[1].classes.push("svg-align");
  11787   } else {
  11788     vlist = buildCommon.makeVList({
  11789       positionType: "bottom",
  11790       positionData: body.depth + 0.1 + braceBody.height,
  11791       children: [{
  11792         type: "elem",
  11793         elem: braceBody
  11794       }, {
  11795         type: "kern",
  11796         size: 0.1
  11797       }, {
  11798         type: "elem",
  11799         elem: body
  11800       }]
  11801     }, options); // $FlowFixMe: Replace this with passing "svg-align" into makeVList.
  11802 
  11803     vlist.children[0].children[0].children[0].classes.push("svg-align");
  11804   }
  11805 
  11806   if (supSubGroup) {
  11807     // To write the supsub, wrap the first vlist in another vlist:
  11808     // They can't all go in the same vlist, because the note might be
  11809     // wider than the equation. We want the equation to control the
  11810     // brace width.
  11811     //      note          long note           long note
  11812     //   ┏━━━━━━━━┓   or    ┏━━━┓     not    ┏━━━━━━━━━┓
  11813     //    equation           eqn                 eqn
  11814     var vSpan = buildCommon.makeSpan(["mord", group.isOver ? "mover" : "munder"], [vlist], options);
  11815 
  11816     if (group.isOver) {
  11817       vlist = buildCommon.makeVList({
  11818         positionType: "firstBaseline",
  11819         children: [{
  11820           type: "elem",
  11821           elem: vSpan
  11822         }, {
  11823           type: "kern",
  11824           size: 0.2
  11825         }, {
  11826           type: "elem",
  11827           elem: supSubGroup
  11828         }]
  11829       }, options);
  11830     } else {
  11831       vlist = buildCommon.makeVList({
  11832         positionType: "bottom",
  11833         positionData: vSpan.depth + 0.2 + supSubGroup.height + supSubGroup.depth,
  11834         children: [{
  11835           type: "elem",
  11836           elem: supSubGroup
  11837         }, {
  11838           type: "kern",
  11839           size: 0.2
  11840         }, {
  11841           type: "elem",
  11842           elem: vSpan
  11843         }]
  11844       }, options);
  11845     }
  11846   }
  11847 
  11848   return buildCommon.makeSpan(["mord", group.isOver ? "mover" : "munder"], [vlist], options);
  11849 };
  11850 
  11851 var mathmlBuilder$7 = (group, options) => {
  11852   var accentNode = stretchy.mathMLnode(group.label);
  11853   return new mathMLTree.MathNode(group.isOver ? "mover" : "munder", [buildGroup$1(group.base, options), accentNode]);
  11854 }; // Horizontal stretchy braces
  11855 
  11856 
  11857 defineFunction({
  11858   type: "horizBrace",
  11859   names: ["\\overbrace", "\\underbrace"],
  11860   props: {
  11861     numArgs: 1
  11862   },
  11863 
  11864   handler(_ref, args) {
  11865     var {
  11866       parser,
  11867       funcName
  11868     } = _ref;
  11869     return {
  11870       type: "horizBrace",
  11871       mode: parser.mode,
  11872       label: funcName,
  11873       isOver: /^\\over/.test(funcName),
  11874       base: args[0]
  11875     };
  11876   },
  11877 
  11878   htmlBuilder: htmlBuilder$7,
  11879   mathmlBuilder: mathmlBuilder$7
  11880 });
  11881 
  11882 defineFunction({
  11883   type: "href",
  11884   names: ["\\href"],
  11885   props: {
  11886     numArgs: 2,
  11887     argTypes: ["url", "original"],
  11888     allowedInText: true
  11889   },
  11890   handler: (_ref, args) => {
  11891     var {
  11892       parser
  11893     } = _ref;
  11894     var body = args[1];
  11895     var href = assertNodeType(args[0], "url").url;
  11896 
  11897     if (!parser.settings.isTrusted({
  11898       command: "\\href",
  11899       url: href
  11900     })) {
  11901       return parser.formatUnsupportedCmd("\\href");
  11902     }
  11903 
  11904     return {
  11905       type: "href",
  11906       mode: parser.mode,
  11907       href,
  11908       body: ordargument(body)
  11909     };
  11910   },
  11911   htmlBuilder: (group, options) => {
  11912     var elements = buildExpression(group.body, options, false);
  11913     return buildCommon.makeAnchor(group.href, [], elements, options);
  11914   },
  11915   mathmlBuilder: (group, options) => {
  11916     var math = buildExpressionRow(group.body, options);
  11917 
  11918     if (!(math instanceof MathNode)) {
  11919       math = new MathNode("mrow", [math]);
  11920     }
  11921 
  11922     math.setAttribute("href", group.href);
  11923     return math;
  11924   }
  11925 });
  11926 defineFunction({
  11927   type: "href",
  11928   names: ["\\url"],
  11929   props: {
  11930     numArgs: 1,
  11931     argTypes: ["url"],
  11932     allowedInText: true
  11933   },
  11934   handler: (_ref2, args) => {
  11935     var {
  11936       parser
  11937     } = _ref2;
  11938     var href = assertNodeType(args[0], "url").url;
  11939 
  11940     if (!parser.settings.isTrusted({
  11941       command: "\\url",
  11942       url: href
  11943     })) {
  11944       return parser.formatUnsupportedCmd("\\url");
  11945     }
  11946 
  11947     var chars = [];
  11948 
  11949     for (var i = 0; i < href.length; i++) {
  11950       var c = href[i];
  11951 
  11952       if (c === "~") {
  11953         c = "\\textasciitilde";
  11954       }
  11955 
  11956       chars.push({
  11957         type: "textord",
  11958         mode: "text",
  11959         text: c
  11960       });
  11961     }
  11962 
  11963     var body = {
  11964       type: "text",
  11965       mode: parser.mode,
  11966       font: "\\texttt",
  11967       body: chars
  11968     };
  11969     return {
  11970       type: "href",
  11971       mode: parser.mode,
  11972       href,
  11973       body: ordargument(body)
  11974     };
  11975   }
  11976 });
  11977 
  11978 // In LaTeX, \vcenter can act only on a box, as in
  11979 // \vcenter{\hbox{$\frac{a+b}{\dfrac{c}{d}}$}}
  11980 // This function by itself doesn't do anything but prevent a soft line break.
  11981 
  11982 defineFunction({
  11983   type: "hbox",
  11984   names: ["\\hbox"],
  11985   props: {
  11986     numArgs: 1,
  11987     argTypes: ["text"],
  11988     allowedInText: true,
  11989     primitive: true
  11990   },
  11991 
  11992   handler(_ref, args) {
  11993     var {
  11994       parser
  11995     } = _ref;
  11996     return {
  11997       type: "hbox",
  11998       mode: parser.mode,
  11999       body: ordargument(args[0])
  12000     };
  12001   },
  12002 
  12003   htmlBuilder(group, options) {
  12004     var elements = buildExpression(group.body, options, false);
  12005     return buildCommon.makeFragment(elements);
  12006   },
  12007 
  12008   mathmlBuilder(group, options) {
  12009     return new mathMLTree.MathNode("mrow", buildExpression$1(group.body, options));
  12010   }
  12011 
  12012 });
  12013 
  12014 defineFunction({
  12015   type: "html",
  12016   names: ["\\htmlClass", "\\htmlId", "\\htmlStyle", "\\htmlData"],
  12017   props: {
  12018     numArgs: 2,
  12019     argTypes: ["raw", "original"],
  12020     allowedInText: true
  12021   },
  12022   handler: (_ref, args) => {
  12023     var {
  12024       parser,
  12025       funcName,
  12026       token
  12027     } = _ref;
  12028     var value = assertNodeType(args[0], "raw").string;
  12029     var body = args[1];
  12030 
  12031     if (parser.settings.strict) {
  12032       parser.settings.reportNonstrict("htmlExtension", "HTML extension is disabled on strict mode");
  12033     }
  12034 
  12035     var trustContext;
  12036     var attributes = {};
  12037 
  12038     switch (funcName) {
  12039       case "\\htmlClass":
  12040         attributes.class = value;
  12041         trustContext = {
  12042           command: "\\htmlClass",
  12043           class: value
  12044         };
  12045         break;
  12046 
  12047       case "\\htmlId":
  12048         attributes.id = value;
  12049         trustContext = {
  12050           command: "\\htmlId",
  12051           id: value
  12052         };
  12053         break;
  12054 
  12055       case "\\htmlStyle":
  12056         attributes.style = value;
  12057         trustContext = {
  12058           command: "\\htmlStyle",
  12059           style: value
  12060         };
  12061         break;
  12062 
  12063       case "\\htmlData":
  12064         {
  12065           var data = value.split(",");
  12066 
  12067           for (var i = 0; i < data.length; i++) {
  12068             var keyVal = data[i].split("=");
  12069 
  12070             if (keyVal.length !== 2) {
  12071               throw new ParseError("Error parsing key-value for \\htmlData");
  12072             }
  12073 
  12074             attributes["data-" + keyVal[0].trim()] = keyVal[1].trim();
  12075           }
  12076 
  12077           trustContext = {
  12078             command: "\\htmlData",
  12079             attributes
  12080           };
  12081           break;
  12082         }
  12083 
  12084       default:
  12085         throw new Error("Unrecognized html command");
  12086     }
  12087 
  12088     if (!parser.settings.isTrusted(trustContext)) {
  12089       return parser.formatUnsupportedCmd(funcName);
  12090     }
  12091 
  12092     return {
  12093       type: "html",
  12094       mode: parser.mode,
  12095       attributes,
  12096       body: ordargument(body)
  12097     };
  12098   },
  12099   htmlBuilder: (group, options) => {
  12100     var elements = buildExpression(group.body, options, false);
  12101     var classes = ["enclosing"];
  12102 
  12103     if (group.attributes.class) {
  12104       classes.push(...group.attributes.class.trim().split(/\s+/));
  12105     }
  12106 
  12107     var span = buildCommon.makeSpan(classes, elements, options);
  12108 
  12109     for (var attr in group.attributes) {
  12110       if (attr !== "class" && group.attributes.hasOwnProperty(attr)) {
  12111         span.setAttribute(attr, group.attributes[attr]);
  12112       }
  12113     }
  12114 
  12115     return span;
  12116   },
  12117   mathmlBuilder: (group, options) => {
  12118     return buildExpressionRow(group.body, options);
  12119   }
  12120 });
  12121 
  12122 defineFunction({
  12123   type: "htmlmathml",
  12124   names: ["\\html@mathml"],
  12125   props: {
  12126     numArgs: 2,
  12127     allowedInText: true
  12128   },
  12129   handler: (_ref, args) => {
  12130     var {
  12131       parser
  12132     } = _ref;
  12133     return {
  12134       type: "htmlmathml",
  12135       mode: parser.mode,
  12136       html: ordargument(args[0]),
  12137       mathml: ordargument(args[1])
  12138     };
  12139   },
  12140   htmlBuilder: (group, options) => {
  12141     var elements = buildExpression(group.html, options, false);
  12142     return buildCommon.makeFragment(elements);
  12143   },
  12144   mathmlBuilder: (group, options) => {
  12145     return buildExpressionRow(group.mathml, options);
  12146   }
  12147 });
  12148 
  12149 var sizeData = function sizeData(str) {
  12150   if (/^[-+]? *(\d+(\.\d*)?|\.\d+)$/.test(str)) {
  12151     // str is a number with no unit specified.
  12152     // default unit is bp, per graphix package.
  12153     return {
  12154       number: +str,
  12155       unit: "bp"
  12156     };
  12157   } else {
  12158     var match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(str);
  12159 
  12160     if (!match) {
  12161       throw new ParseError("Invalid size: '" + str + "' in \\includegraphics");
  12162     }
  12163 
  12164     var data = {
  12165       number: +(match[1] + match[2]),
  12166       // sign + magnitude, cast to number
  12167       unit: match[3]
  12168     };
  12169 
  12170     if (!validUnit(data)) {
  12171       throw new ParseError("Invalid unit: '" + data.unit + "' in \\includegraphics.");
  12172     }
  12173 
  12174     return data;
  12175   }
  12176 };
  12177 
  12178 defineFunction({
  12179   type: "includegraphics",
  12180   names: ["\\includegraphics"],
  12181   props: {
  12182     numArgs: 1,
  12183     numOptionalArgs: 1,
  12184     argTypes: ["raw", "url"],
  12185     allowedInText: false
  12186   },
  12187   handler: (_ref, args, optArgs) => {
  12188     var {
  12189       parser
  12190     } = _ref;
  12191     var width = {
  12192       number: 0,
  12193       unit: "em"
  12194     };
  12195     var height = {
  12196       number: 0.9,
  12197       unit: "em"
  12198     }; // sorta character sized.
  12199 
  12200     var totalheight = {
  12201       number: 0,
  12202       unit: "em"
  12203     };
  12204     var alt = "";
  12205 
  12206     if (optArgs[0]) {
  12207       var attributeStr = assertNodeType(optArgs[0], "raw").string; // Parser.js does not parse key/value pairs. We get a string.
  12208 
  12209       var attributes = attributeStr.split(",");
  12210 
  12211       for (var i = 0; i < attributes.length; i++) {
  12212         var keyVal = attributes[i].split("=");
  12213 
  12214         if (keyVal.length === 2) {
  12215           var str = keyVal[1].trim();
  12216 
  12217           switch (keyVal[0].trim()) {
  12218             case "alt":
  12219               alt = str;
  12220               break;
  12221 
  12222             case "width":
  12223               width = sizeData(str);
  12224               break;
  12225 
  12226             case "height":
  12227               height = sizeData(str);
  12228               break;
  12229 
  12230             case "totalheight":
  12231               totalheight = sizeData(str);
  12232               break;
  12233 
  12234             default:
  12235               throw new ParseError("Invalid key: '" + keyVal[0] + "' in \\includegraphics.");
  12236           }
  12237         }
  12238       }
  12239     }
  12240 
  12241     var src = assertNodeType(args[0], "url").url;
  12242 
  12243     if (alt === "") {
  12244       // No alt given. Use the file name. Strip away the path.
  12245       alt = src;
  12246       alt = alt.replace(/^.*[\\/]/, '');
  12247       alt = alt.substring(0, alt.lastIndexOf('.'));
  12248     }
  12249 
  12250     if (!parser.settings.isTrusted({
  12251       command: "\\includegraphics",
  12252       url: src
  12253     })) {
  12254       return parser.formatUnsupportedCmd("\\includegraphics");
  12255     }
  12256 
  12257     return {
  12258       type: "includegraphics",
  12259       mode: parser.mode,
  12260       alt: alt,
  12261       width: width,
  12262       height: height,
  12263       totalheight: totalheight,
  12264       src: src
  12265     };
  12266   },
  12267   htmlBuilder: (group, options) => {
  12268     var height = calculateSize(group.height, options);
  12269     var depth = 0;
  12270 
  12271     if (group.totalheight.number > 0) {
  12272       depth = calculateSize(group.totalheight, options) - height;
  12273       depth = Number(depth.toFixed(2));
  12274     }
  12275 
  12276     var width = 0;
  12277 
  12278     if (group.width.number > 0) {
  12279       width = calculateSize(group.width, options);
  12280     }
  12281 
  12282     var style = {
  12283       height: height + depth + "em"
  12284     };
  12285 
  12286     if (width > 0) {
  12287       style.width = width + "em";
  12288     }
  12289 
  12290     if (depth > 0) {
  12291       style.verticalAlign = -depth + "em";
  12292     }
  12293 
  12294     var node = new Img(group.src, group.alt, style);
  12295     node.height = height;
  12296     node.depth = depth;
  12297     return node;
  12298   },
  12299   mathmlBuilder: (group, options) => {
  12300     var node = new mathMLTree.MathNode("mglyph", []);
  12301     node.setAttribute("alt", group.alt);
  12302     var height = calculateSize(group.height, options);
  12303     var depth = 0;
  12304 
  12305     if (group.totalheight.number > 0) {
  12306       depth = calculateSize(group.totalheight, options) - height;
  12307       depth = depth.toFixed(2);
  12308       node.setAttribute("valign", "-" + depth + "em");
  12309     }
  12310 
  12311     node.setAttribute("height", height + depth + "em");
  12312 
  12313     if (group.width.number > 0) {
  12314       var width = calculateSize(group.width, options);
  12315       node.setAttribute("width", width + "em");
  12316     }
  12317 
  12318     node.setAttribute("src", group.src);
  12319     return node;
  12320   }
  12321 });
  12322 
  12323 // Horizontal spacing commands
  12324 
  12325 defineFunction({
  12326   type: "kern",
  12327   names: ["\\kern", "\\mkern", "\\hskip", "\\mskip"],
  12328   props: {
  12329     numArgs: 1,
  12330     argTypes: ["size"],
  12331     primitive: true,
  12332     allowedInText: true
  12333   },
  12334 
  12335   handler(_ref, args) {
  12336     var {
  12337       parser,
  12338       funcName
  12339     } = _ref;
  12340     var size = assertNodeType(args[0], "size");
  12341 
  12342     if (parser.settings.strict) {
  12343       var mathFunction = funcName[1] === 'm'; // \mkern, \mskip
  12344 
  12345       var muUnit = size.value.unit === 'mu';
  12346 
  12347       if (mathFunction) {
  12348         if (!muUnit) {
  12349           parser.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + funcName + " supports only mu units, " + ("not " + size.value.unit + " units"));
  12350         }
  12351 
  12352         if (parser.mode !== "math") {
  12353           parser.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + funcName + " works only in math mode");
  12354         }
  12355       } else {
  12356         // !mathFunction
  12357         if (muUnit) {
  12358           parser.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + funcName + " doesn't support mu units");
  12359         }
  12360       }
  12361     }
  12362 
  12363     return {
  12364       type: "kern",
  12365       mode: parser.mode,
  12366       dimension: size.value
  12367     };
  12368   },
  12369 
  12370   htmlBuilder(group, options) {
  12371     return buildCommon.makeGlue(group.dimension, options);
  12372   },
  12373 
  12374   mathmlBuilder(group, options) {
  12375     var dimension = calculateSize(group.dimension, options);
  12376     return new mathMLTree.SpaceNode(dimension);
  12377   }
  12378 
  12379 });
  12380 
  12381 // Horizontal overlap functions
  12382 defineFunction({
  12383   type: "lap",
  12384   names: ["\\mathllap", "\\mathrlap", "\\mathclap"],
  12385   props: {
  12386     numArgs: 1,
  12387     allowedInText: true
  12388   },
  12389   handler: (_ref, args) => {
  12390     var {
  12391       parser,
  12392       funcName
  12393     } = _ref;
  12394     var body = args[0];
  12395     return {
  12396       type: "lap",
  12397       mode: parser.mode,
  12398       alignment: funcName.slice(5),
  12399       body
  12400     };
  12401   },
  12402   htmlBuilder: (group, options) => {
  12403     // mathllap, mathrlap, mathclap
  12404     var inner;
  12405 
  12406     if (group.alignment === "clap") {
  12407       // ref: https://www.math.lsu.edu/~aperlis/publications/mathclap/
  12408       inner = buildCommon.makeSpan([], [buildGroup(group.body, options)]); // wrap, since CSS will center a .clap > .inner > span
  12409 
  12410       inner = buildCommon.makeSpan(["inner"], [inner], options);
  12411     } else {
  12412       inner = buildCommon.makeSpan(["inner"], [buildGroup(group.body, options)]);
  12413     }
  12414 
  12415     var fix = buildCommon.makeSpan(["fix"], []);
  12416     var node = buildCommon.makeSpan([group.alignment], [inner, fix], options); // At this point, we have correctly set horizontal alignment of the
  12417     // two items involved in the lap.
  12418     // Next, use a strut to set the height of the HTML bounding box.
  12419     // Otherwise, a tall argument may be misplaced.
  12420     // This code resolved issue #1153
  12421 
  12422     var strut = buildCommon.makeSpan(["strut"]);
  12423     strut.style.height = node.height + node.depth + "em";
  12424     strut.style.verticalAlign = -node.depth + "em";
  12425     node.children.unshift(strut); // Next, prevent vertical misplacement when next to something tall.
  12426     // This code resolves issue #1234
  12427 
  12428     node = buildCommon.makeSpan(["thinbox"], [node], options);
  12429     return buildCommon.makeSpan(["mord", "vbox"], [node], options);
  12430   },
  12431   mathmlBuilder: (group, options) => {
  12432     // mathllap, mathrlap, mathclap
  12433     var node = new mathMLTree.MathNode("mpadded", [buildGroup$1(group.body, options)]);
  12434 
  12435     if (group.alignment !== "rlap") {
  12436       var offset = group.alignment === "llap" ? "-1" : "-0.5";
  12437       node.setAttribute("lspace", offset + "width");
  12438     }
  12439 
  12440     node.setAttribute("width", "0px");
  12441     return node;
  12442   }
  12443 });
  12444 
  12445 defineFunction({
  12446   type: "styling",
  12447   names: ["\\(", "$"],
  12448   props: {
  12449     numArgs: 0,
  12450     allowedInText: true,
  12451     allowedInMath: false
  12452   },
  12453 
  12454   handler(_ref, args) {
  12455     var {
  12456       funcName,
  12457       parser
  12458     } = _ref;
  12459     var outerMode = parser.mode;
  12460     parser.switchMode("math");
  12461     var close = funcName === "\\(" ? "\\)" : "$";
  12462     var body = parser.parseExpression(false, close);
  12463     parser.expect(close);
  12464     parser.switchMode(outerMode);
  12465     return {
  12466       type: "styling",
  12467       mode: parser.mode,
  12468       style: "text",
  12469       body
  12470     };
  12471   }
  12472 
  12473 }); // Check for extra closing math delimiters
  12474 
  12475 defineFunction({
  12476   type: "text",
  12477   // Doesn't matter what this is.
  12478   names: ["\\)", "\\]"],
  12479   props: {
  12480     numArgs: 0,
  12481     allowedInText: true,
  12482     allowedInMath: false
  12483   },
  12484 
  12485   handler(context, args) {
  12486     throw new ParseError("Mismatched " + context.funcName);
  12487   }
  12488 
  12489 });
  12490 
  12491 var chooseMathStyle = (group, options) => {
  12492   switch (options.style.size) {
  12493     case Style$1.DISPLAY.size:
  12494       return group.display;
  12495 
  12496     case Style$1.TEXT.size:
  12497       return group.text;
  12498 
  12499     case Style$1.SCRIPT.size:
  12500       return group.script;
  12501 
  12502     case Style$1.SCRIPTSCRIPT.size:
  12503       return group.scriptscript;
  12504 
  12505     default:
  12506       return group.text;
  12507   }
  12508 };
  12509 
  12510 defineFunction({
  12511   type: "mathchoice",
  12512   names: ["\\mathchoice"],
  12513   props: {
  12514     numArgs: 4,
  12515     primitive: true
  12516   },
  12517   handler: (_ref, args) => {
  12518     var {
  12519       parser
  12520     } = _ref;
  12521     return {
  12522       type: "mathchoice",
  12523       mode: parser.mode,
  12524       display: ordargument(args[0]),
  12525       text: ordargument(args[1]),
  12526       script: ordargument(args[2]),
  12527       scriptscript: ordargument(args[3])
  12528     };
  12529   },
  12530   htmlBuilder: (group, options) => {
  12531     var body = chooseMathStyle(group, options);
  12532     var elements = buildExpression(body, options, false);
  12533     return buildCommon.makeFragment(elements);
  12534   },
  12535   mathmlBuilder: (group, options) => {
  12536     var body = chooseMathStyle(group, options);
  12537     return buildExpressionRow(body, options);
  12538   }
  12539 });
  12540 
  12541 // For an operator with limits, assemble the base, sup, and sub into a span.
  12542 var assembleSupSub = (base, supGroup, subGroup, options, style, slant, baseShift) => {
  12543   base = buildCommon.makeSpan([], [base]);
  12544   var sub;
  12545   var sup; // We manually have to handle the superscripts and subscripts. This,
  12546   // aside from the kern calculations, is copied from supsub.
  12547 
  12548   if (supGroup) {
  12549     var elem = buildGroup(supGroup, options.havingStyle(style.sup()), options);
  12550     sup = {
  12551       elem,
  12552       kern: Math.max(options.fontMetrics().bigOpSpacing1, options.fontMetrics().bigOpSpacing3 - elem.depth)
  12553     };
  12554   }
  12555 
  12556   if (subGroup) {
  12557     var _elem = buildGroup(subGroup, options.havingStyle(style.sub()), options);
  12558 
  12559     sub = {
  12560       elem: _elem,
  12561       kern: Math.max(options.fontMetrics().bigOpSpacing2, options.fontMetrics().bigOpSpacing4 - _elem.height)
  12562     };
  12563   } // Build the final group as a vlist of the possible subscript, base,
  12564   // and possible superscript.
  12565 
  12566 
  12567   var finalGroup;
  12568 
  12569   if (sup && sub) {
  12570     var bottom = options.fontMetrics().bigOpSpacing5 + sub.elem.height + sub.elem.depth + sub.kern + base.depth + baseShift;
  12571     finalGroup = buildCommon.makeVList({
  12572       positionType: "bottom",
  12573       positionData: bottom,
  12574       children: [{
  12575         type: "kern",
  12576         size: options.fontMetrics().bigOpSpacing5
  12577       }, {
  12578         type: "elem",
  12579         elem: sub.elem,
  12580         marginLeft: -slant + "em"
  12581       }, {
  12582         type: "kern",
  12583         size: sub.kern
  12584       }, {
  12585         type: "elem",
  12586         elem: base
  12587       }, {
  12588         type: "kern",
  12589         size: sup.kern
  12590       }, {
  12591         type: "elem",
  12592         elem: sup.elem,
  12593         marginLeft: slant + "em"
  12594       }, {
  12595         type: "kern",
  12596         size: options.fontMetrics().bigOpSpacing5
  12597       }]
  12598     }, options);
  12599   } else if (sub) {
  12600     var top = base.height - baseShift; // Shift the limits by the slant of the symbol. Note
  12601     // that we are supposed to shift the limits by 1/2 of the slant,
  12602     // but since we are centering the limits adding a full slant of
  12603     // margin will shift by 1/2 that.
  12604 
  12605     finalGroup = buildCommon.makeVList({
  12606       positionType: "top",
  12607       positionData: top,
  12608       children: [{
  12609         type: "kern",
  12610         size: options.fontMetrics().bigOpSpacing5
  12611       }, {
  12612         type: "elem",
  12613         elem: sub.elem,
  12614         marginLeft: -slant + "em"
  12615       }, {
  12616         type: "kern",
  12617         size: sub.kern
  12618       }, {
  12619         type: "elem",
  12620         elem: base
  12621       }]
  12622     }, options);
  12623   } else if (sup) {
  12624     var _bottom = base.depth + baseShift;
  12625 
  12626     finalGroup = buildCommon.makeVList({
  12627       positionType: "bottom",
  12628       positionData: _bottom,
  12629       children: [{
  12630         type: "elem",
  12631         elem: base
  12632       }, {
  12633         type: "kern",
  12634         size: sup.kern
  12635       }, {
  12636         type: "elem",
  12637         elem: sup.elem,
  12638         marginLeft: slant + "em"
  12639       }, {
  12640         type: "kern",
  12641         size: options.fontMetrics().bigOpSpacing5
  12642       }]
  12643     }, options);
  12644   } else {
  12645     // This case probably shouldn't occur (this would mean the
  12646     // supsub was sending us a group with no superscript or
  12647     // subscript) but be safe.
  12648     return base;
  12649   }
  12650 
  12651   return buildCommon.makeSpan(["mop", "op-limits"], [finalGroup], options);
  12652 };
  12653 
  12654 // Limits, symbols
  12655 // Most operators have a large successor symbol, but these don't.
  12656 var noSuccessor = ["\\smallint"]; // NOTE: Unlike most `htmlBuilder`s, this one handles not only "op", but also
  12657 // "supsub" since some of them (like \int) can affect super/subscripting.
  12658 
  12659 var htmlBuilder$8 = (grp, options) => {
  12660   // Operators are handled in the TeXbook pg. 443-444, rule 13(a).
  12661   var supGroup;
  12662   var subGroup;
  12663   var hasLimits = false;
  12664   var group;
  12665 
  12666   if (grp.type === "supsub") {
  12667     // If we have limits, supsub will pass us its group to handle. Pull
  12668     // out the superscript and subscript and set the group to the op in
  12669     // its base.
  12670     supGroup = grp.sup;
  12671     subGroup = grp.sub;
  12672     group = assertNodeType(grp.base, "op");
  12673     hasLimits = true;
  12674   } else {
  12675     group = assertNodeType(grp, "op");
  12676   }
  12677 
  12678   var style = options.style;
  12679   var large = false;
  12680 
  12681   if (style.size === Style$1.DISPLAY.size && group.symbol && !utils.contains(noSuccessor, group.name)) {
  12682     // Most symbol operators get larger in displaystyle (rule 13)
  12683     large = true;
  12684   }
  12685 
  12686   var base;
  12687 
  12688   if (group.symbol) {
  12689     // If this is a symbol, create the symbol.
  12690     var fontName = large ? "Size2-Regular" : "Size1-Regular";
  12691     var stash = "";
  12692 
  12693     if (group.name === "\\oiint" || group.name === "\\oiiint") {
  12694       // No font glyphs yet, so use a glyph w/o the oval.
  12695       // TODO: When font glyphs are available, delete this code.
  12696       stash = group.name.substr(1);
  12697       group.name = stash === "oiint" ? "\\iint" : "\\iiint";
  12698     }
  12699 
  12700     base = buildCommon.makeSymbol(group.name, fontName, "math", options, ["mop", "op-symbol", large ? "large-op" : "small-op"]);
  12701 
  12702     if (stash.length > 0) {
  12703       // We're in \oiint or \oiiint. Overlay the oval.
  12704       // TODO: When font glyphs are available, delete this code.
  12705       var italic = base.italic;
  12706       var oval = buildCommon.staticSvg(stash + "Size" + (large ? "2" : "1"), options);
  12707       base = buildCommon.makeVList({
  12708         positionType: "individualShift",
  12709         children: [{
  12710           type: "elem",
  12711           elem: base,
  12712           shift: 0
  12713         }, {
  12714           type: "elem",
  12715           elem: oval,
  12716           shift: large ? 0.08 : 0
  12717         }]
  12718       }, options);
  12719       group.name = "\\" + stash;
  12720       base.classes.unshift("mop"); // $FlowFixMe
  12721 
  12722       base.italic = italic;
  12723     }
  12724   } else if (group.body) {
  12725     // If this is a list, compose that list.
  12726     var inner = buildExpression(group.body, options, true);
  12727 
  12728     if (inner.length === 1 && inner[0] instanceof SymbolNode) {
  12729       base = inner[0];
  12730       base.classes[0] = "mop"; // replace old mclass
  12731     } else {
  12732       base = buildCommon.makeSpan(["mop"], inner, options);
  12733     }
  12734   } else {
  12735     // Otherwise, this is a text operator. Build the text from the
  12736     // operator's name.
  12737     var output = [];
  12738 
  12739     for (var i = 1; i < group.name.length; i++) {
  12740       output.push(buildCommon.mathsym(group.name[i], group.mode, options));
  12741     }
  12742 
  12743     base = buildCommon.makeSpan(["mop"], output, options);
  12744   } // If content of op is a single symbol, shift it vertically.
  12745 
  12746 
  12747   var baseShift = 0;
  12748   var slant = 0;
  12749 
  12750   if ((base instanceof SymbolNode || group.name === "\\oiint" || group.name === "\\oiiint") && !group.suppressBaseShift) {
  12751     // We suppress the shift of the base of \overset and \underset. Otherwise,
  12752     // shift the symbol so its center lies on the axis (rule 13). It
  12753     // appears that our fonts have the centers of the symbols already
  12754     // almost on the axis, so these numbers are very small. Note we
  12755     // don't actually apply this here, but instead it is used either in
  12756     // the vlist creation or separately when there are no limits.
  12757     baseShift = (base.height - base.depth) / 2 - options.fontMetrics().axisHeight; // The slant of the symbol is just its italic correction.
  12758     // $FlowFixMe
  12759 
  12760     slant = base.italic;
  12761   }
  12762 
  12763   if (hasLimits) {
  12764     return assembleSupSub(base, supGroup, subGroup, options, style, slant, baseShift);
  12765   } else {
  12766     if (baseShift) {
  12767       base.style.position = "relative";
  12768       base.style.top = baseShift + "em";
  12769     }
  12770 
  12771     return base;
  12772   }
  12773 };
  12774 
  12775 var mathmlBuilder$8 = (group, options) => {
  12776   var node;
  12777 
  12778   if (group.symbol) {
  12779     // This is a symbol. Just add the symbol.
  12780     node = new MathNode("mo", [makeText(group.name, group.mode)]);
  12781 
  12782     if (utils.contains(noSuccessor, group.name)) {
  12783       node.setAttribute("largeop", "false");
  12784     }
  12785   } else if (group.body) {
  12786     // This is an operator with children. Add them.
  12787     node = new MathNode("mo", buildExpression$1(group.body, options));
  12788   } else {
  12789     // This is a text operator. Add all of the characters from the
  12790     // operator's name.
  12791     node = new MathNode("mi", [new TextNode(group.name.slice(1))]); // Append an <mo>&ApplyFunction;</mo>.
  12792     // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4
  12793 
  12794     var operator = new MathNode("mo", [makeText("\u2061", "text")]);
  12795 
  12796     if (group.parentIsSupSub) {
  12797       node = new MathNode("mrow", [node, operator]);
  12798     } else {
  12799       node = newDocumentFragment([node, operator]);
  12800     }
  12801   }
  12802 
  12803   return node;
  12804 };
  12805 
  12806 var singleCharBigOps = {
  12807   "\u220F": "\\prod",
  12808   "\u2210": "\\coprod",
  12809   "\u2211": "\\sum",
  12810   "\u22c0": "\\bigwedge",
  12811   "\u22c1": "\\bigvee",
  12812   "\u22c2": "\\bigcap",
  12813   "\u22c3": "\\bigcup",
  12814   "\u2a00": "\\bigodot",
  12815   "\u2a01": "\\bigoplus",
  12816   "\u2a02": "\\bigotimes",
  12817   "\u2a04": "\\biguplus",
  12818   "\u2a06": "\\bigsqcup"
  12819 };
  12820 defineFunction({
  12821   type: "op",
  12822   names: ["\\coprod", "\\bigvee", "\\bigwedge", "\\biguplus", "\\bigcap", "\\bigcup", "\\intop", "\\prod", "\\sum", "\\bigotimes", "\\bigoplus", "\\bigodot", "\\bigsqcup", "\\smallint", "\u220F", "\u2210", "\u2211", "\u22c0", "\u22c1", "\u22c2", "\u22c3", "\u2a00", "\u2a01", "\u2a02", "\u2a04", "\u2a06"],
  12823   props: {
  12824     numArgs: 0
  12825   },
  12826   handler: (_ref, args) => {
  12827     var {
  12828       parser,
  12829       funcName
  12830     } = _ref;
  12831     var fName = funcName;
  12832 
  12833     if (fName.length === 1) {
  12834       fName = singleCharBigOps[fName];
  12835     }
  12836 
  12837     return {
  12838       type: "op",
  12839       mode: parser.mode,
  12840       limits: true,
  12841       parentIsSupSub: false,
  12842       symbol: true,
  12843       name: fName
  12844     };
  12845   },
  12846   htmlBuilder: htmlBuilder$8,
  12847   mathmlBuilder: mathmlBuilder$8
  12848 }); // Note: calling defineFunction with a type that's already been defined only
  12849 // works because the same htmlBuilder and mathmlBuilder are being used.
  12850 
  12851 defineFunction({
  12852   type: "op",
  12853   names: ["\\mathop"],
  12854   props: {
  12855     numArgs: 1,
  12856     primitive: true
  12857   },
  12858   handler: (_ref2, args) => {
  12859     var {
  12860       parser
  12861     } = _ref2;
  12862     var body = args[0];
  12863     return {
  12864       type: "op",
  12865       mode: parser.mode,
  12866       limits: false,
  12867       parentIsSupSub: false,
  12868       symbol: false,
  12869       body: ordargument(body)
  12870     };
  12871   },
  12872   htmlBuilder: htmlBuilder$8,
  12873   mathmlBuilder: mathmlBuilder$8
  12874 }); // There are 2 flags for operators; whether they produce limits in
  12875 // displaystyle, and whether they are symbols and should grow in
  12876 // displaystyle. These four groups cover the four possible choices.
  12877 
  12878 var singleCharIntegrals = {
  12879   "\u222b": "\\int",
  12880   "\u222c": "\\iint",
  12881   "\u222d": "\\iiint",
  12882   "\u222e": "\\oint",
  12883   "\u222f": "\\oiint",
  12884   "\u2230": "\\oiiint"
  12885 }; // No limits, not symbols
  12886 
  12887 defineFunction({
  12888   type: "op",
  12889   names: ["\\arcsin", "\\arccos", "\\arctan", "\\arctg", "\\arcctg", "\\arg", "\\ch", "\\cos", "\\cosec", "\\cosh", "\\cot", "\\cotg", "\\coth", "\\csc", "\\ctg", "\\cth", "\\deg", "\\dim", "\\exp", "\\hom", "\\ker", "\\lg", "\\ln", "\\log", "\\sec", "\\sin", "\\sinh", "\\sh", "\\tan", "\\tanh", "\\tg", "\\th"],
  12890   props: {
  12891     numArgs: 0
  12892   },
  12893 
  12894   handler(_ref3) {
  12895     var {
  12896       parser,
  12897       funcName
  12898     } = _ref3;
  12899     return {
  12900       type: "op",
  12901       mode: parser.mode,
  12902       limits: false,
  12903       parentIsSupSub: false,
  12904       symbol: false,
  12905       name: funcName
  12906     };
  12907   },
  12908 
  12909   htmlBuilder: htmlBuilder$8,
  12910   mathmlBuilder: mathmlBuilder$8
  12911 }); // Limits, not symbols
  12912 
  12913 defineFunction({
  12914   type: "op",
  12915   names: ["\\det", "\\gcd", "\\inf", "\\lim", "\\max", "\\min", "\\Pr", "\\sup"],
  12916   props: {
  12917     numArgs: 0
  12918   },
  12919 
  12920   handler(_ref4) {
  12921     var {
  12922       parser,
  12923       funcName
  12924     } = _ref4;
  12925     return {
  12926       type: "op",
  12927       mode: parser.mode,
  12928       limits: true,
  12929       parentIsSupSub: false,
  12930       symbol: false,
  12931       name: funcName
  12932     };
  12933   },
  12934 
  12935   htmlBuilder: htmlBuilder$8,
  12936   mathmlBuilder: mathmlBuilder$8
  12937 }); // No limits, symbols
  12938 
  12939 defineFunction({
  12940   type: "op",
  12941   names: ["\\int", "\\iint", "\\iiint", "\\oint", "\\oiint", "\\oiiint", "\u222b", "\u222c", "\u222d", "\u222e", "\u222f", "\u2230"],
  12942   props: {
  12943     numArgs: 0
  12944   },
  12945 
  12946   handler(_ref5) {
  12947     var {
  12948       parser,
  12949       funcName
  12950     } = _ref5;
  12951     var fName = funcName;
  12952 
  12953     if (fName.length === 1) {
  12954       fName = singleCharIntegrals[fName];
  12955     }
  12956 
  12957     return {
  12958       type: "op",
  12959       mode: parser.mode,
  12960       limits: false,
  12961       parentIsSupSub: false,
  12962       symbol: true,
  12963       name: fName
  12964     };
  12965   },
  12966 
  12967   htmlBuilder: htmlBuilder$8,
  12968   mathmlBuilder: mathmlBuilder$8
  12969 });
  12970 
  12971 // NOTE: Unlike most `htmlBuilder`s, this one handles not only
  12972 // "operatorname", but also  "supsub" since \operatorname* can
  12973 // affect super/subscripting.
  12974 var htmlBuilder$9 = (grp, options) => {
  12975   // Operators are handled in the TeXbook pg. 443-444, rule 13(a).
  12976   var supGroup;
  12977   var subGroup;
  12978   var hasLimits = false;
  12979   var group;
  12980 
  12981   if (grp.type === "supsub") {
  12982     // If we have limits, supsub will pass us its group to handle. Pull
  12983     // out the superscript and subscript and set the group to the op in
  12984     // its base.
  12985     supGroup = grp.sup;
  12986     subGroup = grp.sub;
  12987     group = assertNodeType(grp.base, "operatorname");
  12988     hasLimits = true;
  12989   } else {
  12990     group = assertNodeType(grp, "operatorname");
  12991   }
  12992 
  12993   var base;
  12994 
  12995   if (group.body.length > 0) {
  12996     var body = group.body.map(child => {
  12997       // $FlowFixMe: Check if the node has a string `text` property.
  12998       var childText = child.text;
  12999 
  13000       if (typeof childText === "string") {
  13001         return {
  13002           type: "textord",
  13003           mode: child.mode,
  13004           text: childText
  13005         };
  13006       } else {
  13007         return child;
  13008       }
  13009     }); // Consolidate function names into symbol characters.
  13010 
  13011     var expression = buildExpression(body, options.withFont("mathrm"), true);
  13012 
  13013     for (var i = 0; i < expression.length; i++) {
  13014       var child = expression[i];
  13015 
  13016       if (child instanceof SymbolNode) {
  13017         // Per amsopn package,
  13018         // change minus to hyphen and \ast to asterisk
  13019         child.text = child.text.replace(/\u2212/, "-").replace(/\u2217/, "*");
  13020       }
  13021     }
  13022 
  13023     base = buildCommon.makeSpan(["mop"], expression, options);
  13024   } else {
  13025     base = buildCommon.makeSpan(["mop"], [], options);
  13026   }
  13027 
  13028   if (hasLimits) {
  13029     return assembleSupSub(base, supGroup, subGroup, options, options.style, 0, 0);
  13030   } else {
  13031     return base;
  13032   }
  13033 };
  13034 
  13035 var mathmlBuilder$9 = (group, options) => {
  13036   // The steps taken here are similar to the html version.
  13037   var expression = buildExpression$1(group.body, options.withFont("mathrm")); // Is expression a string or has it something like a fraction?
  13038 
  13039   var isAllString = true; // default
  13040 
  13041   for (var i = 0; i < expression.length; i++) {
  13042     var node = expression[i];
  13043 
  13044     if (node instanceof mathMLTree.SpaceNode) ; else if (node instanceof mathMLTree.MathNode) {
  13045       switch (node.type) {
  13046         case "mi":
  13047         case "mn":
  13048         case "ms":
  13049         case "mspace":
  13050         case "mtext":
  13051           break;
  13052         // Do nothing yet.
  13053 
  13054         case "mo":
  13055           {
  13056             var child = node.children[0];
  13057 
  13058             if (node.children.length === 1 && child instanceof mathMLTree.TextNode) {
  13059               child.text = child.text.replace(/\u2212/, "-").replace(/\u2217/, "*");
  13060             } else {
  13061               isAllString = false;
  13062             }
  13063 
  13064             break;
  13065           }
  13066 
  13067         default:
  13068           isAllString = false;
  13069       }
  13070     } else {
  13071       isAllString = false;
  13072     }
  13073   }
  13074 
  13075   if (isAllString) {
  13076     // Write a single TextNode instead of multiple nested tags.
  13077     var word = expression.map(node => node.toText()).join("");
  13078     expression = [new mathMLTree.TextNode(word)];
  13079   }
  13080 
  13081   var identifier = new mathMLTree.MathNode("mi", expression);
  13082   identifier.setAttribute("mathvariant", "normal"); // \u2061 is the same as &ApplyFunction;
  13083   // ref: https://www.w3schools.com/charsets/ref_html_entities_a.asp
  13084 
  13085   var operator = new mathMLTree.MathNode("mo", [makeText("\u2061", "text")]);
  13086 
  13087   if (group.parentIsSupSub) {
  13088     return new mathMLTree.MathNode("mrow", [identifier, operator]);
  13089   } else {
  13090     return mathMLTree.newDocumentFragment([identifier, operator]);
  13091   }
  13092 }; // \operatorname
  13093 // amsopn.dtx: \mathop{#1\kern\z@\operator@font#3}\newmcodes@
  13094 
  13095 
  13096 defineFunction({
  13097   type: "operatorname",
  13098   names: ["\\operatorname", "\\operatorname*"],
  13099   props: {
  13100     numArgs: 1
  13101   },
  13102   handler: (_ref, args) => {
  13103     var {
  13104       parser,
  13105       funcName
  13106     } = _ref;
  13107     var body = args[0];
  13108     return {
  13109       type: "operatorname",
  13110       mode: parser.mode,
  13111       body: ordargument(body),
  13112       alwaysHandleSupSub: funcName === "\\operatorname*",
  13113       limits: false,
  13114       parentIsSupSub: false
  13115     };
  13116   },
  13117   htmlBuilder: htmlBuilder$9,
  13118   mathmlBuilder: mathmlBuilder$9
  13119 });
  13120 
  13121 defineFunctionBuilders({
  13122   type: "ordgroup",
  13123 
  13124   htmlBuilder(group, options) {
  13125     if (group.semisimple) {
  13126       return buildCommon.makeFragment(buildExpression(group.body, options, false));
  13127     }
  13128 
  13129     return buildCommon.makeSpan(["mord"], buildExpression(group.body, options, true), options);
  13130   },
  13131 
  13132   mathmlBuilder(group, options) {
  13133     return buildExpressionRow(group.body, options, true);
  13134   }
  13135 
  13136 });
  13137 
  13138 defineFunction({
  13139   type: "overline",
  13140   names: ["\\overline"],
  13141   props: {
  13142     numArgs: 1
  13143   },
  13144 
  13145   handler(_ref, args) {
  13146     var {
  13147       parser
  13148     } = _ref;
  13149     var body = args[0];
  13150     return {
  13151       type: "overline",
  13152       mode: parser.mode,
  13153       body
  13154     };
  13155   },
  13156 
  13157   htmlBuilder(group, options) {
  13158     // Overlines are handled in the TeXbook pg 443, Rule 9.
  13159     // Build the inner group in the cramped style.
  13160     var innerGroup = buildGroup(group.body, options.havingCrampedStyle()); // Create the line above the body
  13161 
  13162     var line = buildCommon.makeLineSpan("overline-line", options); // Generate the vlist, with the appropriate kerns
  13163 
  13164     var defaultRuleThickness = options.fontMetrics().defaultRuleThickness;
  13165     var vlist = buildCommon.makeVList({
  13166       positionType: "firstBaseline",
  13167       children: [{
  13168         type: "elem",
  13169         elem: innerGroup
  13170       }, {
  13171         type: "kern",
  13172         size: 3 * defaultRuleThickness
  13173       }, {
  13174         type: "elem",
  13175         elem: line
  13176       }, {
  13177         type: "kern",
  13178         size: defaultRuleThickness
  13179       }]
  13180     }, options);
  13181     return buildCommon.makeSpan(["mord", "overline"], [vlist], options);
  13182   },
  13183 
  13184   mathmlBuilder(group, options) {
  13185     var operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u203e")]);
  13186     operator.setAttribute("stretchy", "true");
  13187     var node = new mathMLTree.MathNode("mover", [buildGroup$1(group.body, options), operator]);
  13188     node.setAttribute("accent", "true");
  13189     return node;
  13190   }
  13191 
  13192 });
  13193 
  13194 defineFunction({
  13195   type: "phantom",
  13196   names: ["\\phantom"],
  13197   props: {
  13198     numArgs: 1,
  13199     allowedInText: true
  13200   },
  13201   handler: (_ref, args) => {
  13202     var {
  13203       parser
  13204     } = _ref;
  13205     var body = args[0];
  13206     return {
  13207       type: "phantom",
  13208       mode: parser.mode,
  13209       body: ordargument(body)
  13210     };
  13211   },
  13212   htmlBuilder: (group, options) => {
  13213     var elements = buildExpression(group.body, options.withPhantom(), false); // \phantom isn't supposed to affect the elements it contains.
  13214     // See "color" for more details.
  13215 
  13216     return buildCommon.makeFragment(elements);
  13217   },
  13218   mathmlBuilder: (group, options) => {
  13219     var inner = buildExpression$1(group.body, options);
  13220     return new mathMLTree.MathNode("mphantom", inner);
  13221   }
  13222 });
  13223 defineFunction({
  13224   type: "hphantom",
  13225   names: ["\\hphantom"],
  13226   props: {
  13227     numArgs: 1,
  13228     allowedInText: true
  13229   },
  13230   handler: (_ref2, args) => {
  13231     var {
  13232       parser
  13233     } = _ref2;
  13234     var body = args[0];
  13235     return {
  13236       type: "hphantom",
  13237       mode: parser.mode,
  13238       body
  13239     };
  13240   },
  13241   htmlBuilder: (group, options) => {
  13242     var node = buildCommon.makeSpan([], [buildGroup(group.body, options.withPhantom())]);
  13243     node.height = 0;
  13244     node.depth = 0;
  13245 
  13246     if (node.children) {
  13247       for (var i = 0; i < node.children.length; i++) {
  13248         node.children[i].height = 0;
  13249         node.children[i].depth = 0;
  13250       }
  13251     } // See smash for comment re: use of makeVList
  13252 
  13253 
  13254     node = buildCommon.makeVList({
  13255       positionType: "firstBaseline",
  13256       children: [{
  13257         type: "elem",
  13258         elem: node
  13259       }]
  13260     }, options); // For spacing, TeX treats \smash as a math group (same spacing as ord).
  13261 
  13262     return buildCommon.makeSpan(["mord"], [node], options);
  13263   },
  13264   mathmlBuilder: (group, options) => {
  13265     var inner = buildExpression$1(ordargument(group.body), options);
  13266     var phantom = new mathMLTree.MathNode("mphantom", inner);
  13267     var node = new mathMLTree.MathNode("mpadded", [phantom]);
  13268     node.setAttribute("height", "0px");
  13269     node.setAttribute("depth", "0px");
  13270     return node;
  13271   }
  13272 });
  13273 defineFunction({
  13274   type: "vphantom",
  13275   names: ["\\vphantom"],
  13276   props: {
  13277     numArgs: 1,
  13278     allowedInText: true
  13279   },
  13280   handler: (_ref3, args) => {
  13281     var {
  13282       parser
  13283     } = _ref3;
  13284     var body = args[0];
  13285     return {
  13286       type: "vphantom",
  13287       mode: parser.mode,
  13288       body
  13289     };
  13290   },
  13291   htmlBuilder: (group, options) => {
  13292     var inner = buildCommon.makeSpan(["inner"], [buildGroup(group.body, options.withPhantom())]);
  13293     var fix = buildCommon.makeSpan(["fix"], []);
  13294     return buildCommon.makeSpan(["mord", "rlap"], [inner, fix], options);
  13295   },
  13296   mathmlBuilder: (group, options) => {
  13297     var inner = buildExpression$1(ordargument(group.body), options);
  13298     var phantom = new mathMLTree.MathNode("mphantom", inner);
  13299     var node = new mathMLTree.MathNode("mpadded", [phantom]);
  13300     node.setAttribute("width", "0px");
  13301     return node;
  13302   }
  13303 });
  13304 
  13305 defineFunction({
  13306   type: "raisebox",
  13307   names: ["\\raisebox"],
  13308   props: {
  13309     numArgs: 2,
  13310     argTypes: ["size", "hbox"],
  13311     allowedInText: true
  13312   },
  13313 
  13314   handler(_ref, args) {
  13315     var {
  13316       parser
  13317     } = _ref;
  13318     var amount = assertNodeType(args[0], "size").value;
  13319     var body = args[1];
  13320     return {
  13321       type: "raisebox",
  13322       mode: parser.mode,
  13323       dy: amount,
  13324       body
  13325     };
  13326   },
  13327 
  13328   htmlBuilder(group, options) {
  13329     var body = buildGroup(group.body, options);
  13330     var dy = calculateSize(group.dy, options);
  13331     return buildCommon.makeVList({
  13332       positionType: "shift",
  13333       positionData: -dy,
  13334       children: [{
  13335         type: "elem",
  13336         elem: body
  13337       }]
  13338     }, options);
  13339   },
  13340 
  13341   mathmlBuilder(group, options) {
  13342     var node = new mathMLTree.MathNode("mpadded", [buildGroup$1(group.body, options)]);
  13343     var dy = group.dy.number + group.dy.unit;
  13344     node.setAttribute("voffset", dy);
  13345     return node;
  13346   }
  13347 
  13348 });
  13349 
  13350 defineFunction({
  13351   type: "rule",
  13352   names: ["\\rule"],
  13353   props: {
  13354     numArgs: 2,
  13355     numOptionalArgs: 1,
  13356     argTypes: ["size", "size", "size"]
  13357   },
  13358 
  13359   handler(_ref, args, optArgs) {
  13360     var {
  13361       parser
  13362     } = _ref;
  13363     var shift = optArgs[0];
  13364     var width = assertNodeType(args[0], "size");
  13365     var height = assertNodeType(args[1], "size");
  13366     return {
  13367       type: "rule",
  13368       mode: parser.mode,
  13369       shift: shift && assertNodeType(shift, "size").value,
  13370       width: width.value,
  13371       height: height.value
  13372     };
  13373   },
  13374 
  13375   htmlBuilder(group, options) {
  13376     // Make an empty span for the rule
  13377     var rule = buildCommon.makeSpan(["mord", "rule"], [], options); // Calculate the shift, width, and height of the rule, and account for units
  13378 
  13379     var width = calculateSize(group.width, options);
  13380     var height = calculateSize(group.height, options);
  13381     var shift = group.shift ? calculateSize(group.shift, options) : 0; // Style the rule to the right size
  13382 
  13383     rule.style.borderRightWidth = width + "em";
  13384     rule.style.borderTopWidth = height + "em";
  13385     rule.style.bottom = shift + "em"; // Record the height and width
  13386 
  13387     rule.width = width;
  13388     rule.height = height + shift;
  13389     rule.depth = -shift; // Font size is the number large enough that the browser will
  13390     // reserve at least `absHeight` space above the baseline.
  13391     // The 1.125 factor was empirically determined
  13392 
  13393     rule.maxFontSize = height * 1.125 * options.sizeMultiplier;
  13394     return rule;
  13395   },
  13396 
  13397   mathmlBuilder(group, options) {
  13398     var width = calculateSize(group.width, options);
  13399     var height = calculateSize(group.height, options);
  13400     var shift = group.shift ? calculateSize(group.shift, options) : 0;
  13401     var color = options.color && options.getColor() || "black";
  13402     var rule = new mathMLTree.MathNode("mspace");
  13403     rule.setAttribute("mathbackground", color);
  13404     rule.setAttribute("width", width + "em");
  13405     rule.setAttribute("height", height + "em");
  13406     var wrapper = new mathMLTree.MathNode("mpadded", [rule]);
  13407 
  13408     if (shift >= 0) {
  13409       wrapper.setAttribute("height", "+" + shift + "em");
  13410     } else {
  13411       wrapper.setAttribute("height", shift + "em");
  13412       wrapper.setAttribute("depth", "+" + -shift + "em");
  13413     }
  13414 
  13415     wrapper.setAttribute("voffset", shift + "em");
  13416     return wrapper;
  13417   }
  13418 
  13419 });
  13420 
  13421 function sizingGroup(value, options, baseOptions) {
  13422   var inner = buildExpression(value, options, false);
  13423   var multiplier = options.sizeMultiplier / baseOptions.sizeMultiplier; // Add size-resetting classes to the inner list and set maxFontSize
  13424   // manually. Handle nested size changes.
  13425 
  13426   for (var i = 0; i < inner.length; i++) {
  13427     var pos = inner[i].classes.indexOf("sizing");
  13428 
  13429     if (pos < 0) {
  13430       Array.prototype.push.apply(inner[i].classes, options.sizingClasses(baseOptions));
  13431     } else if (inner[i].classes[pos + 1] === "reset-size" + options.size) {
  13432       // This is a nested size change: e.g., inner[i] is the "b" in
  13433       // `\Huge a \small b`. Override the old size (the `reset-` class)
  13434       // but not the new size.
  13435       inner[i].classes[pos + 1] = "reset-size" + baseOptions.size;
  13436     }
  13437 
  13438     inner[i].height *= multiplier;
  13439     inner[i].depth *= multiplier;
  13440   }
  13441 
  13442   return buildCommon.makeFragment(inner);
  13443 }
  13444 var sizeFuncs = ["\\tiny", "\\sixptsize", "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge"];
  13445 var htmlBuilder$a = (group, options) => {
  13446   // Handle sizing operators like \Huge. Real TeX doesn't actually allow
  13447   // these functions inside of math expressions, so we do some special
  13448   // handling.
  13449   var newOptions = options.havingSize(group.size);
  13450   return sizingGroup(group.body, newOptions, options);
  13451 };
  13452 defineFunction({
  13453   type: "sizing",
  13454   names: sizeFuncs,
  13455   props: {
  13456     numArgs: 0,
  13457     allowedInText: true
  13458   },
  13459   handler: (_ref, args) => {
  13460     var {
  13461       breakOnTokenText,
  13462       funcName,
  13463       parser
  13464     } = _ref;
  13465     var body = parser.parseExpression(false, breakOnTokenText);
  13466     return {
  13467       type: "sizing",
  13468       mode: parser.mode,
  13469       // Figure out what size to use based on the list of functions above
  13470       size: sizeFuncs.indexOf(funcName) + 1,
  13471       body
  13472     };
  13473   },
  13474   htmlBuilder: htmlBuilder$a,
  13475   mathmlBuilder: (group, options) => {
  13476     var newOptions = options.havingSize(group.size);
  13477     var inner = buildExpression$1(group.body, newOptions);
  13478     var node = new mathMLTree.MathNode("mstyle", inner); // TODO(emily): This doesn't produce the correct size for nested size
  13479     // changes, because we don't keep state of what style we're currently
  13480     // in, so we can't reset the size to normal before changing it.  Now
  13481     // that we're passing an options parameter we should be able to fix
  13482     // this.
  13483 
  13484     node.setAttribute("mathsize", newOptions.sizeMultiplier + "em");
  13485     return node;
  13486   }
  13487 });
  13488 
  13489 // smash, with optional [tb], as in AMS
  13490 defineFunction({
  13491   type: "smash",
  13492   names: ["\\smash"],
  13493   props: {
  13494     numArgs: 1,
  13495     numOptionalArgs: 1,
  13496     allowedInText: true
  13497   },
  13498   handler: (_ref, args, optArgs) => {
  13499     var {
  13500       parser
  13501     } = _ref;
  13502     var smashHeight = false;
  13503     var smashDepth = false;
  13504     var tbArg = optArgs[0] && assertNodeType(optArgs[0], "ordgroup");
  13505 
  13506     if (tbArg) {
  13507       // Optional [tb] argument is engaged.
  13508       // ref: amsmath: \renewcommand{\smash}[1][tb]{%
  13509       //               def\mb@t{\ht}\def\mb@b{\dp}\def\mb@tb{\ht\z@\z@\dp}%
  13510       var letter = "";
  13511 
  13512       for (var i = 0; i < tbArg.body.length; ++i) {
  13513         var node = tbArg.body[i]; // $FlowFixMe: Not every node type has a `text` property.
  13514 
  13515         letter = node.text;
  13516 
  13517         if (letter === "t") {
  13518           smashHeight = true;
  13519         } else if (letter === "b") {
  13520           smashDepth = true;
  13521         } else {
  13522           smashHeight = false;
  13523           smashDepth = false;
  13524           break;
  13525         }
  13526       }
  13527     } else {
  13528       smashHeight = true;
  13529       smashDepth = true;
  13530     }
  13531 
  13532     var body = args[0];
  13533     return {
  13534       type: "smash",
  13535       mode: parser.mode,
  13536       body,
  13537       smashHeight,
  13538       smashDepth
  13539     };
  13540   },
  13541   htmlBuilder: (group, options) => {
  13542     var node = buildCommon.makeSpan([], [buildGroup(group.body, options)]);
  13543 
  13544     if (!group.smashHeight && !group.smashDepth) {
  13545       return node;
  13546     }
  13547 
  13548     if (group.smashHeight) {
  13549       node.height = 0; // In order to influence makeVList, we have to reset the children.
  13550 
  13551       if (node.children) {
  13552         for (var i = 0; i < node.children.length; i++) {
  13553           node.children[i].height = 0;
  13554         }
  13555       }
  13556     }
  13557 
  13558     if (group.smashDepth) {
  13559       node.depth = 0;
  13560 
  13561       if (node.children) {
  13562         for (var _i = 0; _i < node.children.length; _i++) {
  13563           node.children[_i].depth = 0;
  13564         }
  13565       }
  13566     } // At this point, we've reset the TeX-like height and depth values.
  13567     // But the span still has an HTML line height.
  13568     // makeVList applies "display: table-cell", which prevents the browser
  13569     // from acting on that line height. So we'll call makeVList now.
  13570 
  13571 
  13572     var smashedNode = buildCommon.makeVList({
  13573       positionType: "firstBaseline",
  13574       children: [{
  13575         type: "elem",
  13576         elem: node
  13577       }]
  13578     }, options); // For spacing, TeX treats \hphantom as a math group (same spacing as ord).
  13579 
  13580     return buildCommon.makeSpan(["mord"], [smashedNode], options);
  13581   },
  13582   mathmlBuilder: (group, options) => {
  13583     var node = new mathMLTree.MathNode("mpadded", [buildGroup$1(group.body, options)]);
  13584 
  13585     if (group.smashHeight) {
  13586       node.setAttribute("height", "0px");
  13587     }
  13588 
  13589     if (group.smashDepth) {
  13590       node.setAttribute("depth", "0px");
  13591     }
  13592 
  13593     return node;
  13594   }
  13595 });
  13596 
  13597 defineFunction({
  13598   type: "sqrt",
  13599   names: ["\\sqrt"],
  13600   props: {
  13601     numArgs: 1,
  13602     numOptionalArgs: 1
  13603   },
  13604 
  13605   handler(_ref, args, optArgs) {
  13606     var {
  13607       parser
  13608     } = _ref;
  13609     var index = optArgs[0];
  13610     var body = args[0];
  13611     return {
  13612       type: "sqrt",
  13613       mode: parser.mode,
  13614       body,
  13615       index
  13616     };
  13617   },
  13618 
  13619   htmlBuilder(group, options) {
  13620     // Square roots are handled in the TeXbook pg. 443, Rule 11.
  13621     // First, we do the same steps as in overline to build the inner group
  13622     // and line
  13623     var inner = buildGroup(group.body, options.havingCrampedStyle());
  13624 
  13625     if (inner.height === 0) {
  13626       // Render a small surd.
  13627       inner.height = options.fontMetrics().xHeight;
  13628     } // Some groups can return document fragments.  Handle those by wrapping
  13629     // them in a span.
  13630 
  13631 
  13632     inner = buildCommon.wrapFragment(inner, options); // Calculate the minimum size for the \surd delimiter
  13633 
  13634     var metrics = options.fontMetrics();
  13635     var theta = metrics.defaultRuleThickness;
  13636     var phi = theta;
  13637 
  13638     if (options.style.id < Style$1.TEXT.id) {
  13639       phi = options.fontMetrics().xHeight;
  13640     } // Calculate the clearance between the body and line
  13641 
  13642 
  13643     var lineClearance = theta + phi / 4;
  13644     var minDelimiterHeight = inner.height + inner.depth + lineClearance + theta; // Create a sqrt SVG of the required minimum size
  13645 
  13646     var {
  13647       span: img,
  13648       ruleWidth,
  13649       advanceWidth
  13650     } = delimiter.sqrtImage(minDelimiterHeight, options);
  13651     var delimDepth = img.height - ruleWidth; // Adjust the clearance based on the delimiter size
  13652 
  13653     if (delimDepth > inner.height + inner.depth + lineClearance) {
  13654       lineClearance = (lineClearance + delimDepth - inner.height - inner.depth) / 2;
  13655     } // Shift the sqrt image
  13656 
  13657 
  13658     var imgShift = img.height - inner.height - lineClearance - ruleWidth;
  13659     inner.style.paddingLeft = advanceWidth + "em"; // Overlay the image and the argument.
  13660 
  13661     var body = buildCommon.makeVList({
  13662       positionType: "firstBaseline",
  13663       children: [{
  13664         type: "elem",
  13665         elem: inner,
  13666         wrapperClasses: ["svg-align"]
  13667       }, {
  13668         type: "kern",
  13669         size: -(inner.height + imgShift)
  13670       }, {
  13671         type: "elem",
  13672         elem: img
  13673       }, {
  13674         type: "kern",
  13675         size: ruleWidth
  13676       }]
  13677     }, options);
  13678 
  13679     if (!group.index) {
  13680       return buildCommon.makeSpan(["mord", "sqrt"], [body], options);
  13681     } else {
  13682       // Handle the optional root index
  13683       // The index is always in scriptscript style
  13684       var newOptions = options.havingStyle(Style$1.SCRIPTSCRIPT);
  13685       var rootm = buildGroup(group.index, newOptions, options); // The amount the index is shifted by. This is taken from the TeX
  13686       // source, in the definition of `\r@@t`.
  13687 
  13688       var toShift = 0.6 * (body.height - body.depth); // Build a VList with the superscript shifted up correctly
  13689 
  13690       var rootVList = buildCommon.makeVList({
  13691         positionType: "shift",
  13692         positionData: -toShift,
  13693         children: [{
  13694           type: "elem",
  13695           elem: rootm
  13696         }]
  13697       }, options); // Add a class surrounding it so we can add on the appropriate
  13698       // kerning
  13699 
  13700       var rootVListWrap = buildCommon.makeSpan(["root"], [rootVList]);
  13701       return buildCommon.makeSpan(["mord", "sqrt"], [rootVListWrap, body], options);
  13702     }
  13703   },
  13704 
  13705   mathmlBuilder(group, options) {
  13706     var {
  13707       body,
  13708       index
  13709     } = group;
  13710     return index ? new mathMLTree.MathNode("mroot", [buildGroup$1(body, options), buildGroup$1(index, options)]) : new mathMLTree.MathNode("msqrt", [buildGroup$1(body, options)]);
  13711   }
  13712 
  13713 });
  13714 
  13715 var styleMap$1 = {
  13716   "display": Style$1.DISPLAY,
  13717   "text": Style$1.TEXT,
  13718   "script": Style$1.SCRIPT,
  13719   "scriptscript": Style$1.SCRIPTSCRIPT
  13720 };
  13721 defineFunction({
  13722   type: "styling",
  13723   names: ["\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle"],
  13724   props: {
  13725     numArgs: 0,
  13726     allowedInText: true,
  13727     primitive: true
  13728   },
  13729 
  13730   handler(_ref, args) {
  13731     var {
  13732       breakOnTokenText,
  13733       funcName,
  13734       parser
  13735     } = _ref;
  13736     // parse out the implicit body
  13737     var body = parser.parseExpression(true, breakOnTokenText); // TODO: Refactor to avoid duplicating styleMap in multiple places (e.g.
  13738     // here and in buildHTML and de-dupe the enumeration of all the styles).
  13739     // $FlowFixMe: The names above exactly match the styles.
  13740 
  13741     var style = funcName.slice(1, funcName.length - 5);
  13742     return {
  13743       type: "styling",
  13744       mode: parser.mode,
  13745       // Figure out what style to use by pulling out the style from
  13746       // the function name
  13747       style,
  13748       body
  13749     };
  13750   },
  13751 
  13752   htmlBuilder(group, options) {
  13753     // Style changes are handled in the TeXbook on pg. 442, Rule 3.
  13754     var newStyle = styleMap$1[group.style];
  13755     var newOptions = options.havingStyle(newStyle).withFont('');
  13756     return sizingGroup(group.body, newOptions, options);
  13757   },
  13758 
  13759   mathmlBuilder(group, options) {
  13760     // Figure out what style we're changing to.
  13761     var newStyle = styleMap$1[group.style];
  13762     var newOptions = options.havingStyle(newStyle);
  13763     var inner = buildExpression$1(group.body, newOptions);
  13764     var node = new mathMLTree.MathNode("mstyle", inner);
  13765     var styleAttributes = {
  13766       "display": ["0", "true"],
  13767       "text": ["0", "false"],
  13768       "script": ["1", "false"],
  13769       "scriptscript": ["2", "false"]
  13770     };
  13771     var attr = styleAttributes[group.style];
  13772     node.setAttribute("scriptlevel", attr[0]);
  13773     node.setAttribute("displaystyle", attr[1]);
  13774     return node;
  13775   }
  13776 
  13777 });
  13778 
  13779 /**
  13780  * Sometimes, groups perform special rules when they have superscripts or
  13781  * subscripts attached to them. This function lets the `supsub` group know that
  13782  * Sometimes, groups perform special rules when they have superscripts or
  13783  * its inner element should handle the superscripts and subscripts instead of
  13784  * handling them itself.
  13785  */
  13786 var htmlBuilderDelegate = function htmlBuilderDelegate(group, options) {
  13787   var base = group.base;
  13788 
  13789   if (!base) {
  13790     return null;
  13791   } else if (base.type === "op") {
  13792     // Operators handle supsubs differently when they have limits
  13793     // (e.g. `\displaystyle\sum_2^3`)
  13794     var delegate = base.limits && (options.style.size === Style$1.DISPLAY.size || base.alwaysHandleSupSub);
  13795     return delegate ? htmlBuilder$8 : null;
  13796   } else if (base.type === "operatorname") {
  13797     var _delegate = base.alwaysHandleSupSub && (options.style.size === Style$1.DISPLAY.size || base.limits);
  13798 
  13799     return _delegate ? htmlBuilder$9 : null;
  13800   } else if (base.type === "accent") {
  13801     return utils.isCharacterBox(base.base) ? htmlBuilder : null;
  13802   } else if (base.type === "horizBrace") {
  13803     var isSup = !group.sub;
  13804     return isSup === base.isOver ? htmlBuilder$7 : null;
  13805   } else {
  13806     return null;
  13807   }
  13808 }; // Super scripts and subscripts, whose precise placement can depend on other
  13809 // functions that precede them.
  13810 
  13811 
  13812 defineFunctionBuilders({
  13813   type: "supsub",
  13814 
  13815   htmlBuilder(group, options) {
  13816     // Superscript and subscripts are handled in the TeXbook on page
  13817     // 445-446, rules 18(a-f).
  13818     // Here is where we defer to the inner group if it should handle
  13819     // superscripts and subscripts itself.
  13820     var builderDelegate = htmlBuilderDelegate(group, options);
  13821 
  13822     if (builderDelegate) {
  13823       return builderDelegate(group, options);
  13824     }
  13825 
  13826     var {
  13827       base: valueBase,
  13828       sup: valueSup,
  13829       sub: valueSub
  13830     } = group;
  13831     var base = buildGroup(valueBase, options);
  13832     var supm;
  13833     var subm;
  13834     var metrics = options.fontMetrics(); // Rule 18a
  13835 
  13836     var supShift = 0;
  13837     var subShift = 0;
  13838     var isCharacterBox = valueBase && utils.isCharacterBox(valueBase);
  13839 
  13840     if (valueSup) {
  13841       var newOptions = options.havingStyle(options.style.sup());
  13842       supm = buildGroup(valueSup, newOptions, options);
  13843 
  13844       if (!isCharacterBox) {
  13845         supShift = base.height - newOptions.fontMetrics().supDrop * newOptions.sizeMultiplier / options.sizeMultiplier;
  13846       }
  13847     }
  13848 
  13849     if (valueSub) {
  13850       var _newOptions = options.havingStyle(options.style.sub());
  13851 
  13852       subm = buildGroup(valueSub, _newOptions, options);
  13853 
  13854       if (!isCharacterBox) {
  13855         subShift = base.depth + _newOptions.fontMetrics().subDrop * _newOptions.sizeMultiplier / options.sizeMultiplier;
  13856       }
  13857     } // Rule 18c
  13858 
  13859 
  13860     var minSupShift;
  13861 
  13862     if (options.style === Style$1.DISPLAY) {
  13863       minSupShift = metrics.sup1;
  13864     } else if (options.style.cramped) {
  13865       minSupShift = metrics.sup3;
  13866     } else {
  13867       minSupShift = metrics.sup2;
  13868     } // scriptspace is a font-size-independent size, so scale it
  13869     // appropriately for use as the marginRight.
  13870 
  13871 
  13872     var multiplier = options.sizeMultiplier;
  13873     var marginRight = 0.5 / metrics.ptPerEm / multiplier + "em";
  13874     var marginLeft = null;
  13875 
  13876     if (subm) {
  13877       // Subscripts shouldn't be shifted by the base's italic correction.
  13878       // Account for that by shifting the subscript back the appropriate
  13879       // amount. Note we only do this when the base is a single symbol.
  13880       var isOiint = group.base && group.base.type === "op" && group.base.name && (group.base.name === "\\oiint" || group.base.name === "\\oiiint");
  13881 
  13882       if (base instanceof SymbolNode || isOiint) {
  13883         // $FlowFixMe
  13884         marginLeft = -base.italic + "em";
  13885       }
  13886     }
  13887 
  13888     var supsub;
  13889 
  13890     if (supm && subm) {
  13891       supShift = Math.max(supShift, minSupShift, supm.depth + 0.25 * metrics.xHeight);
  13892       subShift = Math.max(subShift, metrics.sub2);
  13893       var ruleWidth = metrics.defaultRuleThickness; // Rule 18e
  13894 
  13895       var maxWidth = 4 * ruleWidth;
  13896 
  13897       if (supShift - supm.depth - (subm.height - subShift) < maxWidth) {
  13898         subShift = maxWidth - (supShift - supm.depth) + subm.height;
  13899         var psi = 0.8 * metrics.xHeight - (supShift - supm.depth);
  13900 
  13901         if (psi > 0) {
  13902           supShift += psi;
  13903           subShift -= psi;
  13904         }
  13905       }
  13906 
  13907       var vlistElem = [{
  13908         type: "elem",
  13909         elem: subm,
  13910         shift: subShift,
  13911         marginRight,
  13912         marginLeft
  13913       }, {
  13914         type: "elem",
  13915         elem: supm,
  13916         shift: -supShift,
  13917         marginRight
  13918       }];
  13919       supsub = buildCommon.makeVList({
  13920         positionType: "individualShift",
  13921         children: vlistElem
  13922       }, options);
  13923     } else if (subm) {
  13924       // Rule 18b
  13925       subShift = Math.max(subShift, metrics.sub1, subm.height - 0.8 * metrics.xHeight);
  13926       var _vlistElem = [{
  13927         type: "elem",
  13928         elem: subm,
  13929         marginLeft,
  13930         marginRight
  13931       }];
  13932       supsub = buildCommon.makeVList({
  13933         positionType: "shift",
  13934         positionData: subShift,
  13935         children: _vlistElem
  13936       }, options);
  13937     } else if (supm) {
  13938       // Rule 18c, d
  13939       supShift = Math.max(supShift, minSupShift, supm.depth + 0.25 * metrics.xHeight);
  13940       supsub = buildCommon.makeVList({
  13941         positionType: "shift",
  13942         positionData: -supShift,
  13943         children: [{
  13944           type: "elem",
  13945           elem: supm,
  13946           marginRight
  13947         }]
  13948       }, options);
  13949     } else {
  13950       throw new Error("supsub must have either sup or sub.");
  13951     } // Wrap the supsub vlist in a span.msupsub to reset text-align.
  13952 
  13953 
  13954     var mclass = getTypeOfDomTree(base, "right") || "mord";
  13955     return buildCommon.makeSpan([mclass], [base, buildCommon.makeSpan(["msupsub"], [supsub])], options);
  13956   },
  13957 
  13958   mathmlBuilder(group, options) {
  13959     // Is the inner group a relevant horizonal brace?
  13960     var isBrace = false;
  13961     var isOver;
  13962     var isSup;
  13963 
  13964     if (group.base && group.base.type === "horizBrace") {
  13965       isSup = !!group.sup;
  13966 
  13967       if (isSup === group.base.isOver) {
  13968         isBrace = true;
  13969         isOver = group.base.isOver;
  13970       }
  13971     }
  13972 
  13973     if (group.base && (group.base.type === "op" || group.base.type === "operatorname")) {
  13974       group.base.parentIsSupSub = true;
  13975     }
  13976 
  13977     var children = [buildGroup$1(group.base, options)];
  13978 
  13979     if (group.sub) {
  13980       children.push(buildGroup$1(group.sub, options));
  13981     }
  13982 
  13983     if (group.sup) {
  13984       children.push(buildGroup$1(group.sup, options));
  13985     }
  13986 
  13987     var nodeType;
  13988 
  13989     if (isBrace) {
  13990       nodeType = isOver ? "mover" : "munder";
  13991     } else if (!group.sub) {
  13992       var base = group.base;
  13993 
  13994       if (base && base.type === "op" && base.limits && (options.style === Style$1.DISPLAY || base.alwaysHandleSupSub)) {
  13995         nodeType = "mover";
  13996       } else if (base && base.type === "operatorname" && base.alwaysHandleSupSub && (base.limits || options.style === Style$1.DISPLAY)) {
  13997         nodeType = "mover";
  13998       } else {
  13999         nodeType = "msup";
  14000       }
  14001     } else if (!group.sup) {
  14002       var _base = group.base;
  14003 
  14004       if (_base && _base.type === "op" && _base.limits && (options.style === Style$1.DISPLAY || _base.alwaysHandleSupSub)) {
  14005         nodeType = "munder";
  14006       } else if (_base && _base.type === "operatorname" && _base.alwaysHandleSupSub && (_base.limits || options.style === Style$1.DISPLAY)) {
  14007         nodeType = "munder";
  14008       } else {
  14009         nodeType = "msub";
  14010       }
  14011     } else {
  14012       var _base2 = group.base;
  14013 
  14014       if (_base2 && _base2.type === "op" && _base2.limits && options.style === Style$1.DISPLAY) {
  14015         nodeType = "munderover";
  14016       } else if (_base2 && _base2.type === "operatorname" && _base2.alwaysHandleSupSub && (options.style === Style$1.DISPLAY || _base2.limits)) {
  14017         nodeType = "munderover";
  14018       } else {
  14019         nodeType = "msubsup";
  14020       }
  14021     }
  14022 
  14023     return new mathMLTree.MathNode(nodeType, children);
  14024   }
  14025 
  14026 });
  14027 
  14028 defineFunctionBuilders({
  14029   type: "atom",
  14030 
  14031   htmlBuilder(group, options) {
  14032     return buildCommon.mathsym(group.text, group.mode, options, ["m" + group.family]);
  14033   },
  14034 
  14035   mathmlBuilder(group, options) {
  14036     var node = new mathMLTree.MathNode("mo", [makeText(group.text, group.mode)]);
  14037 
  14038     if (group.family === "bin") {
  14039       var variant = getVariant(group, options);
  14040 
  14041       if (variant === "bold-italic") {
  14042         node.setAttribute("mathvariant", variant);
  14043       }
  14044     } else if (group.family === "punct") {
  14045       node.setAttribute("separator", "true");
  14046     } else if (group.family === "open" || group.family === "close") {
  14047       // Delims built here should not stretch vertically.
  14048       // See delimsizing.js for stretchy delims.
  14049       node.setAttribute("stretchy", "false");
  14050     }
  14051 
  14052     return node;
  14053   }
  14054 
  14055 });
  14056 
  14057 // "mathord" and "textord" ParseNodes created in Parser.js from symbol Groups in
  14058 // src/symbols.js.
  14059 var defaultVariant = {
  14060   "mi": "italic",
  14061   "mn": "normal",
  14062   "mtext": "normal"
  14063 };
  14064 defineFunctionBuilders({
  14065   type: "mathord",
  14066 
  14067   htmlBuilder(group, options) {
  14068     return buildCommon.makeOrd(group, options, "mathord");
  14069   },
  14070 
  14071   mathmlBuilder(group, options) {
  14072     var node = new mathMLTree.MathNode("mi", [makeText(group.text, group.mode, options)]);
  14073     var variant = getVariant(group, options) || "italic";
  14074 
  14075     if (variant !== defaultVariant[node.type]) {
  14076       node.setAttribute("mathvariant", variant);
  14077     }
  14078 
  14079     return node;
  14080   }
  14081 
  14082 });
  14083 defineFunctionBuilders({
  14084   type: "textord",
  14085 
  14086   htmlBuilder(group, options) {
  14087     return buildCommon.makeOrd(group, options, "textord");
  14088   },
  14089 
  14090   mathmlBuilder(group, options) {
  14091     var text = makeText(group.text, group.mode, options);
  14092     var variant = getVariant(group, options) || "normal";
  14093     var node;
  14094 
  14095     if (group.mode === 'text') {
  14096       node = new mathMLTree.MathNode("mtext", [text]);
  14097     } else if (/[0-9]/.test(group.text)) {
  14098       node = new mathMLTree.MathNode("mn", [text]);
  14099     } else if (group.text === "\\prime") {
  14100       node = new mathMLTree.MathNode("mo", [text]);
  14101     } else {
  14102       node = new mathMLTree.MathNode("mi", [text]);
  14103     }
  14104 
  14105     if (variant !== defaultVariant[node.type]) {
  14106       node.setAttribute("mathvariant", variant);
  14107     }
  14108 
  14109     return node;
  14110   }
  14111 
  14112 });
  14113 
  14114 var cssSpace = {
  14115   "\\nobreak": "nobreak",
  14116   "\\allowbreak": "allowbreak"
  14117 }; // A lookup table to determine whether a spacing function/symbol should be
  14118 // treated like a regular space character.  If a symbol or command is a key
  14119 // in this table, then it should be a regular space character.  Furthermore,
  14120 // the associated value may have a `className` specifying an extra CSS class
  14121 // to add to the created `span`.
  14122 
  14123 var regularSpace = {
  14124   " ": {},
  14125   "\\ ": {},
  14126   "~": {
  14127     className: "nobreak"
  14128   },
  14129   "\\space": {},
  14130   "\\nobreakspace": {
  14131     className: "nobreak"
  14132   }
  14133 }; // ParseNode<"spacing"> created in Parser.js from the "spacing" symbol Groups in
  14134 // src/symbols.js.
  14135 
  14136 defineFunctionBuilders({
  14137   type: "spacing",
  14138 
  14139   htmlBuilder(group, options) {
  14140     if (regularSpace.hasOwnProperty(group.text)) {
  14141       var className = regularSpace[group.text].className || ""; // Spaces are generated by adding an actual space. Each of these
  14142       // things has an entry in the symbols table, so these will be turned
  14143       // into appropriate outputs.
  14144 
  14145       if (group.mode === "text") {
  14146         var ord = buildCommon.makeOrd(group, options, "textord");
  14147         ord.classes.push(className);
  14148         return ord;
  14149       } else {
  14150         return buildCommon.makeSpan(["mspace", className], [buildCommon.mathsym(group.text, group.mode, options)], options);
  14151       }
  14152     } else if (cssSpace.hasOwnProperty(group.text)) {
  14153       // Spaces based on just a CSS class.
  14154       return buildCommon.makeSpan(["mspace", cssSpace[group.text]], [], options);
  14155     } else {
  14156       throw new ParseError("Unknown type of space \"" + group.text + "\"");
  14157     }
  14158   },
  14159 
  14160   mathmlBuilder(group, options) {
  14161     var node;
  14162 
  14163     if (regularSpace.hasOwnProperty(group.text)) {
  14164       node = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode("\u00a0")]);
  14165     } else if (cssSpace.hasOwnProperty(group.text)) {
  14166       // CSS-based MathML spaces (\nobreak, \allowbreak) are ignored
  14167       return new mathMLTree.MathNode("mspace");
  14168     } else {
  14169       throw new ParseError("Unknown type of space \"" + group.text + "\"");
  14170     }
  14171 
  14172     return node;
  14173   }
  14174 
  14175 });
  14176 
  14177 var pad = () => {
  14178   var padNode = new mathMLTree.MathNode("mtd", []);
  14179   padNode.setAttribute("width", "50%");
  14180   return padNode;
  14181 };
  14182 
  14183 defineFunctionBuilders({
  14184   type: "tag",
  14185 
  14186   mathmlBuilder(group, options) {
  14187     var table = new mathMLTree.MathNode("mtable", [new mathMLTree.MathNode("mtr", [pad(), new mathMLTree.MathNode("mtd", [buildExpressionRow(group.body, options)]), pad(), new mathMLTree.MathNode("mtd", [buildExpressionRow(group.tag, options)])])]);
  14188     table.setAttribute("width", "100%");
  14189     return table; // TODO: Left-aligned tags.
  14190     // Currently, the group and options passed here do not contain
  14191     // enough info to set tag alignment. `leqno` is in Settings but it is
  14192     // not passed to Options. On the HTML side, leqno is
  14193     // set by a CSS class applied in buildTree.js. That would have worked
  14194     // in MathML if browsers supported <mlabeledtr>. Since they don't, we
  14195     // need to rewrite the way this function is called.
  14196   }
  14197 
  14198 });
  14199 
  14200 var textFontFamilies = {
  14201   "\\text": undefined,
  14202   "\\textrm": "textrm",
  14203   "\\textsf": "textsf",
  14204   "\\texttt": "texttt",
  14205   "\\textnormal": "textrm"
  14206 };
  14207 var textFontWeights = {
  14208   "\\textbf": "textbf",
  14209   "\\textmd": "textmd"
  14210 };
  14211 var textFontShapes = {
  14212   "\\textit": "textit",
  14213   "\\textup": "textup"
  14214 };
  14215 
  14216 var optionsWithFont = (group, options) => {
  14217   var font = group.font; // Checks if the argument is a font family or a font style.
  14218 
  14219   if (!font) {
  14220     return options;
  14221   } else if (textFontFamilies[font]) {
  14222     return options.withTextFontFamily(textFontFamilies[font]);
  14223   } else if (textFontWeights[font]) {
  14224     return options.withTextFontWeight(textFontWeights[font]);
  14225   } else {
  14226     return options.withTextFontShape(textFontShapes[font]);
  14227   }
  14228 };
  14229 
  14230 defineFunction({
  14231   type: "text",
  14232   names: [// Font families
  14233   "\\text", "\\textrm", "\\textsf", "\\texttt", "\\textnormal", // Font weights
  14234   "\\textbf", "\\textmd", // Font Shapes
  14235   "\\textit", "\\textup"],
  14236   props: {
  14237     numArgs: 1,
  14238     argTypes: ["text"],
  14239     allowedInArgument: true,
  14240     allowedInText: true
  14241   },
  14242 
  14243   handler(_ref, args) {
  14244     var {
  14245       parser,
  14246       funcName
  14247     } = _ref;
  14248     var body = args[0];
  14249     return {
  14250       type: "text",
  14251       mode: parser.mode,
  14252       body: ordargument(body),
  14253       font: funcName
  14254     };
  14255   },
  14256 
  14257   htmlBuilder(group, options) {
  14258     var newOptions = optionsWithFont(group, options);
  14259     var inner = buildExpression(group.body, newOptions, true);
  14260     return buildCommon.makeSpan(["mord", "text"], inner, newOptions);
  14261   },
  14262 
  14263   mathmlBuilder(group, options) {
  14264     var newOptions = optionsWithFont(group, options);
  14265     return buildExpressionRow(group.body, newOptions);
  14266   }
  14267 
  14268 });
  14269 
  14270 defineFunction({
  14271   type: "underline",
  14272   names: ["\\underline"],
  14273   props: {
  14274     numArgs: 1,
  14275     allowedInText: true
  14276   },
  14277 
  14278   handler(_ref, args) {
  14279     var {
  14280       parser
  14281     } = _ref;
  14282     return {
  14283       type: "underline",
  14284       mode: parser.mode,
  14285       body: args[0]
  14286     };
  14287   },
  14288 
  14289   htmlBuilder(group, options) {
  14290     // Underlines are handled in the TeXbook pg 443, Rule 10.
  14291     // Build the inner group.
  14292     var innerGroup = buildGroup(group.body, options); // Create the line to go below the body
  14293 
  14294     var line = buildCommon.makeLineSpan("underline-line", options); // Generate the vlist, with the appropriate kerns
  14295 
  14296     var defaultRuleThickness = options.fontMetrics().defaultRuleThickness;
  14297     var vlist = buildCommon.makeVList({
  14298       positionType: "top",
  14299       positionData: innerGroup.height,
  14300       children: [{
  14301         type: "kern",
  14302         size: defaultRuleThickness
  14303       }, {
  14304         type: "elem",
  14305         elem: line
  14306       }, {
  14307         type: "kern",
  14308         size: 3 * defaultRuleThickness
  14309       }, {
  14310         type: "elem",
  14311         elem: innerGroup
  14312       }]
  14313     }, options);
  14314     return buildCommon.makeSpan(["mord", "underline"], [vlist], options);
  14315   },
  14316 
  14317   mathmlBuilder(group, options) {
  14318     var operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u203e")]);
  14319     operator.setAttribute("stretchy", "true");
  14320     var node = new mathMLTree.MathNode("munder", [buildGroup$1(group.body, options), operator]);
  14321     node.setAttribute("accentunder", "true");
  14322     return node;
  14323   }
  14324 
  14325 });
  14326 
  14327 defineFunction({
  14328   type: "vcenter",
  14329   names: ["\\vcenter"],
  14330   props: {
  14331     numArgs: 1,
  14332     argTypes: ["original"],
  14333     // In LaTeX, \vcenter can act only on a box.
  14334     allowedInText: false
  14335   },
  14336 
  14337   handler(_ref, args) {
  14338     var {
  14339       parser
  14340     } = _ref;
  14341     return {
  14342       type: "vcenter",
  14343       mode: parser.mode,
  14344       body: args[0]
  14345     };
  14346   },
  14347 
  14348   htmlBuilder(group, options) {
  14349     var body = buildGroup(group.body, options);
  14350     var axisHeight = options.fontMetrics().axisHeight;
  14351     var dy = 0.5 * (body.height - axisHeight - (body.depth + axisHeight));
  14352     return buildCommon.makeVList({
  14353       positionType: "shift",
  14354       positionData: dy,
  14355       children: [{
  14356         type: "elem",
  14357         elem: body
  14358       }]
  14359     }, options);
  14360   },
  14361 
  14362   mathmlBuilder(group, options) {
  14363     // There is no way to do this in MathML.
  14364     // Write a class as a breadcrumb in case some post-processor wants
  14365     // to perform a vcenter adjustment.
  14366     return new mathMLTree.MathNode("mpadded", [buildGroup$1(group.body, options)], ["vcenter"]);
  14367   }
  14368 
  14369 });
  14370 
  14371 defineFunction({
  14372   type: "verb",
  14373   names: ["\\verb"],
  14374   props: {
  14375     numArgs: 0,
  14376     allowedInText: true
  14377   },
  14378 
  14379   handler(context, args, optArgs) {
  14380     // \verb and \verb* are dealt with directly in Parser.js.
  14381     // If we end up here, it's because of a failure to match the two delimiters
  14382     // in the regex in Lexer.js.  LaTeX raises the following error when \verb is
  14383     // terminated by end of line (or file).
  14384     throw new ParseError("\\verb ended by end of line instead of matching delimiter");
  14385   },
  14386 
  14387   htmlBuilder(group, options) {
  14388     var text = makeVerb(group);
  14389     var body = []; // \verb enters text mode and therefore is sized like \textstyle
  14390 
  14391     var newOptions = options.havingStyle(options.style.text());
  14392 
  14393     for (var i = 0; i < text.length; i++) {
  14394       var c = text[i];
  14395 
  14396       if (c === '~') {
  14397         c = '\\textasciitilde';
  14398       }
  14399 
  14400       body.push(buildCommon.makeSymbol(c, "Typewriter-Regular", group.mode, newOptions, ["mord", "texttt"]));
  14401     }
  14402 
  14403     return buildCommon.makeSpan(["mord", "text"].concat(newOptions.sizingClasses(options)), buildCommon.tryCombineChars(body), newOptions);
  14404   },
  14405 
  14406   mathmlBuilder(group, options) {
  14407     var text = new mathMLTree.TextNode(makeVerb(group));
  14408     var node = new mathMLTree.MathNode("mtext", [text]);
  14409     node.setAttribute("mathvariant", "monospace");
  14410     return node;
  14411   }
  14412 
  14413 });
  14414 /**
  14415  * Converts verb group into body string.
  14416  *
  14417  * \verb* replaces each space with an open box \u2423
  14418  * \verb replaces each space with a no-break space \xA0
  14419  */
  14420 
  14421 var makeVerb = group => group.body.replace(/ /g, group.star ? '\u2423' : '\xA0');
  14422 
  14423 /** Include this to ensure that all functions are defined. */
  14424 var functions = _functions;
  14425 
  14426 /**
  14427  * The Lexer class handles tokenizing the input in various ways. Since our
  14428  * parser expects us to be able to backtrack, the lexer allows lexing from any
  14429  * given starting point.
  14430  *
  14431  * Its main exposed function is the `lex` function, which takes a position to
  14432  * lex from and a type of token to lex. It defers to the appropriate `_innerLex`
  14433  * function.
  14434  *
  14435  * The various `_innerLex` functions perform the actual lexing of different
  14436  * kinds.
  14437  */
  14438 
  14439 /* The following tokenRegex
  14440  * - matches typical whitespace (but not NBSP etc.) using its first group
  14441  * - does not match any control character \x00-\x1f except whitespace
  14442  * - does not match a bare backslash
  14443  * - matches any ASCII character except those just mentioned
  14444  * - does not match the BMP private use area \uE000-\uF8FF
  14445  * - does not match bare surrogate code units
  14446  * - matches any BMP character except for those just described
  14447  * - matches any valid Unicode surrogate pair
  14448  * - matches a backslash followed by one or more letters
  14449  * - matches a backslash followed by any BMP character, including newline
  14450  * Just because the Lexer matches something doesn't mean it's valid input:
  14451  * If there is no matching function or symbol definition, the Parser will
  14452  * still reject the input.
  14453  */
  14454 var spaceRegexString = "[ \r\n\t]";
  14455 var controlWordRegexString = "\\\\[a-zA-Z@]+";
  14456 var controlSymbolRegexString = "\\\\[^\uD800-\uDFFF]";
  14457 var controlWordWhitespaceRegexString = "" + controlWordRegexString + spaceRegexString + "*";
  14458 var controlWordWhitespaceRegex = new RegExp("^(" + controlWordRegexString + ")" + spaceRegexString + "*$");
  14459 var combiningDiacriticalMarkString = "[\u0300-\u036f]";
  14460 var combiningDiacriticalMarksEndRegex = new RegExp(combiningDiacriticalMarkString + "+$");
  14461 var tokenRegexString = "(" + spaceRegexString + "+)|" + // whitespace
  14462 "([!-\\[\\]-\u2027\u202A-\uD7FF\uF900-\uFFFF]" + ( // single codepoint
  14463 combiningDiacriticalMarkString + "*") + // ...plus accents
  14464 "|[\uD800-\uDBFF][\uDC00-\uDFFF]" + ( // surrogate pair
  14465 combiningDiacriticalMarkString + "*") + // ...plus accents
  14466 "|\\\\verb\\*([^]).*?\\3" + // \verb*
  14467 "|\\\\verb([^*a-zA-Z]).*?\\4" + // \verb unstarred
  14468 "|\\\\operatorname\\*" + ( // \operatorname*
  14469 "|" + controlWordWhitespaceRegexString) + ( // \macroName + spaces
  14470 "|" + controlSymbolRegexString + ")"); // \\, \', etc.
  14471 
  14472 /** Main Lexer class */
  14473 
  14474 class Lexer {
  14475   // category codes, only supports comment characters (14) for now
  14476   constructor(input, settings) {
  14477     this.input = void 0;
  14478     this.settings = void 0;
  14479     this.tokenRegex = void 0;
  14480     this.catcodes = void 0;
  14481     // Separate accents from characters
  14482     this.input = input;
  14483     this.settings = settings;
  14484     this.tokenRegex = new RegExp(tokenRegexString, 'g');
  14485     this.catcodes = {
  14486       "%": 14 // comment character
  14487 
  14488     };
  14489   }
  14490 
  14491   setCatcode(char, code) {
  14492     this.catcodes[char] = code;
  14493   }
  14494   /**
  14495    * This function lexes a single token.
  14496    */
  14497 
  14498 
  14499   lex() {
  14500     var input = this.input;
  14501     var pos = this.tokenRegex.lastIndex;
  14502 
  14503     if (pos === input.length) {
  14504       return new Token("EOF", new SourceLocation(this, pos, pos));
  14505     }
  14506 
  14507     var match = this.tokenRegex.exec(input);
  14508 
  14509     if (match === null || match.index !== pos) {
  14510       throw new ParseError("Unexpected character: '" + input[pos] + "'", new Token(input[pos], new SourceLocation(this, pos, pos + 1)));
  14511     }
  14512 
  14513     var text = match[2] || " ";
  14514 
  14515     if (this.catcodes[text] === 14) {
  14516       // comment character
  14517       var nlIndex = input.indexOf('\n', this.tokenRegex.lastIndex);
  14518 
  14519       if (nlIndex === -1) {
  14520         this.tokenRegex.lastIndex = input.length; // EOF
  14521 
  14522         this.settings.reportNonstrict("commentAtEnd", "% comment has no terminating newline; LaTeX would " + "fail because of commenting the end of math mode (e.g. $)");
  14523       } else {
  14524         this.tokenRegex.lastIndex = nlIndex + 1;
  14525       }
  14526 
  14527       return this.lex();
  14528     } // Trim any trailing whitespace from control word match
  14529 
  14530 
  14531     var controlMatch = text.match(controlWordWhitespaceRegex);
  14532 
  14533     if (controlMatch) {
  14534       text = controlMatch[1];
  14535     }
  14536 
  14537     return new Token(text, new SourceLocation(this, pos, this.tokenRegex.lastIndex));
  14538   }
  14539 
  14540 }
  14541 
  14542 /**
  14543  * A `Namespace` refers to a space of nameable things like macros or lengths,
  14544  * which can be `set` either globally or local to a nested group, using an
  14545  * undo stack similar to how TeX implements this functionality.
  14546  * Performance-wise, `get` and local `set` take constant time, while global
  14547  * `set` takes time proportional to the depth of group nesting.
  14548  */
  14549 class Namespace {
  14550   /**
  14551    * Both arguments are optional.  The first argument is an object of
  14552    * built-in mappings which never change.  The second argument is an object
  14553    * of initial (global-level) mappings, which will constantly change
  14554    * according to any global/top-level `set`s done.
  14555    */
  14556   constructor(builtins, globalMacros) {
  14557     if (builtins === void 0) {
  14558       builtins = {};
  14559     }
  14560 
  14561     if (globalMacros === void 0) {
  14562       globalMacros = {};
  14563     }
  14564 
  14565     this.current = void 0;
  14566     this.builtins = void 0;
  14567     this.undefStack = void 0;
  14568     this.current = globalMacros;
  14569     this.builtins = builtins;
  14570     this.undefStack = [];
  14571   }
  14572   /**
  14573    * Start a new nested group, affecting future local `set`s.
  14574    */
  14575 
  14576 
  14577   beginGroup() {
  14578     this.undefStack.push({});
  14579   }
  14580   /**
  14581    * End current nested group, restoring values before the group began.
  14582    */
  14583 
  14584 
  14585   endGroup() {
  14586     if (this.undefStack.length === 0) {
  14587       throw new ParseError("Unbalanced namespace destruction: attempt " + "to pop global namespace; please report this as a bug");
  14588     }
  14589 
  14590     var undefs = this.undefStack.pop();
  14591 
  14592     for (var undef in undefs) {
  14593       if (undefs.hasOwnProperty(undef)) {
  14594         if (undefs[undef] === undefined) {
  14595           delete this.current[undef];
  14596         } else {
  14597           this.current[undef] = undefs[undef];
  14598         }
  14599       }
  14600     }
  14601   }
  14602   /**
  14603    * Detect whether `name` has a definition.  Equivalent to
  14604    * `get(name) != null`.
  14605    */
  14606 
  14607 
  14608   has(name) {
  14609     return this.current.hasOwnProperty(name) || this.builtins.hasOwnProperty(name);
  14610   }
  14611   /**
  14612    * Get the current value of a name, or `undefined` if there is no value.
  14613    *
  14614    * Note: Do not use `if (namespace.get(...))` to detect whether a macro
  14615    * is defined, as the definition may be the empty string which evaluates
  14616    * to `false` in JavaScript.  Use `if (namespace.get(...) != null)` or
  14617    * `if (namespace.has(...))`.
  14618    */
  14619 
  14620 
  14621   get(name) {
  14622     if (this.current.hasOwnProperty(name)) {
  14623       return this.current[name];
  14624     } else {
  14625       return this.builtins[name];
  14626     }
  14627   }
  14628   /**
  14629    * Set the current value of a name, and optionally set it globally too.
  14630    * Local set() sets the current value and (when appropriate) adds an undo
  14631    * operation to the undo stack.  Global set() may change the undo
  14632    * operation at every level, so takes time linear in their number.
  14633    */
  14634 
  14635 
  14636   set(name, value, global) {
  14637     if (global === void 0) {
  14638       global = false;
  14639     }
  14640 
  14641     if (global) {
  14642       // Global set is equivalent to setting in all groups.  Simulate this
  14643       // by destroying any undos currently scheduled for this name,
  14644       // and adding an undo with the *new* value (in case it later gets
  14645       // locally reset within this environment).
  14646       for (var i = 0; i < this.undefStack.length; i++) {
  14647         delete this.undefStack[i][name];
  14648       }
  14649 
  14650       if (this.undefStack.length > 0) {
  14651         this.undefStack[this.undefStack.length - 1][name] = value;
  14652       }
  14653     } else {
  14654       // Undo this set at end of this group (possibly to `undefined`),
  14655       // unless an undo is already in place, in which case that older
  14656       // value is the correct one.
  14657       var top = this.undefStack[this.undefStack.length - 1];
  14658 
  14659       if (top && !top.hasOwnProperty(name)) {
  14660         top[name] = this.current[name];
  14661       }
  14662     }
  14663 
  14664     this.current[name] = value;
  14665   }
  14666 
  14667 }
  14668 
  14669 /**
  14670  * Predefined macros for KaTeX.
  14671  * This can be used to define some commands in terms of others.
  14672  */
  14673 var builtinMacros = {};
  14674 
  14675 function defineMacro(name, body) {
  14676   builtinMacros[name] = body;
  14677 } //////////////////////////////////////////////////////////////////////
  14678 // macro tools
  14679 
  14680 defineMacro("\\noexpand", function (context) {
  14681   // The expansion is the token itself; but that token is interpreted
  14682   // as if its meaning were ‘\relax’ if it is a control sequence that
  14683   // would ordinarily be expanded by TeX’s expansion rules.
  14684   var t = context.popToken();
  14685 
  14686   if (context.isExpandable(t.text)) {
  14687     t.noexpand = true;
  14688     t.treatAsRelax = true;
  14689   }
  14690 
  14691   return {
  14692     tokens: [t],
  14693     numArgs: 0
  14694   };
  14695 });
  14696 defineMacro("\\expandafter", function (context) {
  14697   // TeX first reads the token that comes immediately after \expandafter,
  14698   // without expanding it; let’s call this token t. Then TeX reads the
  14699   // token that comes after t (and possibly more tokens, if that token
  14700   // has an argument), replacing it by its expansion. Finally TeX puts
  14701   // t back in front of that expansion.
  14702   var t = context.popToken();
  14703   context.expandOnce(true); // expand only an expandable token
  14704 
  14705   return {
  14706     tokens: [t],
  14707     numArgs: 0
  14708   };
  14709 }); // LaTeX's \@firstoftwo{#1}{#2} expands to #1, skipping #2
  14710 // TeX source: \long\def\@firstoftwo#1#2{#1}
  14711 
  14712 defineMacro("\\@firstoftwo", function (context) {
  14713   var args = context.consumeArgs(2);
  14714   return {
  14715     tokens: args[0],
  14716     numArgs: 0
  14717   };
  14718 }); // LaTeX's \@secondoftwo{#1}{#2} expands to #2, skipping #1
  14719 // TeX source: \long\def\@secondoftwo#1#2{#2}
  14720 
  14721 defineMacro("\\@secondoftwo", function (context) {
  14722   var args = context.consumeArgs(2);
  14723   return {
  14724     tokens: args[1],
  14725     numArgs: 0
  14726   };
  14727 }); // LaTeX's \@ifnextchar{#1}{#2}{#3} looks ahead to the next (unexpanded)
  14728 // symbol that isn't a space, consuming any spaces but not consuming the
  14729 // first nonspace character.  If that nonspace character matches #1, then
  14730 // the macro expands to #2; otherwise, it expands to #3.
  14731 
  14732 defineMacro("\\@ifnextchar", function (context) {
  14733   var args = context.consumeArgs(3); // symbol, if, else
  14734 
  14735   context.consumeSpaces();
  14736   var nextToken = context.future();
  14737 
  14738   if (args[0].length === 1 && args[0][0].text === nextToken.text) {
  14739     return {
  14740       tokens: args[1],
  14741       numArgs: 0
  14742     };
  14743   } else {
  14744     return {
  14745       tokens: args[2],
  14746       numArgs: 0
  14747     };
  14748   }
  14749 }); // LaTeX's \@ifstar{#1}{#2} looks ahead to the next (unexpanded) symbol.
  14750 // If it is `*`, then it consumes the symbol, and the macro expands to #1;
  14751 // otherwise, the macro expands to #2 (without consuming the symbol).
  14752 // TeX source: \def\@ifstar#1{\@ifnextchar *{\@firstoftwo{#1}}}
  14753 
  14754 defineMacro("\\@ifstar", "\\@ifnextchar *{\\@firstoftwo{#1}}"); // LaTeX's \TextOrMath{#1}{#2} expands to #1 in text mode, #2 in math mode
  14755 
  14756 defineMacro("\\TextOrMath", function (context) {
  14757   var args = context.consumeArgs(2);
  14758 
  14759   if (context.mode === 'text') {
  14760     return {
  14761       tokens: args[0],
  14762       numArgs: 0
  14763     };
  14764   } else {
  14765     return {
  14766       tokens: args[1],
  14767       numArgs: 0
  14768     };
  14769   }
  14770 }); // Lookup table for parsing numbers in base 8 through 16
  14771 
  14772 var digitToNumber = {
  14773   "0": 0,
  14774   "1": 1,
  14775   "2": 2,
  14776   "3": 3,
  14777   "4": 4,
  14778   "5": 5,
  14779   "6": 6,
  14780   "7": 7,
  14781   "8": 8,
  14782   "9": 9,
  14783   "a": 10,
  14784   "A": 10,
  14785   "b": 11,
  14786   "B": 11,
  14787   "c": 12,
  14788   "C": 12,
  14789   "d": 13,
  14790   "D": 13,
  14791   "e": 14,
  14792   "E": 14,
  14793   "f": 15,
  14794   "F": 15
  14795 }; // TeX \char makes a literal character (catcode 12) using the following forms:
  14796 // (see The TeXBook, p. 43)
  14797 //   \char123  -- decimal
  14798 //   \char'123 -- octal
  14799 //   \char"123 -- hex
  14800 //   \char`x   -- character that can be written (i.e. isn't active)
  14801 //   \char`\x  -- character that cannot be written (e.g. %)
  14802 // These all refer to characters from the font, so we turn them into special
  14803 // calls to a function \@char dealt with in the Parser.
  14804 
  14805 defineMacro("\\char", function (context) {
  14806   var token = context.popToken();
  14807   var base;
  14808   var number = '';
  14809 
  14810   if (token.text === "'") {
  14811     base = 8;
  14812     token = context.popToken();
  14813   } else if (token.text === '"') {
  14814     base = 16;
  14815     token = context.popToken();
  14816   } else if (token.text === "`") {
  14817     token = context.popToken();
  14818 
  14819     if (token.text[0] === "\\") {
  14820       number = token.text.charCodeAt(1);
  14821     } else if (token.text === "EOF") {
  14822       throw new ParseError("\\char` missing argument");
  14823     } else {
  14824       number = token.text.charCodeAt(0);
  14825     }
  14826   } else {
  14827     base = 10;
  14828   }
  14829 
  14830   if (base) {
  14831     // Parse a number in the given base, starting with first `token`.
  14832     number = digitToNumber[token.text];
  14833 
  14834     if (number == null || number >= base) {
  14835       throw new ParseError("Invalid base-" + base + " digit " + token.text);
  14836     }
  14837 
  14838     var digit;
  14839 
  14840     while ((digit = digitToNumber[context.future().text]) != null && digit < base) {
  14841       number *= base;
  14842       number += digit;
  14843       context.popToken();
  14844     }
  14845   }
  14846 
  14847   return "\\@char{" + number + "}";
  14848 }); // \newcommand{\macro}[args]{definition}
  14849 // \renewcommand{\macro}[args]{definition}
  14850 // TODO: Optional arguments: \newcommand{\macro}[args][default]{definition}
  14851 
  14852 var newcommand = (context, existsOK, nonexistsOK) => {
  14853   var arg = context.consumeArg().tokens;
  14854 
  14855   if (arg.length !== 1) {
  14856     throw new ParseError("\\newcommand's first argument must be a macro name");
  14857   }
  14858 
  14859   var name = arg[0].text;
  14860   var exists = context.isDefined(name);
  14861 
  14862   if (exists && !existsOK) {
  14863     throw new ParseError("\\newcommand{" + name + "} attempting to redefine " + (name + "; use \\renewcommand"));
  14864   }
  14865 
  14866   if (!exists && !nonexistsOK) {
  14867     throw new ParseError("\\renewcommand{" + name + "} when command " + name + " " + "does not yet exist; use \\newcommand");
  14868   }
  14869 
  14870   var numArgs = 0;
  14871   arg = context.consumeArg().tokens;
  14872 
  14873   if (arg.length === 1 && arg[0].text === "[") {
  14874     var argText = '';
  14875     var token = context.expandNextToken();
  14876 
  14877     while (token.text !== "]" && token.text !== "EOF") {
  14878       // TODO: Should properly expand arg, e.g., ignore {}s
  14879       argText += token.text;
  14880       token = context.expandNextToken();
  14881     }
  14882 
  14883     if (!argText.match(/^\s*[0-9]+\s*$/)) {
  14884       throw new ParseError("Invalid number of arguments: " + argText);
  14885     }
  14886 
  14887     numArgs = parseInt(argText);
  14888     arg = context.consumeArg().tokens;
  14889   } // Final arg is the expansion of the macro
  14890 
  14891 
  14892   context.macros.set(name, {
  14893     tokens: arg,
  14894     numArgs
  14895   });
  14896   return '';
  14897 };
  14898 
  14899 defineMacro("\\newcommand", context => newcommand(context, false, true));
  14900 defineMacro("\\renewcommand", context => newcommand(context, true, false));
  14901 defineMacro("\\providecommand", context => newcommand(context, true, true)); // terminal (console) tools
  14902 
  14903 defineMacro("\\message", context => {
  14904   var arg = context.consumeArgs(1)[0]; // eslint-disable-next-line no-console
  14905 
  14906   console.log(arg.reverse().map(token => token.text).join(""));
  14907   return '';
  14908 });
  14909 defineMacro("\\errmessage", context => {
  14910   var arg = context.consumeArgs(1)[0]; // eslint-disable-next-line no-console
  14911 
  14912   console.error(arg.reverse().map(token => token.text).join(""));
  14913   return '';
  14914 });
  14915 defineMacro("\\show", context => {
  14916   var tok = context.popToken();
  14917   var name = tok.text; // eslint-disable-next-line no-console
  14918 
  14919   console.log(tok, context.macros.get(name), functions[name], symbols.math[name], symbols.text[name]);
  14920   return '';
  14921 }); //////////////////////////////////////////////////////////////////////
  14922 // Grouping
  14923 // \let\bgroup={ \let\egroup=}
  14924 
  14925 defineMacro("\\bgroup", "{");
  14926 defineMacro("\\egroup", "}"); // Symbols from latex.ltx:
  14927 // \def\lq{`}
  14928 // \def\rq{'}
  14929 // \def \aa {\r a}
  14930 // \def \AA {\r A}
  14931 
  14932 defineMacro("\\lq", "`");
  14933 defineMacro("\\rq", "'");
  14934 defineMacro("\\aa", "\\r a");
  14935 defineMacro("\\AA", "\\r A"); // Copyright (C) and registered (R) symbols. Use raw symbol in MathML.
  14936 // \DeclareTextCommandDefault{\textcopyright}{\textcircled{c}}
  14937 // \DeclareTextCommandDefault{\textregistered}{\textcircled{%
  14938 //      \check@mathfonts\fontsize\sf@size\z@\math@fontsfalse\selectfont R}}
  14939 // \DeclareRobustCommand{\copyright}{%
  14940 //    \ifmmode{\nfss@text{\textcopyright}}\else\textcopyright\fi}
  14941 
  14942 defineMacro("\\textcopyright", "\\html@mathml{\\textcircled{c}}{\\char`©}");
  14943 defineMacro("\\copyright", "\\TextOrMath{\\textcopyright}{\\text{\\textcopyright}}");
  14944 defineMacro("\\textregistered", "\\html@mathml{\\textcircled{\\scriptsize R}}{\\char`®}"); // Characters omitted from Unicode range 1D400–1D7FF
  14945 
  14946 defineMacro("\u212C", "\\mathscr{B}"); // script
  14947 
  14948 defineMacro("\u2130", "\\mathscr{E}");
  14949 defineMacro("\u2131", "\\mathscr{F}");
  14950 defineMacro("\u210B", "\\mathscr{H}");
  14951 defineMacro("\u2110", "\\mathscr{I}");
  14952 defineMacro("\u2112", "\\mathscr{L}");
  14953 defineMacro("\u2133", "\\mathscr{M}");
  14954 defineMacro("\u211B", "\\mathscr{R}");
  14955 defineMacro("\u212D", "\\mathfrak{C}"); // Fraktur
  14956 
  14957 defineMacro("\u210C", "\\mathfrak{H}");
  14958 defineMacro("\u2128", "\\mathfrak{Z}"); // Define \Bbbk with a macro that works in both HTML and MathML.
  14959 
  14960 defineMacro("\\Bbbk", "\\Bbb{k}"); // Unicode middle dot
  14961 // The KaTeX fonts do not contain U+00B7. Instead, \cdotp displays
  14962 // the dot at U+22C5 and gives it punct spacing.
  14963 
  14964 defineMacro("\u00b7", "\\cdotp"); // \llap and \rlap render their contents in text mode
  14965 
  14966 defineMacro("\\llap", "\\mathllap{\\textrm{#1}}");
  14967 defineMacro("\\rlap", "\\mathrlap{\\textrm{#1}}");
  14968 defineMacro("\\clap", "\\mathclap{\\textrm{#1}}"); // \mathstrut from the TeXbook, p 360
  14969 
  14970 defineMacro("\\mathstrut", "\\vphantom{(}"); // \underbar from TeXbook p 353
  14971 
  14972 defineMacro("\\underbar", "\\underline{\\text{#1}}"); // \not is defined by base/fontmath.ltx via
  14973 // \DeclareMathSymbol{\not}{\mathrel}{symbols}{"36}
  14974 // It's thus treated like a \mathrel, but defined by a symbol that has zero
  14975 // width but extends to the right.  We use \rlap to get that spacing.
  14976 // For MathML we write U+0338 here. buildMathML.js will then do the overlay.
  14977 
  14978 defineMacro("\\not", '\\html@mathml{\\mathrel{\\mathrlap\\@not}}{\\char"338}'); // Negated symbols from base/fontmath.ltx:
  14979 // \def\neq{\not=} \let\ne=\neq
  14980 // \DeclareRobustCommand
  14981 //   \notin{\mathrel{\m@th\mathpalette\c@ncel\in}}
  14982 // \def\c@ncel#1#2{\m@th\ooalign{$\hfil#1\mkern1mu/\hfil$\crcr$#1#2$}}
  14983 
  14984 defineMacro("\\neq", "\\html@mathml{\\mathrel{\\not=}}{\\mathrel{\\char`≠}}");
  14985 defineMacro("\\ne", "\\neq");
  14986 defineMacro("\u2260", "\\neq");
  14987 defineMacro("\\notin", "\\html@mathml{\\mathrel{{\\in}\\mathllap{/\\mskip1mu}}}" + "{\\mathrel{\\char`∉}}");
  14988 defineMacro("\u2209", "\\notin"); // Unicode stacked relations
  14989 
  14990 defineMacro("\u2258", "\\html@mathml{" + "\\mathrel{=\\kern{-1em}\\raisebox{0.4em}{$\\scriptsize\\frown$}}" + "}{\\mathrel{\\char`\u2258}}");
  14991 defineMacro("\u2259", "\\html@mathml{\\stackrel{\\tiny\\wedge}{=}}{\\mathrel{\\char`\u2258}}");
  14992 defineMacro("\u225A", "\\html@mathml{\\stackrel{\\tiny\\vee}{=}}{\\mathrel{\\char`\u225A}}");
  14993 defineMacro("\u225B", "\\html@mathml{\\stackrel{\\scriptsize\\star}{=}}" + "{\\mathrel{\\char`\u225B}}");
  14994 defineMacro("\u225D", "\\html@mathml{\\stackrel{\\tiny\\mathrm{def}}{=}}" + "{\\mathrel{\\char`\u225D}}");
  14995 defineMacro("\u225E", "\\html@mathml{\\stackrel{\\tiny\\mathrm{m}}{=}}" + "{\\mathrel{\\char`\u225E}}");
  14996 defineMacro("\u225F", "\\html@mathml{\\stackrel{\\tiny?}{=}}{\\mathrel{\\char`\u225F}}"); // Misc Unicode
  14997 
  14998 defineMacro("\u27C2", "\\perp");
  14999 defineMacro("\u203C", "\\mathclose{!\\mkern-0.8mu!}");
  15000 defineMacro("\u220C", "\\notni");
  15001 defineMacro("\u231C", "\\ulcorner");
  15002 defineMacro("\u231D", "\\urcorner");
  15003 defineMacro("\u231E", "\\llcorner");
  15004 defineMacro("\u231F", "\\lrcorner");
  15005 defineMacro("\u00A9", "\\copyright");
  15006 defineMacro("\u00AE", "\\textregistered");
  15007 defineMacro("\uFE0F", "\\textregistered"); // The KaTeX fonts have corners at codepoints that don't match Unicode.
  15008 // For MathML purposes, use the Unicode code point.
  15009 
  15010 defineMacro("\\ulcorner", "\\html@mathml{\\@ulcorner}{\\mathop{\\char\"231c}}");
  15011 defineMacro("\\urcorner", "\\html@mathml{\\@urcorner}{\\mathop{\\char\"231d}}");
  15012 defineMacro("\\llcorner", "\\html@mathml{\\@llcorner}{\\mathop{\\char\"231e}}");
  15013 defineMacro("\\lrcorner", "\\html@mathml{\\@lrcorner}{\\mathop{\\char\"231f}}"); //////////////////////////////////////////////////////////////////////
  15014 // LaTeX_2ε
  15015 // \vdots{\vbox{\baselineskip4\p@  \lineskiplimit\z@
  15016 // \kern6\p@\hbox{.}\hbox{.}\hbox{.}}}
  15017 // We'll call \varvdots, which gets a glyph from symbols.js.
  15018 // The zero-width rule gets us an equivalent to the vertical 6pt kern.
  15019 
  15020 defineMacro("\\vdots", "\\mathord{\\varvdots\\rule{0pt}{15pt}}");
  15021 defineMacro("\u22ee", "\\vdots"); //////////////////////////////////////////////////////////////////////
  15022 // amsmath.sty
  15023 // http://mirrors.concertpass.com/tex-archive/macros/latex/required/amsmath/amsmath.pdf
  15024 // Italic Greek capital letters.  AMS defines these with \DeclareMathSymbol,
  15025 // but they are equivalent to \mathit{\Letter}.
  15026 
  15027 defineMacro("\\varGamma", "\\mathit{\\Gamma}");
  15028 defineMacro("\\varDelta", "\\mathit{\\Delta}");
  15029 defineMacro("\\varTheta", "\\mathit{\\Theta}");
  15030 defineMacro("\\varLambda", "\\mathit{\\Lambda}");
  15031 defineMacro("\\varXi", "\\mathit{\\Xi}");
  15032 defineMacro("\\varPi", "\\mathit{\\Pi}");
  15033 defineMacro("\\varSigma", "\\mathit{\\Sigma}");
  15034 defineMacro("\\varUpsilon", "\\mathit{\\Upsilon}");
  15035 defineMacro("\\varPhi", "\\mathit{\\Phi}");
  15036 defineMacro("\\varPsi", "\\mathit{\\Psi}");
  15037 defineMacro("\\varOmega", "\\mathit{\\Omega}"); //\newcommand{\substack}[1]{\subarray{c}#1\endsubarray}
  15038 
  15039 defineMacro("\\substack", "\\begin{subarray}{c}#1\\end{subarray}"); // \renewcommand{\colon}{\nobreak\mskip2mu\mathpunct{}\nonscript
  15040 // \mkern-\thinmuskip{:}\mskip6muplus1mu\relax}
  15041 
  15042 defineMacro("\\colon", "\\nobreak\\mskip2mu\\mathpunct{}" + "\\mathchoice{\\mkern-3mu}{\\mkern-3mu}{}{}{:}\\mskip6mu"); // \newcommand{\boxed}[1]{\fbox{\m@th$\displaystyle#1$}}
  15043 
  15044 defineMacro("\\boxed", "\\fbox{$\\displaystyle{#1}$}"); // \def\iff{\DOTSB\;\Longleftrightarrow\;}
  15045 // \def\implies{\DOTSB\;\Longrightarrow\;}
  15046 // \def\impliedby{\DOTSB\;\Longleftarrow\;}
  15047 
  15048 defineMacro("\\iff", "\\DOTSB\\;\\Longleftrightarrow\\;");
  15049 defineMacro("\\implies", "\\DOTSB\\;\\Longrightarrow\\;");
  15050 defineMacro("\\impliedby", "\\DOTSB\\;\\Longleftarrow\\;"); // AMSMath's automatic \dots, based on \mdots@@ macro.
  15051 
  15052 var dotsByToken = {
  15053   ',': '\\dotsc',
  15054   '\\not': '\\dotsb',
  15055   // \keybin@ checks for the following:
  15056   '+': '\\dotsb',
  15057   '=': '\\dotsb',
  15058   '<': '\\dotsb',
  15059   '>': '\\dotsb',
  15060   '-': '\\dotsb',
  15061   '*': '\\dotsb',
  15062   ':': '\\dotsb',
  15063   // Symbols whose definition starts with \DOTSB:
  15064   '\\DOTSB': '\\dotsb',
  15065   '\\coprod': '\\dotsb',
  15066   '\\bigvee': '\\dotsb',
  15067   '\\bigwedge': '\\dotsb',
  15068   '\\biguplus': '\\dotsb',
  15069   '\\bigcap': '\\dotsb',
  15070   '\\bigcup': '\\dotsb',
  15071   '\\prod': '\\dotsb',
  15072   '\\sum': '\\dotsb',
  15073   '\\bigotimes': '\\dotsb',
  15074   '\\bigoplus': '\\dotsb',
  15075   '\\bigodot': '\\dotsb',
  15076   '\\bigsqcup': '\\dotsb',
  15077   '\\And': '\\dotsb',
  15078   '\\longrightarrow': '\\dotsb',
  15079   '\\Longrightarrow': '\\dotsb',
  15080   '\\longleftarrow': '\\dotsb',
  15081   '\\Longleftarrow': '\\dotsb',
  15082   '\\longleftrightarrow': '\\dotsb',
  15083   '\\Longleftrightarrow': '\\dotsb',
  15084   '\\mapsto': '\\dotsb',
  15085   '\\longmapsto': '\\dotsb',
  15086   '\\hookrightarrow': '\\dotsb',
  15087   '\\doteq': '\\dotsb',
  15088   // Symbols whose definition starts with \mathbin:
  15089   '\\mathbin': '\\dotsb',
  15090   // Symbols whose definition starts with \mathrel:
  15091   '\\mathrel': '\\dotsb',
  15092   '\\relbar': '\\dotsb',
  15093   '\\Relbar': '\\dotsb',
  15094   '\\xrightarrow': '\\dotsb',
  15095   '\\xleftarrow': '\\dotsb',
  15096   // Symbols whose definition starts with \DOTSI:
  15097   '\\DOTSI': '\\dotsi',
  15098   '\\int': '\\dotsi',
  15099   '\\oint': '\\dotsi',
  15100   '\\iint': '\\dotsi',
  15101   '\\iiint': '\\dotsi',
  15102   '\\iiiint': '\\dotsi',
  15103   '\\idotsint': '\\dotsi',
  15104   // Symbols whose definition starts with \DOTSX:
  15105   '\\DOTSX': '\\dotsx'
  15106 };
  15107 defineMacro("\\dots", function (context) {
  15108   // TODO: If used in text mode, should expand to \textellipsis.
  15109   // However, in KaTeX, \textellipsis and \ldots behave the same
  15110   // (in text mode), and it's unlikely we'd see any of the math commands
  15111   // that affect the behavior of \dots when in text mode.  So fine for now
  15112   // (until we support \ifmmode ... \else ... \fi).
  15113   var thedots = '\\dotso';
  15114   var next = context.expandAfterFuture().text;
  15115 
  15116   if (next in dotsByToken) {
  15117     thedots = dotsByToken[next];
  15118   } else if (next.substr(0, 4) === '\\not') {
  15119     thedots = '\\dotsb';
  15120   } else if (next in symbols.math) {
  15121     if (utils.contains(['bin', 'rel'], symbols.math[next].group)) {
  15122       thedots = '\\dotsb';
  15123     }
  15124   }
  15125 
  15126   return thedots;
  15127 });
  15128 var spaceAfterDots = {
  15129   // \rightdelim@ checks for the following:
  15130   ')': true,
  15131   ']': true,
  15132   '\\rbrack': true,
  15133   '\\}': true,
  15134   '\\rbrace': true,
  15135   '\\rangle': true,
  15136   '\\rceil': true,
  15137   '\\rfloor': true,
  15138   '\\rgroup': true,
  15139   '\\rmoustache': true,
  15140   '\\right': true,
  15141   '\\bigr': true,
  15142   '\\biggr': true,
  15143   '\\Bigr': true,
  15144   '\\Biggr': true,
  15145   // \extra@ also tests for the following:
  15146   '$': true,
  15147   // \extrap@ checks for the following:
  15148   ';': true,
  15149   '.': true,
  15150   ',': true
  15151 };
  15152 defineMacro("\\dotso", function (context) {
  15153   var next = context.future().text;
  15154 
  15155   if (next in spaceAfterDots) {
  15156     return "\\ldots\\,";
  15157   } else {
  15158     return "\\ldots";
  15159   }
  15160 });
  15161 defineMacro("\\dotsc", function (context) {
  15162   var next = context.future().text; // \dotsc uses \extra@ but not \extrap@, instead specially checking for
  15163   // ';' and '.', but doesn't check for ','.
  15164 
  15165   if (next in spaceAfterDots && next !== ',') {
  15166     return "\\ldots\\,";
  15167   } else {
  15168     return "\\ldots";
  15169   }
  15170 });
  15171 defineMacro("\\cdots", function (context) {
  15172   var next = context.future().text;
  15173 
  15174   if (next in spaceAfterDots) {
  15175     return "\\@cdots\\,";
  15176   } else {
  15177     return "\\@cdots";
  15178   }
  15179 });
  15180 defineMacro("\\dotsb", "\\cdots");
  15181 defineMacro("\\dotsm", "\\cdots");
  15182 defineMacro("\\dotsi", "\\!\\cdots"); // amsmath doesn't actually define \dotsx, but \dots followed by a macro
  15183 // starting with \DOTSX implies \dotso, and then \extra@ detects this case
  15184 // and forces the added `\,`.
  15185 
  15186 defineMacro("\\dotsx", "\\ldots\\,"); // \let\DOTSI\relax
  15187 // \let\DOTSB\relax
  15188 // \let\DOTSX\relax
  15189 
  15190 defineMacro("\\DOTSI", "\\relax");
  15191 defineMacro("\\DOTSB", "\\relax");
  15192 defineMacro("\\DOTSX", "\\relax"); // Spacing, based on amsmath.sty's override of LaTeX defaults
  15193 // \DeclareRobustCommand{\tmspace}[3]{%
  15194 //   \ifmmode\mskip#1#2\else\kern#1#3\fi\relax}
  15195 
  15196 defineMacro("\\tmspace", "\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"); // \renewcommand{\,}{\tmspace+\thinmuskip{.1667em}}
  15197 // TODO: math mode should use \thinmuskip
  15198 
  15199 defineMacro("\\,", "\\tmspace+{3mu}{.1667em}"); // \let\thinspace\,
  15200 
  15201 defineMacro("\\thinspace", "\\,"); // \def\>{\mskip\medmuskip}
  15202 // \renewcommand{\:}{\tmspace+\medmuskip{.2222em}}
  15203 // TODO: \> and math mode of \: should use \medmuskip = 4mu plus 2mu minus 4mu
  15204 
  15205 defineMacro("\\>", "\\mskip{4mu}");
  15206 defineMacro("\\:", "\\tmspace+{4mu}{.2222em}"); // \let\medspace\:
  15207 
  15208 defineMacro("\\medspace", "\\:"); // \renewcommand{\;}{\tmspace+\thickmuskip{.2777em}}
  15209 // TODO: math mode should use \thickmuskip = 5mu plus 5mu
  15210 
  15211 defineMacro("\\;", "\\tmspace+{5mu}{.2777em}"); // \let\thickspace\;
  15212 
  15213 defineMacro("\\thickspace", "\\;"); // \renewcommand{\!}{\tmspace-\thinmuskip{.1667em}}
  15214 // TODO: math mode should use \thinmuskip
  15215 
  15216 defineMacro("\\!", "\\tmspace-{3mu}{.1667em}"); // \let\negthinspace\!
  15217 
  15218 defineMacro("\\negthinspace", "\\!"); // \newcommand{\negmedspace}{\tmspace-\medmuskip{.2222em}}
  15219 // TODO: math mode should use \medmuskip
  15220 
  15221 defineMacro("\\negmedspace", "\\tmspace-{4mu}{.2222em}"); // \newcommand{\negthickspace}{\tmspace-\thickmuskip{.2777em}}
  15222 // TODO: math mode should use \thickmuskip
  15223 
  15224 defineMacro("\\negthickspace", "\\tmspace-{5mu}{.277em}"); // \def\enspace{\kern.5em }
  15225 
  15226 defineMacro("\\enspace", "\\kern.5em "); // \def\enskip{\hskip.5em\relax}
  15227 
  15228 defineMacro("\\enskip", "\\hskip.5em\\relax"); // \def\quad{\hskip1em\relax}
  15229 
  15230 defineMacro("\\quad", "\\hskip1em\\relax"); // \def\qquad{\hskip2em\relax}
  15231 
  15232 defineMacro("\\qquad", "\\hskip2em\\relax"); // \tag@in@display form of \tag
  15233 
  15234 defineMacro("\\tag", "\\@ifstar\\tag@literal\\tag@paren");
  15235 defineMacro("\\tag@paren", "\\tag@literal{({#1})}");
  15236 defineMacro("\\tag@literal", context => {
  15237   if (context.macros.get("\\df@tag")) {
  15238     throw new ParseError("Multiple \\tag");
  15239   }
  15240 
  15241   return "\\gdef\\df@tag{\\text{#1}}";
  15242 }); // \renewcommand{\bmod}{\nonscript\mskip-\medmuskip\mkern5mu\mathbin
  15243 //   {\operator@font mod}\penalty900
  15244 //   \mkern5mu\nonscript\mskip-\medmuskip}
  15245 // \newcommand{\pod}[1]{\allowbreak
  15246 //   \if@display\mkern18mu\else\mkern8mu\fi(#1)}
  15247 // \renewcommand{\pmod}[1]{\pod{{\operator@font mod}\mkern6mu#1}}
  15248 // \newcommand{\mod}[1]{\allowbreak\if@display\mkern18mu
  15249 //   \else\mkern12mu\fi{\operator@font mod}\,\,#1}
  15250 // TODO: math mode should use \medmuskip = 4mu plus 2mu minus 4mu
  15251 
  15252 defineMacro("\\bmod", "\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}" + "\\mathbin{\\rm mod}" + "\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}");
  15253 defineMacro("\\pod", "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)");
  15254 defineMacro("\\pmod", "\\pod{{\\rm mod}\\mkern6mu#1}");
  15255 defineMacro("\\mod", "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}" + "{\\rm mod}\\,\\,#1"); // \pmb    --   A simulation of bold.
  15256 // The version in ambsy.sty works by typesetting three copies of the argument
  15257 // with small offsets. We use two copies. We omit the vertical offset because
  15258 // of rendering problems that makeVList encounters in Safari.
  15259 
  15260 defineMacro("\\pmb", "\\html@mathml{" + "\\@binrel{#1}{\\mathrlap{#1}\\kern0.5px#1}}" + "{\\mathbf{#1}}"); //////////////////////////////////////////////////////////////////////
  15261 // LaTeX source2e
  15262 // \expandafter\let\expandafter\@normalcr
  15263 //     \csname\expandafter\@gobble\string\\ \endcsname
  15264 // \DeclareRobustCommand\newline{\@normalcr\relax}
  15265 
  15266 defineMacro("\\newline", "\\\\\\relax"); // \def\TeX{T\kern-.1667em\lower.5ex\hbox{E}\kern-.125emX\@}
  15267 // TODO: Doesn't normally work in math mode because \@ fails.  KaTeX doesn't
  15268 // support \@ yet, so that's omitted, and we add \text so that the result
  15269 // doesn't look funny in math mode.
  15270 
  15271 defineMacro("\\TeX", "\\textrm{\\html@mathml{" + "T\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125emX" + "}{TeX}}"); // \DeclareRobustCommand{\LaTeX}{L\kern-.36em%
  15272 //         {\sbox\z@ T%
  15273 //          \vbox to\ht\z@{\hbox{\check@mathfonts
  15274 //                               \fontsize\sf@size\z@
  15275 //                               \math@fontsfalse\selectfont
  15276 //                               A}%
  15277 //                         \vss}%
  15278 //         }%
  15279 //         \kern-.15em%
  15280 //         \TeX}
  15281 // This code aligns the top of the A with the T (from the perspective of TeX's
  15282 // boxes, though visually the A appears to extend above slightly).
  15283 // We compute the corresponding \raisebox when A is rendered in \normalsize
  15284 // \scriptstyle, which has a scale factor of 0.7 (see Options.js).
  15285 
  15286 var latexRaiseA = fontMetricsData['Main-Regular']["T".charCodeAt(0)][1] - 0.7 * fontMetricsData['Main-Regular']["A".charCodeAt(0)][1] + "em";
  15287 defineMacro("\\LaTeX", "\\textrm{\\html@mathml{" + ("L\\kern-.36em\\raisebox{" + latexRaiseA + "}{\\scriptstyle A}") + "\\kern-.15em\\TeX}{LaTeX}}"); // New KaTeX logo based on tweaking LaTeX logo
  15288 
  15289 defineMacro("\\KaTeX", "\\textrm{\\html@mathml{" + ("K\\kern-.17em\\raisebox{" + latexRaiseA + "}{\\scriptstyle A}") + "\\kern-.15em\\TeX}{KaTeX}}"); // \DeclareRobustCommand\hspace{\@ifstar\@hspacer\@hspace}
  15290 // \def\@hspace#1{\hskip  #1\relax}
  15291 // \def\@hspacer#1{\vrule \@width\z@\nobreak
  15292 //                 \hskip #1\hskip \z@skip}
  15293 
  15294 defineMacro("\\hspace", "\\@ifstar\\@hspacer\\@hspace");
  15295 defineMacro("\\@hspace", "\\hskip #1\\relax");
  15296 defineMacro("\\@hspacer", "\\rule{0pt}{0pt}\\hskip #1\\relax"); //////////////////////////////////////////////////////////////////////
  15297 // mathtools.sty
  15298 //\providecommand\ordinarycolon{:}
  15299 
  15300 defineMacro("\\ordinarycolon", ":"); //\def\vcentcolon{\mathrel{\mathop\ordinarycolon}}
  15301 //TODO(edemaine): Not yet centered. Fix via \raisebox or #726
  15302 
  15303 defineMacro("\\vcentcolon", "\\mathrel{\\mathop\\ordinarycolon}"); // \providecommand*\dblcolon{\vcentcolon\mathrel{\mkern-.9mu}\vcentcolon}
  15304 
  15305 defineMacro("\\dblcolon", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-.9mu}\\vcentcolon}}" + "{\\mathop{\\char\"2237}}"); // \providecommand*\coloneqq{\vcentcolon\mathrel{\mkern-1.2mu}=}
  15306 
  15307 defineMacro("\\coloneqq", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}=}}" + "{\\mathop{\\char\"2254}}"); // ≔
  15308 // \providecommand*\Coloneqq{\dblcolon\mathrel{\mkern-1.2mu}=}
  15309 
  15310 defineMacro("\\Coloneqq", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}=}}" + "{\\mathop{\\char\"2237\\char\"3d}}"); // \providecommand*\coloneq{\vcentcolon\mathrel{\mkern-1.2mu}\mathrel{-}}
  15311 
  15312 defineMacro("\\coloneq", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}" + "{\\mathop{\\char\"3a\\char\"2212}}"); // \providecommand*\Coloneq{\dblcolon\mathrel{\mkern-1.2mu}\mathrel{-}}
  15313 
  15314 defineMacro("\\Coloneq", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}" + "{\\mathop{\\char\"2237\\char\"2212}}"); // \providecommand*\eqqcolon{=\mathrel{\mkern-1.2mu}\vcentcolon}
  15315 
  15316 defineMacro("\\eqqcolon", "\\html@mathml{" + "\\mathrel{=\\mathrel{\\mkern-1.2mu}\\vcentcolon}}" + "{\\mathop{\\char\"2255}}"); // ≕
  15317 // \providecommand*\Eqqcolon{=\mathrel{\mkern-1.2mu}\dblcolon}
  15318 
  15319 defineMacro("\\Eqqcolon", "\\html@mathml{" + "\\mathrel{=\\mathrel{\\mkern-1.2mu}\\dblcolon}}" + "{\\mathop{\\char\"3d\\char\"2237}}"); // \providecommand*\eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\vcentcolon}
  15320 
  15321 defineMacro("\\eqcolon", "\\html@mathml{" + "\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\vcentcolon}}" + "{\\mathop{\\char\"2239}}"); // \providecommand*\Eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\dblcolon}
  15322 
  15323 defineMacro("\\Eqcolon", "\\html@mathml{" + "\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\dblcolon}}" + "{\\mathop{\\char\"2212\\char\"2237}}"); // \providecommand*\colonapprox{\vcentcolon\mathrel{\mkern-1.2mu}\approx}
  15324 
  15325 defineMacro("\\colonapprox", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\approx}}" + "{\\mathop{\\char\"3a\\char\"2248}}"); // \providecommand*\Colonapprox{\dblcolon\mathrel{\mkern-1.2mu}\approx}
  15326 
  15327 defineMacro("\\Colonapprox", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\approx}}" + "{\\mathop{\\char\"2237\\char\"2248}}"); // \providecommand*\colonsim{\vcentcolon\mathrel{\mkern-1.2mu}\sim}
  15328 
  15329 defineMacro("\\colonsim", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\sim}}" + "{\\mathop{\\char\"3a\\char\"223c}}"); // \providecommand*\Colonsim{\dblcolon\mathrel{\mkern-1.2mu}\sim}
  15330 
  15331 defineMacro("\\Colonsim", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\sim}}" + "{\\mathop{\\char\"2237\\char\"223c}}"); // Some Unicode characters are implemented with macros to mathtools functions.
  15332 
  15333 defineMacro("\u2237", "\\dblcolon"); // ::
  15334 
  15335 defineMacro("\u2239", "\\eqcolon"); // -:
  15336 
  15337 defineMacro("\u2254", "\\coloneqq"); // :=
  15338 
  15339 defineMacro("\u2255", "\\eqqcolon"); // =:
  15340 
  15341 defineMacro("\u2A74", "\\Coloneqq"); // ::=
  15342 //////////////////////////////////////////////////////////////////////
  15343 // colonequals.sty
  15344 // Alternate names for mathtools's macros:
  15345 
  15346 defineMacro("\\ratio", "\\vcentcolon");
  15347 defineMacro("\\coloncolon", "\\dblcolon");
  15348 defineMacro("\\colonequals", "\\coloneqq");
  15349 defineMacro("\\coloncolonequals", "\\Coloneqq");
  15350 defineMacro("\\equalscolon", "\\eqqcolon");
  15351 defineMacro("\\equalscoloncolon", "\\Eqqcolon");
  15352 defineMacro("\\colonminus", "\\coloneq");
  15353 defineMacro("\\coloncolonminus", "\\Coloneq");
  15354 defineMacro("\\minuscolon", "\\eqcolon");
  15355 defineMacro("\\minuscoloncolon", "\\Eqcolon"); // \colonapprox name is same in mathtools and colonequals.
  15356 
  15357 defineMacro("\\coloncolonapprox", "\\Colonapprox"); // \colonsim name is same in mathtools and colonequals.
  15358 
  15359 defineMacro("\\coloncolonsim", "\\Colonsim"); // Additional macros, implemented by analogy with mathtools definitions:
  15360 
  15361 defineMacro("\\simcolon", "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\vcentcolon}");
  15362 defineMacro("\\simcoloncolon", "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\dblcolon}");
  15363 defineMacro("\\approxcolon", "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\vcentcolon}");
  15364 defineMacro("\\approxcoloncolon", "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\dblcolon}"); // Present in newtxmath, pxfonts and txfonts
  15365 
  15366 defineMacro("\\notni", "\\html@mathml{\\not\\ni}{\\mathrel{\\char`\u220C}}");
  15367 defineMacro("\\limsup", "\\DOTSB\\operatorname*{lim\\,sup}");
  15368 defineMacro("\\liminf", "\\DOTSB\\operatorname*{lim\\,inf}"); //////////////////////////////////////////////////////////////////////
  15369 // From amsopn.sty
  15370 
  15371 defineMacro("\\injlim", "\\DOTSB\\operatorname*{inj\\,lim}");
  15372 defineMacro("\\projlim", "\\DOTSB\\operatorname*{proj\\,lim}");
  15373 defineMacro("\\varlimsup", "\\DOTSB\\operatorname*{\\overline{lim}}");
  15374 defineMacro("\\varliminf", "\\DOTSB\\operatorname*{\\underline{lim}}");
  15375 defineMacro("\\varinjlim", "\\DOTSB\\operatorname*{\\underrightarrow{lim}}");
  15376 defineMacro("\\varprojlim", "\\DOTSB\\operatorname*{\\underleftarrow{lim}}"); //////////////////////////////////////////////////////////////////////
  15377 // MathML alternates for KaTeX glyphs in the Unicode private area
  15378 
  15379 defineMacro("\\gvertneqq", "\\html@mathml{\\@gvertneqq}{\u2269}");
  15380 defineMacro("\\lvertneqq", "\\html@mathml{\\@lvertneqq}{\u2268}");
  15381 defineMacro("\\ngeqq", "\\html@mathml{\\@ngeqq}{\u2271}");
  15382 defineMacro("\\ngeqslant", "\\html@mathml{\\@ngeqslant}{\u2271}");
  15383 defineMacro("\\nleqq", "\\html@mathml{\\@nleqq}{\u2270}");
  15384 defineMacro("\\nleqslant", "\\html@mathml{\\@nleqslant}{\u2270}");
  15385 defineMacro("\\nshortmid", "\\html@mathml{\\@nshortmid}{∤}");
  15386 defineMacro("\\nshortparallel", "\\html@mathml{\\@nshortparallel}{∦}");
  15387 defineMacro("\\nsubseteqq", "\\html@mathml{\\@nsubseteqq}{\u2288}");
  15388 defineMacro("\\nsupseteqq", "\\html@mathml{\\@nsupseteqq}{\u2289}");
  15389 defineMacro("\\varsubsetneq", "\\html@mathml{\\@varsubsetneq}{⊊}");
  15390 defineMacro("\\varsubsetneqq", "\\html@mathml{\\@varsubsetneqq}{⫋}");
  15391 defineMacro("\\varsupsetneq", "\\html@mathml{\\@varsupsetneq}{⊋}");
  15392 defineMacro("\\varsupsetneqq", "\\html@mathml{\\@varsupsetneqq}{⫌}");
  15393 defineMacro("\\imath", "\\html@mathml{\\@imath}{\u0131}");
  15394 defineMacro("\\jmath", "\\html@mathml{\\@jmath}{\u0237}"); //////////////////////////////////////////////////////////////////////
  15395 // stmaryrd and semantic
  15396 // The stmaryrd and semantic packages render the next four items by calling a
  15397 // glyph. Those glyphs do not exist in the KaTeX fonts. Hence the macros.
  15398 
  15399 defineMacro("\\llbracket", "\\html@mathml{" + "\\mathopen{[\\mkern-3.2mu[}}" + "{\\mathopen{\\char`\u27e6}}");
  15400 defineMacro("\\rrbracket", "\\html@mathml{" + "\\mathclose{]\\mkern-3.2mu]}}" + "{\\mathclose{\\char`\u27e7}}");
  15401 defineMacro("\u27e6", "\\llbracket"); // blackboard bold [
  15402 
  15403 defineMacro("\u27e7", "\\rrbracket"); // blackboard bold ]
  15404 
  15405 defineMacro("\\lBrace", "\\html@mathml{" + "\\mathopen{\\{\\mkern-3.2mu[}}" + "{\\mathopen{\\char`\u2983}}");
  15406 defineMacro("\\rBrace", "\\html@mathml{" + "\\mathclose{]\\mkern-3.2mu\\}}}" + "{\\mathclose{\\char`\u2984}}");
  15407 defineMacro("\u2983", "\\lBrace"); // blackboard bold {
  15408 
  15409 defineMacro("\u2984", "\\rBrace"); // blackboard bold }
  15410 // TODO: Create variable sized versions of the last two items. I believe that
  15411 // will require new font glyphs.
  15412 // The stmaryrd function `\minuso` provides a "Plimsoll" symbol that
  15413 // superimposes the characters \circ and \mathminus. Used in chemistry.
  15414 
  15415 defineMacro("\\minuso", "\\mathbin{\\html@mathml{" + "{\\mathrlap{\\mathchoice{\\kern{0.145em}}{\\kern{0.145em}}" + "{\\kern{0.1015em}}{\\kern{0.0725em}}\\circ}{-}}}" + "{\\char`⦵}}");
  15416 defineMacro("⦵", "\\minuso"); //////////////////////////////////////////////////////////////////////
  15417 // texvc.sty
  15418 // The texvc package contains macros available in mediawiki pages.
  15419 // We omit the functions deprecated at
  15420 // https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax
  15421 // We also omit texvc's \O, which conflicts with \text{\O}
  15422 
  15423 defineMacro("\\darr", "\\downarrow");
  15424 defineMacro("\\dArr", "\\Downarrow");
  15425 defineMacro("\\Darr", "\\Downarrow");
  15426 defineMacro("\\lang", "\\langle");
  15427 defineMacro("\\rang", "\\rangle");
  15428 defineMacro("\\uarr", "\\uparrow");
  15429 defineMacro("\\uArr", "\\Uparrow");
  15430 defineMacro("\\Uarr", "\\Uparrow");
  15431 defineMacro("\\N", "\\mathbb{N}");
  15432 defineMacro("\\R", "\\mathbb{R}");
  15433 defineMacro("\\Z", "\\mathbb{Z}");
  15434 defineMacro("\\alef", "\\aleph");
  15435 defineMacro("\\alefsym", "\\aleph");
  15436 defineMacro("\\Alpha", "\\mathrm{A}");
  15437 defineMacro("\\Beta", "\\mathrm{B}");
  15438 defineMacro("\\bull", "\\bullet");
  15439 defineMacro("\\Chi", "\\mathrm{X}");
  15440 defineMacro("\\clubs", "\\clubsuit");
  15441 defineMacro("\\cnums", "\\mathbb{C}");
  15442 defineMacro("\\Complex", "\\mathbb{C}");
  15443 defineMacro("\\Dagger", "\\ddagger");
  15444 defineMacro("\\diamonds", "\\diamondsuit");
  15445 defineMacro("\\empty", "\\emptyset");
  15446 defineMacro("\\Epsilon", "\\mathrm{E}");
  15447 defineMacro("\\Eta", "\\mathrm{H}");
  15448 defineMacro("\\exist", "\\exists");
  15449 defineMacro("\\harr", "\\leftrightarrow");
  15450 defineMacro("\\hArr", "\\Leftrightarrow");
  15451 defineMacro("\\Harr", "\\Leftrightarrow");
  15452 defineMacro("\\hearts", "\\heartsuit");
  15453 defineMacro("\\image", "\\Im");
  15454 defineMacro("\\infin", "\\infty");
  15455 defineMacro("\\Iota", "\\mathrm{I}");
  15456 defineMacro("\\isin", "\\in");
  15457 defineMacro("\\Kappa", "\\mathrm{K}");
  15458 defineMacro("\\larr", "\\leftarrow");
  15459 defineMacro("\\lArr", "\\Leftarrow");
  15460 defineMacro("\\Larr", "\\Leftarrow");
  15461 defineMacro("\\lrarr", "\\leftrightarrow");
  15462 defineMacro("\\lrArr", "\\Leftrightarrow");
  15463 defineMacro("\\Lrarr", "\\Leftrightarrow");
  15464 defineMacro("\\Mu", "\\mathrm{M}");
  15465 defineMacro("\\natnums", "\\mathbb{N}");
  15466 defineMacro("\\Nu", "\\mathrm{N}");
  15467 defineMacro("\\Omicron", "\\mathrm{O}");
  15468 defineMacro("\\plusmn", "\\pm");
  15469 defineMacro("\\rarr", "\\rightarrow");
  15470 defineMacro("\\rArr", "\\Rightarrow");
  15471 defineMacro("\\Rarr", "\\Rightarrow");
  15472 defineMacro("\\real", "\\Re");
  15473 defineMacro("\\reals", "\\mathbb{R}");
  15474 defineMacro("\\Reals", "\\mathbb{R}");
  15475 defineMacro("\\Rho", "\\mathrm{P}");
  15476 defineMacro("\\sdot", "\\cdot");
  15477 defineMacro("\\sect", "\\S");
  15478 defineMacro("\\spades", "\\spadesuit");
  15479 defineMacro("\\sub", "\\subset");
  15480 defineMacro("\\sube", "\\subseteq");
  15481 defineMacro("\\supe", "\\supseteq");
  15482 defineMacro("\\Tau", "\\mathrm{T}");
  15483 defineMacro("\\thetasym", "\\vartheta"); // TODO: defineMacro("\\varcoppa", "\\\mbox{\\coppa}");
  15484 
  15485 defineMacro("\\weierp", "\\wp");
  15486 defineMacro("\\Zeta", "\\mathrm{Z}"); //////////////////////////////////////////////////////////////////////
  15487 // statmath.sty
  15488 // https://ctan.math.illinois.edu/macros/latex/contrib/statmath/statmath.pdf
  15489 
  15490 defineMacro("\\argmin", "\\DOTSB\\operatorname*{arg\\,min}");
  15491 defineMacro("\\argmax", "\\DOTSB\\operatorname*{arg\\,max}");
  15492 defineMacro("\\plim", "\\DOTSB\\mathop{\\operatorname{plim}}\\limits"); //////////////////////////////////////////////////////////////////////
  15493 // braket.sty
  15494 // http://ctan.math.washington.edu/tex-archive/macros/latex/contrib/braket/braket.pdf
  15495 
  15496 defineMacro("\\bra", "\\mathinner{\\langle{#1}|}");
  15497 defineMacro("\\ket", "\\mathinner{|{#1}\\rangle}");
  15498 defineMacro("\\braket", "\\mathinner{\\langle{#1}\\rangle}");
  15499 defineMacro("\\Bra", "\\left\\langle#1\\right|");
  15500 defineMacro("\\Ket", "\\left|#1\\right\\rangle"); //////////////////////////////////////////////////////////////////////
  15501 // actuarialangle.dtx
  15502 
  15503 defineMacro("\\angln", "{\\angl n}"); // Custom Khan Academy colors, should be moved to an optional package
  15504 
  15505 defineMacro("\\blue", "\\textcolor{##6495ed}{#1}");
  15506 defineMacro("\\orange", "\\textcolor{##ffa500}{#1}");
  15507 defineMacro("\\pink", "\\textcolor{##ff00af}{#1}");
  15508 defineMacro("\\red", "\\textcolor{##df0030}{#1}");
  15509 defineMacro("\\green", "\\textcolor{##28ae7b}{#1}");
  15510 defineMacro("\\gray", "\\textcolor{gray}{#1}");
  15511 defineMacro("\\purple", "\\textcolor{##9d38bd}{#1}");
  15512 defineMacro("\\blueA", "\\textcolor{##ccfaff}{#1}");
  15513 defineMacro("\\blueB", "\\textcolor{##80f6ff}{#1}");
  15514 defineMacro("\\blueC", "\\textcolor{##63d9ea}{#1}");
  15515 defineMacro("\\blueD", "\\textcolor{##11accd}{#1}");
  15516 defineMacro("\\blueE", "\\textcolor{##0c7f99}{#1}");
  15517 defineMacro("\\tealA", "\\textcolor{##94fff5}{#1}");
  15518 defineMacro("\\tealB", "\\textcolor{##26edd5}{#1}");
  15519 defineMacro("\\tealC", "\\textcolor{##01d1c1}{#1}");
  15520 defineMacro("\\tealD", "\\textcolor{##01a995}{#1}");
  15521 defineMacro("\\tealE", "\\textcolor{##208170}{#1}");
  15522 defineMacro("\\greenA", "\\textcolor{##b6ffb0}{#1}");
  15523 defineMacro("\\greenB", "\\textcolor{##8af281}{#1}");
  15524 defineMacro("\\greenC", "\\textcolor{##74cf70}{#1}");
  15525 defineMacro("\\greenD", "\\textcolor{##1fab54}{#1}");
  15526 defineMacro("\\greenE", "\\textcolor{##0d923f}{#1}");
  15527 defineMacro("\\goldA", "\\textcolor{##ffd0a9}{#1}");
  15528 defineMacro("\\goldB", "\\textcolor{##ffbb71}{#1}");
  15529 defineMacro("\\goldC", "\\textcolor{##ff9c39}{#1}");
  15530 defineMacro("\\goldD", "\\textcolor{##e07d10}{#1}");
  15531 defineMacro("\\goldE", "\\textcolor{##a75a05}{#1}");
  15532 defineMacro("\\redA", "\\textcolor{##fca9a9}{#1}");
  15533 defineMacro("\\redB", "\\textcolor{##ff8482}{#1}");
  15534 defineMacro("\\redC", "\\textcolor{##f9685d}{#1}");
  15535 defineMacro("\\redD", "\\textcolor{##e84d39}{#1}");
  15536 defineMacro("\\redE", "\\textcolor{##bc2612}{#1}");
  15537 defineMacro("\\maroonA", "\\textcolor{##ffbde0}{#1}");
  15538 defineMacro("\\maroonB", "\\textcolor{##ff92c6}{#1}");
  15539 defineMacro("\\maroonC", "\\textcolor{##ed5fa6}{#1}");
  15540 defineMacro("\\maroonD", "\\textcolor{##ca337c}{#1}");
  15541 defineMacro("\\maroonE", "\\textcolor{##9e034e}{#1}");
  15542 defineMacro("\\purpleA", "\\textcolor{##ddd7ff}{#1}");
  15543 defineMacro("\\purpleB", "\\textcolor{##c6b9fc}{#1}");
  15544 defineMacro("\\purpleC", "\\textcolor{##aa87ff}{#1}");
  15545 defineMacro("\\purpleD", "\\textcolor{##7854ab}{#1}");
  15546 defineMacro("\\purpleE", "\\textcolor{##543b78}{#1}");
  15547 defineMacro("\\mintA", "\\textcolor{##f5f9e8}{#1}");
  15548 defineMacro("\\mintB", "\\textcolor{##edf2df}{#1}");
  15549 defineMacro("\\mintC", "\\textcolor{##e0e5cc}{#1}");
  15550 defineMacro("\\grayA", "\\textcolor{##f6f7f7}{#1}");
  15551 defineMacro("\\grayB", "\\textcolor{##f0f1f2}{#1}");
  15552 defineMacro("\\grayC", "\\textcolor{##e3e5e6}{#1}");
  15553 defineMacro("\\grayD", "\\textcolor{##d6d8da}{#1}");
  15554 defineMacro("\\grayE", "\\textcolor{##babec2}{#1}");
  15555 defineMacro("\\grayF", "\\textcolor{##888d93}{#1}");
  15556 defineMacro("\\grayG", "\\textcolor{##626569}{#1}");
  15557 defineMacro("\\grayH", "\\textcolor{##3b3e40}{#1}");
  15558 defineMacro("\\grayI", "\\textcolor{##21242c}{#1}");
  15559 defineMacro("\\kaBlue", "\\textcolor{##314453}{#1}");
  15560 defineMacro("\\kaGreen", "\\textcolor{##71B307}{#1}");
  15561 
  15562 /**
  15563  * This file contains the “gullet” where macros are expanded
  15564  * until only non-macro tokens remain.
  15565  */
  15566 // List of commands that act like macros but aren't defined as a macro,
  15567 // function, or symbol.  Used in `isDefined`.
  15568 var implicitCommands = {
  15569   "\\relax": true,
  15570   // MacroExpander.js
  15571   "^": true,
  15572   // Parser.js
  15573   "_": true,
  15574   // Parser.js
  15575   "\\limits": true,
  15576   // Parser.js
  15577   "\\nolimits": true // Parser.js
  15578 
  15579 };
  15580 class MacroExpander {
  15581   constructor(input, settings, mode) {
  15582     this.settings = void 0;
  15583     this.expansionCount = void 0;
  15584     this.lexer = void 0;
  15585     this.macros = void 0;
  15586     this.stack = void 0;
  15587     this.mode = void 0;
  15588     this.settings = settings;
  15589     this.expansionCount = 0;
  15590     this.feed(input); // Make new global namespace
  15591 
  15592     this.macros = new Namespace(builtinMacros, settings.macros);
  15593     this.mode = mode;
  15594     this.stack = []; // contains tokens in REVERSE order
  15595   }
  15596   /**
  15597    * Feed a new input string to the same MacroExpander
  15598    * (with existing macros etc.).
  15599    */
  15600 
  15601 
  15602   feed(input) {
  15603     this.lexer = new Lexer(input, this.settings);
  15604   }
  15605   /**
  15606    * Switches between "text" and "math" modes.
  15607    */
  15608 
  15609 
  15610   switchMode(newMode) {
  15611     this.mode = newMode;
  15612   }
  15613   /**
  15614    * Start a new group nesting within all namespaces.
  15615    */
  15616 
  15617 
  15618   beginGroup() {
  15619     this.macros.beginGroup();
  15620   }
  15621   /**
  15622    * End current group nesting within all namespaces.
  15623    */
  15624 
  15625 
  15626   endGroup() {
  15627     this.macros.endGroup();
  15628   }
  15629   /**
  15630    * Returns the topmost token on the stack, without expanding it.
  15631    * Similar in behavior to TeX's `\futurelet`.
  15632    */
  15633 
  15634 
  15635   future() {
  15636     if (this.stack.length === 0) {
  15637       this.pushToken(this.lexer.lex());
  15638     }
  15639 
  15640     return this.stack[this.stack.length - 1];
  15641   }
  15642   /**
  15643    * Remove and return the next unexpanded token.
  15644    */
  15645 
  15646 
  15647   popToken() {
  15648     this.future(); // ensure non-empty stack
  15649 
  15650     return this.stack.pop();
  15651   }
  15652   /**
  15653    * Add a given token to the token stack.  In particular, this get be used
  15654    * to put back a token returned from one of the other methods.
  15655    */
  15656 
  15657 
  15658   pushToken(token) {
  15659     this.stack.push(token);
  15660   }
  15661   /**
  15662    * Append an array of tokens to the token stack.
  15663    */
  15664 
  15665 
  15666   pushTokens(tokens) {
  15667     this.stack.push(...tokens);
  15668   }
  15669   /**
  15670    * Find an macro argument without expanding tokens and append the array of
  15671    * tokens to the token stack. Uses Token as a container for the result.
  15672    */
  15673 
  15674 
  15675   scanArgument(isOptional) {
  15676     var start;
  15677     var end;
  15678     var tokens;
  15679 
  15680     if (isOptional) {
  15681       this.consumeSpaces(); // \@ifnextchar gobbles any space following it
  15682 
  15683       if (this.future().text !== "[") {
  15684         return null;
  15685       }
  15686 
  15687       start = this.popToken(); // don't include [ in tokens
  15688 
  15689       ({
  15690         tokens,
  15691         end
  15692       } = this.consumeArg(["]"]));
  15693     } else {
  15694       ({
  15695         tokens,
  15696         start,
  15697         end
  15698       } = this.consumeArg());
  15699     } // indicate the end of an argument
  15700 
  15701 
  15702     this.pushToken(new Token("EOF", end.loc));
  15703     this.pushTokens(tokens);
  15704     return start.range(end, "");
  15705   }
  15706   /**
  15707    * Consume all following space tokens, without expansion.
  15708    */
  15709 
  15710 
  15711   consumeSpaces() {
  15712     for (;;) {
  15713       var token = this.future();
  15714 
  15715       if (token.text === " ") {
  15716         this.stack.pop();
  15717       } else {
  15718         break;
  15719       }
  15720     }
  15721   }
  15722   /**
  15723    * Consume an argument from the token stream, and return the resulting array
  15724    * of tokens and start/end token.
  15725    */
  15726 
  15727 
  15728   consumeArg(delims) {
  15729     // The argument for a delimited parameter is the shortest (possibly
  15730     // empty) sequence of tokens with properly nested {...} groups that is
  15731     // followed ... by this particular list of non-parameter tokens.
  15732     // The argument for an undelimited parameter is the next nonblank
  15733     // token, unless that token is ‘{’, when the argument will be the
  15734     // entire {...} group that follows.
  15735     var tokens = [];
  15736     var isDelimited = delims && delims.length > 0;
  15737 
  15738     if (!isDelimited) {
  15739       // Ignore spaces between arguments.  As the TeXbook says:
  15740       // "After you have said ‘\def\row#1#2{...}’, you are allowed to
  15741       //  put spaces between the arguments (e.g., ‘\row x n’), because
  15742       //  TeX doesn’t use single spaces as undelimited arguments."
  15743       this.consumeSpaces();
  15744     }
  15745 
  15746     var start = this.future();
  15747     var tok;
  15748     var depth = 0;
  15749     var match = 0;
  15750 
  15751     do {
  15752       tok = this.popToken();
  15753       tokens.push(tok);
  15754 
  15755       if (tok.text === "{") {
  15756         ++depth;
  15757       } else if (tok.text === "}") {
  15758         --depth;
  15759 
  15760         if (depth === -1) {
  15761           throw new ParseError("Extra }", tok);
  15762         }
  15763       } else if (tok.text === "EOF") {
  15764         throw new ParseError("Unexpected end of input in a macro argument" + ", expected '" + (delims && isDelimited ? delims[match] : "}") + "'", tok);
  15765       }
  15766 
  15767       if (delims && isDelimited) {
  15768         if ((depth === 0 || depth === 1 && delims[match] === "{") && tok.text === delims[match]) {
  15769           ++match;
  15770 
  15771           if (match === delims.length) {
  15772             // don't include delims in tokens
  15773             tokens.splice(-match, match);
  15774             break;
  15775           }
  15776         } else {
  15777           match = 0;
  15778         }
  15779       }
  15780     } while (depth !== 0 || isDelimited); // If the argument found ... has the form ‘{<nested tokens>}’,
  15781     // ... the outermost braces enclosing the argument are removed
  15782 
  15783 
  15784     if (start.text === "{" && tokens[tokens.length - 1].text === "}") {
  15785       tokens.pop();
  15786       tokens.shift();
  15787     }
  15788 
  15789     tokens.reverse(); // to fit in with stack order
  15790 
  15791     return {
  15792       tokens,
  15793       start,
  15794       end: tok
  15795     };
  15796   }
  15797   /**
  15798    * Consume the specified number of (delimited) arguments from the token
  15799    * stream and return the resulting array of arguments.
  15800    */
  15801 
  15802 
  15803   consumeArgs(numArgs, delimiters) {
  15804     if (delimiters) {
  15805       if (delimiters.length !== numArgs + 1) {
  15806         throw new ParseError("The length of delimiters doesn't match the number of args!");
  15807       }
  15808 
  15809       var delims = delimiters[0];
  15810 
  15811       for (var i = 0; i < delims.length; i++) {
  15812         var tok = this.popToken();
  15813 
  15814         if (delims[i] !== tok.text) {
  15815           throw new ParseError("Use of the macro doesn't match its definition", tok);
  15816         }
  15817       }
  15818     }
  15819 
  15820     var args = [];
  15821 
  15822     for (var _i = 0; _i < numArgs; _i++) {
  15823       args.push(this.consumeArg(delimiters && delimiters[_i + 1]).tokens);
  15824     }
  15825 
  15826     return args;
  15827   }
  15828   /**
  15829    * Expand the next token only once if possible.
  15830    *
  15831    * If the token is expanded, the resulting tokens will be pushed onto
  15832    * the stack in reverse order and will be returned as an array,
  15833    * also in reverse order.
  15834    *
  15835    * If not, the next token will be returned without removing it
  15836    * from the stack.  This case can be detected by a `Token` return value
  15837    * instead of an `Array` return value.
  15838    *
  15839    * In either case, the next token will be on the top of the stack,
  15840    * or the stack will be empty.
  15841    *
  15842    * Used to implement `expandAfterFuture` and `expandNextToken`.
  15843    *
  15844    * If expandableOnly, only expandable tokens are expanded and
  15845    * an undefined control sequence results in an error.
  15846    */
  15847 
  15848 
  15849   expandOnce(expandableOnly) {
  15850     var topToken = this.popToken();
  15851     var name = topToken.text;
  15852     var expansion = !topToken.noexpand ? this._getExpansion(name) : null;
  15853 
  15854     if (expansion == null || expandableOnly && expansion.unexpandable) {
  15855       if (expandableOnly && expansion == null && name[0] === "\\" && !this.isDefined(name)) {
  15856         throw new ParseError("Undefined control sequence: " + name);
  15857       }
  15858 
  15859       this.pushToken(topToken);
  15860       return topToken;
  15861     }
  15862 
  15863     this.expansionCount++;
  15864 
  15865     if (this.expansionCount > this.settings.maxExpand) {
  15866       throw new ParseError("Too many expansions: infinite loop or " + "need to increase maxExpand setting");
  15867     }
  15868 
  15869     var tokens = expansion.tokens;
  15870     var args = this.consumeArgs(expansion.numArgs, expansion.delimiters);
  15871 
  15872     if (expansion.numArgs) {
  15873       // paste arguments in place of the placeholders
  15874       tokens = tokens.slice(); // make a shallow copy
  15875 
  15876       for (var i = tokens.length - 1; i >= 0; --i) {
  15877         var tok = tokens[i];
  15878 
  15879         if (tok.text === "#") {
  15880           if (i === 0) {
  15881             throw new ParseError("Incomplete placeholder at end of macro body", tok);
  15882           }
  15883 
  15884           tok = tokens[--i]; // next token on stack
  15885 
  15886           if (tok.text === "#") {
  15887             // ## → #
  15888             tokens.splice(i + 1, 1); // drop first #
  15889           } else if (/^[1-9]$/.test(tok.text)) {
  15890             // replace the placeholder with the indicated argument
  15891             tokens.splice(i, 2, ...args[+tok.text - 1]);
  15892           } else {
  15893             throw new ParseError("Not a valid argument number", tok);
  15894           }
  15895         }
  15896       }
  15897     } // Concatenate expansion onto top of stack.
  15898 
  15899 
  15900     this.pushTokens(tokens);
  15901     return tokens;
  15902   }
  15903   /**
  15904    * Expand the next token only once (if possible), and return the resulting
  15905    * top token on the stack (without removing anything from the stack).
  15906    * Similar in behavior to TeX's `\expandafter\futurelet`.
  15907    * Equivalent to expandOnce() followed by future().
  15908    */
  15909 
  15910 
  15911   expandAfterFuture() {
  15912     this.expandOnce();
  15913     return this.future();
  15914   }
  15915   /**
  15916    * Recursively expand first token, then return first non-expandable token.
  15917    */
  15918 
  15919 
  15920   expandNextToken() {
  15921     for (;;) {
  15922       var expanded = this.expandOnce(); // expandOnce returns Token if and only if it's fully expanded.
  15923 
  15924       if (expanded instanceof Token) {
  15925         // \relax stops the expansion, but shouldn't get returned (a
  15926         // null return value couldn't get implemented as a function).
  15927         // the token after \noexpand is interpreted as if its meaning
  15928         // were ‘\relax’
  15929         if (expanded.text === "\\relax" || expanded.treatAsRelax) {
  15930           this.stack.pop();
  15931         } else {
  15932           return this.stack.pop(); // === expanded
  15933         }
  15934       }
  15935     } // Flow unable to figure out that this pathway is impossible.
  15936     // https://github.com/facebook/flow/issues/4808
  15937 
  15938 
  15939     throw new Error(); // eslint-disable-line no-unreachable
  15940   }
  15941   /**
  15942    * Fully expand the given macro name and return the resulting list of
  15943    * tokens, or return `undefined` if no such macro is defined.
  15944    */
  15945 
  15946 
  15947   expandMacro(name) {
  15948     return this.macros.has(name) ? this.expandTokens([new Token(name)]) : undefined;
  15949   }
  15950   /**
  15951    * Fully expand the given token stream and return the resulting list of tokens
  15952    */
  15953 
  15954 
  15955   expandTokens(tokens) {
  15956     var output = [];
  15957     var oldStackLength = this.stack.length;
  15958     this.pushTokens(tokens);
  15959 
  15960     while (this.stack.length > oldStackLength) {
  15961       var expanded = this.expandOnce(true); // expand only expandable tokens
  15962       // expandOnce returns Token if and only if it's fully expanded.
  15963 
  15964       if (expanded instanceof Token) {
  15965         if (expanded.treatAsRelax) {
  15966           // the expansion of \noexpand is the token itself
  15967           expanded.noexpand = false;
  15968           expanded.treatAsRelax = false;
  15969         }
  15970 
  15971         output.push(this.stack.pop());
  15972       }
  15973     }
  15974 
  15975     return output;
  15976   }
  15977   /**
  15978    * Fully expand the given macro name and return the result as a string,
  15979    * or return `undefined` if no such macro is defined.
  15980    */
  15981 
  15982 
  15983   expandMacroAsText(name) {
  15984     var tokens = this.expandMacro(name);
  15985 
  15986     if (tokens) {
  15987       return tokens.map(token => token.text).join("");
  15988     } else {
  15989       return tokens;
  15990     }
  15991   }
  15992   /**
  15993    * Returns the expanded macro as a reversed array of tokens and a macro
  15994    * argument count.  Or returns `null` if no such macro.
  15995    */
  15996 
  15997 
  15998   _getExpansion(name) {
  15999     var definition = this.macros.get(name);
  16000 
  16001     if (definition == null) {
  16002       // mainly checking for undefined here
  16003       return definition;
  16004     }
  16005 
  16006     var expansion = typeof definition === "function" ? definition(this) : definition;
  16007 
  16008     if (typeof expansion === "string") {
  16009       var numArgs = 0;
  16010 
  16011       if (expansion.indexOf("#") !== -1) {
  16012         var stripped = expansion.replace(/##/g, "");
  16013 
  16014         while (stripped.indexOf("#" + (numArgs + 1)) !== -1) {
  16015           ++numArgs;
  16016         }
  16017       }
  16018 
  16019       var bodyLexer = new Lexer(expansion, this.settings);
  16020       var tokens = [];
  16021       var tok = bodyLexer.lex();
  16022 
  16023       while (tok.text !== "EOF") {
  16024         tokens.push(tok);
  16025         tok = bodyLexer.lex();
  16026       }
  16027 
  16028       tokens.reverse(); // to fit in with stack using push and pop
  16029 
  16030       var expanded = {
  16031         tokens,
  16032         numArgs
  16033       };
  16034       return expanded;
  16035     }
  16036 
  16037     return expansion;
  16038   }
  16039   /**
  16040    * Determine whether a command is currently "defined" (has some
  16041    * functionality), meaning that it's a macro (in the current group),
  16042    * a function, a symbol, or one of the special commands listed in
  16043    * `implicitCommands`.
  16044    */
  16045 
  16046 
  16047   isDefined(name) {
  16048     return this.macros.has(name) || functions.hasOwnProperty(name) || symbols.math.hasOwnProperty(name) || symbols.text.hasOwnProperty(name) || implicitCommands.hasOwnProperty(name);
  16049   }
  16050   /**
  16051    * Determine whether a command is expandable.
  16052    */
  16053 
  16054 
  16055   isExpandable(name) {
  16056     var macro = this.macros.get(name);
  16057     return macro != null ? typeof macro === "string" || typeof macro === "function" || !macro.unexpandable : functions.hasOwnProperty(name) && !functions[name].primitive;
  16058   }
  16059 
  16060 }
  16061 
  16062 /* eslint no-constant-condition:0 */
  16063 
  16064 var unicodeAccents = {
  16065   "́": {
  16066     "text": "\\'",
  16067     "math": "\\acute"
  16068   },
  16069   "̀": {
  16070     "text": "\\`",
  16071     "math": "\\grave"
  16072   },
  16073   "̈": {
  16074     "text": "\\\"",
  16075     "math": "\\ddot"
  16076   },
  16077   "̃": {
  16078     "text": "\\~",
  16079     "math": "\\tilde"
  16080   },
  16081   "̄": {
  16082     "text": "\\=",
  16083     "math": "\\bar"
  16084   },
  16085   "̆": {
  16086     "text": "\\u",
  16087     "math": "\\breve"
  16088   },
  16089   "̌": {
  16090     "text": "\\v",
  16091     "math": "\\check"
  16092   },
  16093   "̂": {
  16094     "text": "\\^",
  16095     "math": "\\hat"
  16096   },
  16097   "̇": {
  16098     "text": "\\.",
  16099     "math": "\\dot"
  16100   },
  16101   "̊": {
  16102     "text": "\\r",
  16103     "math": "\\mathring"
  16104   },
  16105   "̋": {
  16106     "text": "\\H"
  16107   }
  16108 };
  16109 var unicodeSymbols = {
  16110   "á": "á",
  16111   "à": "à",
  16112   "ä": "ä",
  16113   "ǟ": "ǟ",
  16114   "ã": "ã",
  16115   "ā": "ā",
  16116   "ă": "ă",
  16117   "ắ": "ắ",
  16118   "ằ": "ằ",
  16119   "ẵ": "ẵ",
  16120   "ǎ": "ǎ",
  16121   "â": "â",
  16122   "ấ": "ấ",
  16123   "ầ": "ầ",
  16124   "ẫ": "ẫ",
  16125   "ȧ": "ȧ",
  16126   "ǡ": "ǡ",
  16127   "å": "å",
  16128   "ǻ": "ǻ",
  16129   "ḃ": "ḃ",
  16130   "ć": "ć",
  16131   "č": "č",
  16132   "ĉ": "ĉ",
  16133   "ċ": "ċ",
  16134   "ď": "ď",
  16135   "ḋ": "ḋ",
  16136   "é": "é",
  16137   "è": "è",
  16138   "ë": "ë",
  16139   "ẽ": "ẽ",
  16140   "ē": "ē",
  16141   "ḗ": "ḗ",
  16142   "ḕ": "ḕ",
  16143   "ĕ": "ĕ",
  16144   "ě": "ě",
  16145   "ê": "ê",
  16146   "ế": "ế",
  16147   "ề": "ề",
  16148   "ễ": "ễ",
  16149   "ė": "ė",
  16150   "ḟ": "ḟ",
  16151   "ǵ": "ǵ",
  16152   "ḡ": "ḡ",
  16153   "ğ": "ğ",
  16154   "ǧ": "ǧ",
  16155   "ĝ": "ĝ",
  16156   "ġ": "ġ",
  16157   "ḧ": "ḧ",
  16158   "ȟ": "ȟ",
  16159   "ĥ": "ĥ",
  16160   "ḣ": "ḣ",
  16161   "í": "í",
  16162   "ì": "ì",
  16163   "ï": "ï",
  16164   "ḯ": "ḯ",
  16165   "ĩ": "ĩ",
  16166   "ī": "ī",
  16167   "ĭ": "ĭ",
  16168   "ǐ": "ǐ",
  16169   "î": "î",
  16170   "ǰ": "ǰ",
  16171   "ĵ": "ĵ",
  16172   "ḱ": "ḱ",
  16173   "ǩ": "ǩ",
  16174   "ĺ": "ĺ",
  16175   "ľ": "ľ",
  16176   "ḿ": "ḿ",
  16177   "ṁ": "ṁ",
  16178   "ń": "ń",
  16179   "ǹ": "ǹ",
  16180   "ñ": "ñ",
  16181   "ň": "ň",
  16182   "ṅ": "ṅ",
  16183   "ó": "ó",
  16184   "ò": "ò",
  16185   "ö": "ö",
  16186   "ȫ": "ȫ",
  16187   "õ": "õ",
  16188   "ṍ": "ṍ",
  16189   "ṏ": "ṏ",
  16190   "ȭ": "ȭ",
  16191   "ō": "ō",
  16192   "ṓ": "ṓ",
  16193   "ṑ": "ṑ",
  16194   "ŏ": "ŏ",
  16195   "ǒ": "ǒ",
  16196   "ô": "ô",
  16197   "ố": "ố",
  16198   "ồ": "ồ",
  16199   "ỗ": "ỗ",
  16200   "ȯ": "ȯ",
  16201   "ȱ": "ȱ",
  16202   "ő": "ő",
  16203   "ṕ": "ṕ",
  16204   "ṗ": "ṗ",
  16205   "ŕ": "ŕ",
  16206   "ř": "ř",
  16207   "ṙ": "ṙ",
  16208   "ś": "ś",
  16209   "ṥ": "ṥ",
  16210   "š": "š",
  16211   "ṧ": "ṧ",
  16212   "ŝ": "ŝ",
  16213   "ṡ": "ṡ",
  16214   "ẗ": "ẗ",
  16215   "ť": "ť",
  16216   "ṫ": "ṫ",
  16217   "ú": "ú",
  16218   "ù": "ù",
  16219   "ü": "ü",
  16220   "ǘ": "ǘ",
  16221   "ǜ": "ǜ",
  16222   "ǖ": "ǖ",
  16223   "ǚ": "ǚ",
  16224   "ũ": "ũ",
  16225   "ṹ": "ṹ",
  16226   "ū": "ū",
  16227   "ṻ": "ṻ",
  16228   "ŭ": "ŭ",
  16229   "ǔ": "ǔ",
  16230   "û": "û",
  16231   "ů": "ů",
  16232   "ű": "ű",
  16233   "ṽ": "ṽ",
  16234   "ẃ": "ẃ",
  16235   "ẁ": "ẁ",
  16236   "ẅ": "ẅ",
  16237   "ŵ": "ŵ",
  16238   "ẇ": "ẇ",
  16239   "ẘ": "ẘ",
  16240   "ẍ": "ẍ",
  16241   "ẋ": "ẋ",
  16242   "ý": "ý",
  16243   "ỳ": "ỳ",
  16244   "ÿ": "ÿ",
  16245   "ỹ": "ỹ",
  16246   "ȳ": "ȳ",
  16247   "ŷ": "ŷ",
  16248   "ẏ": "ẏ",
  16249   "ẙ": "ẙ",
  16250   "ź": "ź",
  16251   "ž": "ž",
  16252   "ẑ": "ẑ",
  16253   "ż": "ż",
  16254   "Á": "Á",
  16255   "À": "À",
  16256   "Ä": "Ä",
  16257   "Ǟ": "Ǟ",
  16258   "Ã": "Ã",
  16259   "Ā": "Ā",
  16260   "Ă": "Ă",
  16261   "Ắ": "Ắ",
  16262   "Ằ": "Ằ",
  16263   "Ẵ": "Ẵ",
  16264   "Ǎ": "Ǎ",
  16265   "Â": "Â",
  16266   "Ấ": "Ấ",
  16267   "Ầ": "Ầ",
  16268   "Ẫ": "Ẫ",
  16269   "Ȧ": "Ȧ",
  16270   "Ǡ": "Ǡ",
  16271   "Å": "Å",
  16272   "Ǻ": "Ǻ",
  16273   "Ḃ": "Ḃ",
  16274   "Ć": "Ć",
  16275   "Č": "Č",
  16276   "Ĉ": "Ĉ",
  16277   "Ċ": "Ċ",
  16278   "Ď": "Ď",
  16279   "Ḋ": "Ḋ",
  16280   "É": "É",
  16281   "È": "È",
  16282   "Ë": "Ë",
  16283   "Ẽ": "Ẽ",
  16284   "Ē": "Ē",
  16285   "Ḗ": "Ḗ",
  16286   "Ḕ": "Ḕ",
  16287   "Ĕ": "Ĕ",
  16288   "Ě": "Ě",
  16289   "Ê": "Ê",
  16290   "Ế": "Ế",
  16291   "Ề": "Ề",
  16292   "Ễ": "Ễ",
  16293   "Ė": "Ė",
  16294   "Ḟ": "Ḟ",
  16295   "Ǵ": "Ǵ",
  16296   "Ḡ": "Ḡ",
  16297   "Ğ": "Ğ",
  16298   "Ǧ": "Ǧ",
  16299   "Ĝ": "Ĝ",
  16300   "Ġ": "Ġ",
  16301   "Ḧ": "Ḧ",
  16302   "Ȟ": "Ȟ",
  16303   "Ĥ": "Ĥ",
  16304   "Ḣ": "Ḣ",
  16305   "Í": "Í",
  16306   "Ì": "Ì",
  16307   "Ï": "Ï",
  16308   "Ḯ": "Ḯ",
  16309   "Ĩ": "Ĩ",
  16310   "Ī": "Ī",
  16311   "Ĭ": "Ĭ",
  16312   "Ǐ": "Ǐ",
  16313   "Î": "Î",
  16314   "İ": "İ",
  16315   "Ĵ": "Ĵ",
  16316   "Ḱ": "Ḱ",
  16317   "Ǩ": "Ǩ",
  16318   "Ĺ": "Ĺ",
  16319   "Ľ": "Ľ",
  16320   "Ḿ": "Ḿ",
  16321   "Ṁ": "Ṁ",
  16322   "Ń": "Ń",
  16323   "Ǹ": "Ǹ",
  16324   "Ñ": "Ñ",
  16325   "Ň": "Ň",
  16326   "Ṅ": "Ṅ",
  16327   "Ó": "Ó",
  16328   "Ò": "Ò",
  16329   "Ö": "Ö",
  16330   "Ȫ": "Ȫ",
  16331   "Õ": "Õ",
  16332   "Ṍ": "Ṍ",
  16333   "Ṏ": "Ṏ",
  16334   "Ȭ": "Ȭ",
  16335   "Ō": "Ō",
  16336   "Ṓ": "Ṓ",
  16337   "Ṑ": "Ṑ",
  16338   "Ŏ": "Ŏ",
  16339   "Ǒ": "Ǒ",
  16340   "Ô": "Ô",
  16341   "Ố": "Ố",
  16342   "Ồ": "Ồ",
  16343   "Ỗ": "Ỗ",
  16344   "Ȯ": "Ȯ",
  16345   "Ȱ": "Ȱ",
  16346   "Ő": "Ő",
  16347   "Ṕ": "Ṕ",
  16348   "Ṗ": "Ṗ",
  16349   "Ŕ": "Ŕ",
  16350   "Ř": "Ř",
  16351   "Ṙ": "Ṙ",
  16352   "Ś": "Ś",
  16353   "Ṥ": "Ṥ",
  16354   "Š": "Š",
  16355   "Ṧ": "Ṧ",
  16356   "Ŝ": "Ŝ",
  16357   "Ṡ": "Ṡ",
  16358   "Ť": "Ť",
  16359   "Ṫ": "Ṫ",
  16360   "Ú": "Ú",
  16361   "Ù": "Ù",
  16362   "Ü": "Ü",
  16363   "Ǘ": "Ǘ",
  16364   "Ǜ": "Ǜ",
  16365   "Ǖ": "Ǖ",
  16366   "Ǚ": "Ǚ",
  16367   "Ũ": "Ũ",
  16368   "Ṹ": "Ṹ",
  16369   "Ū": "Ū",
  16370   "Ṻ": "Ṻ",
  16371   "Ŭ": "Ŭ",
  16372   "Ǔ": "Ǔ",
  16373   "Û": "Û",
  16374   "Ů": "Ů",
  16375   "Ű": "Ű",
  16376   "Ṽ": "Ṽ",
  16377   "Ẃ": "Ẃ",
  16378   "Ẁ": "Ẁ",
  16379   "Ẅ": "Ẅ",
  16380   "Ŵ": "Ŵ",
  16381   "Ẇ": "Ẇ",
  16382   "Ẍ": "Ẍ",
  16383   "Ẋ": "Ẋ",
  16384   "Ý": "Ý",
  16385   "Ỳ": "Ỳ",
  16386   "Ÿ": "Ÿ",
  16387   "Ỹ": "Ỹ",
  16388   "Ȳ": "Ȳ",
  16389   "Ŷ": "Ŷ",
  16390   "Ẏ": "Ẏ",
  16391   "Ź": "Ź",
  16392   "Ž": "Ž",
  16393   "Ẑ": "Ẑ",
  16394   "Ż": "Ż",
  16395   "ά": "ά",
  16396   "ὰ": "ὰ",
  16397   "ᾱ": "ᾱ",
  16398   "ᾰ": "ᾰ",
  16399   "έ": "έ",
  16400   "ὲ": "ὲ",
  16401   "ή": "ή",
  16402   "ὴ": "ὴ",
  16403   "ί": "ί",
  16404   "ὶ": "ὶ",
  16405   "ϊ": "ϊ",
  16406   "ΐ": "ΐ",
  16407   "ῒ": "ῒ",
  16408   "ῑ": "ῑ",
  16409   "ῐ": "ῐ",
  16410   "ό": "ό",
  16411   "ὸ": "ὸ",
  16412   "ύ": "ύ",
  16413   "ὺ": "ὺ",
  16414   "ϋ": "ϋ",
  16415   "ΰ": "ΰ",
  16416   "ῢ": "ῢ",
  16417   "ῡ": "ῡ",
  16418   "ῠ": "ῠ",
  16419   "ώ": "ώ",
  16420   "ὼ": "ὼ",
  16421   "Ύ": "Ύ",
  16422   "Ὺ": "Ὺ",
  16423   "Ϋ": "Ϋ",
  16424   "Ῡ": "Ῡ",
  16425   "Ῠ": "Ῠ",
  16426   "Ώ": "Ώ",
  16427   "Ὼ": "Ὼ"
  16428 };
  16429 
  16430 /**
  16431  * This file contains the parser used to parse out a TeX expression from the
  16432  * input. Since TeX isn't context-free, standard parsers don't work particularly
  16433  * well.
  16434  *
  16435  * The strategy of this parser is as such:
  16436  *
  16437  * The main functions (the `.parse...` ones) take a position in the current
  16438  * parse string to parse tokens from. The lexer (found in Lexer.js, stored at
  16439  * this.gullet.lexer) also supports pulling out tokens at arbitrary places. When
  16440  * individual tokens are needed at a position, the lexer is called to pull out a
  16441  * token, which is then used.
  16442  *
  16443  * The parser has a property called "mode" indicating the mode that
  16444  * the parser is currently in. Currently it has to be one of "math" or
  16445  * "text", which denotes whether the current environment is a math-y
  16446  * one or a text-y one (e.g. inside \text). Currently, this serves to
  16447  * limit the functions which can be used in text mode.
  16448  *
  16449  * The main functions then return an object which contains the useful data that
  16450  * was parsed at its given point, and a new position at the end of the parsed
  16451  * data. The main functions can call each other and continue the parsing by
  16452  * using the returned position as a new starting point.
  16453  *
  16454  * There are also extra `.handle...` functions, which pull out some reused
  16455  * functionality into self-contained functions.
  16456  *
  16457  * The functions return ParseNodes.
  16458  */
  16459 class Parser {
  16460   constructor(input, settings) {
  16461     this.mode = void 0;
  16462     this.gullet = void 0;
  16463     this.settings = void 0;
  16464     this.leftrightDepth = void 0;
  16465     this.nextToken = void 0;
  16466     // Start in math mode
  16467     this.mode = "math"; // Create a new macro expander (gullet) and (indirectly via that) also a
  16468     // new lexer (mouth) for this parser (stomach, in the language of TeX)
  16469 
  16470     this.gullet = new MacroExpander(input, settings, this.mode); // Store the settings for use in parsing
  16471 
  16472     this.settings = settings; // Count leftright depth (for \middle errors)
  16473 
  16474     this.leftrightDepth = 0;
  16475   }
  16476   /**
  16477    * Checks a result to make sure it has the right type, and throws an
  16478    * appropriate error otherwise.
  16479    */
  16480 
  16481 
  16482   expect(text, consume) {
  16483     if (consume === void 0) {
  16484       consume = true;
  16485     }
  16486 
  16487     if (this.fetch().text !== text) {
  16488       throw new ParseError("Expected '" + text + "', got '" + this.fetch().text + "'", this.fetch());
  16489     }
  16490 
  16491     if (consume) {
  16492       this.consume();
  16493     }
  16494   }
  16495   /**
  16496    * Discards the current lookahead token, considering it consumed.
  16497    */
  16498 
  16499 
  16500   consume() {
  16501     this.nextToken = null;
  16502   }
  16503   /**
  16504    * Return the current lookahead token, or if there isn't one (at the
  16505    * beginning, or if the previous lookahead token was consume()d),
  16506    * fetch the next token as the new lookahead token and return it.
  16507    */
  16508 
  16509 
  16510   fetch() {
  16511     if (this.nextToken == null) {
  16512       this.nextToken = this.gullet.expandNextToken();
  16513     }
  16514 
  16515     return this.nextToken;
  16516   }
  16517   /**
  16518    * Switches between "text" and "math" modes.
  16519    */
  16520 
  16521 
  16522   switchMode(newMode) {
  16523     this.mode = newMode;
  16524     this.gullet.switchMode(newMode);
  16525   }
  16526   /**
  16527    * Main parsing function, which parses an entire input.
  16528    */
  16529 
  16530 
  16531   parse() {
  16532     if (!this.settings.globalGroup) {
  16533       // Create a group namespace for the math expression.
  16534       // (LaTeX creates a new group for every $...$, $$...$$, \[...\].)
  16535       this.gullet.beginGroup();
  16536     } // Use old \color behavior (same as LaTeX's \textcolor) if requested.
  16537     // We do this within the group for the math expression, so it doesn't
  16538     // pollute settings.macros.
  16539 
  16540 
  16541     if (this.settings.colorIsTextColor) {
  16542       this.gullet.macros.set("\\color", "\\textcolor");
  16543     } // Try to parse the input
  16544 
  16545 
  16546     var parse = this.parseExpression(false); // If we succeeded, make sure there's an EOF at the end
  16547 
  16548     this.expect("EOF"); // End the group namespace for the expression
  16549 
  16550     if (!this.settings.globalGroup) {
  16551       this.gullet.endGroup();
  16552     }
  16553 
  16554     return parse;
  16555   }
  16556 
  16557   /**
  16558    * Parses an "expression", which is a list of atoms.
  16559    *
  16560    * `breakOnInfix`: Should the parsing stop when we hit infix nodes? This
  16561    *                 happens when functions have higher precendence han infix
  16562    *                 nodes in implicit parses.
  16563    *
  16564    * `breakOnTokenText`: The text of the token that the expression should end
  16565    *                     with, or `null` if something else should end the
  16566    *                     expression.
  16567    */
  16568   parseExpression(breakOnInfix, breakOnTokenText) {
  16569     var body = []; // Keep adding atoms to the body until we can't parse any more atoms (either
  16570     // we reached the end, a }, or a \right)
  16571 
  16572     while (true) {
  16573       // Ignore spaces in math mode
  16574       if (this.mode === "math") {
  16575         this.consumeSpaces();
  16576       }
  16577 
  16578       var lex = this.fetch();
  16579 
  16580       if (Parser.endOfExpression.indexOf(lex.text) !== -1) {
  16581         break;
  16582       }
  16583 
  16584       if (breakOnTokenText && lex.text === breakOnTokenText) {
  16585         break;
  16586       }
  16587 
  16588       if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) {
  16589         break;
  16590       }
  16591 
  16592       var atom = this.parseAtom(breakOnTokenText);
  16593 
  16594       if (!atom) {
  16595         break;
  16596       } else if (atom.type === "internal") {
  16597         continue;
  16598       }
  16599 
  16600       body.push(atom);
  16601     }
  16602 
  16603     if (this.mode === "text") {
  16604       this.formLigatures(body);
  16605     }
  16606 
  16607     return this.handleInfixNodes(body);
  16608   }
  16609   /**
  16610    * Rewrites infix operators such as \over with corresponding commands such
  16611    * as \frac.
  16612    *
  16613    * There can only be one infix operator per group.  If there's more than one
  16614    * then the expression is ambiguous.  This can be resolved by adding {}.
  16615    */
  16616 
  16617 
  16618   handleInfixNodes(body) {
  16619     var overIndex = -1;
  16620     var funcName;
  16621 
  16622     for (var i = 0; i < body.length; i++) {
  16623       if (body[i].type === "infix") {
  16624         if (overIndex !== -1) {
  16625           throw new ParseError("only one infix operator per group", body[i].token);
  16626         }
  16627 
  16628         overIndex = i;
  16629         funcName = body[i].replaceWith;
  16630       }
  16631     }
  16632 
  16633     if (overIndex !== -1 && funcName) {
  16634       var numerNode;
  16635       var denomNode;
  16636       var numerBody = body.slice(0, overIndex);
  16637       var denomBody = body.slice(overIndex + 1);
  16638 
  16639       if (numerBody.length === 1 && numerBody[0].type === "ordgroup") {
  16640         numerNode = numerBody[0];
  16641       } else {
  16642         numerNode = {
  16643           type: "ordgroup",
  16644           mode: this.mode,
  16645           body: numerBody
  16646         };
  16647       }
  16648 
  16649       if (denomBody.length === 1 && denomBody[0].type === "ordgroup") {
  16650         denomNode = denomBody[0];
  16651       } else {
  16652         denomNode = {
  16653           type: "ordgroup",
  16654           mode: this.mode,
  16655           body: denomBody
  16656         };
  16657       }
  16658 
  16659       var node;
  16660 
  16661       if (funcName === "\\\\abovefrac") {
  16662         node = this.callFunction(funcName, [numerNode, body[overIndex], denomNode], []);
  16663       } else {
  16664         node = this.callFunction(funcName, [numerNode, denomNode], []);
  16665       }
  16666 
  16667       return [node];
  16668     } else {
  16669       return body;
  16670     }
  16671   }
  16672   /**
  16673    * Handle a subscript or superscript with nice errors.
  16674    */
  16675 
  16676 
  16677   handleSupSubscript(name) {
  16678     var symbolToken = this.fetch();
  16679     var symbol = symbolToken.text;
  16680     this.consume();
  16681     this.consumeSpaces(); // ignore spaces before sup/subscript argument
  16682 
  16683     var group = this.parseGroup(name);
  16684 
  16685     if (!group) {
  16686       throw new ParseError("Expected group after '" + symbol + "'", symbolToken);
  16687     }
  16688 
  16689     return group;
  16690   }
  16691   /**
  16692    * Converts the textual input of an unsupported command into a text node
  16693    * contained within a color node whose color is determined by errorColor
  16694    */
  16695 
  16696 
  16697   formatUnsupportedCmd(text) {
  16698     var textordArray = [];
  16699 
  16700     for (var i = 0; i < text.length; i++) {
  16701       textordArray.push({
  16702         type: "textord",
  16703         mode: "text",
  16704         text: text[i]
  16705       });
  16706     }
  16707 
  16708     var textNode = {
  16709       type: "text",
  16710       mode: this.mode,
  16711       body: textordArray
  16712     };
  16713     var colorNode = {
  16714       type: "color",
  16715       mode: this.mode,
  16716       color: this.settings.errorColor,
  16717       body: [textNode]
  16718     };
  16719     return colorNode;
  16720   }
  16721   /**
  16722    * Parses a group with optional super/subscripts.
  16723    */
  16724 
  16725 
  16726   parseAtom(breakOnTokenText) {
  16727     // The body of an atom is an implicit group, so that things like
  16728     // \left(x\right)^2 work correctly.
  16729     var base = this.parseGroup("atom", breakOnTokenText); // In text mode, we don't have superscripts or subscripts
  16730 
  16731     if (this.mode === "text") {
  16732       return base;
  16733     } // Note that base may be empty (i.e. null) at this point.
  16734 
  16735 
  16736     var superscript;
  16737     var subscript;
  16738 
  16739     while (true) {
  16740       // Guaranteed in math mode, so eat any spaces first.
  16741       this.consumeSpaces(); // Lex the first token
  16742 
  16743       var lex = this.fetch();
  16744 
  16745       if (lex.text === "\\limits" || lex.text === "\\nolimits") {
  16746         // We got a limit control
  16747         if (base && base.type === "op") {
  16748           var limits = lex.text === "\\limits";
  16749           base.limits = limits;
  16750           base.alwaysHandleSupSub = true;
  16751         } else if (base && base.type === "operatorname" && base.alwaysHandleSupSub) {
  16752           var _limits = lex.text === "\\limits";
  16753 
  16754           base.limits = _limits;
  16755         } else {
  16756           throw new ParseError("Limit controls must follow a math operator", lex);
  16757         }
  16758 
  16759         this.consume();
  16760       } else if (lex.text === "^") {
  16761         // We got a superscript start
  16762         if (superscript) {
  16763           throw new ParseError("Double superscript", lex);
  16764         }
  16765 
  16766         superscript = this.handleSupSubscript("superscript");
  16767       } else if (lex.text === "_") {
  16768         // We got a subscript start
  16769         if (subscript) {
  16770           throw new ParseError("Double subscript", lex);
  16771         }
  16772 
  16773         subscript = this.handleSupSubscript("subscript");
  16774       } else if (lex.text === "'") {
  16775         // We got a prime
  16776         if (superscript) {
  16777           throw new ParseError("Double superscript", lex);
  16778         }
  16779 
  16780         var prime = {
  16781           type: "textord",
  16782           mode: this.mode,
  16783           text: "\\prime"
  16784         }; // Many primes can be grouped together, so we handle this here
  16785 
  16786         var primes = [prime];
  16787         this.consume(); // Keep lexing tokens until we get something that's not a prime
  16788 
  16789         while (this.fetch().text === "'") {
  16790           // For each one, add another prime to the list
  16791           primes.push(prime);
  16792           this.consume();
  16793         } // If there's a superscript following the primes, combine that
  16794         // superscript in with the primes.
  16795 
  16796 
  16797         if (this.fetch().text === "^") {
  16798           primes.push(this.handleSupSubscript("superscript"));
  16799         } // Put everything into an ordgroup as the superscript
  16800 
  16801 
  16802         superscript = {
  16803           type: "ordgroup",
  16804           mode: this.mode,
  16805           body: primes
  16806         };
  16807       } else {
  16808         // If it wasn't ^, _, or ', stop parsing super/subscripts
  16809         break;
  16810       }
  16811     } // Base must be set if superscript or subscript are set per logic above,
  16812     // but need to check here for type check to pass.
  16813 
  16814 
  16815     if (superscript || subscript) {
  16816       // If we got either a superscript or subscript, create a supsub
  16817       return {
  16818         type: "supsub",
  16819         mode: this.mode,
  16820         base: base,
  16821         sup: superscript,
  16822         sub: subscript
  16823       };
  16824     } else {
  16825       // Otherwise return the original body
  16826       return base;
  16827     }
  16828   }
  16829   /**
  16830    * Parses an entire function, including its base and all of its arguments.
  16831    */
  16832 
  16833 
  16834   parseFunction(breakOnTokenText, name) {
  16835     var token = this.fetch();
  16836     var func = token.text;
  16837     var funcData = functions[func];
  16838 
  16839     if (!funcData) {
  16840       return null;
  16841     }
  16842 
  16843     this.consume(); // consume command token
  16844 
  16845     if (name && name !== "atom" && !funcData.allowedInArgument) {
  16846       throw new ParseError("Got function '" + func + "' with no arguments" + (name ? " as " + name : ""), token);
  16847     } else if (this.mode === "text" && !funcData.allowedInText) {
  16848       throw new ParseError("Can't use function '" + func + "' in text mode", token);
  16849     } else if (this.mode === "math" && funcData.allowedInMath === false) {
  16850       throw new ParseError("Can't use function '" + func + "' in math mode", token);
  16851     }
  16852 
  16853     var {
  16854       args,
  16855       optArgs
  16856     } = this.parseArguments(func, funcData);
  16857     return this.callFunction(func, args, optArgs, token, breakOnTokenText);
  16858   }
  16859   /**
  16860    * Call a function handler with a suitable context and arguments.
  16861    */
  16862 
  16863 
  16864   callFunction(name, args, optArgs, token, breakOnTokenText) {
  16865     var context = {
  16866       funcName: name,
  16867       parser: this,
  16868       token,
  16869       breakOnTokenText
  16870     };
  16871     var func = functions[name];
  16872 
  16873     if (func && func.handler) {
  16874       return func.handler(context, args, optArgs);
  16875     } else {
  16876       throw new ParseError("No function handler for " + name);
  16877     }
  16878   }
  16879   /**
  16880    * Parses the arguments of a function or environment
  16881    */
  16882 
  16883 
  16884   parseArguments(func, // Should look like "\name" or "\begin{name}".
  16885   funcData) {
  16886     var totalArgs = funcData.numArgs + funcData.numOptionalArgs;
  16887 
  16888     if (totalArgs === 0) {
  16889       return {
  16890         args: [],
  16891         optArgs: []
  16892       };
  16893     }
  16894 
  16895     var args = [];
  16896     var optArgs = [];
  16897 
  16898     for (var i = 0; i < totalArgs; i++) {
  16899       var argType = funcData.argTypes && funcData.argTypes[i];
  16900       var isOptional = i < funcData.numOptionalArgs;
  16901 
  16902       if (funcData.primitive && argType == null || // \sqrt expands into primitive if optional argument doesn't exist
  16903       funcData.type === "sqrt" && i === 1 && optArgs[0] == null) {
  16904         argType = "primitive";
  16905       }
  16906 
  16907       var arg = this.parseGroupOfType("argument to '" + func + "'", argType, isOptional);
  16908 
  16909       if (isOptional) {
  16910         optArgs.push(arg);
  16911       } else if (arg != null) {
  16912         args.push(arg);
  16913       } else {
  16914         // should be unreachable
  16915         throw new ParseError("Null argument, please report this as a bug");
  16916       }
  16917     }
  16918 
  16919     return {
  16920       args,
  16921       optArgs
  16922     };
  16923   }
  16924   /**
  16925    * Parses a group when the mode is changing.
  16926    */
  16927 
  16928 
  16929   parseGroupOfType(name, type, optional) {
  16930     switch (type) {
  16931       case "color":
  16932         return this.parseColorGroup(optional);
  16933 
  16934       case "size":
  16935         return this.parseSizeGroup(optional);
  16936 
  16937       case "url":
  16938         return this.parseUrlGroup(optional);
  16939 
  16940       case "math":
  16941       case "text":
  16942         return this.parseArgumentGroup(optional, type);
  16943 
  16944       case "hbox":
  16945         {
  16946           // hbox argument type wraps the argument in the equivalent of
  16947           // \hbox, which is like \text but switching to \textstyle size.
  16948           var group = this.parseArgumentGroup(optional, "text");
  16949           return group != null ? {
  16950             type: "styling",
  16951             mode: group.mode,
  16952             body: [group],
  16953             style: "text" // simulate \textstyle
  16954 
  16955           } : null;
  16956         }
  16957 
  16958       case "raw":
  16959         {
  16960           var token = this.parseStringGroup("raw", optional);
  16961           return token != null ? {
  16962             type: "raw",
  16963             mode: "text",
  16964             string: token.text
  16965           } : null;
  16966         }
  16967 
  16968       case "primitive":
  16969         {
  16970           if (optional) {
  16971             throw new ParseError("A primitive argument cannot be optional");
  16972           }
  16973 
  16974           var _group = this.parseGroup(name);
  16975 
  16976           if (_group == null) {
  16977             throw new ParseError("Expected group as " + name, this.fetch());
  16978           }
  16979 
  16980           return _group;
  16981         }
  16982 
  16983       case "original":
  16984       case null:
  16985       case undefined:
  16986         return this.parseArgumentGroup(optional);
  16987 
  16988       default:
  16989         throw new ParseError("Unknown group type as " + name, this.fetch());
  16990     }
  16991   }
  16992   /**
  16993    * Discard any space tokens, fetching the next non-space token.
  16994    */
  16995 
  16996 
  16997   consumeSpaces() {
  16998     while (this.fetch().text === " ") {
  16999       this.consume();
  17000     }
  17001   }
  17002   /**
  17003    * Parses a group, essentially returning the string formed by the
  17004    * brace-enclosed tokens plus some position information.
  17005    */
  17006 
  17007 
  17008   parseStringGroup(modeName, // Used to describe the mode in error messages.
  17009   optional) {
  17010     var argToken = this.gullet.scanArgument(optional);
  17011 
  17012     if (argToken == null) {
  17013       return null;
  17014     }
  17015 
  17016     var str = "";
  17017     var nextToken;
  17018 
  17019     while ((nextToken = this.fetch()).text !== "EOF") {
  17020       str += nextToken.text;
  17021       this.consume();
  17022     }
  17023 
  17024     this.consume(); // consume the end of the argument
  17025 
  17026     argToken.text = str;
  17027     return argToken;
  17028   }
  17029   /**
  17030    * Parses a regex-delimited group: the largest sequence of tokens
  17031    * whose concatenated strings match `regex`. Returns the string
  17032    * formed by the tokens plus some position information.
  17033    */
  17034 
  17035 
  17036   parseRegexGroup(regex, modeName) {
  17037     var firstToken = this.fetch();
  17038     var lastToken = firstToken;
  17039     var str = "";
  17040     var nextToken;
  17041 
  17042     while ((nextToken = this.fetch()).text !== "EOF" && regex.test(str + nextToken.text)) {
  17043       lastToken = nextToken;
  17044       str += lastToken.text;
  17045       this.consume();
  17046     }
  17047 
  17048     if (str === "") {
  17049       throw new ParseError("Invalid " + modeName + ": '" + firstToken.text + "'", firstToken);
  17050     }
  17051 
  17052     return firstToken.range(lastToken, str);
  17053   }
  17054   /**
  17055    * Parses a color description.
  17056    */
  17057 
  17058 
  17059   parseColorGroup(optional) {
  17060     var res = this.parseStringGroup("color", optional);
  17061 
  17062     if (res == null) {
  17063       return null;
  17064     }
  17065 
  17066     var match = /^(#[a-f0-9]{3}|#?[a-f0-9]{6}|[a-z]+)$/i.exec(res.text);
  17067 
  17068     if (!match) {
  17069       throw new ParseError("Invalid color: '" + res.text + "'", res);
  17070     }
  17071 
  17072     var color = match[0];
  17073 
  17074     if (/^[0-9a-f]{6}$/i.test(color)) {
  17075       // We allow a 6-digit HTML color spec without a leading "#".
  17076       // This follows the xcolor package's HTML color model.
  17077       // Predefined color names are all missed by this RegEx pattern.
  17078       color = "#" + color;
  17079     }
  17080 
  17081     return {
  17082       type: "color-token",
  17083       mode: this.mode,
  17084       color
  17085     };
  17086   }
  17087   /**
  17088    * Parses a size specification, consisting of magnitude and unit.
  17089    */
  17090 
  17091 
  17092   parseSizeGroup(optional) {
  17093     var res;
  17094     var isBlank = false; // don't expand before parseStringGroup
  17095 
  17096     this.gullet.consumeSpaces();
  17097 
  17098     if (!optional && this.gullet.future().text !== "{") {
  17099       res = this.parseRegexGroup(/^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2} *$/, "size");
  17100     } else {
  17101       res = this.parseStringGroup("size", optional);
  17102     }
  17103 
  17104     if (!res) {
  17105       return null;
  17106     }
  17107 
  17108     if (!optional && res.text.length === 0) {
  17109       // Because we've tested for what is !optional, this block won't
  17110       // affect \kern, \hspace, etc. It will capture the mandatory arguments
  17111       // to \genfrac and \above.
  17112       res.text = "0pt"; // Enable \above{}
  17113 
  17114       isBlank = true; // This is here specifically for \genfrac
  17115     }
  17116 
  17117     var match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(res.text);
  17118 
  17119     if (!match) {
  17120       throw new ParseError("Invalid size: '" + res.text + "'", res);
  17121     }
  17122 
  17123     var data = {
  17124       number: +(match[1] + match[2]),
  17125       // sign + magnitude, cast to number
  17126       unit: match[3]
  17127     };
  17128 
  17129     if (!validUnit(data)) {
  17130       throw new ParseError("Invalid unit: '" + data.unit + "'", res);
  17131     }
  17132 
  17133     return {
  17134       type: "size",
  17135       mode: this.mode,
  17136       value: data,
  17137       isBlank
  17138     };
  17139   }
  17140   /**
  17141    * Parses an URL, checking escaped letters and allowed protocols,
  17142    * and setting the catcode of % as an active character (as in \hyperref).
  17143    */
  17144 
  17145 
  17146   parseUrlGroup(optional) {
  17147     this.gullet.lexer.setCatcode("%", 13); // active character
  17148 
  17149     var res = this.parseStringGroup("url", optional);
  17150     this.gullet.lexer.setCatcode("%", 14); // comment character
  17151 
  17152     if (res == null) {
  17153       return null;
  17154     } // hyperref package allows backslashes alone in href, but doesn't
  17155     // generate valid links in such cases; we interpret this as
  17156     // "undefined" behaviour, and keep them as-is. Some browser will
  17157     // replace backslashes with forward slashes.
  17158 
  17159 
  17160     var url = res.text.replace(/\\([#$%&~_^{}])/g, '$1');
  17161     return {
  17162       type: "url",
  17163       mode: this.mode,
  17164       url
  17165     };
  17166   }
  17167   /**
  17168    * Parses an argument with the mode specified.
  17169    */
  17170 
  17171 
  17172   parseArgumentGroup(optional, mode) {
  17173     var argToken = this.gullet.scanArgument(optional);
  17174 
  17175     if (argToken == null) {
  17176       return null;
  17177     }
  17178 
  17179     var outerMode = this.mode;
  17180 
  17181     if (mode) {
  17182       // Switch to specified mode
  17183       this.switchMode(mode);
  17184     }
  17185 
  17186     this.gullet.beginGroup();
  17187     var expression = this.parseExpression(false, "EOF"); // TODO: find an alternative way to denote the end
  17188 
  17189     this.expect("EOF"); // expect the end of the argument
  17190 
  17191     this.gullet.endGroup();
  17192     var result = {
  17193       type: "ordgroup",
  17194       mode: this.mode,
  17195       loc: argToken.loc,
  17196       body: expression
  17197     };
  17198 
  17199     if (mode) {
  17200       // Switch mode back
  17201       this.switchMode(outerMode);
  17202     }
  17203 
  17204     return result;
  17205   }
  17206   /**
  17207    * Parses an ordinary group, which is either a single nucleus (like "x")
  17208    * or an expression in braces (like "{x+y}") or an implicit group, a group
  17209    * that starts at the current position, and ends right before a higher explicit
  17210    * group ends, or at EOF.
  17211    */
  17212 
  17213 
  17214   parseGroup(name, // For error reporting.
  17215   breakOnTokenText) {
  17216     var firstToken = this.fetch();
  17217     var text = firstToken.text;
  17218     var result; // Try to parse an open brace or \begingroup
  17219 
  17220     if (text === "{" || text === "\\begingroup") {
  17221       this.consume();
  17222       var groupEnd = text === "{" ? "}" : "\\endgroup";
  17223       this.gullet.beginGroup(); // If we get a brace, parse an expression
  17224 
  17225       var expression = this.parseExpression(false, groupEnd);
  17226       var lastToken = this.fetch();
  17227       this.expect(groupEnd); // Check that we got a matching closing brace
  17228 
  17229       this.gullet.endGroup();
  17230       result = {
  17231         type: "ordgroup",
  17232         mode: this.mode,
  17233         loc: SourceLocation.range(firstToken, lastToken),
  17234         body: expression,
  17235         // A group formed by \begingroup...\endgroup is a semi-simple group
  17236         // which doesn't affect spacing in math mode, i.e., is transparent.
  17237         // https://tex.stackexchange.com/questions/1930/when-should-one-
  17238         // use-begingroup-instead-of-bgroup
  17239         semisimple: text === "\\begingroup" || undefined
  17240       };
  17241     } else {
  17242       // If there exists a function with this name, parse the function.
  17243       // Otherwise, just return a nucleus
  17244       result = this.parseFunction(breakOnTokenText, name) || this.parseSymbol();
  17245 
  17246       if (result == null && text[0] === "\\" && !implicitCommands.hasOwnProperty(text)) {
  17247         if (this.settings.throwOnError) {
  17248           throw new ParseError("Undefined control sequence: " + text, firstToken);
  17249         }
  17250 
  17251         result = this.formatUnsupportedCmd(text);
  17252         this.consume();
  17253       }
  17254     }
  17255 
  17256     return result;
  17257   }
  17258   /**
  17259    * Form ligature-like combinations of characters for text mode.
  17260    * This includes inputs like "--", "---", "``" and "''".
  17261    * The result will simply replace multiple textord nodes with a single
  17262    * character in each value by a single textord node having multiple
  17263    * characters in its value.  The representation is still ASCII source.
  17264    * The group will be modified in place.
  17265    */
  17266 
  17267 
  17268   formLigatures(group) {
  17269     var n = group.length - 1;
  17270 
  17271     for (var i = 0; i < n; ++i) {
  17272       var a = group[i]; // $FlowFixMe: Not every node type has a `text` property.
  17273 
  17274       var v = a.text;
  17275 
  17276       if (v === "-" && group[i + 1].text === "-") {
  17277         if (i + 1 < n && group[i + 2].text === "-") {
  17278           group.splice(i, 3, {
  17279             type: "textord",
  17280             mode: "text",
  17281             loc: SourceLocation.range(a, group[i + 2]),
  17282             text: "---"
  17283           });
  17284           n -= 2;
  17285         } else {
  17286           group.splice(i, 2, {
  17287             type: "textord",
  17288             mode: "text",
  17289             loc: SourceLocation.range(a, group[i + 1]),
  17290             text: "--"
  17291           });
  17292           n -= 1;
  17293         }
  17294       }
  17295 
  17296       if ((v === "'" || v === "`") && group[i + 1].text === v) {
  17297         group.splice(i, 2, {
  17298           type: "textord",
  17299           mode: "text",
  17300           loc: SourceLocation.range(a, group[i + 1]),
  17301           text: v + v
  17302         });
  17303         n -= 1;
  17304       }
  17305     }
  17306   }
  17307   /**
  17308    * Parse a single symbol out of the string. Here, we handle single character
  17309    * symbols and special functions like \verb.
  17310    */
  17311 
  17312 
  17313   parseSymbol() {
  17314     var nucleus = this.fetch();
  17315     var text = nucleus.text;
  17316 
  17317     if (/^\\verb[^a-zA-Z]/.test(text)) {
  17318       this.consume();
  17319       var arg = text.slice(5);
  17320       var star = arg.charAt(0) === "*";
  17321 
  17322       if (star) {
  17323         arg = arg.slice(1);
  17324       } // Lexer's tokenRegex is constructed to always have matching
  17325       // first/last characters.
  17326 
  17327 
  17328       if (arg.length < 2 || arg.charAt(0) !== arg.slice(-1)) {
  17329         throw new ParseError("\\verb assertion failed --\n                    please report what input caused this bug");
  17330       }
  17331 
  17332       arg = arg.slice(1, -1); // remove first and last char
  17333 
  17334       return {
  17335         type: "verb",
  17336         mode: "text",
  17337         body: arg,
  17338         star
  17339       };
  17340     } // At this point, we should have a symbol, possibly with accents.
  17341     // First expand any accented base symbol according to unicodeSymbols.
  17342 
  17343 
  17344     if (unicodeSymbols.hasOwnProperty(text[0]) && !symbols[this.mode][text[0]]) {
  17345       // This behavior is not strict (XeTeX-compatible) in math mode.
  17346       if (this.settings.strict && this.mode === "math") {
  17347         this.settings.reportNonstrict("unicodeTextInMathMode", "Accented Unicode text character \"" + text[0] + "\" used in " + "math mode", nucleus);
  17348       }
  17349 
  17350       text = unicodeSymbols[text[0]] + text.substr(1);
  17351     } // Strip off any combining characters
  17352 
  17353 
  17354     var match = combiningDiacriticalMarksEndRegex.exec(text);
  17355 
  17356     if (match) {
  17357       text = text.substring(0, match.index);
  17358 
  17359       if (text === 'i') {
  17360         text = '\u0131'; // dotless i, in math and text mode
  17361       } else if (text === 'j') {
  17362         text = '\u0237'; // dotless j, in math and text mode
  17363       }
  17364     } // Recognize base symbol
  17365 
  17366 
  17367     var symbol;
  17368 
  17369     if (symbols[this.mode][text]) {
  17370       if (this.settings.strict && this.mode === 'math' && extraLatin.indexOf(text) >= 0) {
  17371         this.settings.reportNonstrict("unicodeTextInMathMode", "Latin-1/Unicode text character \"" + text[0] + "\" used in " + "math mode", nucleus);
  17372       }
  17373 
  17374       var group = symbols[this.mode][text].group;
  17375       var loc = SourceLocation.range(nucleus);
  17376       var s;
  17377 
  17378       if (ATOMS.hasOwnProperty(group)) {
  17379         // $FlowFixMe
  17380         var family = group;
  17381         s = {
  17382           type: "atom",
  17383           mode: this.mode,
  17384           family,
  17385           loc,
  17386           text
  17387         };
  17388       } else {
  17389         // $FlowFixMe
  17390         s = {
  17391           type: group,
  17392           mode: this.mode,
  17393           loc,
  17394           text
  17395         };
  17396       } // $FlowFixMe
  17397 
  17398 
  17399       symbol = s;
  17400     } else if (text.charCodeAt(0) >= 0x80) {
  17401       // no symbol for e.g. ^
  17402       if (this.settings.strict) {
  17403         if (!supportedCodepoint(text.charCodeAt(0))) {
  17404           this.settings.reportNonstrict("unknownSymbol", "Unrecognized Unicode character \"" + text[0] + "\"" + (" (" + text.charCodeAt(0) + ")"), nucleus);
  17405         } else if (this.mode === "math") {
  17406           this.settings.reportNonstrict("unicodeTextInMathMode", "Unicode text character \"" + text[0] + "\" used in math mode", nucleus);
  17407         }
  17408       } // All nonmathematical Unicode characters are rendered as if they
  17409       // are in text mode (wrapped in \text) because that's what it
  17410       // takes to render them in LaTeX.  Setting `mode: this.mode` is
  17411       // another natural choice (the user requested math mode), but
  17412       // this makes it more difficult for getCharacterMetrics() to
  17413       // distinguish Unicode characters without metrics and those for
  17414       // which we want to simulate the letter M.
  17415 
  17416 
  17417       symbol = {
  17418         type: "textord",
  17419         mode: "text",
  17420         loc: SourceLocation.range(nucleus),
  17421         text
  17422       };
  17423     } else {
  17424       return null; // EOF, ^, _, {, }, etc.
  17425     }
  17426 
  17427     this.consume(); // Transform combining characters into accents
  17428 
  17429     if (match) {
  17430       for (var i = 0; i < match[0].length; i++) {
  17431         var accent = match[0][i];
  17432 
  17433         if (!unicodeAccents[accent]) {
  17434           throw new ParseError("Unknown accent ' " + accent + "'", nucleus);
  17435         }
  17436 
  17437         var command = unicodeAccents[accent][this.mode];
  17438 
  17439         if (!command) {
  17440           throw new ParseError("Accent " + accent + " unsupported in " + this.mode + " mode", nucleus);
  17441         }
  17442 
  17443         symbol = {
  17444           type: "accent",
  17445           mode: this.mode,
  17446           loc: SourceLocation.range(nucleus),
  17447           label: command,
  17448           isStretchy: false,
  17449           isShifty: true,
  17450           // $FlowFixMe
  17451           base: symbol
  17452         };
  17453       }
  17454     } // $FlowFixMe
  17455 
  17456 
  17457     return symbol;
  17458   }
  17459 
  17460 }
  17461 Parser.endOfExpression = ["}", "\\endgroup", "\\end", "\\right", "&"];
  17462 
  17463 /**
  17464  * Provides a single function for parsing an expression using a Parser
  17465  * TODO(emily): Remove this
  17466  */
  17467 
  17468 /**
  17469  * Parses an expression using a Parser, then returns the parsed result.
  17470  */
  17471 var parseTree = function parseTree(toParse, settings) {
  17472   if (!(typeof toParse === 'string' || toParse instanceof String)) {
  17473     throw new TypeError('KaTeX can only parse string typed expression');
  17474   }
  17475 
  17476   var parser = new Parser(toParse, settings); // Blank out any \df@tag to avoid spurious "Duplicate \tag" errors
  17477 
  17478   delete parser.gullet.macros.current["\\df@tag"];
  17479   var tree = parser.parse(); // Prevent a color definition from persisting between calls to katex.render().
  17480 
  17481   delete parser.gullet.macros.current["\\current@color"];
  17482   delete parser.gullet.macros.current["\\color"]; // If the input used \tag, it will set the \df@tag macro to the tag.
  17483   // In this case, we separately parse the tag and wrap the tree.
  17484 
  17485   if (parser.gullet.macros.get("\\df@tag")) {
  17486     if (!settings.displayMode) {
  17487       throw new ParseError("\\tag works only in display equations");
  17488     }
  17489 
  17490     parser.gullet.feed("\\df@tag");
  17491     tree = [{
  17492       type: "tag",
  17493       mode: "text",
  17494       body: tree,
  17495       tag: parser.parse()
  17496     }];
  17497   }
  17498 
  17499   return tree;
  17500 };
  17501 
  17502 /* eslint no-console:0 */
  17503 
  17504 /**
  17505  * Parse and build an expression, and place that expression in the DOM node
  17506  * given.
  17507  */
  17508 var render = function render(expression, baseNode, options) {
  17509   baseNode.textContent = "";
  17510   var node = renderToDomTree(expression, options).toNode();
  17511   baseNode.appendChild(node);
  17512 }; // KaTeX's styles don't work properly in quirks mode. Print out an error, and
  17513 // disable rendering.
  17514 
  17515 
  17516 if (typeof document !== "undefined") {
  17517   if (document.compatMode !== "CSS1Compat") {
  17518     typeof console !== "undefined" && console.warn("Warning: KaTeX doesn't work in quirks mode. Make sure your " + "website has a suitable doctype.");
  17519 
  17520     render = function render() {
  17521       throw new ParseError("KaTeX doesn't work in quirks mode.");
  17522     };
  17523   }
  17524 }
  17525 /**
  17526  * Parse and build an expression, and return the markup for that.
  17527  */
  17528 
  17529 
  17530 var renderToString = function renderToString(expression, options) {
  17531   var markup = renderToDomTree(expression, options).toMarkup();
  17532   return markup;
  17533 };
  17534 /**
  17535  * Parse an expression and return the parse tree.
  17536  */
  17537 
  17538 
  17539 var generateParseTree = function generateParseTree(expression, options) {
  17540   var settings = new Settings(options);
  17541   return parseTree(expression, settings);
  17542 };
  17543 /**
  17544  * If the given error is a KaTeX ParseError and options.throwOnError is false,
  17545  * renders the invalid LaTeX as a span with hover title giving the KaTeX
  17546  * error message.  Otherwise, simply throws the error.
  17547  */
  17548 
  17549 
  17550 var renderError = function renderError(error, expression, options) {
  17551   if (options.throwOnError || !(error instanceof ParseError)) {
  17552     throw error;
  17553   }
  17554 
  17555   var node = buildCommon.makeSpan(["katex-error"], [new SymbolNode(expression)]);
  17556   node.setAttribute("title", error.toString());
  17557   node.setAttribute("style", "color:" + options.errorColor);
  17558   return node;
  17559 };
  17560 /**
  17561  * Generates and returns the katex build tree. This is used for advanced
  17562  * use cases (like rendering to custom output).
  17563  */
  17564 
  17565 
  17566 var renderToDomTree = function renderToDomTree(expression, options) {
  17567   var settings = new Settings(options);
  17568 
  17569   try {
  17570     var tree = parseTree(expression, settings);
  17571     return buildTree(tree, expression, settings);
  17572   } catch (error) {
  17573     return renderError(error, expression, settings);
  17574   }
  17575 };
  17576 /**
  17577  * Generates and returns the katex build tree, with just HTML (no MathML).
  17578  * This is used for advanced use cases (like rendering to custom output).
  17579  */
  17580 
  17581 
  17582 var renderToHTMLTree = function renderToHTMLTree(expression, options) {
  17583   var settings = new Settings(options);
  17584 
  17585   try {
  17586     var tree = parseTree(expression, settings);
  17587     return buildHTMLTree(tree, expression, settings);
  17588   } catch (error) {
  17589     return renderError(error, expression, settings);
  17590   }
  17591 };
  17592 
  17593 var katex = {
  17594   /**
  17595    * Current KaTeX version
  17596    */
  17597   version: "0.13.0",
  17598 
  17599   /**
  17600    * Renders the given LaTeX into an HTML+MathML combination, and adds
  17601    * it as a child to the specified DOM node.
  17602    */
  17603   render,
  17604 
  17605   /**
  17606    * Renders the given LaTeX into an HTML+MathML combination string,
  17607    * for sending to the client.
  17608    */
  17609   renderToString,
  17610 
  17611   /**
  17612    * KaTeX error, usually during parsing.
  17613    */
  17614   ParseError,
  17615 
  17616   /**
  17617    * Parses the given LaTeX into KaTeX's internal parse tree structure,
  17618    * without rendering to HTML or MathML.
  17619    *
  17620    * NOTE: This method is not currently recommended for public use.
  17621    * The internal tree representation is unstable and is very likely
  17622    * to change. Use at your own risk.
  17623    */
  17624   __parse: generateParseTree,
  17625 
  17626   /**
  17627    * Renders the given LaTeX into an HTML+MathML internal DOM tree
  17628    * representation, without flattening that representation to a string.
  17629    *
  17630    * NOTE: This method is not currently recommended for public use.
  17631    * The internal tree representation is unstable and is very likely
  17632    * to change. Use at your own risk.
  17633    */
  17634   __renderToDomTree: renderToDomTree,
  17635 
  17636   /**
  17637    * Renders the given LaTeX into an HTML internal DOM tree representation,
  17638    * without MathML and without flattening that representation to a string.
  17639    *
  17640    * NOTE: This method is not currently recommended for public use.
  17641    * The internal tree representation is unstable and is very likely
  17642    * to change. Use at your own risk.
  17643    */
  17644   __renderToHTMLTree: renderToHTMLTree,
  17645 
  17646   /**
  17647    * extends internal font metrics object with a new object
  17648    * each key in the new object represents a font name
  17649   */
  17650   __setFontMetrics: setFontMetrics,
  17651 
  17652   /**
  17653    * adds a new symbol to builtin symbols table
  17654    */
  17655   __defineSymbol: defineSymbol,
  17656 
  17657   /**
  17658    * adds a new macro to builtin macro list
  17659    */
  17660   __defineMacro: defineMacro,
  17661 
  17662   /**
  17663    * Expose the dom tree node types, which can be useful for type checking nodes.
  17664    *
  17665    * NOTE: This method is not currently recommended for public use.
  17666    * The internal tree representation is unstable and is very likely
  17667    * to change. Use at your own risk.
  17668    */
  17669   __domTree: {
  17670     Span,
  17671     Anchor,
  17672     SymbolNode,
  17673     SvgNode,
  17674     PathNode,
  17675     LineNode
  17676   }
  17677 };
  17678 
  17679 export default katex;