arnaucube
arnaucube/arnaucube.comPublic Self-hosted repository
arnaucube.com/public/js/katex/katex.mjs
public/js/katex/katex.mjsRaw
    1/**
    2 * Lexing or parsing positional information for error reporting.
    3 * This object is immutable.
    4 */
    5class 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 */
   58class 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 // the text of the newly constructed token
   78  ) {
   79    return new Token(text, SourceLocation.range(this, endToken));
   80  }
   81
   82}
   83
   84/**
   85 * This is the ParseError class, which is the main error thrown by KaTeX
   86 * functions when something has gone wrong. This is used to distinguish internal
   87 * errors from errors in the expression that the user provided.
   88 *
   89 * If possible, a caller should provide a Token or ParseNode with information
   90 * about where in the source string the problem occurred.
   91 */
   92class ParseError {
   93  // Error position based on passed-in Token or ParseNode.
   94  constructor(message, // The error message
   95  token // An object providing position information
   96  ) {
   97    this.position = void 0;
   98    var error = "KaTeX parse error: " + message;
   99    var start;
  100    var loc = token && token.loc;
  101
  102    if (loc && loc.start <= loc.end) {
  103      // If we have the input and a position, make the error a bit fancier
  104      // Get the input
  105      var input = loc.lexer.input; // Prepend some information
  106
  107      start = loc.start;
  108      var end = loc.end;
  109
  110      if (start === input.length) {
  111        error += " at end of input: ";
  112      } else {
  113        error += " at position " + (start + 1) + ": ";
  114      } // Underline token in question using combining underscores
  115
  116
  117      var underlined = input.slice(start, end).replace(/[^]/g, "$&\u0332"); // Extract some context from the input and add it to the error
  118
  119      var left;
  120
  121      if (start > 15) {
  122        left = "…" + input.slice(start - 15, start);
  123      } else {
  124        left = input.slice(0, start);
  125      }
  126
  127      var right;
  128
  129      if (end + 15 < input.length) {
  130        right = input.slice(end, end + 15) + "…";
  131      } else {
  132        right = input.slice(end);
  133      }
  134
  135      error += left + underlined + right;
  136    } // Some hackery to make ParseError a prototype of Error
  137    // See http://stackoverflow.com/a/8460753
  138
  139
  140    var self = new Error(error);
  141    self.name = "ParseError"; // $FlowFixMe
  142
  143    self.__proto__ = ParseError.prototype; // $FlowFixMe
  144
  145    self.position = start;
  146    return self;
  147  }
  148
  149} // $FlowFixMe More hackery
  150
  151
  152ParseError.prototype.__proto__ = Error.prototype;
  153
  154/**
  155 * This file contains a list of utility functions which are useful in other
  156 * files.
  157 */
  158
  159/**
  160 * Return whether an element is contained in a list
  161 */
  162var contains = function contains(list, elem) {
  163  return list.indexOf(elem) !== -1;
  164};
  165/**
  166 * Provide a default value if a setting is undefined
  167 * NOTE: Couldn't use `T` as the output type due to facebook/flow#5022.
  168 */
  169
  170
  171var deflt = function deflt(setting, defaultIfUndefined) {
  172  return setting === undefined ? defaultIfUndefined : setting;
  173}; // hyphenate and escape adapted from Facebook's React under Apache 2 license
  174
  175
  176var uppercase = /([A-Z])/g;
  177
  178var hyphenate = function hyphenate(str) {
  179  return str.replace(uppercase, "-$1").toLowerCase();
  180};
  181
  182var ESCAPE_LOOKUP = {
  183  "&": "&amp;",
  184  ">": "&gt;",
  185  "<": "&lt;",
  186  "\"": "&quot;",
  187  "'": "&#x27;"
  188};
  189var ESCAPE_REGEX = /[&><"']/g;
  190/**
  191 * Escapes text to prevent scripting attacks.
  192 */
  193
  194function escape(text) {
  195  return String(text).replace(ESCAPE_REGEX, match => ESCAPE_LOOKUP[match]);
  196}
  197/**
  198 * Sometimes we want to pull out the innermost element of a group. In most
  199 * cases, this will just be the group itself, but when ordgroups and colors have
  200 * a single element, we want to pull that out.
  201 */
  202
  203
  204var getBaseElem = function getBaseElem(group) {
  205  if (group.type === "ordgroup") {
  206    if (group.body.length === 1) {
  207      return getBaseElem(group.body[0]);
  208    } else {
  209      return group;
  210    }
  211  } else if (group.type === "color") {
  212    if (group.body.length === 1) {
  213      return getBaseElem(group.body[0]);
  214    } else {
  215      return group;
  216    }
  217  } else if (group.type === "font") {
  218    return getBaseElem(group.body);
  219  } else {
  220    return group;
  221  }
  222};
  223/**
  224 * TeXbook algorithms often reference "character boxes", which are simply groups
  225 * with a single character in them. To decide if something is a character box,
  226 * we find its innermost group, and see if it is a single character.
  227 */
  228
  229
  230var isCharacterBox = function isCharacterBox(group) {
  231  var baseElem = getBaseElem(group); // These are all they types of groups which hold single characters
  232
  233  return baseElem.type === "mathord" || baseElem.type === "textord" || baseElem.type === "atom";
  234};
  235
  236var assert = function assert(value) {
  237  if (!value) {
  238    throw new Error('Expected non-null, but got ' + String(value));
  239  }
  240
  241  return value;
  242};
  243/**
  244 * Return the protocol of a URL, or "_relative" if the URL does not specify a
  245 * protocol (and thus is relative).
  246 */
  247
  248var protocolFromUrl = function protocolFromUrl(url) {
  249  var protocol = /^\s*([^\\/#]*?)(?::|&#0*58|&#x0*3a)/i.exec(url);
  250  return protocol != null ? protocol[1] : "_relative";
  251};
  252var utils = {
  253  contains,
  254  deflt,
  255  escape,
  256  hyphenate,
  257  getBaseElem,
  258  isCharacterBox,
  259  protocolFromUrl
  260};
  261
  262/* eslint no-console:0 */
  263// TODO: automatically generate documentation
  264// TODO: check all properties on Settings exist
  265// TODO: check the type of a property on Settings matches
  266var SETTINGS_SCHEMA = {
  267  displayMode: {
  268    type: "boolean",
  269    description: "Render math in display mode, which puts the math in " + "display style (so \\int and \\sum are large, for example), and " + "centers the math on the page on its own line.",
  270    cli: "-d, --display-mode"
  271  },
  272  output: {
  273    type: {
  274      enum: ["htmlAndMathml", "html", "mathml"]
  275    },
  276    description: "Determines the markup language of the output.",
  277    cli: "-F, --format <type>"
  278  },
  279  leqno: {
  280    type: "boolean",
  281    description: "Render display math in leqno style (left-justified tags)."
  282  },
  283  fleqn: {
  284    type: "boolean",
  285    description: "Render display math flush left."
  286  },
  287  throwOnError: {
  288    type: "boolean",
  289    default: true,
  290    cli: "-t, --no-throw-on-error",
  291    cliDescription: "Render errors (in the color given by --error-color) ins" + "tead of throwing a ParseError exception when encountering an error."
  292  },
  293  errorColor: {
  294    type: "string",
  295    default: "#cc0000",
  296    cli: "-c, --error-color <color>",
  297    cliDescription: "A color string given in the format 'rgb' or 'rrggbb' " + "(no #). This option determines the color of errors rendered by the " + "-t option.",
  298    cliProcessor: color => "#" + color
  299  },
  300  macros: {
  301    type: "object",
  302    cli: "-m, --macro <def>",
  303    cliDescription: "Define custom macro of the form '\\foo:expansion' (use " + "multiple -m arguments for multiple macros).",
  304    cliDefault: [],
  305    cliProcessor: (def, defs) => {
  306      defs.push(def);
  307      return defs;
  308    }
  309  },
  310  minRuleThickness: {
  311    type: "number",
  312    description: "Specifies a minimum thickness, in ems, for fraction lines," + " `\\sqrt` top lines, `{array}` vertical lines, `\\hline`, " + "`\\hdashline`, `\\underline`, `\\overline`, and the borders of " + "`\\fbox`, `\\boxed`, and `\\fcolorbox`.",
  313    processor: t => Math.max(0, t),
  314    cli: "--min-rule-thickness <size>",
  315    cliProcessor: parseFloat
  316  },
  317  colorIsTextColor: {
  318    type: "boolean",
  319    description: "Makes \\color behave like LaTeX's 2-argument \\textcolor, " + "instead of LaTeX's one-argument \\color mode change.",
  320    cli: "-b, --color-is-text-color"
  321  },
  322  strict: {
  323    type: [{
  324      enum: ["warn", "ignore", "error"]
  325    }, "boolean", "function"],
  326    description: "Turn on strict / LaTeX faithfulness mode, which throws an " + "error if the input uses features that are not supported by LaTeX.",
  327    cli: "-S, --strict",
  328    cliDefault: false
  329  },
  330  trust: {
  331    type: ["boolean", "function"],
  332    description: "Trust the input, enabling all HTML features such as \\url.",
  333    cli: "-T, --trust"
  334  },
  335  maxSize: {
  336    type: "number",
  337    default: Infinity,
  338    description: "If non-zero, all user-specified sizes, e.g. in " + "\\rule{500em}{500em}, will be capped to maxSize ems. Otherwise, " + "elements and spaces can be arbitrarily large",
  339    processor: s => Math.max(0, s),
  340    cli: "-s, --max-size <n>",
  341    cliProcessor: parseInt
  342  },
  343  maxExpand: {
  344    type: "number",
  345    default: 1000,
  346    description: "Limit the number of macro expansions to the specified " + "number, to prevent e.g. infinite macro loops. If set to Infinity, " + "the macro expander will try to fully expand as in LaTeX.",
  347    processor: n => Math.max(0, n),
  348    cli: "-e, --max-expand <n>",
  349    cliProcessor: n => n === "Infinity" ? Infinity : parseInt(n)
  350  },
  351  globalGroup: {
  352    type: "boolean",
  353    cli: false
  354  }
  355};
  356
  357function getDefaultValue(schema) {
  358  if (schema.default) {
  359    return schema.default;
  360  }
  361
  362  var type = schema.type;
  363  var defaultType = Array.isArray(type) ? type[0] : type;
  364
  365  if (typeof defaultType !== 'string') {
  366    return defaultType.enum[0];
  367  }
  368
  369  switch (defaultType) {
  370    case 'boolean':
  371      return false;
  372
  373    case 'string':
  374      return '';
  375
  376    case 'number':
  377      return 0;
  378
  379    case 'object':
  380      return {};
  381  }
  382}
  383/**
  384 * The main Settings object
  385 *
  386 * The current options stored are:
  387 *  - displayMode: Whether the expression should be typeset as inline math
  388 *                 (false, the default), meaning that the math starts in
  389 *                 \textstyle and is placed in an inline-block); or as display
  390 *                 math (true), meaning that the math starts in \displaystyle
  391 *                 and is placed in a block with vertical margin.
  392 */
  393
  394
  395class Settings {
  396  constructor(options) {
  397    this.displayMode = void 0;
  398    this.output = void 0;
  399    this.leqno = void 0;
  400    this.fleqn = void 0;
  401    this.throwOnError = void 0;
  402    this.errorColor = void 0;
  403    this.macros = void 0;
  404    this.minRuleThickness = void 0;
  405    this.colorIsTextColor = void 0;
  406    this.strict = void 0;
  407    this.trust = void 0;
  408    this.maxSize = void 0;
  409    this.maxExpand = void 0;
  410    this.globalGroup = void 0;
  411    // allow null options
  412    options = options || {};
  413
  414    for (var prop in SETTINGS_SCHEMA) {
  415      if (SETTINGS_SCHEMA.hasOwnProperty(prop)) {
  416        // $FlowFixMe
  417        var schema = SETTINGS_SCHEMA[prop]; // TODO: validate options
  418        // $FlowFixMe
  419
  420        this[prop] = options[prop] !== undefined ? schema.processor ? schema.processor(options[prop]) : options[prop] : getDefaultValue(schema);
  421      }
  422    }
  423  }
  424  /**
  425   * Report nonstrict (non-LaTeX-compatible) input.
  426   * Can safely not be called if `this.strict` is false in JavaScript.
  427   */
  428
  429
  430  reportNonstrict(errorCode, errorMsg, token) {
  431    var strict = this.strict;
  432
  433    if (typeof strict === "function") {
  434      // Allow return value of strict function to be boolean or string
  435      // (or null/undefined, meaning no further processing).
  436      strict = strict(errorCode, errorMsg, token);
  437    }
  438
  439    if (!strict || strict === "ignore") {
  440      return;
  441    } else if (strict === true || strict === "error") {
  442      throw new ParseError("LaTeX-incompatible input and strict mode is set to 'error': " + (errorMsg + " [" + errorCode + "]"), token);
  443    } else if (strict === "warn") {
  444      typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to 'warn': " + (errorMsg + " [" + errorCode + "]"));
  445    } else {
  446      // won't happen in type-safe code
  447      typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to " + ("unrecognized '" + strict + "': " + errorMsg + " [" + errorCode + "]"));
  448    }
  449  }
  450  /**
  451   * Check whether to apply strict (LaTeX-adhering) behavior for unusual
  452   * input (like `\\`).  Unlike `nonstrict`, will not throw an error;
  453   * instead, "error" translates to a return value of `true`, while "ignore"
  454   * translates to a return value of `false`.  May still print a warning:
  455   * "warn" prints a warning and returns `false`.
  456   * This is for the second category of `errorCode`s listed in the README.
  457   */
  458
  459
  460  useStrictBehavior(errorCode, errorMsg, token) {
  461    var strict = this.strict;
  462
  463    if (typeof strict === "function") {
  464      // Allow return value of strict function to be boolean or string
  465      // (or null/undefined, meaning no further processing).
  466      // But catch any exceptions thrown by function, treating them
  467      // like "error".
  468      try {
  469        strict = strict(errorCode, errorMsg, token);
  470      } catch (error) {
  471        strict = "error";
  472      }
  473    }
  474
  475    if (!strict || strict === "ignore") {
  476      return false;
  477    } else if (strict === true || strict === "error") {
  478      return true;
  479    } else if (strict === "warn") {
  480      typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to 'warn': " + (errorMsg + " [" + errorCode + "]"));
  481      return false;
  482    } else {
  483      // won't happen in type-safe code
  484      typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to " + ("unrecognized '" + strict + "': " + errorMsg + " [" + errorCode + "]"));
  485      return false;
  486    }
  487  }
  488  /**
  489   * Check whether to test potentially dangerous input, and return
  490   * `true` (trusted) or `false` (untrusted).  The sole argument `context`
  491   * should be an object with `command` field specifying the relevant LaTeX
  492   * command (as a string starting with `\`), and any other arguments, etc.
  493   * If `context` has a `url` field, a `protocol` field will automatically
  494   * get added by this function (changing the specified object).
  495   */
  496
  497
  498  isTrusted(context) {
  499    if (context.url && !context.protocol) {
  500      context.protocol = utils.protocolFromUrl(context.url);
  501    }
  502
  503    var trust = typeof this.trust === "function" ? this.trust(context) : this.trust;
  504    return Boolean(trust);
  505  }
  506
  507}
  508
  509/**
  510 * This file contains information and classes for the various kinds of styles
  511 * used in TeX. It provides a generic `Style` class, which holds information
  512 * about a specific style. It then provides instances of all the different kinds
  513 * of styles possible, and provides functions to move between them and get
  514 * information about them.
  515 */
  516
  517/**
  518 * The main style class. Contains a unique id for the style, a size (which is
  519 * the same for cramped and uncramped version of a style), and a cramped flag.
  520 */
  521class Style {
  522  constructor(id, size, cramped) {
  523    this.id = void 0;
  524    this.size = void 0;
  525    this.cramped = void 0;
  526    this.id = id;
  527    this.size = size;
  528    this.cramped = cramped;
  529  }
  530  /**
  531   * Get the style of a superscript given a base in the current style.
  532   */
  533
  534
  535  sup() {
  536    return styles[sup[this.id]];
  537  }
  538  /**
  539   * Get the style of a subscript given a base in the current style.
  540   */
  541
  542
  543  sub() {
  544    return styles[sub[this.id]];
  545  }
  546  /**
  547   * Get the style of a fraction numerator given the fraction in the current
  548   * style.
  549   */
  550
  551
  552  fracNum() {
  553    return styles[fracNum[this.id]];
  554  }
  555  /**
  556   * Get the style of a fraction denominator given the fraction in the current
  557   * style.
  558   */
  559
  560
  561  fracDen() {
  562    return styles[fracDen[this.id]];
  563  }
  564  /**
  565   * Get the cramped version of a style (in particular, cramping a cramped style
  566   * doesn't change the style).
  567   */
  568
  569
  570  cramp() {
  571    return styles[cramp[this.id]];
  572  }
  573  /**
  574   * Get a text or display version of this style.
  575   */
  576
  577
  578  text() {
  579    return styles[text$1[this.id]];
  580  }
  581  /**
  582   * Return true if this style is tightly spaced (scriptstyle/scriptscriptstyle)
  583   */
  584
  585
  586  isTight() {
  587    return this.size >= 2;
  588  }
  589
  590} // Export an interface for type checking, but don't expose the implementation.
  591// This way, no more styles can be generated.
  592
  593
  594// IDs of the different styles
  595var D = 0;
  596var Dc = 1;
  597var T = 2;
  598var Tc = 3;
  599var S = 4;
  600var Sc = 5;
  601var SS = 6;
  602var SSc = 7; // Instances of the different styles
  603
  604var 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
  605
  606var sup = [S, Sc, S, Sc, SS, SSc, SS, SSc];
  607var sub = [Sc, Sc, Sc, Sc, SSc, SSc, SSc, SSc];
  608var fracNum = [T, Tc, S, Sc, SS, SSc, SS, SSc];
  609var fracDen = [Tc, Tc, Sc, Sc, SSc, SSc, SSc, SSc];
  610var cramp = [Dc, Dc, Tc, Tc, Sc, Sc, SSc, SSc];
  611var text$1 = [D, Dc, T, Tc, T, Tc, T, Tc]; // We only export some of the styles.
  612
  613var Style$1 = {
  614  DISPLAY: styles[D],
  615  TEXT: styles[T],
  616  SCRIPT: styles[S],
  617  SCRIPTSCRIPT: styles[SS]
  618};
  619
  620/*
  621 * This file defines the Unicode scripts and script families that we
  622 * support. To add new scripts or families, just add a new entry to the
  623 * scriptData array below. Adding scripts to the scriptData array allows
  624 * characters from that script to appear in \text{} environments.
  625 */
  626
  627/**
  628 * Each script or script family has a name and an array of blocks.
  629 * Each block is an array of two numbers which specify the start and
  630 * end points (inclusive) of a block of Unicode codepoints.
  631 */
  632
  633/**
  634 * Unicode block data for the families of scripts we support in \text{}.
  635 * Scripts only need to appear here if they do not have font metrics.
  636 */
  637var scriptData = [{
  638  // Latin characters beyond the Latin-1 characters we have metrics for.
  639  // Needed for Czech, Hungarian and Turkish text, for example.
  640  name: 'latin',
  641  blocks: [[0x0100, 0x024f], // Latin Extended-A and Latin Extended-B
  642  [0x0300, 0x036f] // Combining Diacritical marks
  643  ]
  644}, {
  645  // The Cyrillic script used by Russian and related languages.
  646  // A Cyrillic subset used to be supported as explicitly defined
  647  // symbols in symbols.js
  648  name: 'cyrillic',
  649  blocks: [[0x0400, 0x04ff]]
  650}, {
  651  // Armenian
  652  name: 'armenian',
  653  blocks: [[0x0530, 0x058F]]
  654}, {
  655  // The Brahmic scripts of South and Southeast Asia
  656  // Devanagari (0900–097F)
  657  // Bengali (0980–09FF)
  658  // Gurmukhi (0A00–0A7F)
  659  // Gujarati (0A80–0AFF)
  660  // Oriya (0B00–0B7F)
  661  // Tamil (0B80–0BFF)
  662  // Telugu (0C00–0C7F)
  663  // Kannada (0C80–0CFF)
  664  // Malayalam (0D00–0D7F)
  665  // Sinhala (0D80–0DFF)
  666  // Thai (0E00–0E7F)
  667  // Lao (0E80–0EFF)
  668  // Tibetan (0F00–0FFF)
  669  // Myanmar (1000–109F)
  670  name: 'brahmic',
  671  blocks: [[0x0900, 0x109F]]
  672}, {
  673  name: 'georgian',
  674  blocks: [[0x10A0, 0x10ff]]
  675}, {
  676  // Chinese and Japanese.
  677  // The "k" in cjk is for Korean, but we've separated Korean out
  678  name: "cjk",
  679  blocks: [[0x3000, 0x30FF], // CJK symbols and punctuation, Hiragana, Katakana
  680  [0x4E00, 0x9FAF], // CJK ideograms
  681  [0xFF00, 0xFF60] // Fullwidth punctuation
  682  // TODO: add halfwidth Katakana and Romanji glyphs
  683  ]
  684}, {
  685  // Korean
  686  name: 'hangul',
  687  blocks: [[0xAC00, 0xD7AF]]
  688}];
  689/**
  690 * Given a codepoint, return the name of the script or script family
  691 * it is from, or null if it is not part of a known block
  692 */
  693
  694function scriptFromCodepoint(codepoint) {
  695  for (var i = 0; i < scriptData.length; i++) {
  696    var script = scriptData[i];
  697
  698    for (var _i = 0; _i < script.blocks.length; _i++) {
  699      var block = script.blocks[_i];
  700
  701      if (codepoint >= block[0] && codepoint <= block[1]) {
  702        return script.name;
  703      }
  704    }
  705  }
  706
  707  return null;
  708}
  709/**
  710 * A flattened version of all the supported blocks in a single array.
  711 * This is an optimization to make supportedCodepoint() fast.
  712 */
  713
  714var allBlocks = [];
  715scriptData.forEach(s => s.blocks.forEach(b => allBlocks.push(...b)));
  716/**
  717 * Given a codepoint, return true if it falls within one of the
  718 * scripts or script families defined above and false otherwise.
  719 *
  720 * Micro benchmarks shows that this is faster than
  721 * /[\u3000-\u30FF\u4E00-\u9FAF\uFF00-\uFF60\uAC00-\uD7AF\u0900-\u109F]/.test()
  722 * in Firefox, Chrome and Node.
  723 */
  724
  725function supportedCodepoint(codepoint) {
  726  for (var i = 0; i < allBlocks.length; i += 2) {
  727    if (codepoint >= allBlocks[i] && codepoint <= allBlocks[i + 1]) {
  728      return true;
  729    }
  730  }
  731
  732  return false;
  733}
  734
  735/**
  736 * This file provides support to domTree.js and delimiter.js.
  737 * It's a storehouse of path geometry for SVG images.
  738 */
  739// In all paths below, the viewBox-to-em scale is 1000:1.
  740var hLinePad = 80; // padding above a sqrt viniculum. Prevents image cropping.
  741// The viniculum of a \sqrt can be made thicker by a KaTeX rendering option.
  742// Think of variable extraViniculum as two detours in the SVG path.
  743// The detour begins at the lower left of the area labeled extraViniculum below.
  744// The detour proceeds one extraViniculum distance up and slightly to the right,
  745// displacing the radiused corner between surd and viniculum. The radius is
  746// traversed as usual, then the detour resumes. It goes right, to the end of
  747// the very long viniculumn, then down one extraViniculum distance,
  748// after which it resumes regular path geometry for the radical.
  749
  750/*                                                  viniculum
  751                                                   /
  752         /▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒←extraViniculum
  753        / █████████████████████←0.04em (40 unit) std viniculum thickness
  754       / /
  755      / /
  756     / /\
  757    / / surd
  758*/
  759
  760var sqrtMain = function sqrtMain(extraViniculum, hLinePad) {
  761  // sqrtMain path geometry is from glyph U221A in the font KaTeX Main
  762  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";
  763};
  764
  765var sqrtSize1 = function sqrtSize1(extraViniculum, hLinePad) {
  766  // size1 is from glyph U221A in the font KaTeX_Size1-Regular
  767  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";
  768};
  769
  770var sqrtSize2 = function sqrtSize2(extraViniculum, hLinePad) {
  771  // size2 is from glyph U221A in the font KaTeX_Size2-Regular
  772  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";
  773};
  774
  775var sqrtSize3 = function sqrtSize3(extraViniculum, hLinePad) {
  776  // size3 is from glyph U221A in the font KaTeX_Size3-Regular
  777  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";
  778};
  779
  780var sqrtSize4 = function sqrtSize4(extraViniculum, hLinePad) {
  781  // size4 is from glyph U221A in the font KaTeX_Size4-Regular
  782  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";
  783};
  784
  785var phasePath = function phasePath(y) {
  786  var x = y / 2; // x coordinate at top of angle
  787
  788  return "M400000 " + y + " H0 L" + x + " 0 l65 45 L145 " + (y - 80) + " H400000z";
  789};
  790
  791var sqrtTall = function sqrtTall(extraViniculum, hLinePad, viewBoxHeight) {
  792  // sqrtTall is from glyph U23B7 in the font KaTeX_Size4-Regular
  793  // One path edge has a variable length. It runs vertically from the viniculumn
  794  // to a point near (14 units) the bottom of the surd. The viniculum
  795  // is normally 40 units thick. So the length of the line in question is:
  796  var vertSegment = viewBoxHeight - 54 - hLinePad - extraViniculum;
  797  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";
  798};
  799
  800var sqrtPath = function sqrtPath(size, extraViniculum, viewBoxHeight) {
  801  extraViniculum = 1000 * extraViniculum; // Convert from document ems to viewBox.
  802
  803  var path = "";
  804
  805  switch (size) {
  806    case "sqrtMain":
  807      path = sqrtMain(extraViniculum, hLinePad);
  808      break;
  809
  810    case "sqrtSize1":
  811      path = sqrtSize1(extraViniculum, hLinePad);
  812      break;
  813
  814    case "sqrtSize2":
  815      path = sqrtSize2(extraViniculum, hLinePad);
  816      break;
  817
  818    case "sqrtSize3":
  819      path = sqrtSize3(extraViniculum, hLinePad);
  820      break;
  821
  822    case "sqrtSize4":
  823      path = sqrtSize4(extraViniculum, hLinePad);
  824      break;
  825
  826    case "sqrtTall":
  827      path = sqrtTall(extraViniculum, hLinePad, viewBoxHeight);
  828  }
  829
  830  return path;
  831};
  832var innerPath = function innerPath(name, height) {
  833  // The inner part of stretchy tall delimiters
  834  switch (name) {
  835    case "\u239c":
  836      return "M291 0 H417 V" + height + " H291z M291 0 H417 V" + height + " H291z";
  837
  838    case "\u2223":
  839      return "M145 0 H188 V" + height + " H145z M145 0 H188 V" + height + " H145z";
  840
  841    case "\u2225":
  842      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");
  843
  844    case "\u239f":
  845      return "M457 0 H583 V" + height + " H457z M457 0 H583 V" + height + " H457z";
  846
  847    case "\u23a2":
  848      return "M319 0 H403 V" + height + " H319z M319 0 H403 V" + height + " H319z";
  849
  850    case "\u23a5":
  851      return "M263 0 H347 V" + height + " H263z M263 0 H347 V" + height + " H263z";
  852
  853    case "\u23aa":
  854      return "M384 0 H504 V" + height + " H384z M384 0 H504 V" + height + " H384z";
  855
  856    case "\u23d0":
  857      return "M312 0 H355 V" + height + " H312z M312 0 H355 V" + height + " H312z";
  858
  859    case "\u2016":
  860      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");
  861
  862    default:
  863      return "";
  864  }
  865};
  866var path = {
  867  // The doubleleftarrow geometry is from glyph U+21D0 in the font KaTeX Main
  868  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",
  869  // doublerightarrow is from glyph U+21D2 in font KaTeX Main
  870  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",
  871  // leftarrow is from glyph U+2190 in font KaTeX Main
  872  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",
  873  // overbrace is from glyphs U+23A9/23A8/23A7 in font KaTeX_Size4-Regular
  874  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",
  875  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",
  876  // overgroup is from the MnSymbol package (public domain)
  877  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",
  878  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",
  879  // Harpoons are from glyph U+21BD in font KaTeX Main
  880  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",
  881  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",
  882  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",
  883  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",
  884  // hook is from glyph U+21A9 in font KaTeX Main
  885  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",
  886  leftlinesegment: "M40 281 V428 H0 V94 H40 V241 H400000 v40z\nM40 281 V428 H0 V94 H40 V241 H400000 v40z",
  887  leftmapsto: "M40 281 V448H0V74H40V241H400000v40z\nM40 281 V448H0V74H40V241H400000v40z",
  888  // tofrom is from glyph U+21C4 in font KaTeX AMS Regular
  889  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",
  890  longequal: "M0 50 h400000 v40H0z m0 194h40000v40H0z\nM0 50 h400000 v40H0z m0 194h40000v40H0z",
  891  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",
  892  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",
  893  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",
  894  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",
  895  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",
  896  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",
  897  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",
  898  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",
  899  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",
  900  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",
  901  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",
  902  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",
  903  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",
  904  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",
  905  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",
  906  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",
  907  rightlinesegment: "M399960 241 V94 h40 V428 h-40 V281 H0 v-40z\nM399960 241 V94 h40 V428 h-40 V281 H0 v-40z",
  908  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",
  909  // twoheadleftarrow is from glyph U+219E in font KaTeX AMS Regular
  910  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",
  911  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",
  912  // tilde1 is a modified version of a glyph from the MnSymbol package
  913  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",
  914  // ditto tilde2, tilde3, & tilde4
  915  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",
  916  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",
  917  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",
  918  // vec is from glyph U+20D7 in font KaTeX Main
  919  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",
  920  // widehat1 is a modified version of a glyph from the MnSymbol package
  921  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",
  922  // ditto widehat2, widehat3, & widehat4
  923  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",
  924  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",
  925  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",
  926  // widecheck paths are all inverted versions of widehat
  927  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",
  928  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",
  929  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",
  930  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",
  931  // The next ten paths support reaction arrows from the mhchem package.
  932  // Arrows for \ce{<-->} are offset from xAxis by 0.22ex, per mhchem in LaTeX
  933  // baraboveleftarrow is mostly from from glyph U+2190 in font KaTeX Main
  934  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",
  935  // rightarrowabovebar is mostly from glyph U+2192, KaTeX Main
  936  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",
  937  // The short left harpoon has 0.5em (i.e. 500 units) kern on the left end.
  938  // Ref from mhchem.sty: \rlap{\raisebox{-.22ex}{$\kern0.5em
  939  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",
  940  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",
  941  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",
  942  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"
  943};
  944
  945/**
  946 * This node represents a document fragment, which contains elements, but when
  947 * placed into the DOM doesn't have any representation itself. It only contains
  948 * children and doesn't have any DOM node properties.
  949 */
  950class DocumentFragment {
  951  // HtmlDomNode
  952  // Never used; needed for satisfying interface.
  953  constructor(children) {
  954    this.children = void 0;
  955    this.classes = void 0;
  956    this.height = void 0;
  957    this.depth = void 0;
  958    this.maxFontSize = void 0;
  959    this.style = void 0;
  960    this.children = children;
  961    this.classes = [];
  962    this.height = 0;
  963    this.depth = 0;
  964    this.maxFontSize = 0;
  965    this.style = {};
  966  }
  967
  968  hasClass(className) {
  969    return utils.contains(this.classes, className);
  970  }
  971  /** Convert the fragment into a node. */
  972
  973
  974  toNode() {
  975    var frag = document.createDocumentFragment();
  976
  977    for (var i = 0; i < this.children.length; i++) {
  978      frag.appendChild(this.children[i].toNode());
  979    }
  980
  981    return frag;
  982  }
  983  /** Convert the fragment into HTML markup. */
  984
  985
  986  toMarkup() {
  987    var markup = ""; // Simply concatenate the markup for the children together.
  988
  989    for (var i = 0; i < this.children.length; i++) {
  990      markup += this.children[i].toMarkup();
  991    }
  992
  993    return markup;
  994  }
  995  /**
  996   * Converts the math node into a string, similar to innerText. Applies to
  997   * MathDomNode's only.
  998   */
  999
 1000
 1001  toText() {
 1002    // To avoid this, we would subclass documentFragment separately for
 1003    // MathML, but polyfills for subclassing is expensive per PR 1469.
 1004    // $FlowFixMe: Only works for ChildType = MathDomNode.
 1005    var toText = child => child.toText();
 1006
 1007    return this.children.map(toText).join("");
 1008  }
 1009
 1010}
 1011
 1012// This file is GENERATED by buildMetrics.sh. DO NOT MODIFY.
 1013var fontMetricsData = {
 1014  "AMS-Regular": {
 1015    "32": [0, 0, 0, 0, 0.25],
 1016    "65": [0, 0.68889, 0, 0, 0.72222],
 1017    "66": [0, 0.68889, 0, 0, 0.66667],
 1018    "67": [0, 0.68889, 0, 0, 0.72222],
 1019    "68": [0, 0.68889, 0, 0, 0.72222],
 1020    "69": [0, 0.68889, 0, 0, 0.66667],
 1021    "70": [0, 0.68889, 0, 0, 0.61111],
 1022    "71": [0, 0.68889, 0, 0, 0.77778],
 1023    "72": [0, 0.68889, 0, 0, 0.77778],
 1024    "73": [0, 0.68889, 0, 0, 0.38889],
 1025    "74": [0.16667, 0.68889, 0, 0, 0.5],
 1026    "75": [0, 0.68889, 0, 0, 0.77778],
 1027    "76": [0, 0.68889, 0, 0, 0.66667],
 1028    "77": [0, 0.68889, 0, 0, 0.94445],
 1029    "78": [0, 0.68889, 0, 0, 0.72222],
 1030    "79": [0.16667, 0.68889, 0, 0, 0.77778],
 1031    "80": [0, 0.68889, 0, 0, 0.61111],
 1032    "81": [0.16667, 0.68889, 0, 0, 0.77778],
 1033    "82": [0, 0.68889, 0, 0, 0.72222],
 1034    "83": [0, 0.68889, 0, 0, 0.55556],
 1035    "84": [0, 0.68889, 0, 0, 0.66667],
 1036    "85": [0, 0.68889, 0, 0, 0.72222],
 1037    "86": [0, 0.68889, 0, 0, 0.72222],
 1038    "87": [0, 0.68889, 0, 0, 1.0],
 1039    "88": [0, 0.68889, 0, 0, 0.72222],
 1040    "89": [0, 0.68889, 0, 0, 0.72222],
 1041    "90": [0, 0.68889, 0, 0, 0.66667],
 1042    "107": [0, 0.68889, 0, 0, 0.55556],
 1043    "160": [0, 0, 0, 0, 0.25],
 1044    "165": [0, 0.675, 0.025, 0, 0.75],
 1045    "174": [0.15559, 0.69224, 0, 0, 0.94666],
 1046    "240": [0, 0.68889, 0, 0, 0.55556],
 1047    "295": [0, 0.68889, 0, 0, 0.54028],
 1048    "710": [0, 0.825, 0, 0, 2.33334],
 1049    "732": [0, 0.9, 0, 0, 2.33334],
 1050    "770": [0, 0.825, 0, 0, 2.33334],
 1051    "771": [0, 0.9, 0, 0, 2.33334],
 1052    "989": [0.08167, 0.58167, 0, 0, 0.77778],
 1053    "1008": [0, 0.43056, 0.04028, 0, 0.66667],
 1054    "8245": [0, 0.54986, 0, 0, 0.275],
 1055    "8463": [0, 0.68889, 0, 0, 0.54028],
 1056    "8487": [0, 0.68889, 0, 0, 0.72222],
 1057    "8498": [0, 0.68889, 0, 0, 0.55556],
 1058    "8502": [0, 0.68889, 0, 0, 0.66667],
 1059    "8503": [0, 0.68889, 0, 0, 0.44445],
 1060    "8504": [0, 0.68889, 0, 0, 0.66667],
 1061    "8513": [0, 0.68889, 0, 0, 0.63889],
 1062    "8592": [-0.03598, 0.46402, 0, 0, 0.5],
 1063    "8594": [-0.03598, 0.46402, 0, 0, 0.5],
 1064    "8602": [-0.13313, 0.36687, 0, 0, 1.0],
 1065    "8603": [-0.13313, 0.36687, 0, 0, 1.0],
 1066    "8606": [0.01354, 0.52239, 0, 0, 1.0],
 1067    "8608": [0.01354, 0.52239, 0, 0, 1.0],
 1068    "8610": [0.01354, 0.52239, 0, 0, 1.11111],
 1069    "8611": [0.01354, 0.52239, 0, 0, 1.11111],
 1070    "8619": [0, 0.54986, 0, 0, 1.0],
 1071    "8620": [0, 0.54986, 0, 0, 1.0],
 1072    "8621": [-0.13313, 0.37788, 0, 0, 1.38889],
 1073    "8622": [-0.13313, 0.36687, 0, 0, 1.0],
 1074    "8624": [0, 0.69224, 0, 0, 0.5],
 1075    "8625": [0, 0.69224, 0, 0, 0.5],
 1076    "8630": [0, 0.43056, 0, 0, 1.0],
 1077    "8631": [0, 0.43056, 0, 0, 1.0],
 1078    "8634": [0.08198, 0.58198, 0, 0, 0.77778],
 1079    "8635": [0.08198, 0.58198, 0, 0, 0.77778],
 1080    "8638": [0.19444, 0.69224, 0, 0, 0.41667],
 1081    "8639": [0.19444, 0.69224, 0, 0, 0.41667],
 1082    "8642": [0.19444, 0.69224, 0, 0, 0.41667],
 1083    "8643": [0.19444, 0.69224, 0, 0, 0.41667],
 1084    "8644": [0.1808, 0.675, 0, 0, 1.0],
 1085    "8646": [0.1808, 0.675, 0, 0, 1.0],
 1086    "8647": [0.1808, 0.675, 0, 0, 1.0],
 1087    "8648": [0.19444, 0.69224, 0, 0, 0.83334],
 1088    "8649": [0.1808, 0.675, 0, 0, 1.0],
 1089    "8650": [0.19444, 0.69224, 0, 0, 0.83334],
 1090    "8651": [0.01354, 0.52239, 0, 0, 1.0],
 1091    "8652": [0.01354, 0.52239, 0, 0, 1.0],
 1092    "8653": [-0.13313, 0.36687, 0, 0, 1.0],
 1093    "8654": [-0.13313, 0.36687, 0, 0, 1.0],
 1094    "8655": [-0.13313, 0.36687, 0, 0, 1.0],
 1095    "8666": [0.13667, 0.63667, 0, 0, 1.0],
 1096    "8667": [0.13667, 0.63667, 0, 0, 1.0],
 1097    "8669": [-0.13313, 0.37788, 0, 0, 1.0],
 1098    "8672": [-0.064, 0.437, 0, 0, 1.334],
 1099    "8674": [-0.064, 0.437, 0, 0, 1.334],
 1100    "8705": [0, 0.825, 0, 0, 0.5],
 1101    "8708": [0, 0.68889, 0, 0, 0.55556],
 1102    "8709": [0.08167, 0.58167, 0, 0, 0.77778],
 1103    "8717": [0, 0.43056, 0, 0, 0.42917],
 1104    "8722": [-0.03598, 0.46402, 0, 0, 0.5],
 1105    "8724": [0.08198, 0.69224, 0, 0, 0.77778],
 1106    "8726": [0.08167, 0.58167, 0, 0, 0.77778],
 1107    "8733": [0, 0.69224, 0, 0, 0.77778],
 1108    "8736": [0, 0.69224, 0, 0, 0.72222],
 1109    "8737": [0, 0.69224, 0, 0, 0.72222],
 1110    "8738": [0.03517, 0.52239, 0, 0, 0.72222],
 1111    "8739": [0.08167, 0.58167, 0, 0, 0.22222],
 1112    "8740": [0.25142, 0.74111, 0, 0, 0.27778],
 1113    "8741": [0.08167, 0.58167, 0, 0, 0.38889],
 1114    "8742": [0.25142, 0.74111, 0, 0, 0.5],
 1115    "8756": [0, 0.69224, 0, 0, 0.66667],
 1116    "8757": [0, 0.69224, 0, 0, 0.66667],
 1117    "8764": [-0.13313, 0.36687, 0, 0, 0.77778],
 1118    "8765": [-0.13313, 0.37788, 0, 0, 0.77778],
 1119    "8769": [-0.13313, 0.36687, 0, 0, 0.77778],
 1120    "8770": [-0.03625, 0.46375, 0, 0, 0.77778],
 1121    "8774": [0.30274, 0.79383, 0, 0, 0.77778],
 1122    "8776": [-0.01688, 0.48312, 0, 0, 0.77778],
 1123    "8778": [0.08167, 0.58167, 0, 0, 0.77778],
 1124    "8782": [0.06062, 0.54986, 0, 0, 0.77778],
 1125    "8783": [0.06062, 0.54986, 0, 0, 0.77778],
 1126    "8785": [0.08198, 0.58198, 0, 0, 0.77778],
 1127    "8786": [0.08198, 0.58198, 0, 0, 0.77778],
 1128    "8787": [0.08198, 0.58198, 0, 0, 0.77778],
 1129    "8790": [0, 0.69224, 0, 0, 0.77778],
 1130    "8791": [0.22958, 0.72958, 0, 0, 0.77778],
 1131    "8796": [0.08198, 0.91667, 0, 0, 0.77778],
 1132    "8806": [0.25583, 0.75583, 0, 0, 0.77778],
 1133    "8807": [0.25583, 0.75583, 0, 0, 0.77778],
 1134    "8808": [0.25142, 0.75726, 0, 0, 0.77778],
 1135    "8809": [0.25142, 0.75726, 0, 0, 0.77778],
 1136    "8812": [0.25583, 0.75583, 0, 0, 0.5],
 1137    "8814": [0.20576, 0.70576, 0, 0, 0.77778],
 1138    "8815": [0.20576, 0.70576, 0, 0, 0.77778],
 1139    "8816": [0.30274, 0.79383, 0, 0, 0.77778],
 1140    "8817": [0.30274, 0.79383, 0, 0, 0.77778],
 1141    "8818": [0.22958, 0.72958, 0, 0, 0.77778],
 1142    "8819": [0.22958, 0.72958, 0, 0, 0.77778],
 1143    "8822": [0.1808, 0.675, 0, 0, 0.77778],
 1144    "8823": [0.1808, 0.675, 0, 0, 0.77778],
 1145    "8828": [0.13667, 0.63667, 0, 0, 0.77778],
 1146    "8829": [0.13667, 0.63667, 0, 0, 0.77778],
 1147    "8830": [0.22958, 0.72958, 0, 0, 0.77778],
 1148    "8831": [0.22958, 0.72958, 0, 0, 0.77778],
 1149    "8832": [0.20576, 0.70576, 0, 0, 0.77778],
 1150    "8833": [0.20576, 0.70576, 0, 0, 0.77778],
 1151    "8840": [0.30274, 0.79383, 0, 0, 0.77778],
 1152    "8841": [0.30274, 0.79383, 0, 0, 0.77778],
 1153    "8842": [0.13597, 0.63597, 0, 0, 0.77778],
 1154    "8843": [0.13597, 0.63597, 0, 0, 0.77778],
 1155    "8847": [0.03517, 0.54986, 0, 0, 0.77778],
 1156    "8848": [0.03517, 0.54986, 0, 0, 0.77778],
 1157    "8858": [0.08198, 0.58198, 0, 0, 0.77778],
 1158    "8859": [0.08198, 0.58198, 0, 0, 0.77778],
 1159    "8861": [0.08198, 0.58198, 0, 0, 0.77778],
 1160    "8862": [0, 0.675, 0, 0, 0.77778],
 1161    "8863": [0, 0.675, 0, 0, 0.77778],
 1162    "8864": [0, 0.675, 0, 0, 0.77778],
 1163    "8865": [0, 0.675, 0, 0, 0.77778],
 1164    "8872": [0, 0.69224, 0, 0, 0.61111],
 1165    "8873": [0, 0.69224, 0, 0, 0.72222],
 1166    "8874": [0, 0.69224, 0, 0, 0.88889],
 1167    "8876": [0, 0.68889, 0, 0, 0.61111],
 1168    "8877": [0, 0.68889, 0, 0, 0.61111],
 1169    "8878": [0, 0.68889, 0, 0, 0.72222],
 1170    "8879": [0, 0.68889, 0, 0, 0.72222],
 1171    "8882": [0.03517, 0.54986, 0, 0, 0.77778],
 1172    "8883": [0.03517, 0.54986, 0, 0, 0.77778],
 1173    "8884": [0.13667, 0.63667, 0, 0, 0.77778],
 1174    "8885": [0.13667, 0.63667, 0, 0, 0.77778],
 1175    "8888": [0, 0.54986, 0, 0, 1.11111],
 1176    "8890": [0.19444, 0.43056, 0, 0, 0.55556],
 1177    "8891": [0.19444, 0.69224, 0, 0, 0.61111],
 1178    "8892": [0.19444, 0.69224, 0, 0, 0.61111],
 1179    "8901": [0, 0.54986, 0, 0, 0.27778],
 1180    "8903": [0.08167, 0.58167, 0, 0, 0.77778],
 1181    "8905": [0.08167, 0.58167, 0, 0, 0.77778],
 1182    "8906": [0.08167, 0.58167, 0, 0, 0.77778],
 1183    "8907": [0, 0.69224, 0, 0, 0.77778],
 1184    "8908": [0, 0.69224, 0, 0, 0.77778],
 1185    "8909": [-0.03598, 0.46402, 0, 0, 0.77778],
 1186    "8910": [0, 0.54986, 0, 0, 0.76042],
 1187    "8911": [0, 0.54986, 0, 0, 0.76042],
 1188    "8912": [0.03517, 0.54986, 0, 0, 0.77778],
 1189    "8913": [0.03517, 0.54986, 0, 0, 0.77778],
 1190    "8914": [0, 0.54986, 0, 0, 0.66667],
 1191    "8915": [0, 0.54986, 0, 0, 0.66667],
 1192    "8916": [0, 0.69224, 0, 0, 0.66667],
 1193    "8918": [0.0391, 0.5391, 0, 0, 0.77778],
 1194    "8919": [0.0391, 0.5391, 0, 0, 0.77778],
 1195    "8920": [0.03517, 0.54986, 0, 0, 1.33334],
 1196    "8921": [0.03517, 0.54986, 0, 0, 1.33334],
 1197    "8922": [0.38569, 0.88569, 0, 0, 0.77778],
 1198    "8923": [0.38569, 0.88569, 0, 0, 0.77778],
 1199    "8926": [0.13667, 0.63667, 0, 0, 0.77778],
 1200    "8927": [0.13667, 0.63667, 0, 0, 0.77778],
 1201    "8928": [0.30274, 0.79383, 0, 0, 0.77778],
 1202    "8929": [0.30274, 0.79383, 0, 0, 0.77778],
 1203    "8934": [0.23222, 0.74111, 0, 0, 0.77778],
 1204    "8935": [0.23222, 0.74111, 0, 0, 0.77778],
 1205    "8936": [0.23222, 0.74111, 0, 0, 0.77778],
 1206    "8937": [0.23222, 0.74111, 0, 0, 0.77778],
 1207    "8938": [0.20576, 0.70576, 0, 0, 0.77778],
 1208    "8939": [0.20576, 0.70576, 0, 0, 0.77778],
 1209    "8940": [0.30274, 0.79383, 0, 0, 0.77778],
 1210    "8941": [0.30274, 0.79383, 0, 0, 0.77778],
 1211    "8994": [0.19444, 0.69224, 0, 0, 0.77778],
 1212    "8995": [0.19444, 0.69224, 0, 0, 0.77778],
 1213    "9416": [0.15559, 0.69224, 0, 0, 0.90222],
 1214    "9484": [0, 0.69224, 0, 0, 0.5],
 1215    "9488": [0, 0.69224, 0, 0, 0.5],
 1216    "9492": [0, 0.37788, 0, 0, 0.5],
 1217    "9496": [0, 0.37788, 0, 0, 0.5],
 1218    "9585": [0.19444, 0.68889, 0, 0, 0.88889],
 1219    "9586": [0.19444, 0.74111, 0, 0, 0.88889],
 1220    "9632": [0, 0.675, 0, 0, 0.77778],
 1221    "9633": [0, 0.675, 0, 0, 0.77778],
 1222    "9650": [0, 0.54986, 0, 0, 0.72222],
 1223    "9651": [0, 0.54986, 0, 0, 0.72222],
 1224    "9654": [0.03517, 0.54986, 0, 0, 0.77778],
 1225    "9660": [0, 0.54986, 0, 0, 0.72222],
 1226    "9661": [0, 0.54986, 0, 0, 0.72222],
 1227    "9664": [0.03517, 0.54986, 0, 0, 0.77778],
 1228    "9674": [0.11111, 0.69224, 0, 0, 0.66667],
 1229    "9733": [0.19444, 0.69224, 0, 0, 0.94445],
 1230    "10003": [0, 0.69224, 0, 0, 0.83334],
 1231    "10016": [0, 0.69224, 0, 0, 0.83334],
 1232    "10731": [0.11111, 0.69224, 0, 0, 0.66667],
 1233    "10846": [0.19444, 0.75583, 0, 0, 0.61111],
 1234    "10877": [0.13667, 0.63667, 0, 0, 0.77778],
 1235    "10878": [0.13667, 0.63667, 0, 0, 0.77778],
 1236    "10885": [0.25583, 0.75583, 0, 0, 0.77778],
 1237    "10886": [0.25583, 0.75583, 0, 0, 0.77778],
 1238    "10887": [0.13597, 0.63597, 0, 0, 0.77778],
 1239    "10888": [0.13597, 0.63597, 0, 0, 0.77778],
 1240    "10889": [0.26167, 0.75726, 0, 0, 0.77778],
 1241    "10890": [0.26167, 0.75726, 0, 0, 0.77778],
 1242    "10891": [0.48256, 0.98256, 0, 0, 0.77778],
 1243    "10892": [0.48256, 0.98256, 0, 0, 0.77778],
 1244    "10901": [0.13667, 0.63667, 0, 0, 0.77778],
 1245    "10902": [0.13667, 0.63667, 0, 0, 0.77778],
 1246    "10933": [0.25142, 0.75726, 0, 0, 0.77778],
 1247    "10934": [0.25142, 0.75726, 0, 0, 0.77778],
 1248    "10935": [0.26167, 0.75726, 0, 0, 0.77778],
 1249    "10936": [0.26167, 0.75726, 0, 0, 0.77778],
 1250    "10937": [0.26167, 0.75726, 0, 0, 0.77778],
 1251    "10938": [0.26167, 0.75726, 0, 0, 0.77778],
 1252    "10949": [0.25583, 0.75583, 0, 0, 0.77778],
 1253    "10950": [0.25583, 0.75583, 0, 0, 0.77778],
 1254    "10955": [0.28481, 0.79383, 0, 0, 0.77778],
 1255    "10956": [0.28481, 0.79383, 0, 0, 0.77778],
 1256    "57350": [0.08167, 0.58167, 0, 0, 0.22222],
 1257    "57351": [0.08167, 0.58167, 0, 0, 0.38889],
 1258    "57352": [0.08167, 0.58167, 0, 0, 0.77778],
 1259    "57353": [0, 0.43056, 0.04028, 0, 0.66667],
 1260    "57356": [0.25142, 0.75726, 0, 0, 0.77778],
 1261    "57357": [0.25142, 0.75726, 0, 0, 0.77778],
 1262    "57358": [0.41951, 0.91951, 0, 0, 0.77778],
 1263    "57359": [0.30274, 0.79383, 0, 0, 0.77778],
 1264    "57360": [0.30274, 0.79383, 0, 0, 0.77778],
 1265    "57361": [0.41951, 0.91951, 0, 0, 0.77778],
 1266    "57366": [0.25142, 0.75726, 0, 0, 0.77778],
 1267    "57367": [0.25142, 0.75726, 0, 0, 0.77778],
 1268    "57368": [0.25142, 0.75726, 0, 0, 0.77778],
 1269    "57369": [0.25142, 0.75726, 0, 0, 0.77778],
 1270    "57370": [0.13597, 0.63597, 0, 0, 0.77778],
 1271    "57371": [0.13597, 0.63597, 0, 0, 0.77778]
 1272  },
 1273  "Caligraphic-Regular": {
 1274    "32": [0, 0, 0, 0, 0.25],
 1275    "65": [0, 0.68333, 0, 0.19445, 0.79847],
 1276    "66": [0, 0.68333, 0.03041, 0.13889, 0.65681],
 1277    "67": [0, 0.68333, 0.05834, 0.13889, 0.52653],
 1278    "68": [0, 0.68333, 0.02778, 0.08334, 0.77139],
 1279    "69": [0, 0.68333, 0.08944, 0.11111, 0.52778],
 1280    "70": [0, 0.68333, 0.09931, 0.11111, 0.71875],
 1281    "71": [0.09722, 0.68333, 0.0593, 0.11111, 0.59487],
 1282    "72": [0, 0.68333, 0.00965, 0.11111, 0.84452],
 1283    "73": [0, 0.68333, 0.07382, 0, 0.54452],
 1284    "74": [0.09722, 0.68333, 0.18472, 0.16667, 0.67778],
 1285    "75": [0, 0.68333, 0.01445, 0.05556, 0.76195],
 1286    "76": [0, 0.68333, 0, 0.13889, 0.68972],
 1287    "77": [0, 0.68333, 0, 0.13889, 1.2009],
 1288    "78": [0, 0.68333, 0.14736, 0.08334, 0.82049],
 1289    "79": [0, 0.68333, 0.02778, 0.11111, 0.79611],
 1290    "80": [0, 0.68333, 0.08222, 0.08334, 0.69556],
 1291    "81": [0.09722, 0.68333, 0, 0.11111, 0.81667],
 1292    "82": [0, 0.68333, 0, 0.08334, 0.8475],
 1293    "83": [0, 0.68333, 0.075, 0.13889, 0.60556],
 1294    "84": [0, 0.68333, 0.25417, 0, 0.54464],
 1295    "85": [0, 0.68333, 0.09931, 0.08334, 0.62583],
 1296    "86": [0, 0.68333, 0.08222, 0, 0.61278],
 1297    "87": [0, 0.68333, 0.08222, 0.08334, 0.98778],
 1298    "88": [0, 0.68333, 0.14643, 0.13889, 0.7133],
 1299    "89": [0.09722, 0.68333, 0.08222, 0.08334, 0.66834],
 1300    "90": [0, 0.68333, 0.07944, 0.13889, 0.72473],
 1301    "160": [0, 0, 0, 0, 0.25]
 1302  },
 1303  "Fraktur-Regular": {
 1304    "32": [0, 0, 0, 0, 0.25],
 1305    "33": [0, 0.69141, 0, 0, 0.29574],
 1306    "34": [0, 0.69141, 0, 0, 0.21471],
 1307    "38": [0, 0.69141, 0, 0, 0.73786],
 1308    "39": [0, 0.69141, 0, 0, 0.21201],
 1309    "40": [0.24982, 0.74947, 0, 0, 0.38865],
 1310    "41": [0.24982, 0.74947, 0, 0, 0.38865],
 1311    "42": [0, 0.62119, 0, 0, 0.27764],
 1312    "43": [0.08319, 0.58283, 0, 0, 0.75623],
 1313    "44": [0, 0.10803, 0, 0, 0.27764],
 1314    "45": [0.08319, 0.58283, 0, 0, 0.75623],
 1315    "46": [0, 0.10803, 0, 0, 0.27764],
 1316    "47": [0.24982, 0.74947, 0, 0, 0.50181],
 1317    "48": [0, 0.47534, 0, 0, 0.50181],
 1318    "49": [0, 0.47534, 0, 0, 0.50181],
 1319    "50": [0, 0.47534, 0, 0, 0.50181],
 1320    "51": [0.18906, 0.47534, 0, 0, 0.50181],
 1321    "52": [0.18906, 0.47534, 0, 0, 0.50181],
 1322    "53": [0.18906, 0.47534, 0, 0, 0.50181],
 1323    "54": [0, 0.69141, 0, 0, 0.50181],
 1324    "55": [0.18906, 0.47534, 0, 0, 0.50181],
 1325    "56": [0, 0.69141, 0, 0, 0.50181],
 1326    "57": [0.18906, 0.47534, 0, 0, 0.50181],
 1327    "58": [0, 0.47534, 0, 0, 0.21606],
 1328    "59": [0.12604, 0.47534, 0, 0, 0.21606],
 1329    "61": [-0.13099, 0.36866, 0, 0, 0.75623],
 1330    "63": [0, 0.69141, 0, 0, 0.36245],
 1331    "65": [0, 0.69141, 0, 0, 0.7176],
 1332    "66": [0, 0.69141, 0, 0, 0.88397],
 1333    "67": [0, 0.69141, 0, 0, 0.61254],
 1334    "68": [0, 0.69141, 0, 0, 0.83158],
 1335    "69": [0, 0.69141, 0, 0, 0.66278],
 1336    "70": [0.12604, 0.69141, 0, 0, 0.61119],
 1337    "71": [0, 0.69141, 0, 0, 0.78539],
 1338    "72": [0.06302, 0.69141, 0, 0, 0.7203],
 1339    "73": [0, 0.69141, 0, 0, 0.55448],
 1340    "74": [0.12604, 0.69141, 0, 0, 0.55231],
 1341    "75": [0, 0.69141, 0, 0, 0.66845],
 1342    "76": [0, 0.69141, 0, 0, 0.66602],
 1343    "77": [0, 0.69141, 0, 0, 1.04953],
 1344    "78": [0, 0.69141, 0, 0, 0.83212],
 1345    "79": [0, 0.69141, 0, 0, 0.82699],
 1346    "80": [0.18906, 0.69141, 0, 0, 0.82753],
 1347    "81": [0.03781, 0.69141, 0, 0, 0.82699],
 1348    "82": [0, 0.69141, 0, 0, 0.82807],
 1349    "83": [0, 0.69141, 0, 0, 0.82861],
 1350    "84": [0, 0.69141, 0, 0, 0.66899],
 1351    "85": [0, 0.69141, 0, 0, 0.64576],
 1352    "86": [0, 0.69141, 0, 0, 0.83131],
 1353    "87": [0, 0.69141, 0, 0, 1.04602],
 1354    "88": [0, 0.69141, 0, 0, 0.71922],
 1355    "89": [0.18906, 0.69141, 0, 0, 0.83293],
 1356    "90": [0.12604, 0.69141, 0, 0, 0.60201],
 1357    "91": [0.24982, 0.74947, 0, 0, 0.27764],
 1358    "93": [0.24982, 0.74947, 0, 0, 0.27764],
 1359    "94": [0, 0.69141, 0, 0, 0.49965],
 1360    "97": [0, 0.47534, 0, 0, 0.50046],
 1361    "98": [0, 0.69141, 0, 0, 0.51315],
 1362    "99": [0, 0.47534, 0, 0, 0.38946],
 1363    "100": [0, 0.62119, 0, 0, 0.49857],
 1364    "101": [0, 0.47534, 0, 0, 0.40053],
 1365    "102": [0.18906, 0.69141, 0, 0, 0.32626],
 1366    "103": [0.18906, 0.47534, 0, 0, 0.5037],
 1367    "104": [0.18906, 0.69141, 0, 0, 0.52126],
 1368    "105": [0, 0.69141, 0, 0, 0.27899],
 1369    "106": [0, 0.69141, 0, 0, 0.28088],
 1370    "107": [0, 0.69141, 0, 0, 0.38946],
 1371    "108": [0, 0.69141, 0, 0, 0.27953],
 1372    "109": [0, 0.47534, 0, 0, 0.76676],
 1373    "110": [0, 0.47534, 0, 0, 0.52666],
 1374    "111": [0, 0.47534, 0, 0, 0.48885],
 1375    "112": [0.18906, 0.52396, 0, 0, 0.50046],
 1376    "113": [0.18906, 0.47534, 0, 0, 0.48912],
 1377    "114": [0, 0.47534, 0, 0, 0.38919],
 1378    "115": [0, 0.47534, 0, 0, 0.44266],
 1379    "116": [0, 0.62119, 0, 0, 0.33301],
 1380    "117": [0, 0.47534, 0, 0, 0.5172],
 1381    "118": [0, 0.52396, 0, 0, 0.5118],
 1382    "119": [0, 0.52396, 0, 0, 0.77351],
 1383    "120": [0.18906, 0.47534, 0, 0, 0.38865],
 1384    "121": [0.18906, 0.47534, 0, 0, 0.49884],
 1385    "122": [0.18906, 0.47534, 0, 0, 0.39054],
 1386    "160": [0, 0, 0, 0, 0.25],
 1387    "8216": [0, 0.69141, 0, 0, 0.21471],
 1388    "8217": [0, 0.69141, 0, 0, 0.21471],
 1389    "58112": [0, 0.62119, 0, 0, 0.49749],
 1390    "58113": [0, 0.62119, 0, 0, 0.4983],
 1391    "58114": [0.18906, 0.69141, 0, 0, 0.33328],
 1392    "58115": [0.18906, 0.69141, 0, 0, 0.32923],
 1393    "58116": [0.18906, 0.47534, 0, 0, 0.50343],
 1394    "58117": [0, 0.69141, 0, 0, 0.33301],
 1395    "58118": [0, 0.62119, 0, 0, 0.33409],
 1396    "58119": [0, 0.47534, 0, 0, 0.50073]
 1397  },
 1398  "Main-Bold": {
 1399    "32": [0, 0, 0, 0, 0.25],
 1400    "33": [0, 0.69444, 0, 0, 0.35],
 1401    "34": [0, 0.69444, 0, 0, 0.60278],
 1402    "35": [0.19444, 0.69444, 0, 0, 0.95833],
 1403    "36": [0.05556, 0.75, 0, 0, 0.575],
 1404    "37": [0.05556, 0.75, 0, 0, 0.95833],
 1405    "38": [0, 0.69444, 0, 0, 0.89444],
 1406    "39": [0, 0.69444, 0, 0, 0.31944],
 1407    "40": [0.25, 0.75, 0, 0, 0.44722],
 1408    "41": [0.25, 0.75, 0, 0, 0.44722],
 1409    "42": [0, 0.75, 0, 0, 0.575],
 1410    "43": [0.13333, 0.63333, 0, 0, 0.89444],
 1411    "44": [0.19444, 0.15556, 0, 0, 0.31944],
 1412    "45": [0, 0.44444, 0, 0, 0.38333],
 1413    "46": [0, 0.15556, 0, 0, 0.31944],
 1414    "47": [0.25, 0.75, 0, 0, 0.575],
 1415    "48": [0, 0.64444, 0, 0, 0.575],
 1416    "49": [0, 0.64444, 0, 0, 0.575],
 1417    "50": [0, 0.64444, 0, 0, 0.575],
 1418    "51": [0, 0.64444, 0, 0, 0.575],
 1419    "52": [0, 0.64444, 0, 0, 0.575],
 1420    "53": [0, 0.64444, 0, 0, 0.575],
 1421    "54": [0, 0.64444, 0, 0, 0.575],
 1422    "55": [0, 0.64444, 0, 0, 0.575],
 1423    "56": [0, 0.64444, 0, 0, 0.575],
 1424    "57": [0, 0.64444, 0, 0, 0.575],
 1425    "58": [0, 0.44444, 0, 0, 0.31944],
 1426    "59": [0.19444, 0.44444, 0, 0, 0.31944],
 1427    "60": [0.08556, 0.58556, 0, 0, 0.89444],
 1428    "61": [-0.10889, 0.39111, 0, 0, 0.89444],
 1429    "62": [0.08556, 0.58556, 0, 0, 0.89444],
 1430    "63": [0, 0.69444, 0, 0, 0.54305],
 1431    "64": [0, 0.69444, 0, 0, 0.89444],
 1432    "65": [0, 0.68611, 0, 0, 0.86944],
 1433    "66": [0, 0.68611, 0, 0, 0.81805],
 1434    "67": [0, 0.68611, 0, 0, 0.83055],
 1435    "68": [0, 0.68611, 0, 0, 0.88194],
 1436    "69": [0, 0.68611, 0, 0, 0.75555],
 1437    "70": [0, 0.68611, 0, 0, 0.72361],
 1438    "71": [0, 0.68611, 0, 0, 0.90416],
 1439    "72": [0, 0.68611, 0, 0, 0.9],
 1440    "73": [0, 0.68611, 0, 0, 0.43611],
 1441    "74": [0, 0.68611, 0, 0, 0.59444],
 1442    "75": [0, 0.68611, 0, 0, 0.90138],
 1443    "76": [0, 0.68611, 0, 0, 0.69166],
 1444    "77": [0, 0.68611, 0, 0, 1.09166],
 1445    "78": [0, 0.68611, 0, 0, 0.9],
 1446    "79": [0, 0.68611, 0, 0, 0.86388],
 1447    "80": [0, 0.68611, 0, 0, 0.78611],
 1448    "81": [0.19444, 0.68611, 0, 0, 0.86388],
 1449    "82": [0, 0.68611, 0, 0, 0.8625],
 1450    "83": [0, 0.68611, 0, 0, 0.63889],
 1451    "84": [0, 0.68611, 0, 0, 0.8],
 1452    "85": [0, 0.68611, 0, 0, 0.88472],
 1453    "86": [0, 0.68611, 0.01597, 0, 0.86944],
 1454    "87": [0, 0.68611, 0.01597, 0, 1.18888],
 1455    "88": [0, 0.68611, 0, 0, 0.86944],
 1456    "89": [0, 0.68611, 0.02875, 0, 0.86944],
 1457    "90": [0, 0.68611, 0, 0, 0.70277],
 1458    "91": [0.25, 0.75, 0, 0, 0.31944],
 1459    "92": [0.25, 0.75, 0, 0, 0.575],
 1460    "93": [0.25, 0.75, 0, 0, 0.31944],
 1461    "94": [0, 0.69444, 0, 0, 0.575],
 1462    "95": [0.31, 0.13444, 0.03194, 0, 0.575],
 1463    "97": [0, 0.44444, 0, 0, 0.55902],
 1464    "98": [0, 0.69444, 0, 0, 0.63889],
 1465    "99": [0, 0.44444, 0, 0, 0.51111],
 1466    "100": [0, 0.69444, 0, 0, 0.63889],
 1467    "101": [0, 0.44444, 0, 0, 0.52708],
 1468    "102": [0, 0.69444, 0.10903, 0, 0.35139],
 1469    "103": [0.19444, 0.44444, 0.01597, 0, 0.575],
 1470    "104": [0, 0.69444, 0, 0, 0.63889],
 1471    "105": [0, 0.69444, 0, 0, 0.31944],
 1472    "106": [0.19444, 0.69444, 0, 0, 0.35139],
 1473    "107": [0, 0.69444, 0, 0, 0.60694],
 1474    "108": [0, 0.69444, 0, 0, 0.31944],
 1475    "109": [0, 0.44444, 0, 0, 0.95833],
 1476    "110": [0, 0.44444, 0, 0, 0.63889],
 1477    "111": [0, 0.44444, 0, 0, 0.575],
 1478    "112": [0.19444, 0.44444, 0, 0, 0.63889],
 1479    "113": [0.19444, 0.44444, 0, 0, 0.60694],
 1480    "114": [0, 0.44444, 0, 0, 0.47361],
 1481    "115": [0, 0.44444, 0, 0, 0.45361],
 1482    "116": [0, 0.63492, 0, 0, 0.44722],
 1483    "117": [0, 0.44444, 0, 0, 0.63889],
 1484    "118": [0, 0.44444, 0.01597, 0, 0.60694],
 1485    "119": [0, 0.44444, 0.01597, 0, 0.83055],
 1486    "120": [0, 0.44444, 0, 0, 0.60694],
 1487    "121": [0.19444, 0.44444, 0.01597, 0, 0.60694],
 1488    "122": [0, 0.44444, 0, 0, 0.51111],
 1489    "123": [0.25, 0.75, 0, 0, 0.575],
 1490    "124": [0.25, 0.75, 0, 0, 0.31944],
 1491    "125": [0.25, 0.75, 0, 0, 0.575],
 1492    "126": [0.35, 0.34444, 0, 0, 0.575],
 1493    "160": [0, 0, 0, 0, 0.25],
 1494    "163": [0, 0.69444, 0, 0, 0.86853],
 1495    "168": [0, 0.69444, 0, 0, 0.575],
 1496    "172": [0, 0.44444, 0, 0, 0.76666],
 1497    "176": [0, 0.69444, 0, 0, 0.86944],
 1498    "177": [0.13333, 0.63333, 0, 0, 0.89444],
 1499    "184": [0.17014, 0, 0, 0, 0.51111],
 1500    "198": [0, 0.68611, 0, 0, 1.04166],
 1501    "215": [0.13333, 0.63333, 0, 0, 0.89444],
 1502    "216": [0.04861, 0.73472, 0, 0, 0.89444],
 1503    "223": [0, 0.69444, 0, 0, 0.59722],
 1504    "230": [0, 0.44444, 0, 0, 0.83055],
 1505    "247": [0.13333, 0.63333, 0, 0, 0.89444],
 1506    "248": [0.09722, 0.54167, 0, 0, 0.575],
 1507    "305": [0, 0.44444, 0, 0, 0.31944],
 1508    "338": [0, 0.68611, 0, 0, 1.16944],
 1509    "339": [0, 0.44444, 0, 0, 0.89444],
 1510    "567": [0.19444, 0.44444, 0, 0, 0.35139],
 1511    "710": [0, 0.69444, 0, 0, 0.575],
 1512    "711": [0, 0.63194, 0, 0, 0.575],
 1513    "713": [0, 0.59611, 0, 0, 0.575],
 1514    "714": [0, 0.69444, 0, 0, 0.575],
 1515    "715": [0, 0.69444, 0, 0, 0.575],
 1516    "728": [0, 0.69444, 0, 0, 0.575],
 1517    "729": [0, 0.69444, 0, 0, 0.31944],
 1518    "730": [0, 0.69444, 0, 0, 0.86944],
 1519    "732": [0, 0.69444, 0, 0, 0.575],
 1520    "733": [0, 0.69444, 0, 0, 0.575],
 1521    "915": [0, 0.68611, 0, 0, 0.69166],
 1522    "916": [0, 0.68611, 0, 0, 0.95833],
 1523    "920": [0, 0.68611, 0, 0, 0.89444],
 1524    "923": [0, 0.68611, 0, 0, 0.80555],
 1525    "926": [0, 0.68611, 0, 0, 0.76666],
 1526    "928": [0, 0.68611, 0, 0, 0.9],
 1527    "931": [0, 0.68611, 0, 0, 0.83055],
 1528    "933": [0, 0.68611, 0, 0, 0.89444],
 1529    "934": [0, 0.68611, 0, 0, 0.83055],
 1530    "936": [0, 0.68611, 0, 0, 0.89444],
 1531    "937": [0, 0.68611, 0, 0, 0.83055],
 1532    "8211": [0, 0.44444, 0.03194, 0, 0.575],
 1533    "8212": [0, 0.44444, 0.03194, 0, 1.14999],
 1534    "8216": [0, 0.69444, 0, 0, 0.31944],
 1535    "8217": [0, 0.69444, 0, 0, 0.31944],
 1536    "8220": [0, 0.69444, 0, 0, 0.60278],
 1537    "8221": [0, 0.69444, 0, 0, 0.60278],
 1538    "8224": [0.19444, 0.69444, 0, 0, 0.51111],
 1539    "8225": [0.19444, 0.69444, 0, 0, 0.51111],
 1540    "8242": [0, 0.55556, 0, 0, 0.34444],
 1541    "8407": [0, 0.72444, 0.15486, 0, 0.575],
 1542    "8463": [0, 0.69444, 0, 0, 0.66759],
 1543    "8465": [0, 0.69444, 0, 0, 0.83055],
 1544    "8467": [0, 0.69444, 0, 0, 0.47361],
 1545    "8472": [0.19444, 0.44444, 0, 0, 0.74027],
 1546    "8476": [0, 0.69444, 0, 0, 0.83055],
 1547    "8501": [0, 0.69444, 0, 0, 0.70277],
 1548    "8592": [-0.10889, 0.39111, 0, 0, 1.14999],
 1549    "8593": [0.19444, 0.69444, 0, 0, 0.575],
 1550    "8594": [-0.10889, 0.39111, 0, 0, 1.14999],
 1551    "8595": [0.19444, 0.69444, 0, 0, 0.575],
 1552    "8596": [-0.10889, 0.39111, 0, 0, 1.14999],
 1553    "8597": [0.25, 0.75, 0, 0, 0.575],
 1554    "8598": [0.19444, 0.69444, 0, 0, 1.14999],
 1555    "8599": [0.19444, 0.69444, 0, 0, 1.14999],
 1556    "8600": [0.19444, 0.69444, 0, 0, 1.14999],
 1557    "8601": [0.19444, 0.69444, 0, 0, 1.14999],
 1558    "8636": [-0.10889, 0.39111, 0, 0, 1.14999],
 1559    "8637": [-0.10889, 0.39111, 0, 0, 1.14999],
 1560    "8640": [-0.10889, 0.39111, 0, 0, 1.14999],
 1561    "8641": [-0.10889, 0.39111, 0, 0, 1.14999],
 1562    "8656": [-0.10889, 0.39111, 0, 0, 1.14999],
 1563    "8657": [0.19444, 0.69444, 0, 0, 0.70277],
 1564    "8658": [-0.10889, 0.39111, 0, 0, 1.14999],
 1565    "8659": [0.19444, 0.69444, 0, 0, 0.70277],
 1566    "8660": [-0.10889, 0.39111, 0, 0, 1.14999],
 1567    "8661": [0.25, 0.75, 0, 0, 0.70277],
 1568    "8704": [0, 0.69444, 0, 0, 0.63889],
 1569    "8706": [0, 0.69444, 0.06389, 0, 0.62847],
 1570    "8707": [0, 0.69444, 0, 0, 0.63889],
 1571    "8709": [0.05556, 0.75, 0, 0, 0.575],
 1572    "8711": [0, 0.68611, 0, 0, 0.95833],
 1573    "8712": [0.08556, 0.58556, 0, 0, 0.76666],
 1574    "8715": [0.08556, 0.58556, 0, 0, 0.76666],
 1575    "8722": [0.13333, 0.63333, 0, 0, 0.89444],
 1576    "8723": [0.13333, 0.63333, 0, 0, 0.89444],
 1577    "8725": [0.25, 0.75, 0, 0, 0.575],
 1578    "8726": [0.25, 0.75, 0, 0, 0.575],
 1579    "8727": [-0.02778, 0.47222, 0, 0, 0.575],
 1580    "8728": [-0.02639, 0.47361, 0, 0, 0.575],
 1581    "8729": [-0.02639, 0.47361, 0, 0, 0.575],
 1582    "8730": [0.18, 0.82, 0, 0, 0.95833],
 1583    "8733": [0, 0.44444, 0, 0, 0.89444],
 1584    "8734": [0, 0.44444, 0, 0, 1.14999],
 1585    "8736": [0, 0.69224, 0, 0, 0.72222],
 1586    "8739": [0.25, 0.75, 0, 0, 0.31944],
 1587    "8741": [0.25, 0.75, 0, 0, 0.575],
 1588    "8743": [0, 0.55556, 0, 0, 0.76666],
 1589    "8744": [0, 0.55556, 0, 0, 0.76666],
 1590    "8745": [0, 0.55556, 0, 0, 0.76666],
 1591    "8746": [0, 0.55556, 0, 0, 0.76666],
 1592    "8747": [0.19444, 0.69444, 0.12778, 0, 0.56875],
 1593    "8764": [-0.10889, 0.39111, 0, 0, 0.89444],
 1594    "8768": [0.19444, 0.69444, 0, 0, 0.31944],
 1595    "8771": [0.00222, 0.50222, 0, 0, 0.89444],
 1596    "8773": [0.027, 0.638, 0, 0, 0.894],
 1597    "8776": [0.02444, 0.52444, 0, 0, 0.89444],
 1598    "8781": [0.00222, 0.50222, 0, 0, 0.89444],
 1599    "8801": [0.00222, 0.50222, 0, 0, 0.89444],
 1600    "8804": [0.19667, 0.69667, 0, 0, 0.89444],
 1601    "8805": [0.19667, 0.69667, 0, 0, 0.89444],
 1602    "8810": [0.08556, 0.58556, 0, 0, 1.14999],
 1603    "8811": [0.08556, 0.58556, 0, 0, 1.14999],
 1604    "8826": [0.08556, 0.58556, 0, 0, 0.89444],
 1605    "8827": [0.08556, 0.58556, 0, 0, 0.89444],
 1606    "8834": [0.08556, 0.58556, 0, 0, 0.89444],
 1607    "8835": [0.08556, 0.58556, 0, 0, 0.89444],
 1608    "8838": [0.19667, 0.69667, 0, 0, 0.89444],
 1609    "8839": [0.19667, 0.69667, 0, 0, 0.89444],
 1610    "8846": [0, 0.55556, 0, 0, 0.76666],
 1611    "8849": [0.19667, 0.69667, 0, 0, 0.89444],
 1612    "8850": [0.19667, 0.69667, 0, 0, 0.89444],
 1613    "8851": [0, 0.55556, 0, 0, 0.76666],
 1614    "8852": [0, 0.55556, 0, 0, 0.76666],
 1615    "8853": [0.13333, 0.63333, 0, 0, 0.89444],
 1616    "8854": [0.13333, 0.63333, 0, 0, 0.89444],
 1617    "8855": [0.13333, 0.63333, 0, 0, 0.89444],
 1618    "8856": [0.13333, 0.63333, 0, 0, 0.89444],
 1619    "8857": [0.13333, 0.63333, 0, 0, 0.89444],
 1620    "8866": [0, 0.69444, 0, 0, 0.70277],
 1621    "8867": [0, 0.69444, 0, 0, 0.70277],
 1622    "8868": [0, 0.69444, 0, 0, 0.89444],
 1623    "8869": [0, 0.69444, 0, 0, 0.89444],
 1624    "8900": [-0.02639, 0.47361, 0, 0, 0.575],
 1625    "8901": [-0.02639, 0.47361, 0, 0, 0.31944],
 1626    "8902": [-0.02778, 0.47222, 0, 0, 0.575],
 1627    "8968": [0.25, 0.75, 0, 0, 0.51111],
 1628    "8969": [0.25, 0.75, 0, 0, 0.51111],
 1629    "8970": [0.25, 0.75, 0, 0, 0.51111],
 1630    "8971": [0.25, 0.75, 0, 0, 0.51111],
 1631    "8994": [-0.13889, 0.36111, 0, 0, 1.14999],
 1632    "8995": [-0.13889, 0.36111, 0, 0, 1.14999],
 1633    "9651": [0.19444, 0.69444, 0, 0, 1.02222],
 1634    "9657": [-0.02778, 0.47222, 0, 0, 0.575],
 1635    "9661": [0.19444, 0.69444, 0, 0, 1.02222],
 1636    "9667": [-0.02778, 0.47222, 0, 0, 0.575],
 1637    "9711": [0.19444, 0.69444, 0, 0, 1.14999],
 1638    "9824": [0.12963, 0.69444, 0, 0, 0.89444],
 1639    "9825": [0.12963, 0.69444, 0, 0, 0.89444],
 1640    "9826": [0.12963, 0.69444, 0, 0, 0.89444],
 1641    "9827": [0.12963, 0.69444, 0, 0, 0.89444],
 1642    "9837": [0, 0.75, 0, 0, 0.44722],
 1643    "9838": [0.19444, 0.69444, 0, 0, 0.44722],
 1644    "9839": [0.19444, 0.69444, 0, 0, 0.44722],
 1645    "10216": [0.25, 0.75, 0, 0, 0.44722],
 1646    "10217": [0.25, 0.75, 0, 0, 0.44722],
 1647    "10815": [0, 0.68611, 0, 0, 0.9],
 1648    "10927": [0.19667, 0.69667, 0, 0, 0.89444],
 1649    "10928": [0.19667, 0.69667, 0, 0, 0.89444],
 1650    "57376": [0.19444, 0.69444, 0, 0, 0]
 1651  },
 1652  "Main-BoldItalic": {
 1653    "32": [0, 0, 0, 0, 0.25],
 1654    "33": [0, 0.69444, 0.11417, 0, 0.38611],
 1655    "34": [0, 0.69444, 0.07939, 0, 0.62055],
 1656    "35": [0.19444, 0.69444, 0.06833, 0, 0.94444],
 1657    "37": [0.05556, 0.75, 0.12861, 0, 0.94444],
 1658    "38": [0, 0.69444, 0.08528, 0, 0.88555],
 1659    "39": [0, 0.69444, 0.12945, 0, 0.35555],
 1660    "40": [0.25, 0.75, 0.15806, 0, 0.47333],
 1661    "41": [0.25, 0.75, 0.03306, 0, 0.47333],
 1662    "42": [0, 0.75, 0.14333, 0, 0.59111],
 1663    "43": [0.10333, 0.60333, 0.03306, 0, 0.88555],
 1664    "44": [0.19444, 0.14722, 0, 0, 0.35555],
 1665    "45": [0, 0.44444, 0.02611, 0, 0.41444],
 1666    "46": [0, 0.14722, 0, 0, 0.35555],
 1667    "47": [0.25, 0.75, 0.15806, 0, 0.59111],
 1668    "48": [0, 0.64444, 0.13167, 0, 0.59111],
 1669    "49": [0, 0.64444, 0.13167, 0, 0.59111],
 1670    "50": [0, 0.64444, 0.13167, 0, 0.59111],
 1671    "51": [0, 0.64444, 0.13167, 0, 0.59111],
 1672    "52": [0.19444, 0.64444, 0.13167, 0, 0.59111],
 1673    "53": [0, 0.64444, 0.13167, 0, 0.59111],
 1674    "54": [0, 0.64444, 0.13167, 0, 0.59111],
 1675    "55": [0.19444, 0.64444, 0.13167, 0, 0.59111],
 1676    "56": [0, 0.64444, 0.13167, 0, 0.59111],
 1677    "57": [0, 0.64444, 0.13167, 0, 0.59111],
 1678    "58": [0, 0.44444, 0.06695, 0, 0.35555],
 1679    "59": [0.19444, 0.44444, 0.06695, 0, 0.35555],
 1680    "61": [-0.10889, 0.39111, 0.06833, 0, 0.88555],
 1681    "63": [0, 0.69444, 0.11472, 0, 0.59111],
 1682    "64": [0, 0.69444, 0.09208, 0, 0.88555],
 1683    "65": [0, 0.68611, 0, 0, 0.86555],
 1684    "66": [0, 0.68611, 0.0992, 0, 0.81666],
 1685    "67": [0, 0.68611, 0.14208, 0, 0.82666],
 1686    "68": [0, 0.68611, 0.09062, 0, 0.87555],
 1687    "69": [0, 0.68611, 0.11431, 0, 0.75666],
 1688    "70": [0, 0.68611, 0.12903, 0, 0.72722],
 1689    "71": [0, 0.68611, 0.07347, 0, 0.89527],
 1690    "72": [0, 0.68611, 0.17208, 0, 0.8961],
 1691    "73": [0, 0.68611, 0.15681, 0, 0.47166],
 1692    "74": [0, 0.68611, 0.145, 0, 0.61055],
 1693    "75": [0, 0.68611, 0.14208, 0, 0.89499],
 1694    "76": [0, 0.68611, 0, 0, 0.69777],
 1695    "77": [0, 0.68611, 0.17208, 0, 1.07277],
 1696    "78": [0, 0.68611, 0.17208, 0, 0.8961],
 1697    "79": [0, 0.68611, 0.09062, 0, 0.85499],
 1698    "80": [0, 0.68611, 0.0992, 0, 0.78721],
 1699    "81": [0.19444, 0.68611, 0.09062, 0, 0.85499],
 1700    "82": [0, 0.68611, 0.02559, 0, 0.85944],
 1701    "83": [0, 0.68611, 0.11264, 0, 0.64999],
 1702    "84": [0, 0.68611, 0.12903, 0, 0.7961],
 1703    "85": [0, 0.68611, 0.17208, 0, 0.88083],
 1704    "86": [0, 0.68611, 0.18625, 0, 0.86555],
 1705    "87": [0, 0.68611, 0.18625, 0, 1.15999],
 1706    "88": [0, 0.68611, 0.15681, 0, 0.86555],
 1707    "89": [0, 0.68611, 0.19803, 0, 0.86555],
 1708    "90": [0, 0.68611, 0.14208, 0, 0.70888],
 1709    "91": [0.25, 0.75, 0.1875, 0, 0.35611],
 1710    "93": [0.25, 0.75, 0.09972, 0, 0.35611],
 1711    "94": [0, 0.69444, 0.06709, 0, 0.59111],
 1712    "95": [0.31, 0.13444, 0.09811, 0, 0.59111],
 1713    "97": [0, 0.44444, 0.09426, 0, 0.59111],
 1714    "98": [0, 0.69444, 0.07861, 0, 0.53222],
 1715    "99": [0, 0.44444, 0.05222, 0, 0.53222],
 1716    "100": [0, 0.69444, 0.10861, 0, 0.59111],
 1717    "101": [0, 0.44444, 0.085, 0, 0.53222],
 1718    "102": [0.19444, 0.69444, 0.21778, 0, 0.4],
 1719    "103": [0.19444, 0.44444, 0.105, 0, 0.53222],
 1720    "104": [0, 0.69444, 0.09426, 0, 0.59111],
 1721    "105": [0, 0.69326, 0.11387, 0, 0.35555],
 1722    "106": [0.19444, 0.69326, 0.1672, 0, 0.35555],
 1723    "107": [0, 0.69444, 0.11111, 0, 0.53222],
 1724    "108": [0, 0.69444, 0.10861, 0, 0.29666],
 1725    "109": [0, 0.44444, 0.09426, 0, 0.94444],
 1726    "110": [0, 0.44444, 0.09426, 0, 0.64999],
 1727    "111": [0, 0.44444, 0.07861, 0, 0.59111],
 1728    "112": [0.19444, 0.44444, 0.07861, 0, 0.59111],
 1729    "113": [0.19444, 0.44444, 0.105, 0, 0.53222],
 1730    "114": [0, 0.44444, 0.11111, 0, 0.50167],
 1731    "115": [0, 0.44444, 0.08167, 0, 0.48694],
 1732    "116": [0, 0.63492, 0.09639, 0, 0.385],
 1733    "117": [0, 0.44444, 0.09426, 0, 0.62055],
 1734    "118": [0, 0.44444, 0.11111, 0, 0.53222],
 1735    "119": [0, 0.44444, 0.11111, 0, 0.76777],
 1736    "120": [0, 0.44444, 0.12583, 0, 0.56055],
 1737    "121": [0.19444, 0.44444, 0.105, 0, 0.56166],
 1738    "122": [0, 0.44444, 0.13889, 0, 0.49055],
 1739    "126": [0.35, 0.34444, 0.11472, 0, 0.59111],
 1740    "160": [0, 0, 0, 0, 0.25],
 1741    "168": [0, 0.69444, 0.11473, 0, 0.59111],
 1742    "176": [0, 0.69444, 0, 0, 0.94888],
 1743    "184": [0.17014, 0, 0, 0, 0.53222],
 1744    "198": [0, 0.68611, 0.11431, 0, 1.02277],
 1745    "216": [0.04861, 0.73472, 0.09062, 0, 0.88555],
 1746    "223": [0.19444, 0.69444, 0.09736, 0, 0.665],
 1747    "230": [0, 0.44444, 0.085, 0, 0.82666],
 1748    "248": [0.09722, 0.54167, 0.09458, 0, 0.59111],
 1749    "305": [0, 0.44444, 0.09426, 0, 0.35555],
 1750    "338": [0, 0.68611, 0.11431, 0, 1.14054],
 1751    "339": [0, 0.44444, 0.085, 0, 0.82666],
 1752    "567": [0.19444, 0.44444, 0.04611, 0, 0.385],
 1753    "710": [0, 0.69444, 0.06709, 0, 0.59111],
 1754    "711": [0, 0.63194, 0.08271, 0, 0.59111],
 1755    "713": [0, 0.59444, 0.10444, 0, 0.59111],
 1756    "714": [0, 0.69444, 0.08528, 0, 0.59111],
 1757    "715": [0, 0.69444, 0, 0, 0.59111],
 1758    "728": [0, 0.69444, 0.10333, 0, 0.59111],
 1759    "729": [0, 0.69444, 0.12945, 0, 0.35555],
 1760    "730": [0, 0.69444, 0, 0, 0.94888],
 1761    "732": [0, 0.69444, 0.11472, 0, 0.59111],
 1762    "733": [0, 0.69444, 0.11472, 0, 0.59111],
 1763    "915": [0, 0.68611, 0.12903, 0, 0.69777],
 1764    "916": [0, 0.68611, 0, 0, 0.94444],
 1765    "920": [0, 0.68611, 0.09062, 0, 0.88555],
 1766    "923": [0, 0.68611, 0, 0, 0.80666],
 1767    "926": [0, 0.68611, 0.15092, 0, 0.76777],
 1768    "928": [0, 0.68611, 0.17208, 0, 0.8961],
 1769    "931": [0, 0.68611, 0.11431, 0, 0.82666],
 1770    "933": [0, 0.68611, 0.10778, 0, 0.88555],
 1771    "934": [0, 0.68611, 0.05632, 0, 0.82666],
 1772    "936": [0, 0.68611, 0.10778, 0, 0.88555],
 1773    "937": [0, 0.68611, 0.0992, 0, 0.82666],
 1774    "8211": [0, 0.44444, 0.09811, 0, 0.59111],
 1775    "8212": [0, 0.44444, 0.09811, 0, 1.18221],
 1776    "8216": [0, 0.69444, 0.12945, 0, 0.35555],
 1777    "8217": [0, 0.69444, 0.12945, 0, 0.35555],
 1778    "8220": [0, 0.69444, 0.16772, 0, 0.62055],
 1779    "8221": [0, 0.69444, 0.07939, 0, 0.62055]
 1780  },
 1781  "Main-Italic": {
 1782    "32": [0, 0, 0, 0, 0.25],
 1783    "33": [0, 0.69444, 0.12417, 0, 0.30667],
 1784    "34": [0, 0.69444, 0.06961, 0, 0.51444],
 1785    "35": [0.19444, 0.69444, 0.06616, 0, 0.81777],
 1786    "37": [0.05556, 0.75, 0.13639, 0, 0.81777],
 1787    "38": [0, 0.69444, 0.09694, 0, 0.76666],
 1788    "39": [0, 0.69444, 0.12417, 0, 0.30667],
 1789    "40": [0.25, 0.75, 0.16194, 0, 0.40889],
 1790    "41": [0.25, 0.75, 0.03694, 0, 0.40889],
 1791    "42": [0, 0.75, 0.14917, 0, 0.51111],
 1792    "43": [0.05667, 0.56167, 0.03694, 0, 0.76666],
 1793    "44": [0.19444, 0.10556, 0, 0, 0.30667],
 1794    "45": [0, 0.43056, 0.02826, 0, 0.35778],
 1795    "46": [0, 0.10556, 0, 0, 0.30667],
 1796    "47": [0.25, 0.75, 0.16194, 0, 0.51111],
 1797    "48": [0, 0.64444, 0.13556, 0, 0.51111],
 1798    "49": [0, 0.64444, 0.13556, 0, 0.51111],
 1799    "50": [0, 0.64444, 0.13556, 0, 0.51111],
 1800    "51": [0, 0.64444, 0.13556, 0, 0.51111],
 1801    "52": [0.19444, 0.64444, 0.13556, 0, 0.51111],
 1802    "53": [0, 0.64444, 0.13556, 0, 0.51111],
 1803    "54": [0, 0.64444, 0.13556, 0, 0.51111],
 1804    "55": [0.19444, 0.64444, 0.13556, 0, 0.51111],
 1805    "56": [0, 0.64444, 0.13556, 0, 0.51111],
 1806    "57": [0, 0.64444, 0.13556, 0, 0.51111],
 1807    "58": [0, 0.43056, 0.0582, 0, 0.30667],
 1808    "59": [0.19444, 0.43056, 0.0582, 0, 0.30667],
 1809    "61": [-0.13313, 0.36687, 0.06616, 0, 0.76666],
 1810    "63": [0, 0.69444, 0.1225, 0, 0.51111],
 1811    "64": [0, 0.69444, 0.09597, 0, 0.76666],
 1812    "65": [0, 0.68333, 0, 0, 0.74333],
 1813    "66": [0, 0.68333, 0.10257, 0, 0.70389],
 1814    "67": [0, 0.68333, 0.14528, 0, 0.71555],
 1815    "68": [0, 0.68333, 0.09403, 0, 0.755],
 1816    "69": [0, 0.68333, 0.12028, 0, 0.67833],
 1817    "70": [0, 0.68333, 0.13305, 0, 0.65277],
 1818    "71": [0, 0.68333, 0.08722, 0, 0.77361],
 1819    "72": [0, 0.68333, 0.16389, 0, 0.74333],
 1820    "73": [0, 0.68333, 0.15806, 0, 0.38555],
 1821    "74": [0, 0.68333, 0.14028, 0, 0.525],
 1822    "75": [0, 0.68333, 0.14528, 0, 0.76888],
 1823    "76": [0, 0.68333, 0, 0, 0.62722],
 1824    "77": [0, 0.68333, 0.16389, 0, 0.89666],
 1825    "78": [0, 0.68333, 0.16389, 0, 0.74333],
 1826    "79": [0, 0.68333, 0.09403, 0, 0.76666],
 1827    "80": [0, 0.68333, 0.10257, 0, 0.67833],
 1828    "81": [0.19444, 0.68333, 0.09403, 0, 0.76666],
 1829    "82": [0, 0.68333, 0.03868, 0, 0.72944],
 1830    "83": [0, 0.68333, 0.11972, 0, 0.56222],
 1831    "84": [0, 0.68333, 0.13305, 0, 0.71555],
 1832    "85": [0, 0.68333, 0.16389, 0, 0.74333],
 1833    "86": [0, 0.68333, 0.18361, 0, 0.74333],
 1834    "87": [0, 0.68333, 0.18361, 0, 0.99888],
 1835    "88": [0, 0.68333, 0.15806, 0, 0.74333],
 1836    "89": [0, 0.68333, 0.19383, 0, 0.74333],
 1837    "90": [0, 0.68333, 0.14528, 0, 0.61333],
 1838    "91": [0.25, 0.75, 0.1875, 0, 0.30667],
 1839    "93": [0.25, 0.75, 0.10528, 0, 0.30667],
 1840    "94": [0, 0.69444, 0.06646, 0, 0.51111],
 1841    "95": [0.31, 0.12056, 0.09208, 0, 0.51111],
 1842    "97": [0, 0.43056, 0.07671, 0, 0.51111],
 1843    "98": [0, 0.69444, 0.06312, 0, 0.46],
 1844    "99": [0, 0.43056, 0.05653, 0, 0.46],
 1845    "100": [0, 0.69444, 0.10333, 0, 0.51111],
 1846    "101": [0, 0.43056, 0.07514, 0, 0.46],
 1847    "102": [0.19444, 0.69444, 0.21194, 0, 0.30667],
 1848    "103": [0.19444, 0.43056, 0.08847, 0, 0.46],
 1849    "104": [0, 0.69444, 0.07671, 0, 0.51111],
 1850    "105": [0, 0.65536, 0.1019, 0, 0.30667],
 1851    "106": [0.19444, 0.65536, 0.14467, 0, 0.30667],
 1852    "107": [0, 0.69444, 0.10764, 0, 0.46],
 1853    "108": [0, 0.69444, 0.10333, 0, 0.25555],
 1854    "109": [0, 0.43056, 0.07671, 0, 0.81777],
 1855    "110": [0, 0.43056, 0.07671, 0, 0.56222],
 1856    "111": [0, 0.43056, 0.06312, 0, 0.51111],
 1857    "112": [0.19444, 0.43056, 0.06312, 0, 0.51111],
 1858    "113": [0.19444, 0.43056, 0.08847, 0, 0.46],
 1859    "114": [0, 0.43056, 0.10764, 0, 0.42166],
 1860    "115": [0, 0.43056, 0.08208, 0, 0.40889],
 1861    "116": [0, 0.61508, 0.09486, 0, 0.33222],
 1862    "117": [0, 0.43056, 0.07671, 0, 0.53666],
 1863    "118": [0, 0.43056, 0.10764, 0, 0.46],
 1864    "119": [0, 0.43056, 0.10764, 0, 0.66444],
 1865    "120": [0, 0.43056, 0.12042, 0, 0.46389],
 1866    "121": [0.19444, 0.43056, 0.08847, 0, 0.48555],
 1867    "122": [0, 0.43056, 0.12292, 0, 0.40889],
 1868    "126": [0.35, 0.31786, 0.11585, 0, 0.51111],
 1869    "160": [0, 0, 0, 0, 0.25],
 1870    "168": [0, 0.66786, 0.10474, 0, 0.51111],
 1871    "176": [0, 0.69444, 0, 0, 0.83129],
 1872    "184": [0.17014, 0, 0, 0, 0.46],
 1873    "198": [0, 0.68333, 0.12028, 0, 0.88277],
 1874    "216": [0.04861, 0.73194, 0.09403, 0, 0.76666],
 1875    "223": [0.19444, 0.69444, 0.10514, 0, 0.53666],
 1876    "230": [0, 0.43056, 0.07514, 0, 0.71555],
 1877    "248": [0.09722, 0.52778, 0.09194, 0, 0.51111],
 1878    "338": [0, 0.68333, 0.12028, 0, 0.98499],
 1879    "339": [0, 0.43056, 0.07514, 0, 0.71555],
 1880    "710": [0, 0.69444, 0.06646, 0, 0.51111],
 1881    "711": [0, 0.62847, 0.08295, 0, 0.51111],
 1882    "713": [0, 0.56167, 0.10333, 0, 0.51111],
 1883    "714": [0, 0.69444, 0.09694, 0, 0.51111],
 1884    "715": [0, 0.69444, 0, 0, 0.51111],
 1885    "728": [0, 0.69444, 0.10806, 0, 0.51111],
 1886    "729": [0, 0.66786, 0.11752, 0, 0.30667],
 1887    "730": [0, 0.69444, 0, 0, 0.83129],
 1888    "732": [0, 0.66786, 0.11585, 0, 0.51111],
 1889    "733": [0, 0.69444, 0.1225, 0, 0.51111],
 1890    "915": [0, 0.68333, 0.13305, 0, 0.62722],
 1891    "916": [0, 0.68333, 0, 0, 0.81777],
 1892    "920": [0, 0.68333, 0.09403, 0, 0.76666],
 1893    "923": [0, 0.68333, 0, 0, 0.69222],
 1894    "926": [0, 0.68333, 0.15294, 0, 0.66444],
 1895    "928": [0, 0.68333, 0.16389, 0, 0.74333],
 1896    "931": [0, 0.68333, 0.12028, 0, 0.71555],
 1897    "933": [0, 0.68333, 0.11111, 0, 0.76666],
 1898    "934": [0, 0.68333, 0.05986, 0, 0.71555],
 1899    "936": [0, 0.68333, 0.11111, 0, 0.76666],
 1900    "937": [0, 0.68333, 0.10257, 0, 0.71555],
 1901    "8211": [0, 0.43056, 0.09208, 0, 0.51111],
 1902    "8212": [0, 0.43056, 0.09208, 0, 1.02222],
 1903    "8216": [0, 0.69444, 0.12417, 0, 0.30667],
 1904    "8217": [0, 0.69444, 0.12417, 0, 0.30667],
 1905    "8220": [0, 0.69444, 0.1685, 0, 0.51444],
 1906    "8221": [0, 0.69444, 0.06961, 0, 0.51444],
 1907    "8463": [0, 0.68889, 0, 0, 0.54028]
 1908  },
 1909  "Main-Regular": {
 1910    "32": [0, 0, 0, 0, 0.25],
 1911    "33": [0, 0.69444, 0, 0, 0.27778],
 1912    "34": [0, 0.69444, 0, 0, 0.5],
 1913    "35": [0.19444, 0.69444, 0, 0, 0.83334],
 1914    "36": [0.05556, 0.75, 0, 0, 0.5],
 1915    "37": [0.05556, 0.75, 0, 0, 0.83334],
 1916    "38": [0, 0.69444, 0, 0, 0.77778],
 1917    "39": [0, 0.69444, 0, 0, 0.27778],
 1918    "40": [0.25, 0.75, 0, 0, 0.38889],
 1919    "41": [0.25, 0.75, 0, 0, 0.38889],
 1920    "42": [0, 0.75, 0, 0, 0.5],
 1921    "43": [0.08333, 0.58333, 0, 0, 0.77778],
 1922    "44": [0.19444, 0.10556, 0, 0, 0.27778],
 1923    "45": [0, 0.43056, 0, 0, 0.33333],
 1924    "46": [0, 0.10556, 0, 0, 0.27778],
 1925    "47": [0.25, 0.75, 0, 0, 0.5],
 1926    "48": [0, 0.64444, 0, 0, 0.5],
 1927    "49": [0, 0.64444, 0, 0, 0.5],
 1928    "50": [0, 0.64444, 0, 0, 0.5],
 1929    "51": [0, 0.64444, 0, 0, 0.5],
 1930    "52": [0, 0.64444, 0, 0, 0.5],
 1931    "53": [0, 0.64444, 0, 0, 0.5],
 1932    "54": [0, 0.64444, 0, 0, 0.5],
 1933    "55": [0, 0.64444, 0, 0, 0.5],
 1934    "56": [0, 0.64444, 0, 0, 0.5],
 1935    "57": [0, 0.64444, 0, 0, 0.5],
 1936    "58": [0, 0.43056, 0, 0, 0.27778],
 1937    "59": [0.19444, 0.43056, 0, 0, 0.27778],
 1938    "60": [0.0391, 0.5391, 0, 0, 0.77778],
 1939    "61": [-0.13313, 0.36687, 0, 0, 0.77778],
 1940    "62": [0.0391, 0.5391, 0, 0, 0.77778],
 1941    "63": [0, 0.69444, 0, 0, 0.47222],
 1942    "64": [0, 0.69444, 0, 0, 0.77778],
 1943    "65": [0, 0.68333, 0, 0, 0.75],
 1944    "66": [0, 0.68333, 0, 0, 0.70834],
 1945    "67": [0, 0.68333, 0, 0, 0.72222],
 1946    "68": [0, 0.68333, 0, 0, 0.76389],
 1947    "69": [0, 0.68333, 0, 0, 0.68056],
 1948    "70": [0, 0.68333, 0, 0, 0.65278],
 1949    "71": [0, 0.68333, 0, 0, 0.78472],
 1950    "72": [0, 0.68333, 0, 0, 0.75],
 1951    "73": [0, 0.68333, 0, 0, 0.36111],
 1952    "74": [0, 0.68333, 0, 0, 0.51389],
 1953    "75": [0, 0.68333, 0, 0, 0.77778],
 1954    "76": [0, 0.68333, 0, 0, 0.625],
 1955    "77": [0, 0.68333, 0, 0, 0.91667],
 1956    "78": [0, 0.68333, 0, 0, 0.75],
 1957    "79": [0, 0.68333, 0, 0, 0.77778],
 1958    "80": [0, 0.68333, 0, 0, 0.68056],
 1959    "81": [0.19444, 0.68333, 0, 0, 0.77778],
 1960    "82": [0, 0.68333, 0, 0, 0.73611],
 1961    "83": [0, 0.68333, 0, 0, 0.55556],
 1962    "84": [0, 0.68333, 0, 0, 0.72222],
 1963    "85": [0, 0.68333, 0, 0, 0.75],
 1964    "86": [0, 0.68333, 0.01389, 0, 0.75],
 1965    "87": [0, 0.68333, 0.01389, 0, 1.02778],
 1966    "88": [0, 0.68333, 0, 0, 0.75],
 1967    "89": [0, 0.68333, 0.025, 0, 0.75],
 1968    "90": [0, 0.68333, 0, 0, 0.61111],
 1969    "91": [0.25, 0.75, 0, 0, 0.27778],
 1970    "92": [0.25, 0.75, 0, 0, 0.5],
 1971    "93": [0.25, 0.75, 0, 0, 0.27778],
 1972    "94": [0, 0.69444, 0, 0, 0.5],
 1973    "95": [0.31, 0.12056, 0.02778, 0, 0.5],
 1974    "97": [0, 0.43056, 0, 0, 0.5],
 1975    "98": [0, 0.69444, 0, 0, 0.55556],
 1976    "99": [0, 0.43056, 0, 0, 0.44445],
 1977    "100": [0, 0.69444, 0, 0, 0.55556],
 1978    "101": [0, 0.43056, 0, 0, 0.44445],
 1979    "102": [0, 0.69444, 0.07778, 0, 0.30556],
 1980    "103": [0.19444, 0.43056, 0.01389, 0, 0.5],
 1981    "104": [0, 0.69444, 0, 0, 0.55556],
 1982    "105": [0, 0.66786, 0, 0, 0.27778],
 1983    "106": [0.19444, 0.66786, 0, 0, 0.30556],
 1984    "107": [0, 0.69444, 0, 0, 0.52778],
 1985    "108": [0, 0.69444, 0, 0, 0.27778],
 1986    "109": [0, 0.43056, 0, 0, 0.83334],
 1987    "110": [0, 0.43056, 0, 0, 0.55556],
 1988    "111": [0, 0.43056, 0, 0, 0.5],
 1989    "112": [0.19444, 0.43056, 0, 0, 0.55556],
 1990    "113": [0.19444, 0.43056, 0, 0, 0.52778],
 1991    "114": [0, 0.43056, 0, 0, 0.39167],
 1992    "115": [0, 0.43056, 0, 0, 0.39445],
 1993    "116": [0, 0.61508, 0, 0, 0.38889],
 1994    "117": [0, 0.43056, 0, 0, 0.55556],
 1995    "118": [0, 0.43056, 0.01389, 0, 0.52778],
 1996    "119": [0, 0.43056, 0.01389, 0, 0.72222],
 1997    "120": [0, 0.43056, 0, 0, 0.52778],
 1998    "121": [0.19444, 0.43056, 0.01389, 0, 0.52778],
 1999    "122": [0, 0.43056, 0, 0, 0.44445],
 2000    "123": [0.25, 0.75, 0, 0, 0.5],
 2001    "124": [0.25, 0.75, 0, 0, 0.27778],
 2002    "125": [0.25, 0.75, 0, 0, 0.5],
 2003    "126": [0.35, 0.31786, 0, 0, 0.5],
 2004    "160": [0, 0, 0, 0, 0.25],
 2005    "163": [0, 0.69444, 0, 0, 0.76909],
 2006    "167": [0.19444, 0.69444, 0, 0, 0.44445],
 2007    "168": [0, 0.66786, 0, 0, 0.5],
 2008    "172": [0, 0.43056, 0, 0, 0.66667],
 2009    "176": [0, 0.69444, 0, 0, 0.75],
 2010    "177": [0.08333, 0.58333, 0, 0, 0.77778],
 2011    "182": [0.19444, 0.69444, 0, 0, 0.61111],
 2012    "184": [0.17014, 0, 0, 0, 0.44445],
 2013    "198": [0, 0.68333, 0, 0, 0.90278],
 2014    "215": [0.08333, 0.58333, 0, 0, 0.77778],
 2015    "216": [0.04861, 0.73194, 0, 0, 0.77778],
 2016    "223": [0, 0.69444, 0, 0, 0.5],
 2017    "230": [0, 0.43056, 0, 0, 0.72222],
 2018    "247": [0.08333, 0.58333, 0, 0, 0.77778],
 2019    "248": [0.09722, 0.52778, 0, 0, 0.5],
 2020    "305": [0, 0.43056, 0, 0, 0.27778],
 2021    "338": [0, 0.68333, 0, 0, 1.01389],
 2022    "339": [0, 0.43056, 0, 0, 0.77778],
 2023    "567": [0.19444, 0.43056, 0, 0, 0.30556],
 2024    "710": [0, 0.69444, 0, 0, 0.5],
 2025    "711": [0, 0.62847, 0, 0, 0.5],
 2026    "713": [0, 0.56778, 0, 0, 0.5],
 2027    "714": [0, 0.69444, 0, 0, 0.5],
 2028    "715": [0, 0.69444, 0, 0, 0.5],
 2029    "728": [0, 0.69444, 0, 0, 0.5],
 2030    "729": [0, 0.66786, 0, 0, 0.27778],
 2031    "730": [0, 0.69444, 0, 0, 0.75],
 2032    "732": [0, 0.66786, 0, 0, 0.5],
 2033    "733": [0, 0.69444, 0, 0, 0.5],
 2034    "915": [0, 0.68333, 0, 0, 0.625],
 2035    "916": [0, 0.68333, 0, 0, 0.83334],
 2036    "920": [0, 0.68333, 0, 0, 0.77778],
 2037    "923": [0, 0.68333, 0, 0, 0.69445],
 2038    "926": [0, 0.68333, 0, 0, 0.66667],
 2039    "928": [0, 0.68333, 0, 0, 0.75],
 2040    "931": [0, 0.68333, 0, 0, 0.72222],
 2041    "933": [0, 0.68333, 0, 0, 0.77778],
 2042    "934": [0, 0.68333, 0, 0, 0.72222],
 2043    "936": [0, 0.68333, 0, 0, 0.77778],
 2044    "937": [0, 0.68333, 0, 0, 0.72222],
 2045    "8211": [0, 0.43056, 0.02778, 0, 0.5],
 2046    "8212": [0, 0.43056, 0.02778, 0, 1.0],
 2047    "8216": [0, 0.69444, 0, 0, 0.27778],
 2048    "8217": [0, 0.69444, 0, 0, 0.27778],
 2049    "8220": [0, 0.69444, 0, 0, 0.5],
 2050    "8221": [0, 0.69444, 0, 0, 0.5],
 2051    "8224": [0.19444, 0.69444, 0, 0, 0.44445],
 2052    "8225": [0.19444, 0.69444, 0, 0, 0.44445],
 2053    "8230": [0, 0.123, 0, 0, 1.172],
 2054    "8242": [0, 0.55556, 0, 0, 0.275],
 2055    "8407": [0, 0.71444, 0.15382, 0, 0.5],
 2056    "8463": [0, 0.68889, 0, 0, 0.54028],
 2057    "8465": [0, 0.69444, 0, 0, 0.72222],
 2058    "8467": [0, 0.69444, 0, 0.11111, 0.41667],
 2059    "8472": [0.19444, 0.43056, 0, 0.11111, 0.63646],
 2060    "8476": [0, 0.69444, 0, 0, 0.72222],
 2061    "8501": [0, 0.69444, 0, 0, 0.61111],
 2062    "8592": [-0.13313, 0.36687, 0, 0, 1.0],
 2063    "8593": [0.19444, 0.69444, 0, 0, 0.5],
 2064    "8594": [-0.13313, 0.36687, 0, 0, 1.0],
 2065    "8595": [0.19444, 0.69444, 0, 0, 0.5],
 2066    "8596": [-0.13313, 0.36687, 0, 0, 1.0],
 2067    "8597": [0.25, 0.75, 0, 0, 0.5],
 2068    "8598": [0.19444, 0.69444, 0, 0, 1.0],
 2069    "8599": [0.19444, 0.69444, 0, 0, 1.0],
 2070    "8600": [0.19444, 0.69444, 0, 0, 1.0],
 2071    "8601": [0.19444, 0.69444, 0, 0, 1.0],
 2072    "8614": [0.011, 0.511, 0, 0, 1.0],
 2073    "8617": [0.011, 0.511, 0, 0, 1.126],
 2074    "8618": [0.011, 0.511, 0, 0, 1.126],
 2075    "8636": [-0.13313, 0.36687, 0, 0, 1.0],
 2076    "8637": [-0.13313, 0.36687, 0, 0, 1.0],
 2077    "8640": [-0.13313, 0.36687, 0, 0, 1.0],
 2078    "8641": [-0.13313, 0.36687, 0, 0, 1.0],
 2079    "8652": [0.011, 0.671, 0, 0, 1.0],
 2080    "8656": [-0.13313, 0.36687, 0, 0, 1.0],
 2081    "8657": [0.19444, 0.69444, 0, 0, 0.61111],
 2082    "8658": [-0.13313, 0.36687, 0, 0, 1.0],
 2083    "8659": [0.19444, 0.69444, 0, 0, 0.61111],
 2084    "8660": [-0.13313, 0.36687, 0, 0, 1.0],
 2085    "8661": [0.25, 0.75, 0, 0, 0.61111],
 2086    "8704": [0, 0.69444, 0, 0, 0.55556],
 2087    "8706": [0, 0.69444, 0.05556, 0.08334, 0.5309],
 2088    "8707": [0, 0.69444, 0, 0, 0.55556],
 2089    "8709": [0.05556, 0.75, 0, 0, 0.5],
 2090    "8711": [0, 0.68333, 0, 0, 0.83334],
 2091    "8712": [0.0391, 0.5391, 0, 0, 0.66667],
 2092    "8715": [0.0391, 0.5391, 0, 0, 0.66667],
 2093    "8722": [0.08333, 0.58333, 0, 0, 0.77778],
 2094    "8723": [0.08333, 0.58333, 0, 0, 0.77778],
 2095    "8725": [0.25, 0.75, 0, 0, 0.5],
 2096    "8726": [0.25, 0.75, 0, 0, 0.5],
 2097    "8727": [-0.03472, 0.46528, 0, 0, 0.5],
 2098    "8728": [-0.05555, 0.44445, 0, 0, 0.5],
 2099    "8729": [-0.05555, 0.44445, 0, 0, 0.5],
 2100    "8730": [0.2, 0.8, 0, 0, 0.83334],
 2101    "8733": [0, 0.43056, 0, 0, 0.77778],
 2102    "8734": [0, 0.43056, 0, 0, 1.0],
 2103    "8736": [0, 0.69224, 0, 0, 0.72222],
 2104    "8739": [0.25, 0.75, 0, 0, 0.27778],
 2105    "8741": [0.25, 0.75, 0, 0, 0.5],
 2106    "8743": [0, 0.55556, 0, 0, 0.66667],
 2107    "8744": [0, 0.55556, 0, 0, 0.66667],
 2108    "8745": [0, 0.55556, 0, 0, 0.66667],
 2109    "8746": [0, 0.55556, 0, 0, 0.66667],
 2110    "8747": [0.19444, 0.69444, 0.11111, 0, 0.41667],
 2111    "8764": [-0.13313, 0.36687, 0, 0, 0.77778],
 2112    "8768": [0.19444, 0.69444, 0, 0, 0.27778],
 2113    "8771": [-0.03625, 0.46375, 0, 0, 0.77778],
 2114    "8773": [-0.022, 0.589, 0, 0, 0.778],
 2115    "8776": [-0.01688, 0.48312, 0, 0, 0.77778],
 2116    "8781": [-0.03625, 0.46375, 0, 0, 0.77778],
 2117    "8784": [-0.133, 0.673, 0, 0, 0.778],
 2118    "8801": [-0.03625, 0.46375, 0, 0, 0.77778],
 2119    "8804": [0.13597, 0.63597, 0, 0, 0.77778],
 2120    "8805": [0.13597, 0.63597, 0, 0, 0.77778],
 2121    "8810": [0.0391, 0.5391, 0, 0, 1.0],
 2122    "8811": [0.0391, 0.5391, 0, 0, 1.0],
 2123    "8826": [0.0391, 0.5391, 0, 0, 0.77778],
 2124    "8827": [0.0391, 0.5391, 0, 0, 0.77778],
 2125    "8834": [0.0391, 0.5391, 0, 0, 0.77778],
 2126    "8835": [0.0391, 0.5391, 0, 0, 0.77778],
 2127    "8838": [0.13597, 0.63597, 0, 0, 0.77778],
 2128    "8839": [0.13597, 0.63597, 0, 0, 0.77778],
 2129    "8846": [0, 0.55556, 0, 0, 0.66667],
 2130    "8849": [0.13597, 0.63597, 0, 0, 0.77778],
 2131    "8850": [0.13597, 0.63597, 0, 0, 0.77778],
 2132    "8851": [0, 0.55556, 0, 0, 0.66667],
 2133    "8852": [0, 0.55556, 0, 0, 0.66667],
 2134    "8853": [0.08333, 0.58333, 0, 0, 0.77778],
 2135    "8854": [0.08333, 0.58333, 0, 0, 0.77778],
 2136    "8855": [0.08333, 0.58333, 0, 0, 0.77778],
 2137    "8856": [0.08333, 0.58333, 0, 0, 0.77778],
 2138    "8857": [0.08333, 0.58333, 0, 0, 0.77778],
 2139    "8866": [0, 0.69444, 0, 0, 0.61111],
 2140    "8867": [0, 0.69444, 0, 0, 0.61111],
 2141    "8868": [0, 0.69444, 0, 0, 0.77778],
 2142    "8869": [0, 0.69444, 0, 0, 0.77778],
 2143    "8872": [0.249, 0.75, 0, 0, 0.867],
 2144    "8900": [-0.05555, 0.44445, 0, 0, 0.5],
 2145    "8901": [-0.05555, 0.44445, 0, 0, 0.27778],
 2146    "8902": [-0.03472, 0.46528, 0, 0, 0.5],
 2147    "8904": [0.005, 0.505, 0, 0, 0.9],
 2148    "8942": [0.03, 0.903, 0, 0, 0.278],
 2149    "8943": [-0.19, 0.313, 0, 0, 1.172],
 2150    "8945": [-0.1, 0.823, 0, 0, 1.282],
 2151    "8968": [0.25, 0.75, 0, 0, 0.44445],
 2152    "8969": [0.25, 0.75, 0, 0, 0.44445],
 2153    "8970": [0.25, 0.75, 0, 0, 0.44445],
 2154    "8971": [0.25, 0.75, 0, 0, 0.44445],
 2155    "8994": [-0.14236, 0.35764, 0, 0, 1.0],
 2156    "8995": [-0.14236, 0.35764, 0, 0, 1.0],
 2157    "9136": [0.244, 0.744, 0, 0, 0.412],
 2158    "9137": [0.244, 0.745, 0, 0, 0.412],
 2159    "9651": [0.19444, 0.69444, 0, 0, 0.88889],
 2160    "9657": [-0.03472, 0.46528, 0, 0, 0.5],
 2161    "9661": [0.19444, 0.69444, 0, 0, 0.88889],
 2162    "9667": [-0.03472, 0.46528, 0, 0, 0.5],
 2163    "9711": [0.19444, 0.69444, 0, 0, 1.0],
 2164    "9824": [0.12963, 0.69444, 0, 0, 0.77778],
 2165    "9825": [0.12963, 0.69444, 0, 0, 0.77778],
 2166    "9826": [0.12963, 0.69444, 0, 0, 0.77778],
 2167    "9827": [0.12963, 0.69444, 0, 0, 0.77778],
 2168    "9837": [0, 0.75, 0, 0, 0.38889],
 2169    "9838": [0.19444, 0.69444, 0, 0, 0.38889],
 2170    "9839": [0.19444, 0.69444, 0, 0, 0.38889],
 2171    "10216": [0.25, 0.75, 0, 0, 0.38889],
 2172    "10217": [0.25, 0.75, 0, 0, 0.38889],
 2173    "10222": [0.244, 0.744, 0, 0, 0.412],
 2174    "10223": [0.244, 0.745, 0, 0, 0.412],
 2175    "10229": [0.011, 0.511, 0, 0, 1.609],
 2176    "10230": [0.011, 0.511, 0, 0, 1.638],
 2177    "10231": [0.011, 0.511, 0, 0, 1.859],
 2178    "10232": [0.024, 0.525, 0, 0, 1.609],
 2179    "10233": [0.024, 0.525, 0, 0, 1.638],
 2180    "10234": [0.024, 0.525, 0, 0, 1.858],
 2181    "10236": [0.011, 0.511, 0, 0, 1.638],
 2182    "10815": [0, 0.68333, 0, 0, 0.75],
 2183    "10927": [0.13597, 0.63597, 0, 0, 0.77778],
 2184    "10928": [0.13597, 0.63597, 0, 0, 0.77778],
 2185    "57376": [0.19444, 0.69444, 0, 0, 0]
 2186  },
 2187  "Math-BoldItalic": {
 2188    "32": [0, 0, 0, 0, 0.25],
 2189    "48": [0, 0.44444, 0, 0, 0.575],
 2190    "49": [0, 0.44444, 0, 0, 0.575],
 2191    "50": [0, 0.44444, 0, 0, 0.575],
 2192    "51": [0.19444, 0.44444, 0, 0, 0.575],
 2193    "52": [0.19444, 0.44444, 0, 0, 0.575],
 2194    "53": [0.19444, 0.44444, 0, 0, 0.575],
 2195    "54": [0, 0.64444, 0, 0, 0.575],
 2196    "55": [0.19444, 0.44444, 0, 0, 0.575],
 2197    "56": [0, 0.64444, 0, 0, 0.575],
 2198    "57": [0.19444, 0.44444, 0, 0, 0.575],
 2199    "65": [0, 0.68611, 0, 0, 0.86944],
 2200    "66": [0, 0.68611, 0.04835, 0, 0.8664],
 2201    "67": [0, 0.68611, 0.06979, 0, 0.81694],
 2202    "68": [0, 0.68611, 0.03194, 0, 0.93812],
 2203    "69": [0, 0.68611, 0.05451, 0, 0.81007],
 2204    "70": [0, 0.68611, 0.15972, 0, 0.68889],
 2205    "71": [0, 0.68611, 0, 0, 0.88673],
 2206    "72": [0, 0.68611, 0.08229, 0, 0.98229],
 2207    "73": [0, 0.68611, 0.07778, 0, 0.51111],
 2208    "74": [0, 0.68611, 0.10069, 0, 0.63125],
 2209    "75": [0, 0.68611, 0.06979, 0, 0.97118],
 2210    "76": [0, 0.68611, 0, 0, 0.75555],
 2211    "77": [0, 0.68611, 0.11424, 0, 1.14201],
 2212    "78": [0, 0.68611, 0.11424, 0, 0.95034],
 2213    "79": [0, 0.68611, 0.03194, 0, 0.83666],
 2214    "80": [0, 0.68611, 0.15972, 0, 0.72309],
 2215    "81": [0.19444, 0.68611, 0, 0, 0.86861],
 2216    "82": [0, 0.68611, 0.00421, 0, 0.87235],
 2217    "83": [0, 0.68611, 0.05382, 0, 0.69271],
 2218    "84": [0, 0.68611, 0.15972, 0, 0.63663],
 2219    "85": [0, 0.68611, 0.11424, 0, 0.80027],
 2220    "86": [0, 0.68611, 0.25555, 0, 0.67778],
 2221    "87": [0, 0.68611, 0.15972, 0, 1.09305],
 2222    "88": [0, 0.68611, 0.07778, 0, 0.94722],
 2223    "89": [0, 0.68611, 0.25555, 0, 0.67458],
 2224    "90": [0, 0.68611, 0.06979, 0, 0.77257],
 2225    "97": [0, 0.44444, 0, 0, 0.63287],
 2226    "98": [0, 0.69444, 0, 0, 0.52083],
 2227    "99": [0, 0.44444, 0, 0, 0.51342],
 2228    "100": [0, 0.69444, 0, 0, 0.60972],
 2229    "101": [0, 0.44444, 0, 0, 0.55361],
 2230    "102": [0.19444, 0.69444, 0.11042, 0, 0.56806],
 2231    "103": [0.19444, 0.44444, 0.03704, 0, 0.5449],
 2232    "104": [0, 0.69444, 0, 0, 0.66759],
 2233    "105": [0, 0.69326, 0, 0, 0.4048],
 2234    "106": [0.19444, 0.69326, 0.0622, 0, 0.47083],
 2235    "107": [0, 0.69444, 0.01852, 0, 0.6037],
 2236    "108": [0, 0.69444, 0.0088, 0, 0.34815],
 2237    "109": [0, 0.44444, 0, 0, 1.0324],
 2238    "110": [0, 0.44444, 0, 0, 0.71296],
 2239    "111": [0, 0.44444, 0, 0, 0.58472],
 2240    "112": [0.19444, 0.44444, 0, 0, 0.60092],
 2241    "113": [0.19444, 0.44444, 0.03704, 0, 0.54213],
 2242    "114": [0, 0.44444, 0.03194, 0, 0.5287],
 2243    "115": [0, 0.44444, 0, 0, 0.53125],
 2244    "116": [0, 0.63492, 0, 0, 0.41528],
 2245    "117": [0, 0.44444, 0, 0, 0.68102],
 2246    "118": [0, 0.44444, 0.03704, 0, 0.56666],
 2247    "119": [0, 0.44444, 0.02778, 0, 0.83148],
 2248    "120": [0, 0.44444, 0, 0, 0.65903],
 2249    "121": [0.19444, 0.44444, 0.03704, 0, 0.59028],
 2250    "122": [0, 0.44444, 0.04213, 0, 0.55509],
 2251    "160": [0, 0, 0, 0, 0.25],
 2252    "915": [0, 0.68611, 0.15972, 0, 0.65694],
 2253    "916": [0, 0.68611, 0, 0, 0.95833],
 2254    "920": [0, 0.68611, 0.03194, 0, 0.86722],
 2255    "923": [0, 0.68611, 0, 0, 0.80555],
 2256    "926": [0, 0.68611, 0.07458, 0, 0.84125],
 2257    "928": [0, 0.68611, 0.08229, 0, 0.98229],
 2258    "931": [0, 0.68611, 0.05451, 0, 0.88507],
 2259    "933": [0, 0.68611, 0.15972, 0, 0.67083],
 2260    "934": [0, 0.68611, 0, 0, 0.76666],
 2261    "936": [0, 0.68611, 0.11653, 0, 0.71402],
 2262    "937": [0, 0.68611, 0.04835, 0, 0.8789],
 2263    "945": [0, 0.44444, 0, 0, 0.76064],
 2264    "946": [0.19444, 0.69444, 0.03403, 0, 0.65972],
 2265    "947": [0.19444, 0.44444, 0.06389, 0, 0.59003],
 2266    "948": [0, 0.69444, 0.03819, 0, 0.52222],
 2267    "949": [0, 0.44444, 0, 0, 0.52882],
 2268    "950": [0.19444, 0.69444, 0.06215, 0, 0.50833],
 2269    "951": [0.19444, 0.44444, 0.03704, 0, 0.6],
 2270    "952": [0, 0.69444, 0.03194, 0, 0.5618],
 2271    "953": [0, 0.44444, 0, 0, 0.41204],
 2272    "954": [0, 0.44444, 0, 0, 0.66759],
 2273    "955": [0, 0.69444, 0, 0, 0.67083],
 2274    "956": [0.19444, 0.44444, 0, 0, 0.70787],
 2275    "957": [0, 0.44444, 0.06898, 0, 0.57685],
 2276    "958": [0.19444, 0.69444, 0.03021, 0, 0.50833],
 2277    "959": [0, 0.44444, 0, 0, 0.58472],
 2278    "960": [0, 0.44444, 0.03704, 0, 0.68241],
 2279    "961": [0.19444, 0.44444, 0, 0, 0.6118],
 2280    "962": [0.09722, 0.44444, 0.07917, 0, 0.42361],
 2281    "963": [0, 0.44444, 0.03704, 0, 0.68588],
 2282    "964": [0, 0.44444, 0.13472, 0, 0.52083],
 2283    "965": [0, 0.44444, 0.03704, 0, 0.63055],
 2284    "966": [0.19444, 0.44444, 0, 0, 0.74722],
 2285    "967": [0.19444, 0.44444, 0, 0, 0.71805],
 2286    "968": [0.19444, 0.69444, 0.03704, 0, 0.75833],
 2287    "969": [0, 0.44444, 0.03704, 0, 0.71782],
 2288    "977": [0, 0.69444, 0, 0, 0.69155],
 2289    "981": [0.19444, 0.69444, 0, 0, 0.7125],
 2290    "982": [0, 0.44444, 0.03194, 0, 0.975],
 2291    "1009": [0.19444, 0.44444, 0, 0, 0.6118],
 2292    "1013": [0, 0.44444, 0, 0, 0.48333],
 2293    "57649": [0, 0.44444, 0, 0, 0.39352],
 2294    "57911": [0.19444, 0.44444, 0, 0, 0.43889]
 2295  },
 2296  "Math-Italic": {
 2297    "32": [0, 0, 0, 0, 0.25],
 2298    "48": [0, 0.43056, 0, 0, 0.5],
 2299    "49": [0, 0.43056, 0, 0, 0.5],
 2300    "50": [0, 0.43056, 0, 0, 0.5],
 2301    "51": [0.19444, 0.43056, 0, 0, 0.5],
 2302    "52": [0.19444, 0.43056, 0, 0, 0.5],
 2303    "53": [0.19444, 0.43056, 0, 0, 0.5],
 2304    "54": [0, 0.64444, 0, 0, 0.5],
 2305    "55": [0.19444, 0.43056, 0, 0, 0.5],
 2306    "56": [0, 0.64444, 0, 0, 0.5],
 2307    "57": [0.19444, 0.43056, 0, 0, 0.5],
 2308    "65": [0, 0.68333, 0, 0.13889, 0.75],
 2309    "66": [0, 0.68333, 0.05017, 0.08334, 0.75851],
 2310    "67": [0, 0.68333, 0.07153, 0.08334, 0.71472],
 2311    "68": [0, 0.68333, 0.02778, 0.05556, 0.82792],
 2312    "69": [0, 0.68333, 0.05764, 0.08334, 0.7382],
 2313    "70": [0, 0.68333, 0.13889, 0.08334, 0.64306],
 2314    "71": [0, 0.68333, 0, 0.08334, 0.78625],
 2315    "72": [0, 0.68333, 0.08125, 0.05556, 0.83125],
 2316    "73": [0, 0.68333, 0.07847, 0.11111, 0.43958],
 2317    "74": [0, 0.68333, 0.09618, 0.16667, 0.55451],
 2318    "75": [0, 0.68333, 0.07153, 0.05556, 0.84931],
 2319    "76": [0, 0.68333, 0, 0.02778, 0.68056],
 2320    "77": [0, 0.68333, 0.10903, 0.08334, 0.97014],
 2321    "78": [0, 0.68333, 0.10903, 0.08334, 0.80347],
 2322    "79": [0, 0.68333, 0.02778, 0.08334, 0.76278],
 2323    "80": [0, 0.68333, 0.13889, 0.08334, 0.64201],
 2324    "81": [0.19444, 0.68333, 0, 0.08334, 0.79056],
 2325    "82": [0, 0.68333, 0.00773, 0.08334, 0.75929],
 2326    "83": [0, 0.68333, 0.05764, 0.08334, 0.6132],
 2327    "84": [0, 0.68333, 0.13889, 0.08334, 0.58438],
 2328    "85": [0, 0.68333, 0.10903, 0.02778, 0.68278],
 2329    "86": [0, 0.68333, 0.22222, 0, 0.58333],
 2330    "87": [0, 0.68333, 0.13889, 0, 0.94445],
 2331    "88": [0, 0.68333, 0.07847, 0.08334, 0.82847],
 2332    "89": [0, 0.68333, 0.22222, 0, 0.58056],
 2333    "90": [0, 0.68333, 0.07153, 0.08334, 0.68264],
 2334    "97": [0, 0.43056, 0, 0, 0.52859],
 2335    "98": [0, 0.69444, 0, 0, 0.42917],
 2336    "99": [0, 0.43056, 0, 0.05556, 0.43276],
 2337    "100": [0, 0.69444, 0, 0.16667, 0.52049],
 2338    "101": [0, 0.43056, 0, 0.05556, 0.46563],
 2339    "102": [0.19444, 0.69444, 0.10764, 0.16667, 0.48959],
 2340    "103": [0.19444, 0.43056, 0.03588, 0.02778, 0.47697],
 2341    "104": [0, 0.69444, 0, 0, 0.57616],
 2342    "105": [0, 0.65952, 0, 0, 0.34451],
 2343    "106": [0.19444, 0.65952, 0.05724, 0, 0.41181],
 2344    "107": [0, 0.69444, 0.03148, 0, 0.5206],
 2345    "108": [0, 0.69444, 0.01968, 0.08334, 0.29838],
 2346    "109": [0, 0.43056, 0, 0, 0.87801],
 2347    "110": [0, 0.43056, 0, 0, 0.60023],
 2348    "111": [0, 0.43056, 0, 0.05556, 0.48472],
 2349    "112": [0.19444, 0.43056, 0, 0.08334, 0.50313],
 2350    "113": [0.19444, 0.43056, 0.03588, 0.08334, 0.44641],
 2351    "114": [0, 0.43056, 0.02778, 0.05556, 0.45116],
 2352    "115": [0, 0.43056, 0, 0.05556, 0.46875],
 2353    "116": [0, 0.61508, 0, 0.08334, 0.36111],
 2354    "117": [0, 0.43056, 0, 0.02778, 0.57246],
 2355    "118": [0, 0.43056, 0.03588, 0.02778, 0.48472],
 2356    "119": [0, 0.43056, 0.02691, 0.08334, 0.71592],
 2357    "120": [0, 0.43056, 0, 0.02778, 0.57153],
 2358    "121": [0.19444, 0.43056, 0.03588, 0.05556, 0.49028],
 2359    "122": [0, 0.43056, 0.04398, 0.05556, 0.46505],
 2360    "160": [0, 0, 0, 0, 0.25],
 2361    "915": [0, 0.68333, 0.13889, 0.08334, 0.61528],
 2362    "916": [0, 0.68333, 0, 0.16667, 0.83334],
 2363    "920": [0, 0.68333, 0.02778, 0.08334, 0.76278],
 2364    "923": [0, 0.68333, 0, 0.16667, 0.69445],
 2365    "926": [0, 0.68333, 0.07569, 0.08334, 0.74236],
 2366    "928": [0, 0.68333, 0.08125, 0.05556, 0.83125],
 2367    "931": [0, 0.68333, 0.05764, 0.08334, 0.77986],
 2368    "933": [0, 0.68333, 0.13889, 0.05556, 0.58333],
 2369    "934": [0, 0.68333, 0, 0.08334, 0.66667],
 2370    "936": [0, 0.68333, 0.11, 0.05556, 0.61222],
 2371    "937": [0, 0.68333, 0.05017, 0.08334, 0.7724],
 2372    "945": [0, 0.43056, 0.0037, 0.02778, 0.6397],
 2373    "946": [0.19444, 0.69444, 0.05278, 0.08334, 0.56563],
 2374    "947": [0.19444, 0.43056, 0.05556, 0, 0.51773],
 2375    "948": [0, 0.69444, 0.03785, 0.05556, 0.44444],
 2376    "949": [0, 0.43056, 0, 0.08334, 0.46632],
 2377    "950": [0.19444, 0.69444, 0.07378, 0.08334, 0.4375],
 2378    "951": [0.19444, 0.43056, 0.03588, 0.05556, 0.49653],
 2379    "952": [0, 0.69444, 0.02778, 0.08334, 0.46944],
 2380    "953": [0, 0.43056, 0, 0.05556, 0.35394],
 2381    "954": [0, 0.43056, 0, 0, 0.57616],
 2382    "955": [0, 0.69444, 0, 0, 0.58334],
 2383    "956": [0.19444, 0.43056, 0, 0.02778, 0.60255],
 2384    "957": [0, 0.43056, 0.06366, 0.02778, 0.49398],
 2385    "958": [0.19444, 0.69444, 0.04601, 0.11111, 0.4375],
 2386    "959": [0, 0.43056, 0, 0.05556, 0.48472],
 2387    "960": [0, 0.43056, 0.03588, 0, 0.57003],
 2388    "961": [0.19444, 0.43056, 0, 0.08334, 0.51702],
 2389    "962": [0.09722, 0.43056, 0.07986, 0.08334, 0.36285],
 2390    "963": [0, 0.43056, 0.03588, 0, 0.57141],
 2391    "964": [0, 0.43056, 0.1132, 0.02778, 0.43715],
 2392    "965": [0, 0.43056, 0.03588, 0.02778, 0.54028],
 2393    "966": [0.19444, 0.43056, 0, 0.08334, 0.65417],
 2394    "967": [0.19444, 0.43056, 0, 0.05556, 0.62569],
 2395    "968": [0.19444, 0.69444, 0.03588, 0.11111, 0.65139],
 2396    "969": [0, 0.43056, 0.03588, 0, 0.62245],
 2397    "977": [0, 0.69444, 0, 0.08334, 0.59144],
 2398    "981": [0.19444, 0.69444, 0, 0.08334, 0.59583],
 2399    "982": [0, 0.43056, 0.02778, 0, 0.82813],
 2400    "1009": [0.19444, 0.43056, 0, 0.08334, 0.51702],
 2401    "1013": [0, 0.43056, 0, 0.05556, 0.4059],
 2402    "57649": [0, 0.43056, 0, 0.02778, 0.32246],
 2403    "57911": [0.19444, 0.43056, 0, 0.08334, 0.38403]
 2404  },
 2405  "SansSerif-Bold": {
 2406    "32": [0, 0, 0, 0, 0.25],
 2407    "33": [0, 0.69444, 0, 0, 0.36667],
 2408    "34": [0, 0.69444, 0, 0, 0.55834],
 2409    "35": [0.19444, 0.69444, 0, 0, 0.91667],
 2410    "36": [0.05556, 0.75, 0, 0, 0.55],
 2411    "37": [0.05556, 0.75, 0, 0, 1.02912],
 2412    "38": [0, 0.69444, 0, 0, 0.83056],
 2413    "39": [0, 0.69444, 0, 0, 0.30556],
 2414    "40": [0.25, 0.75, 0, 0, 0.42778],
 2415    "41": [0.25, 0.75, 0, 0, 0.42778],
 2416    "42": [0, 0.75, 0, 0, 0.55],
 2417    "43": [0.11667, 0.61667, 0, 0, 0.85556],
 2418    "44": [0.10556, 0.13056, 0, 0, 0.30556],
 2419    "45": [0, 0.45833, 0, 0, 0.36667],
 2420    "46": [0, 0.13056, 0, 0, 0.30556],
 2421    "47": [0.25, 0.75, 0, 0, 0.55],
 2422    "48": [0, 0.69444, 0, 0, 0.55],
 2423    "49": [0, 0.69444, 0, 0, 0.55],
 2424    "50": [0, 0.69444, 0, 0, 0.55],
 2425    "51": [0, 0.69444, 0, 0, 0.55],
 2426    "52": [0, 0.69444, 0, 0, 0.55],
 2427    "53": [0, 0.69444, 0, 0, 0.55],
 2428    "54": [0, 0.69444, 0, 0, 0.55],
 2429    "55": [0, 0.69444, 0, 0, 0.55],
 2430    "56": [0, 0.69444, 0, 0, 0.55],
 2431    "57": [0, 0.69444, 0, 0, 0.55],
 2432    "58": [0, 0.45833, 0, 0, 0.30556],
 2433    "59": [0.10556, 0.45833, 0, 0, 0.30556],
 2434    "61": [-0.09375, 0.40625, 0, 0, 0.85556],
 2435    "63": [0, 0.69444, 0, 0, 0.51945],
 2436    "64": [0, 0.69444, 0, 0, 0.73334],
 2437    "65": [0, 0.69444, 0, 0, 0.73334],
 2438    "66": [0, 0.69444, 0, 0, 0.73334],
 2439    "67": [0, 0.69444, 0, 0, 0.70278],
 2440    "68": [0, 0.69444, 0, 0, 0.79445],
 2441    "69": [0, 0.69444, 0, 0, 0.64167],
 2442    "70": [0, 0.69444, 0, 0, 0.61111],
 2443    "71": [0, 0.69444, 0, 0, 0.73334],
 2444    "72": [0, 0.69444, 0, 0, 0.79445],
 2445    "73": [0, 0.69444, 0, 0, 0.33056],
 2446    "74": [0, 0.69444, 0, 0, 0.51945],
 2447    "75": [0, 0.69444, 0, 0, 0.76389],
 2448    "76": [0, 0.69444, 0, 0, 0.58056],
 2449    "77": [0, 0.69444, 0, 0, 0.97778],
 2450    "78": [0, 0.69444, 0, 0, 0.79445],
 2451    "79": [0, 0.69444, 0, 0, 0.79445],
 2452    "80": [0, 0.69444, 0, 0, 0.70278],
 2453    "81": [0.10556, 0.69444, 0, 0, 0.79445],
 2454    "82": [0, 0.69444, 0, 0, 0.70278],
 2455    "83": [0, 0.69444, 0, 0, 0.61111],
 2456    "84": [0, 0.69444, 0, 0, 0.73334],
 2457    "85": [0, 0.69444, 0, 0, 0.76389],
 2458    "86": [0, 0.69444, 0.01528, 0, 0.73334],
 2459    "87": [0, 0.69444, 0.01528, 0, 1.03889],
 2460    "88": [0, 0.69444, 0, 0, 0.73334],
 2461    "89": [0, 0.69444, 0.0275, 0, 0.73334],
 2462    "90": [0, 0.69444, 0, 0, 0.67223],
 2463    "91": [0.25, 0.75, 0, 0, 0.34306],
 2464    "93": [0.25, 0.75, 0, 0, 0.34306],
 2465    "94": [0, 0.69444, 0, 0, 0.55],
 2466    "95": [0.35, 0.10833, 0.03056, 0, 0.55],
 2467    "97": [0, 0.45833, 0, 0, 0.525],
 2468    "98": [0, 0.69444, 0, 0, 0.56111],
 2469    "99": [0, 0.45833, 0, 0, 0.48889],
 2470    "100": [0, 0.69444, 0, 0, 0.56111],
 2471    "101": [0, 0.45833, 0, 0, 0.51111],
 2472    "102": [0, 0.69444, 0.07639, 0, 0.33611],
 2473    "103": [0.19444, 0.45833, 0.01528, 0, 0.55],
 2474    "104": [0, 0.69444, 0, 0, 0.56111],
 2475    "105": [0, 0.69444, 0, 0, 0.25556],
 2476    "106": [0.19444, 0.69444, 0, 0, 0.28611],
 2477    "107": [0, 0.69444, 0, 0, 0.53056],
 2478    "108": [0, 0.69444, 0, 0, 0.25556],
 2479    "109": [0, 0.45833, 0, 0, 0.86667],
 2480    "110": [0, 0.45833, 0, 0, 0.56111],
 2481    "111": [0, 0.45833, 0, 0, 0.55],
 2482    "112": [0.19444, 0.45833, 0, 0, 0.56111],
 2483    "113": [0.19444, 0.45833, 0, 0, 0.56111],
 2484    "114": [0, 0.45833, 0.01528, 0, 0.37222],
 2485    "115": [0, 0.45833, 0, 0, 0.42167],
 2486    "116": [0, 0.58929, 0, 0, 0.40417],
 2487    "117": [0, 0.45833, 0, 0, 0.56111],
 2488    "118": [0, 0.45833, 0.01528, 0, 0.5],
 2489    "119": [0, 0.45833, 0.01528, 0, 0.74445],
 2490    "120": [0, 0.45833, 0, 0, 0.5],
 2491    "121": [0.19444, 0.45833, 0.01528, 0, 0.5],
 2492    "122": [0, 0.45833, 0, 0, 0.47639],
 2493    "126": [0.35, 0.34444, 0, 0, 0.55],
 2494    "160": [0, 0, 0, 0, 0.25],
 2495    "168": [0, 0.69444, 0, 0, 0.55],
 2496    "176": [0, 0.69444, 0, 0, 0.73334],
 2497    "180": [0, 0.69444, 0, 0, 0.55],
 2498    "184": [0.17014, 0, 0, 0, 0.48889],
 2499    "305": [0, 0.45833, 0, 0, 0.25556],
 2500    "567": [0.19444, 0.45833, 0, 0, 0.28611],
 2501    "710": [0, 0.69444, 0, 0, 0.55],
 2502    "711": [0, 0.63542, 0, 0, 0.55],
 2503    "713": [0, 0.63778, 0, 0, 0.55],
 2504    "728": [0, 0.69444, 0, 0, 0.55],
 2505    "729": [0, 0.69444, 0, 0, 0.30556],
 2506    "730": [0, 0.69444, 0, 0, 0.73334],
 2507    "732": [0, 0.69444, 0, 0, 0.55],
 2508    "733": [0, 0.69444, 0, 0, 0.55],
 2509    "915": [0, 0.69444, 0, 0, 0.58056],
 2510    "916": [0, 0.69444, 0, 0, 0.91667],
 2511    "920": [0, 0.69444, 0, 0, 0.85556],
 2512    "923": [0, 0.69444, 0, 0, 0.67223],
 2513    "926": [0, 0.69444, 0, 0, 0.73334],
 2514    "928": [0, 0.69444, 0, 0, 0.79445],
 2515    "931": [0, 0.69444, 0, 0, 0.79445],
 2516    "933": [0, 0.69444, 0, 0, 0.85556],
 2517    "934": [0, 0.69444, 0, 0, 0.79445],
 2518    "936": [0, 0.69444, 0, 0, 0.85556],
 2519    "937": [0, 0.69444, 0, 0, 0.79445],
 2520    "8211": [0, 0.45833, 0.03056, 0, 0.55],
 2521    "8212": [0, 0.45833, 0.03056, 0, 1.10001],
 2522    "8216": [0, 0.69444, 0, 0, 0.30556],
 2523    "8217": [0, 0.69444, 0, 0, 0.30556],
 2524    "8220": [0, 0.69444, 0, 0, 0.55834],
 2525    "8221": [0, 0.69444, 0, 0, 0.55834]
 2526  },
 2527  "SansSerif-Italic": {
 2528    "32": [0, 0, 0, 0, 0.25],
 2529    "33": [0, 0.69444, 0.05733, 0, 0.31945],
 2530    "34": [0, 0.69444, 0.00316, 0, 0.5],
 2531    "35": [0.19444, 0.69444, 0.05087, 0, 0.83334],
 2532    "36": [0.05556, 0.75, 0.11156, 0, 0.5],
 2533    "37": [0.05556, 0.75, 0.03126, 0, 0.83334],
 2534    "38": [0, 0.69444, 0.03058, 0, 0.75834],
 2535    "39": [0, 0.69444, 0.07816, 0, 0.27778],
 2536    "40": [0.25, 0.75, 0.13164, 0, 0.38889],
 2537    "41": [0.25, 0.75, 0.02536, 0, 0.38889],
 2538    "42": [0, 0.75, 0.11775, 0, 0.5],
 2539    "43": [0.08333, 0.58333, 0.02536, 0, 0.77778],
 2540    "44": [0.125, 0.08333, 0, 0, 0.27778],
 2541    "45": [0, 0.44444, 0.01946, 0, 0.33333],
 2542    "46": [0, 0.08333, 0, 0, 0.27778],
 2543    "47": [0.25, 0.75, 0.13164, 0, 0.5],
 2544    "48": [0, 0.65556, 0.11156, 0, 0.5],
 2545    "49": [0, 0.65556, 0.11156, 0, 0.5],
 2546    "50": [0, 0.65556, 0.11156, 0, 0.5],
 2547    "51": [0, 0.65556, 0.11156, 0, 0.5],
 2548    "52": [0, 0.65556, 0.11156, 0, 0.5],
 2549    "53": [0, 0.65556, 0.11156, 0, 0.5],
 2550    "54": [0, 0.65556, 0.11156, 0, 0.5],
 2551    "55": [0, 0.65556, 0.11156, 0, 0.5],
 2552    "56": [0, 0.65556, 0.11156, 0, 0.5],
 2553    "57": [0, 0.65556, 0.11156, 0, 0.5],
 2554    "58": [0, 0.44444, 0.02502, 0, 0.27778],
 2555    "59": [0.125, 0.44444, 0.02502, 0, 0.27778],
 2556    "61": [-0.13, 0.37, 0.05087, 0, 0.77778],
 2557    "63": [0, 0.69444, 0.11809, 0, 0.47222],
 2558    "64": [0, 0.69444, 0.07555, 0, 0.66667],
 2559    "65": [0, 0.69444, 0, 0, 0.66667],
 2560    "66": [0, 0.69444, 0.08293, 0, 0.66667],
 2561    "67": [0, 0.69444, 0.11983, 0, 0.63889],
 2562    "68": [0, 0.69444, 0.07555, 0, 0.72223],
 2563    "69": [0, 0.69444, 0.11983, 0, 0.59722],
 2564    "70": [0, 0.69444, 0.13372, 0, 0.56945],
 2565    "71": [0, 0.69444, 0.11983, 0, 0.66667],
 2566    "72": [0, 0.69444, 0.08094, 0, 0.70834],
 2567    "73": [0, 0.69444, 0.13372, 0, 0.27778],
 2568    "74": [0, 0.69444, 0.08094, 0, 0.47222],
 2569    "75": [0, 0.69444, 0.11983, 0, 0.69445],
 2570    "76": [0, 0.69444, 0, 0, 0.54167],
 2571    "77": [0, 0.69444, 0.08094, 0, 0.875],
 2572    "78": [0, 0.69444, 0.08094, 0, 0.70834],
 2573    "79": [0, 0.69444, 0.07555, 0, 0.73611],
 2574    "80": [0, 0.69444, 0.08293, 0, 0.63889],
 2575    "81": [0.125, 0.69444, 0.07555, 0, 0.73611],
 2576    "82": [0, 0.69444, 0.08293, 0, 0.64584],
 2577    "83": [0, 0.69444, 0.09205, 0, 0.55556],
 2578    "84": [0, 0.69444, 0.13372, 0, 0.68056],
 2579    "85": [0, 0.69444, 0.08094, 0, 0.6875],
 2580    "86": [0, 0.69444, 0.1615, 0, 0.66667],
 2581    "87": [0, 0.69444, 0.1615, 0, 0.94445],
 2582    "88": [0, 0.69444, 0.13372, 0, 0.66667],
 2583    "89": [0, 0.69444, 0.17261, 0, 0.66667],
 2584    "90": [0, 0.69444, 0.11983, 0, 0.61111],
 2585    "91": [0.25, 0.75, 0.15942, 0, 0.28889],
 2586    "93": [0.25, 0.75, 0.08719, 0, 0.28889],
 2587    "94": [0, 0.69444, 0.0799, 0, 0.5],
 2588    "95": [0.35, 0.09444, 0.08616, 0, 0.5],
 2589    "97": [0, 0.44444, 0.00981, 0, 0.48056],
 2590    "98": [0, 0.69444, 0.03057, 0, 0.51667],
 2591    "99": [0, 0.44444, 0.08336, 0, 0.44445],
 2592    "100": [0, 0.69444, 0.09483, 0, 0.51667],
 2593    "101": [0, 0.44444, 0.06778, 0, 0.44445],
 2594    "102": [0, 0.69444, 0.21705, 0, 0.30556],
 2595    "103": [0.19444, 0.44444, 0.10836, 0, 0.5],
 2596    "104": [0, 0.69444, 0.01778, 0, 0.51667],
 2597    "105": [0, 0.67937, 0.09718, 0, 0.23889],
 2598    "106": [0.19444, 0.67937, 0.09162, 0, 0.26667],
 2599    "107": [0, 0.69444, 0.08336, 0, 0.48889],
 2600    "108": [0, 0.69444, 0.09483, 0, 0.23889],
 2601    "109": [0, 0.44444, 0.01778, 0, 0.79445],
 2602    "110": [0, 0.44444, 0.01778, 0, 0.51667],
 2603    "111": [0, 0.44444, 0.06613, 0, 0.5],
 2604    "112": [0.19444, 0.44444, 0.0389, 0, 0.51667],
 2605    "113": [0.19444, 0.44444, 0.04169, 0, 0.51667],
 2606    "114": [0, 0.44444, 0.10836, 0, 0.34167],
 2607    "115": [0, 0.44444, 0.0778, 0, 0.38333],
 2608    "116": [0, 0.57143, 0.07225, 0, 0.36111],
 2609    "117": [0, 0.44444, 0.04169, 0, 0.51667],
 2610    "118": [0, 0.44444, 0.10836, 0, 0.46111],
 2611    "119": [0, 0.44444, 0.10836, 0, 0.68334],
 2612    "120": [0, 0.44444, 0.09169, 0, 0.46111],
 2613    "121": [0.19444, 0.44444, 0.10836, 0, 0.46111],
 2614    "122": [0, 0.44444, 0.08752, 0, 0.43472],
 2615    "126": [0.35, 0.32659, 0.08826, 0, 0.5],
 2616    "160": [0, 0, 0, 0, 0.25],
 2617    "168": [0, 0.67937, 0.06385, 0, 0.5],
 2618    "176": [0, 0.69444, 0, 0, 0.73752],
 2619    "184": [0.17014, 0, 0, 0, 0.44445],
 2620    "305": [0, 0.44444, 0.04169, 0, 0.23889],
 2621    "567": [0.19444, 0.44444, 0.04169, 0, 0.26667],
 2622    "710": [0, 0.69444, 0.0799, 0, 0.5],
 2623    "711": [0, 0.63194, 0.08432, 0, 0.5],
 2624    "713": [0, 0.60889, 0.08776, 0, 0.5],
 2625    "714": [0, 0.69444, 0.09205, 0, 0.5],
 2626    "715": [0, 0.69444, 0, 0, 0.5],
 2627    "728": [0, 0.69444, 0.09483, 0, 0.5],
 2628    "729": [0, 0.67937, 0.07774, 0, 0.27778],
 2629    "730": [0, 0.69444, 0, 0, 0.73752],
 2630    "732": [0, 0.67659, 0.08826, 0, 0.5],
 2631    "733": [0, 0.69444, 0.09205, 0, 0.5],
 2632    "915": [0, 0.69444, 0.13372, 0, 0.54167],
 2633    "916": [0, 0.69444, 0, 0, 0.83334],
 2634    "920": [0, 0.69444, 0.07555, 0, 0.77778],
 2635    "923": [0, 0.69444, 0, 0, 0.61111],
 2636    "926": [0, 0.69444, 0.12816, 0, 0.66667],
 2637    "928": [0, 0.69444, 0.08094, 0, 0.70834],
 2638    "931": [0, 0.69444, 0.11983, 0, 0.72222],
 2639    "933": [0, 0.69444, 0.09031, 0, 0.77778],
 2640    "934": [0, 0.69444, 0.04603, 0, 0.72222],
 2641    "936": [0, 0.69444, 0.09031, 0, 0.77778],
 2642    "937": [0, 0.69444, 0.08293, 0, 0.72222],
 2643    "8211": [0, 0.44444, 0.08616, 0, 0.5],
 2644    "8212": [0, 0.44444, 0.08616, 0, 1.0],
 2645    "8216": [0, 0.69444, 0.07816, 0, 0.27778],
 2646    "8217": [0, 0.69444, 0.07816, 0, 0.27778],
 2647    "8220": [0, 0.69444, 0.14205, 0, 0.5],
 2648    "8221": [0, 0.69444, 0.00316, 0, 0.5]
 2649  },
 2650  "SansSerif-Regular": {
 2651    "32": [0, 0, 0, 0, 0.25],
 2652    "33": [0, 0.69444, 0, 0, 0.31945],
 2653    "34": [0, 0.69444, 0, 0, 0.5],
 2654    "35": [0.19444, 0.69444, 0, 0, 0.83334],
 2655    "36": [0.05556, 0.75, 0, 0, 0.5],
 2656    "37": [0.05556, 0.75, 0, 0, 0.83334],
 2657    "38": [0, 0.69444, 0, 0, 0.75834],
 2658    "39": [0, 0.69444, 0, 0, 0.27778],
 2659    "40": [0.25, 0.75, 0, 0, 0.38889],
 2660    "41": [0.25, 0.75, 0, 0, 0.38889],
 2661    "42": [0, 0.75, 0, 0, 0.5],
 2662    "43": [0.08333, 0.58333, 0, 0, 0.77778],
 2663    "44": [0.125, 0.08333, 0, 0, 0.27778],
 2664    "45": [0, 0.44444, 0, 0, 0.33333],
 2665    "46": [0, 0.08333, 0, 0, 0.27778],
 2666    "47": [0.25, 0.75, 0, 0, 0.5],
 2667    "48": [0, 0.65556, 0, 0, 0.5],
 2668    "49": [0, 0.65556, 0, 0, 0.5],
 2669    "50": [0, 0.65556, 0, 0, 0.5],
 2670    "51": [0, 0.65556, 0, 0, 0.5],
 2671    "52": [0, 0.65556, 0, 0, 0.5],
 2672    "53": [0, 0.65556, 0, 0, 0.5],
 2673    "54": [0, 0.65556, 0, 0, 0.5],
 2674    "55": [0, 0.65556, 0, 0, 0.5],
 2675    "56": [0, 0.65556, 0, 0, 0.5],
 2676    "57": [0, 0.65556, 0, 0, 0.5],
 2677    "58": [0, 0.44444, 0, 0, 0.27778],
 2678    "59": [0.125, 0.44444, 0, 0, 0.27778],
 2679    "61": [-0.13, 0.37, 0, 0, 0.77778],
 2680    "63": [0, 0.69444, 0, 0, 0.47222],
 2681    "64": [0, 0.69444, 0, 0, 0.66667],
 2682    "65": [0, 0.69444, 0, 0, 0.66667],
 2683    "66": [0, 0.69444, 0, 0, 0.66667],
 2684    "67": [0, 0.69444, 0, 0, 0.63889],
 2685    "68": [0, 0.69444, 0, 0, 0.72223],
 2686    "69": [0, 0.69444, 0, 0, 0.59722],
 2687    "70": [0, 0.69444, 0, 0, 0.56945],
 2688    "71": [0, 0.69444, 0, 0, 0.66667],
 2689    "72": [0, 0.69444, 0, 0, 0.70834],
 2690    "73": [0, 0.69444, 0, 0, 0.27778],
 2691    "74": [0, 0.69444, 0, 0, 0.47222],
 2692    "75": [0, 0.69444, 0, 0, 0.69445],
 2693    "76": [0, 0.69444, 0, 0, 0.54167],
 2694    "77": [0, 0.69444, 0, 0, 0.875],
 2695    "78": [0, 0.69444, 0, 0, 0.70834],
 2696    "79": [0, 0.69444, 0, 0, 0.73611],
 2697    "80": [0, 0.69444, 0, 0, 0.63889],
 2698    "81": [0.125, 0.69444, 0, 0, 0.73611],
 2699    "82": [0, 0.69444, 0, 0, 0.64584],
 2700    "83": [0, 0.69444, 0, 0, 0.55556],
 2701    "84": [0, 0.69444, 0, 0, 0.68056],
 2702    "85": [0, 0.69444, 0, 0, 0.6875],
 2703    "86": [0, 0.69444, 0.01389, 0, 0.66667],
 2704    "87": [0, 0.69444, 0.01389, 0, 0.94445],
 2705    "88": [0, 0.69444, 0, 0, 0.66667],
 2706    "89": [0, 0.69444, 0.025, 0, 0.66667],
 2707    "90": [0, 0.69444, 0, 0, 0.61111],
 2708    "91": [0.25, 0.75, 0, 0, 0.28889],
 2709    "93": [0.25, 0.75, 0, 0, 0.28889],
 2710    "94": [0, 0.69444, 0, 0, 0.5],
 2711    "95": [0.35, 0.09444, 0.02778, 0, 0.5],
 2712    "97": [0, 0.44444, 0, 0, 0.48056],
 2713    "98": [0, 0.69444, 0, 0, 0.51667],
 2714    "99": [0, 0.44444, 0, 0, 0.44445],
 2715    "100": [0, 0.69444, 0, 0, 0.51667],
 2716    "101": [0, 0.44444, 0, 0, 0.44445],
 2717    "102": [0, 0.69444, 0.06944, 0, 0.30556],
 2718    "103": [0.19444, 0.44444, 0.01389, 0, 0.5],
 2719    "104": [0, 0.69444, 0, 0, 0.51667],
 2720    "105": [0, 0.67937, 0, 0, 0.23889],
 2721    "106": [0.19444, 0.67937, 0, 0, 0.26667],
 2722    "107": [0, 0.69444, 0, 0, 0.48889],
 2723    "108": [0, 0.69444, 0, 0, 0.23889],
 2724    "109": [0, 0.44444, 0, 0, 0.79445],
 2725    "110": [0, 0.44444, 0, 0, 0.51667],
 2726    "111": [0, 0.44444, 0, 0, 0.5],
 2727    "112": [0.19444, 0.44444, 0, 0, 0.51667],
 2728    "113": [0.19444, 0.44444, 0, 0, 0.51667],
 2729    "114": [0, 0.44444, 0.01389, 0, 0.34167],
 2730    "115": [0, 0.44444, 0, 0, 0.38333],
 2731    "116": [0, 0.57143, 0, 0, 0.36111],
 2732    "117": [0, 0.44444, 0, 0, 0.51667],
 2733    "118": [0, 0.44444, 0.01389, 0, 0.46111],
 2734    "119": [0, 0.44444, 0.01389, 0, 0.68334],
 2735    "120": [0, 0.44444, 0, 0, 0.46111],
 2736    "121": [0.19444, 0.44444, 0.01389, 0, 0.46111],
 2737    "122": [0, 0.44444, 0, 0, 0.43472],
 2738    "126": [0.35, 0.32659, 0, 0, 0.5],
 2739    "160": [0, 0, 0, 0, 0.25],
 2740    "168": [0, 0.67937, 0, 0, 0.5],
 2741    "176": [0, 0.69444, 0, 0, 0.66667],
 2742    "184": [0.17014, 0, 0, 0, 0.44445],
 2743    "305": [0, 0.44444, 0, 0, 0.23889],
 2744    "567": [0.19444, 0.44444, 0, 0, 0.26667],
 2745    "710": [0, 0.69444, 0, 0, 0.5],
 2746    "711": [0, 0.63194, 0, 0, 0.5],
 2747    "713": [0, 0.60889, 0, 0, 0.5],
 2748    "714": [0, 0.69444, 0, 0, 0.5],
 2749    "715": [0, 0.69444, 0, 0, 0.5],
 2750    "728": [0, 0.69444, 0, 0, 0.5],
 2751    "729": [0, 0.67937, 0, 0, 0.27778],
 2752    "730": [0, 0.69444, 0, 0, 0.66667],
 2753    "732": [0, 0.67659, 0, 0, 0.5],
 2754    "733": [0, 0.69444, 0, 0, 0.5],
 2755    "915": [0, 0.69444, 0, 0, 0.54167],
 2756    "916": [0, 0.69444, 0, 0, 0.83334],
 2757    "920": [0, 0.69444, 0, 0, 0.77778],
 2758    "923": [0, 0.69444, 0, 0, 0.61111],
 2759    "926": [0, 0.69444, 0, 0, 0.66667],
 2760    "928": [0, 0.69444, 0, 0, 0.70834],
 2761    "931": [0, 0.69444, 0, 0, 0.72222],
 2762    "933": [0, 0.69444, 0, 0, 0.77778],
 2763    "934": [0, 0.69444, 0, 0, 0.72222],
 2764    "936": [0, 0.69444, 0, 0, 0.77778],
 2765    "937": [0, 0.69444, 0, 0, 0.72222],
 2766    "8211": [0, 0.44444, 0.02778, 0, 0.5],
 2767    "8212": [0, 0.44444, 0.02778, 0, 1.0],
 2768    "8216": [0, 0.69444, 0, 0, 0.27778],
 2769    "8217": [0, 0.69444, 0, 0, 0.27778],
 2770    "8220": [0, 0.69444, 0, 0, 0.5],
 2771    "8221": [0, 0.69444, 0, 0, 0.5]
 2772  },
 2773  "Script-Regular": {
 2774    "32": [0, 0, 0, 0, 0.25],
 2775    "65": [0, 0.7, 0.22925, 0, 0.80253],
 2776    "66": [0, 0.7, 0.04087, 0, 0.90757],
 2777    "67": [0, 0.7, 0.1689, 0, 0.66619],
 2778    "68": [0, 0.7, 0.09371, 0, 0.77443],
 2779    "69": [0, 0.7, 0.18583, 0, 0.56162],
 2780    "70": [0, 0.7, 0.13634, 0, 0.89544],
 2781    "71": [0, 0.7, 0.17322, 0, 0.60961],
 2782    "72": [0, 0.7, 0.29694, 0, 0.96919],
 2783    "73": [0, 0.7, 0.19189, 0, 0.80907],
 2784    "74": [0.27778, 0.7, 0.19189, 0, 1.05159],
 2785    "75": [0, 0.7, 0.31259, 0, 0.91364],
 2786    "76": [0, 0.7, 0.19189, 0, 0.87373],
 2787    "77": [0, 0.7, 0.15981, 0, 1.08031],
 2788    "78": [0, 0.7, 0.3525, 0, 0.9015],
 2789    "79": [0, 0.7, 0.08078, 0, 0.73787],
 2790    "80": [0, 0.7, 0.08078, 0, 1.01262],
 2791    "81": [0, 0.7, 0.03305, 0, 0.88282],
 2792    "82": [0, 0.7, 0.06259, 0, 0.85],
 2793    "83": [0, 0.7, 0.19189, 0, 0.86767],
 2794    "84": [0, 0.7, 0.29087, 0, 0.74697],
 2795    "85": [0, 0.7, 0.25815, 0, 0.79996],
 2796    "86": [0, 0.7, 0.27523, 0, 0.62204],
 2797    "87": [0, 0.7, 0.27523, 0, 0.80532],
 2798    "88": [0, 0.7, 0.26006, 0, 0.94445],
 2799    "89": [0, 0.7, 0.2939, 0, 0.70961],
 2800    "90": [0, 0.7, 0.24037, 0, 0.8212],
 2801    "160": [0, 0, 0, 0, 0.25]
 2802  },
 2803  "Size1-Regular": {
 2804    "32": [0, 0, 0, 0, 0.25],
 2805    "40": [0.35001, 0.85, 0, 0, 0.45834],
 2806    "41": [0.35001, 0.85, 0, 0, 0.45834],
 2807    "47": [0.35001, 0.85, 0, 0, 0.57778],
 2808    "91": [0.35001, 0.85, 0, 0, 0.41667],
 2809    "92": [0.35001, 0.85, 0, 0, 0.57778],
 2810    "93": [0.35001, 0.85, 0, 0, 0.41667],
 2811    "123": [0.35001, 0.85, 0, 0, 0.58334],
 2812    "125": [0.35001, 0.85, 0, 0, 0.58334],
 2813    "160": [0, 0, 0, 0, 0.25],
 2814    "710": [0, 0.72222, 0, 0, 0.55556],
 2815    "732": [0, 0.72222, 0, 0, 0.55556],
 2816    "770": [0, 0.72222, 0, 0, 0.55556],
 2817    "771": [0, 0.72222, 0, 0, 0.55556],
 2818    "8214": [-0.00099, 0.601, 0, 0, 0.77778],
 2819    "8593": [1e-05, 0.6, 0, 0, 0.66667],
 2820    "8595": [1e-05, 0.6, 0, 0, 0.66667],
 2821    "8657": [1e-05, 0.6, 0, 0, 0.77778],
 2822    "8659": [1e-05, 0.6, 0, 0, 0.77778],
 2823    "8719": [0.25001, 0.75, 0, 0, 0.94445],
 2824    "8720": [0.25001, 0.75, 0, 0, 0.94445],
 2825    "8721": [0.25001, 0.75, 0, 0, 1.05556],
 2826    "8730": [0.35001, 0.85, 0, 0, 1.0],
 2827    "8739": [-0.00599, 0.606, 0, 0, 0.33333],
 2828    "8741": [-0.00599, 0.606, 0, 0, 0.55556],
 2829    "8747": [0.30612, 0.805, 0.19445, 0, 0.47222],
 2830    "8748": [0.306, 0.805, 0.19445, 0, 0.47222],
 2831    "8749": [0.306, 0.805, 0.19445, 0, 0.47222],
 2832    "8750": [0.30612, 0.805, 0.19445, 0, 0.47222],
 2833    "8896": [0.25001, 0.75, 0, 0, 0.83334],
 2834    "8897": [0.25001, 0.75, 0, 0, 0.83334],
 2835    "8898": [0.25001, 0.75, 0, 0, 0.83334],
 2836    "8899": [0.25001, 0.75, 0, 0, 0.83334],
 2837    "8968": [0.35001, 0.85, 0, 0, 0.47222],
 2838    "8969": [0.35001, 0.85, 0, 0, 0.47222],
 2839    "8970": [0.35001, 0.85, 0, 0, 0.47222],
 2840    "8971": [0.35001, 0.85, 0, 0, 0.47222],
 2841    "9168": [-0.00099, 0.601, 0, 0, 0.66667],
 2842    "10216": [0.35001, 0.85, 0, 0, 0.47222],
 2843    "10217": [0.35001, 0.85, 0, 0, 0.47222],
 2844    "10752": [0.25001, 0.75, 0, 0, 1.11111],
 2845    "10753": [0.25001, 0.75, 0, 0, 1.11111],
 2846    "10754": [0.25001, 0.75, 0, 0, 1.11111],
 2847    "10756": [0.25001, 0.75, 0, 0, 0.83334],
 2848    "10758": [0.25001, 0.75, 0, 0, 0.83334]
 2849  },
 2850  "Size2-Regular": {
 2851    "32": [0, 0, 0, 0, 0.25],
 2852    "40": [0.65002, 1.15, 0, 0, 0.59722],
 2853    "41": [0.65002, 1.15, 0, 0, 0.59722],
 2854    "47": [0.65002, 1.15, 0, 0, 0.81111],
 2855    "91": [0.65002, 1.15, 0, 0, 0.47222],
 2856    "92": [0.65002, 1.15, 0, 0, 0.81111],
 2857    "93": [0.65002, 1.15, 0, 0, 0.47222],
 2858    "123": [0.65002, 1.15, 0, 0, 0.66667],
 2859    "125": [0.65002, 1.15, 0, 0, 0.66667],
 2860    "160": [0, 0, 0, 0, 0.25],
 2861    "710": [0, 0.75, 0, 0, 1.0],
 2862    "732": [0, 0.75, 0, 0, 1.0],
 2863    "770": [0, 0.75, 0, 0, 1.0],
 2864    "771": [0, 0.75, 0, 0, 1.0],
 2865    "8719": [0.55001, 1.05, 0, 0, 1.27778],
 2866    "8720": [0.55001, 1.05, 0, 0, 1.27778],
 2867    "8721": [0.55001, 1.05, 0, 0, 1.44445],
 2868    "8730": [0.65002, 1.15, 0, 0, 1.0],
 2869    "8747": [0.86225, 1.36, 0.44445, 0, 0.55556],
 2870    "8748": [0.862, 1.36, 0.44445, 0, 0.55556],
 2871    "8749": [0.862, 1.36, 0.44445, 0, 0.55556],
 2872    "8750": [0.86225, 1.36, 0.44445, 0, 0.55556],
 2873    "8896": [0.55001, 1.05, 0, 0, 1.11111],
 2874    "8897": [0.55001, 1.05, 0, 0, 1.11111],
 2875    "8898": [0.55001, 1.05, 0, 0, 1.11111],
 2876    "8899": [0.55001, 1.05, 0, 0, 1.11111],
 2877    "8968": [0.65002, 1.15, 0, 0, 0.52778],
 2878    "8969": [0.65002, 1.15, 0, 0, 0.52778],
 2879    "8970": [0.65002, 1.15, 0, 0, 0.52778],
 2880    "8971": [0.65002, 1.15, 0, 0, 0.52778],
 2881    "10216": [0.65002, 1.15, 0, 0, 0.61111],
 2882    "10217": [0.65002, 1.15, 0, 0, 0.61111],
 2883    "10752": [0.55001, 1.05, 0, 0, 1.51112],
 2884    "10753": [0.55001, 1.05, 0, 0, 1.51112],
 2885    "10754": [0.55001, 1.05, 0, 0, 1.51112],
 2886    "10756": [0.55001, 1.05, 0, 0, 1.11111],
 2887    "10758": [0.55001, 1.05, 0, 0, 1.11111]
 2888  },
 2889  "Size3-Regular": {
 2890    "32": [0, 0, 0, 0, 0.25],
 2891    "40": [0.95003, 1.45, 0, 0, 0.73611],
 2892    "41": [0.95003, 1.45, 0, 0, 0.73611],
 2893    "47": [0.95003, 1.45, 0, 0, 1.04445],
 2894    "91": [0.95003, 1.45, 0, 0, 0.52778],
 2895    "92": [0.95003, 1.45, 0, 0, 1.04445],
 2896    "93": [0.95003, 1.45, 0, 0, 0.52778],
 2897    "123": [0.95003, 1.45, 0, 0, 0.75],
 2898    "125": [0.95003, 1.45, 0, 0, 0.75],
 2899    "160": [0, 0, 0, 0, 0.25],
 2900    "710": [0, 0.75, 0, 0, 1.44445],
 2901    "732": [0, 0.75, 0, 0, 1.44445],
 2902    "770": [0, 0.75, 0, 0, 1.44445],
 2903    "771": [0, 0.75, 0, 0, 1.44445],
 2904    "8730": [0.95003, 1.45, 0, 0, 1.0],
 2905    "8968": [0.95003, 1.45, 0, 0, 0.58334],
 2906    "8969": [0.95003, 1.45, 0, 0, 0.58334],
 2907    "8970": [0.95003, 1.45, 0, 0, 0.58334],
 2908    "8971": [0.95003, 1.45, 0, 0, 0.58334],
 2909    "10216": [0.95003, 1.45, 0, 0, 0.75],
 2910    "10217": [0.95003, 1.45, 0, 0, 0.75]
 2911  },
 2912  "Size4-Regular": {
 2913    "32": [0, 0, 0, 0, 0.25],
 2914    "40": [1.25003, 1.75, 0, 0, 0.79167],
 2915    "41": [1.25003, 1.75, 0, 0, 0.79167],
 2916    "47": [1.25003, 1.75, 0, 0, 1.27778],
 2917    "91": [1.25003, 1.75, 0, 0, 0.58334],
 2918    "92": [1.25003, 1.75, 0, 0, 1.27778],
 2919    "93": [1.25003, 1.75, 0, 0, 0.58334],
 2920    "123": [1.25003, 1.75, 0, 0, 0.80556],
 2921    "125": [1.25003, 1.75, 0, 0, 0.80556],
 2922    "160": [0, 0, 0, 0, 0.25],
 2923    "710": [0, 0.825, 0, 0, 1.8889],
 2924    "732": [0, 0.825, 0, 0, 1.8889],
 2925    "770": [0, 0.825, 0, 0, 1.8889],
 2926    "771": [0, 0.825, 0, 0, 1.8889],
 2927    "8730": [1.25003, 1.75, 0, 0, 1.0],
 2928    "8968": [1.25003, 1.75, 0, 0, 0.63889],
 2929    "8969": [1.25003, 1.75, 0, 0, 0.63889],
 2930    "8970": [1.25003, 1.75, 0, 0, 0.63889],
 2931    "8971": [1.25003, 1.75, 0, 0, 0.63889],
 2932    "9115": [0.64502, 1.155, 0, 0, 0.875],
 2933    "9116": [1e-05, 0.6, 0, 0, 0.875],
 2934    "9117": [0.64502, 1.155, 0, 0, 0.875],
 2935    "9118": [0.64502, 1.155, 0, 0, 0.875],
 2936    "9119": [1e-05, 0.6, 0, 0, 0.875],
 2937    "9120": [0.64502, 1.155, 0, 0, 0.875],
 2938    "9121": [0.64502, 1.155, 0, 0, 0.66667],
 2939    "9122": [-0.00099, 0.601, 0, 0, 0.66667],
 2940    "9123": [0.64502, 1.155, 0, 0, 0.66667],
 2941    "9124": [0.64502, 1.155, 0, 0, 0.66667],
 2942    "9125": [-0.00099, 0.601, 0, 0, 0.66667],
 2943    "9126": [0.64502, 1.155, 0, 0, 0.66667],
 2944    "9127": [1e-05, 0.9, 0, 0, 0.88889],
 2945    "9128": [0.65002, 1.15, 0, 0, 0.88889],
 2946    "9129": [0.90001, 0, 0, 0, 0.88889],
 2947    "9130": [0, 0.3, 0, 0, 0.88889],
 2948    "9131": [1e-05, 0.9, 0, 0, 0.88889],
 2949    "9132": [0.65002, 1.15, 0, 0, 0.88889],
 2950    "9133": [0.90001, 0, 0, 0, 0.88889],
 2951    "9143": [0.88502, 0.915, 0, 0, 1.05556],
 2952    "10216": [1.25003, 1.75, 0, 0, 0.80556],
 2953    "10217": [1.25003, 1.75, 0, 0, 0.80556],
 2954    "57344": [-0.00499, 0.605, 0, 0, 1.05556],
 2955    "57345": [-0.00499, 0.605, 0, 0, 1.05556],
 2956    "57680": [0, 0.12, 0, 0, 0.45],
 2957    "57681": [0, 0.12, 0, 0, 0.45],
 2958    "57682": [0, 0.12, 0, 0, 0.45],
 2959    "57683": [0, 0.12, 0, 0, 0.45]
 2960  },
 2961  "Typewriter-Regular": {
 2962    "32": [0, 0, 0, 0, 0.525],
 2963    "33": [0, 0.61111, 0, 0, 0.525],
 2964    "34": [0, 0.61111, 0, 0, 0.525],
 2965    "35": [0, 0.61111, 0, 0, 0.525],
 2966    "36": [0.08333, 0.69444, 0, 0, 0.525],
 2967    "37": [0.08333, 0.69444, 0, 0, 0.525],
 2968    "38": [0, 0.61111, 0, 0, 0.525],
 2969    "39": [0, 0.61111, 0, 0, 0.525],
 2970    "40": [0.08333, 0.69444, 0, 0, 0.525],
 2971    "41": [0.08333, 0.69444, 0, 0, 0.525],
 2972    "42": [0, 0.52083, 0, 0, 0.525],
 2973    "43": [-0.08056, 0.53055, 0, 0, 0.525],
 2974    "44": [0.13889, 0.125, 0, 0, 0.525],
 2975    "45": [-0.08056, 0.53055, 0, 0, 0.525],
 2976    "46": [0, 0.125, 0, 0, 0.525],
 2977    "47": [0.08333, 0.69444, 0, 0, 0.525],
 2978    "48": [0, 0.61111, 0, 0, 0.525],
 2979    "49": [0, 0.61111, 0, 0, 0.525],
 2980    "50": [0, 0.61111, 0, 0, 0.525],
 2981    "51": [0, 0.61111, 0, 0, 0.525],
 2982    "52": [0, 0.61111, 0, 0, 0.525],
 2983    "53": [0, 0.61111, 0, 0, 0.525],
 2984    "54": [0, 0.61111, 0, 0, 0.525],
 2985    "55": [0, 0.61111, 0, 0, 0.525],
 2986    "56": [0, 0.61111, 0, 0, 0.525],
 2987    "57": [0, 0.61111, 0, 0, 0.525],
 2988    "58": [0, 0.43056, 0, 0, 0.525],
 2989    "59": [0.13889, 0.43056, 0, 0, 0.525],
 2990    "60": [-0.05556, 0.55556, 0, 0, 0.525],
 2991    "61": [-0.19549, 0.41562, 0, 0, 0.525],
 2992    "62": [-0.05556, 0.55556, 0, 0, 0.525],
 2993    "63": [0, 0.61111, 0, 0, 0.525],
 2994    "64": [0, 0.61111, 0, 0, 0.525],
 2995    "65": [0, 0.61111, 0, 0, 0.525],
 2996    "66": [0, 0.61111, 0, 0, 0.525],
 2997    "67": [0, 0.61111, 0, 0, 0.525],
 2998    "68": [0, 0.61111, 0, 0, 0.525],
 2999    "69": [0, 0.61111, 0, 0, 0.525],
 3000    "70": [0, 0.61111, 0, 0, 0.525],
 3001    "71": [0, 0.61111, 0, 0, 0.525],
 3002    "72": [0, 0.61111, 0, 0, 0.525],
 3003    "73": [0, 0.61111, 0, 0, 0.525],
 3004    "74": [0, 0.61111, 0, 0, 0.525],
 3005    "75": [0, 0.61111, 0, 0, 0.525],
 3006    "76": [0, 0.61111, 0, 0, 0.525],
 3007    "77": [0, 0.61111, 0, 0, 0.525],
 3008    "78": [0, 0.61111, 0, 0, 0.525],
 3009    "79": [0, 0.61111, 0, 0, 0.525],
 3010    "80": [0, 0.61111, 0, 0, 0.525],
 3011    "81": [0.13889, 0.61111, 0, 0, 0.525],
 3012    "82": [0, 0.61111, 0, 0, 0.525],
 3013    "83": [0, 0.61111, 0, 0, 0.525],
 3014    "84": [0, 0.61111, 0, 0, 0.525],
 3015    "85": [0, 0.61111, 0, 0, 0.525],
 3016    "86": [0, 0.61111, 0, 0, 0.525],
 3017    "87": [0, 0.61111, 0, 0, 0.525],
 3018    "88": [0, 0.61111, 0, 0, 0.525],
 3019    "89": [0, 0.61111, 0, 0, 0.525],
 3020    "90": [0, 0.61111, 0, 0, 0.525],
 3021    "91": [0.08333, 0.69444, 0, 0, 0.525],
 3022    "92": [0.08333, 0.69444, 0, 0, 0.525],
 3023    "93": [0.08333, 0.69444, 0, 0, 0.525],
 3024    "94": [0, 0.61111, 0, 0, 0.525],
 3025    "95": [0.09514, 0, 0, 0, 0.525],
 3026    "96": [0, 0.61111, 0, 0, 0.525],
 3027    "97": [0, 0.43056, 0, 0, 0.525],
 3028    "98": [0, 0.61111, 0, 0, 0.525],
 3029    "99": [0, 0.43056, 0, 0, 0.525],
 3030    "100": [0, 0.61111, 0, 0, 0.525],
 3031    "101": [0, 0.43056, 0, 0, 0.525],
 3032    "102": [0, 0.61111, 0, 0, 0.525],
 3033    "103": [0.22222, 0.43056, 0, 0, 0.525],
 3034    "104": [0, 0.61111, 0, 0, 0.525],
 3035    "105": [0, 0.61111, 0, 0, 0.525],
 3036    "106": [0.22222, 0.61111, 0, 0, 0.525],
 3037    "107": [0, 0.61111, 0, 0, 0.525],
 3038    "108": [0, 0.61111, 0, 0, 0.525],
 3039    "109": [0, 0.43056, 0, 0, 0.525],
 3040    "110": [0, 0.43056, 0, 0, 0.525],
 3041    "111": [0, 0.43056, 0, 0, 0.525],
 3042    "112": [0.22222, 0.43056, 0, 0, 0.525],
 3043    "113": [0.22222, 0.43056, 0, 0, 0.525],
 3044    "114": [0, 0.43056, 0, 0, 0.525],
 3045    "115": [0, 0.43056, 0, 0, 0.525],
 3046    "116": [0, 0.55358, 0, 0, 0.525],
 3047    "117": [0, 0.43056, 0, 0, 0.525],
 3048    "118": [0, 0.43056, 0, 0, 0.525],
 3049    "119": [0, 0.43056, 0, 0, 0.525],
 3050    "120": [0, 0.43056, 0, 0, 0.525],
 3051    "121": [0.22222, 0.43056, 0, 0, 0.525],
 3052    "122": [0, 0.43056, 0, 0, 0.525],
 3053    "123": [0.08333, 0.69444, 0, 0, 0.525],
 3054    "124": [0.08333, 0.69444, 0, 0, 0.525],
 3055    "125": [0.08333, 0.69444, 0, 0, 0.525],
 3056    "126": [0, 0.61111, 0, 0, 0.525],
 3057    "127": [0, 0.61111, 0, 0, 0.525],
 3058    "160": [0, 0, 0, 0, 0.525],
 3059    "176": [0, 0.61111, 0, 0, 0.525],
 3060    "184": [0.19445, 0, 0, 0, 0.525],
 3061    "305": [0, 0.43056, 0, 0, 0.525],
 3062    "567": [0.22222, 0.43056, 0, 0, 0.525],
 3063    "711": [0, 0.56597, 0, 0, 0.525],
 3064    "713": [0, 0.56555, 0, 0, 0.525],
 3065    "714": [0, 0.61111, 0, 0, 0.525],
 3066    "715": [0, 0.61111, 0, 0, 0.525],
 3067    "728": [0, 0.61111, 0, 0, 0.525],
 3068    "730": [0, 0.61111, 0, 0, 0.525],
 3069    "770": [0, 0.61111, 0, 0, 0.525],
 3070    "771": [0, 0.61111, 0, 0, 0.525],
 3071    "776": [0, 0.61111, 0, 0, 0.525],
 3072    "915": [0, 0.61111, 0, 0, 0.525],
 3073    "916": [0, 0.61111, 0, 0, 0.525],
 3074    "920": [0, 0.61111, 0, 0, 0.525],
 3075    "923": [0, 0.61111, 0, 0, 0.525],
 3076    "926": [0, 0.61111, 0, 0, 0.525],
 3077    "928": [0, 0.61111, 0, 0, 0.525],
 3078    "931": [0, 0.61111, 0, 0, 0.525],
 3079    "933": [0, 0.61111, 0, 0, 0.525],
 3080    "934": [0, 0.61111, 0, 0, 0.525],
 3081    "936": [0, 0.61111, 0, 0, 0.525],
 3082    "937": [0, 0.61111, 0, 0, 0.525],
 3083    "8216": [0, 0.61111, 0, 0, 0.525],
 3084    "8217": [0, 0.61111, 0, 0, 0.525],
 3085    "8242": [0, 0.61111, 0, 0, 0.525],
 3086    "9251": [0.11111, 0.21944, 0, 0, 0.525]
 3087  }
 3088};
 3089
 3090/**
 3091 * This file contains metrics regarding fonts and individual symbols. The sigma
 3092 * and xi variables, as well as the metricMap map contain data extracted from
 3093 * TeX, TeX font metrics, and the TTF files. These data are then exposed via the
 3094 * `metrics` variable and the getCharacterMetrics function.
 3095 */
 3096// In TeX, there are actually three sets of dimensions, one for each of
 3097// textstyle (size index 5 and higher: >=9pt), scriptstyle (size index 3 and 4:
 3098// 7-8pt), and scriptscriptstyle (size index 1 and 2: 5-6pt).  These are
 3099// provided in the the arrays below, in that order.
 3100//
 3101// The font metrics are stored in fonts cmsy10, cmsy7, and cmsy5 respsectively.
 3102// This was determined by running the following script:
 3103//
 3104//     latex -interaction=nonstopmode \
 3105//     '\documentclass{article}\usepackage{amsmath}\begin{document}' \
 3106//     '$a$ \expandafter\show\the\textfont2' \
 3107//     '\expandafter\show\the\scriptfont2' \
 3108//     '\expandafter\show\the\scriptscriptfont2' \
 3109//     '\stop'
 3110//
 3111// The metrics themselves were retreived using the following commands:
 3112//
 3113//     tftopl cmsy10
 3114//     tftopl cmsy7
 3115//     tftopl cmsy5
 3116//
 3117// The output of each of these commands is quite lengthy.  The only part we
 3118// care about is the FONTDIMEN section. Each value is measured in EMs.
 3119var sigmasAndXis = {
 3120  slant: [0.250, 0.250, 0.250],
 3121  // sigma1
 3122  space: [0.000, 0.000, 0.000],
 3123  // sigma2
 3124  stretch: [0.000, 0.000, 0.000],
 3125  // sigma3
 3126  shrink: [0.000, 0.000, 0.000],
 3127  // sigma4
 3128  xHeight: [0.431, 0.431, 0.431],
 3129  // sigma5
 3130  quad: [1.000, 1.171, 1.472],
 3131  // sigma6
 3132  extraSpace: [0.000, 0.000, 0.000],
 3133  // sigma7
 3134  num1: [0.677, 0.732, 0.925],
 3135  // sigma8
 3136  num2: [0.394, 0.384, 0.387],
 3137  // sigma9
 3138  num3: [0.444, 0.471, 0.504],
 3139  // sigma10
 3140  denom1: [0.686, 0.752, 1.025],
 3141  // sigma11
 3142  denom2: [0.345, 0.344, 0.532],
 3143  // sigma12
 3144  sup1: [0.413, 0.503, 0.504],
 3145  // sigma13
 3146  sup2: [0.363, 0.431, 0.404],
 3147  // sigma14
 3148  sup3: [0.289, 0.286, 0.294],
 3149  // sigma15
 3150  sub1: [0.150, 0.143, 0.200],
 3151  // sigma16
 3152  sub2: [0.247, 0.286, 0.400],
 3153  // sigma17
 3154  supDrop: [0.386, 0.353, 0.494],
 3155  // sigma18
 3156  subDrop: [0.050, 0.071, 0.100],
 3157  // sigma19
 3158  delim1: [2.390, 1.700, 1.980],
 3159  // sigma20
 3160  delim2: [1.010, 1.157, 1.420],
 3161  // sigma21
 3162  axisHeight: [0.250, 0.250, 0.250],
 3163  // sigma22
 3164  // These font metrics are extracted from TeX by using tftopl on cmex10.tfm;
 3165  // they correspond to the font parameters of the extension fonts (family 3).
 3166  // See the TeXbook, page 441. In AMSTeX, the extension fonts scale; to
 3167  // match cmex7, we'd use cmex7.tfm values for script and scriptscript
 3168  // values.
 3169  defaultRuleThickness: [0.04, 0.049, 0.049],
 3170  // xi8; cmex7: 0.049
 3171  bigOpSpacing1: [0.111, 0.111, 0.111],
 3172  // xi9
 3173  bigOpSpacing2: [0.166, 0.166, 0.166],
 3174  // xi10
 3175  bigOpSpacing3: [0.2, 0.2, 0.2],
 3176  // xi11
 3177  bigOpSpacing4: [0.6, 0.611, 0.611],
 3178  // xi12; cmex7: 0.611
 3179  bigOpSpacing5: [0.1, 0.143, 0.143],
 3180  // xi13; cmex7: 0.143
 3181  // The \sqrt rule width is taken from the height of the surd character.
 3182  // Since we use the same font at all sizes, this thickness doesn't scale.
 3183  sqrtRuleThickness: [0.04, 0.04, 0.04],
 3184  // This value determines how large a pt is, for metrics which are defined
 3185  // in terms of pts.
 3186  // This value is also used in katex.less; if you change it make sure the
 3187  // values match.
 3188  ptPerEm: [10.0, 10.0, 10.0],
 3189  // The space between adjacent `|` columns in an array definition. From
 3190  // `\showthe\doublerulesep` in LaTeX. Equals 2.0 / ptPerEm.
 3191  doubleRuleSep: [0.2, 0.2, 0.2],
 3192  // The width of separator lines in {array} environments. From
 3193  // `\showthe\arrayrulewidth` in LaTeX. Equals 0.4 / ptPerEm.
 3194  arrayRuleWidth: [0.04, 0.04, 0.04],
 3195  // Two values from LaTeX source2e:
 3196  fboxsep: [0.3, 0.3, 0.3],
 3197  //        3 pt / ptPerEm
 3198  fboxrule: [0.04, 0.04, 0.04] // 0.4 pt / ptPerEm
 3199
 3200}; // This map contains a mapping from font name and character code to character
 3201// should have Latin-1 and Cyrillic characters, but may not depending on the
 3202// operating system.  The metrics do not account for extra height from the
 3203// accents.  In the case of Cyrillic characters which have both ascenders and
 3204// descenders we prefer approximations with ascenders, primarily to prevent
 3205// the fraction bar or root line from intersecting the glyph.
 3206// TODO(kevinb) allow union of multiple glyph metrics for better accuracy.
 3207
 3208var extraCharacterMap = {
 3209  // Latin-1
 3210  'Å': 'A',
 3211  'Ð': 'D',
 3212  'Þ': 'o',
 3213  'å': 'a',
 3214  'ð': 'd',
 3215  'þ': 'o',
 3216  // Cyrillic
 3217  'А': 'A',
 3218  'Б': 'B',
 3219  'В': 'B',
 3220  'Г': 'F',
 3221  'Д': 'A',
 3222  'Е': 'E',
 3223  'Ж': 'K',
 3224  'З': '3',
 3225  'И': 'N',
 3226  'Й': 'N',
 3227  'К': 'K',
 3228  'Л': 'N',
 3229  'М': 'M',
 3230  'Н': 'H',
 3231  'О': 'O',
 3232  'П': 'N',
 3233  'Р': 'P',
 3234  'С': 'C',
 3235  'Т': 'T',
 3236  'У': 'y',
 3237  'Ф': 'O',
 3238  'Х': 'X',
 3239  'Ц': 'U',
 3240  'Ч': 'h',
 3241  'Ш': 'W',
 3242  'Щ': 'W',
 3243  'Ъ': 'B',
 3244  'Ы': 'X',
 3245  'Ь': 'B',
 3246  'Э': '3',
 3247  'Ю': 'X',
 3248  'Я': 'R',
 3249  'а': 'a',
 3250  'б': 'b',
 3251  'в': 'a',
 3252  'г': 'r',
 3253  'д': 'y',
 3254  'е': 'e',
 3255  'ж': 'm',
 3256  'з': 'e',
 3257  'и': 'n',
 3258  'й': 'n',
 3259  'к': 'n',
 3260  'л': 'n',
 3261  'м': 'm',
 3262  'н': 'n',
 3263  'о': 'o',
 3264  'п': 'n',
 3265  'р': 'p',
 3266  'с': 'c',
 3267  'т': 'o',
 3268  'у': 'y',
 3269  'ф': 'b',
 3270  'х': 'x',
 3271  'ц': 'n',
 3272  'ч': 'n',
 3273  'ш': 'w',
 3274  'щ': 'w',
 3275  'ъ': 'a',
 3276  'ы': 'm',
 3277  'ь': 'a',
 3278  'э': 'e',
 3279  'ю': 'm',
 3280  'я': 'r'
 3281};
 3282
 3283/**
 3284 * This function adds new font metrics to default metricMap
 3285 * It can also override existing metrics
 3286 */
 3287function setFontMetrics(fontName, metrics) {
 3288  fontMetricsData[fontName] = metrics;
 3289}
 3290/**
 3291 * This function is a convenience function for looking up information in the
 3292 * metricMap table. It takes a character as a string, and a font.
 3293 *
 3294 * Note: the `width` property may be undefined if fontMetricsData.js wasn't
 3295 * built using `Make extended_metrics`.
 3296 */
 3297
 3298function getCharacterMetrics(character, font, mode) {
 3299  if (!fontMetricsData[font]) {
 3300    throw new Error("Font metrics not found for font: " + font + ".");
 3301  }
 3302
 3303  var ch = character.charCodeAt(0);
 3304  var metrics = fontMetricsData[font][ch];
 3305
 3306  if (!metrics && character[0] in extraCharacterMap) {
 3307    ch = extraCharacterMap[character[0]].charCodeAt(0);
 3308    metrics = fontMetricsData[font][ch];
 3309  }
 3310
 3311  if (!metrics && mode === 'text') {
 3312    // We don't typically have font metrics for Asian scripts.
 3313    // But since we support them in text mode, we need to return
 3314    // some sort of metrics.
 3315    // So if the character is in a script we support but we
 3316    // don't have metrics for it, just use the metrics for
 3317    // the Latin capital letter M. This is close enough because
 3318    // we (currently) only care about the height of the glpyh
 3319    // not its width.
 3320    if (supportedCodepoint(ch)) {
 3321      metrics = fontMetricsData[font][77]; // 77 is the charcode for 'M'
 3322    }
 3323  }
 3324
 3325  if (metrics) {
 3326    return {
 3327      depth: metrics[0],
 3328      height: metrics[1],
 3329      italic: metrics[2],
 3330      skew: metrics[3],
 3331      width: metrics[4]
 3332    };
 3333  }
 3334}
 3335var fontMetricsBySizeIndex = {};
 3336/**
 3337 * Get the font metrics for a given size.
 3338 */
 3339
 3340function getGlobalMetrics(size) {
 3341  var sizeIndex;
 3342
 3343  if (size >= 5) {
 3344    sizeIndex = 0;
 3345  } else if (size >= 3) {
 3346    sizeIndex = 1;
 3347  } else {
 3348    sizeIndex = 2;
 3349  }
 3350
 3351  if (!fontMetricsBySizeIndex[sizeIndex]) {
 3352    var metrics = fontMetricsBySizeIndex[sizeIndex] = {
 3353      cssEmPerMu: sigmasAndXis.quad[sizeIndex] / 18
 3354    };
 3355
 3356    for (var key in sigmasAndXis) {
 3357      if (sigmasAndXis.hasOwnProperty(key)) {
 3358        metrics[key] = sigmasAndXis[key][sizeIndex];
 3359      }
 3360    }
 3361  }
 3362
 3363  return fontMetricsBySizeIndex[sizeIndex];
 3364}
 3365
 3366/**
 3367 * This file contains information about the options that the Parser carries
 3368 * around with it while parsing. Data is held in an `Options` object, and when
 3369 * recursing, a new `Options` object can be created with the `.with*` and
 3370 * `.reset` functions.
 3371 */
 3372var sizeStyleMap = [// Each element contains [textsize, scriptsize, scriptscriptsize].
 3373// The size mappings are taken from TeX with \normalsize=10pt.
 3374[1, 1, 1], // size1: [5, 5, 5]              \tiny
 3375[2, 1, 1], // size2: [6, 5, 5]
 3376[3, 1, 1], // size3: [7, 5, 5]              \scriptsize
 3377[4, 2, 1], // size4: [8, 6, 5]              \footnotesize
 3378[5, 2, 1], // size5: [9, 6, 5]              \small
 3379[6, 3, 1], // size6: [10, 7, 5]             \normalsize
 3380[7, 4, 2], // size7: [12, 8, 6]             \large
 3381[8, 6, 3], // size8: [14.4, 10, 7]          \Large
 3382[9, 7, 6], // size9: [17.28, 12, 10]        \LARGE
 3383[10, 8, 7], // size10: [20.74, 14.4, 12]     \huge
 3384[11, 10, 9] // size11: [24.88, 20.74, 17.28] \HUGE
 3385];
 3386var sizeMultipliers = [// fontMetrics.js:getGlobalMetrics also uses size indexes, so if
 3387// you change size indexes, change that function.
 33880.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.2, 1.44, 1.728, 2.074, 2.488];
 3389
 3390var sizeAtStyle = function sizeAtStyle(size, style) {
 3391  return style.size < 2 ? size : sizeStyleMap[size - 1][style.size - 1];
 3392}; // In these types, "" (empty string) means "no change".
 3393
 3394
 3395/**
 3396 * This is the main options class. It contains the current style, size, color,
 3397 * and font.
 3398 *
 3399 * Options objects should not be modified. To create a new Options with
 3400 * different properties, call a `.having*` method.
 3401 */
 3402class Options {
 3403  // A font family applies to a group of fonts (i.e. SansSerif), while a font
 3404  // represents a specific font (i.e. SansSerif Bold).
 3405  // See: https://tex.stackexchange.com/questions/22350/difference-between-textrm-and-mathrm
 3406
 3407  /**
 3408   * The base size index.
 3409   */
 3410  constructor(data) {
 3411    this.style = void 0;
 3412    this.color = void 0;
 3413    this.size = void 0;
 3414    this.textSize = void 0;
 3415    this.phantom = void 0;
 3416    this.font = void 0;
 3417    this.fontFamily = void 0;
 3418    this.fontWeight = void 0;
 3419    this.fontShape = void 0;
 3420    this.sizeMultiplier = void 0;
 3421    this.maxSize = void 0;
 3422    this.minRuleThickness = void 0;
 3423    this._fontMetrics = void 0;
 3424    this.style = data.style;
 3425    this.color = data.color;
 3426    this.size = data.size || Options.BASESIZE;
 3427    this.textSize = data.textSize || this.size;
 3428    this.phantom = !!data.phantom;
 3429    this.font = data.font || "";
 3430    this.fontFamily = data.fontFamily || "";
 3431    this.fontWeight = data.fontWeight || '';
 3432    this.fontShape = data.fontShape || '';
 3433    this.sizeMultiplier = sizeMultipliers[this.size - 1];
 3434    this.maxSize = data.maxSize;
 3435    this.minRuleThickness = data.minRuleThickness;
 3436    this._fontMetrics = undefined;
 3437  }
 3438  /**
 3439   * Returns a new options object with the same properties as "this".  Properties
 3440   * from "extension" will be copied to the new options object.
 3441   */
 3442
 3443
 3444  extend(extension) {
 3445    var data = {
 3446      style: this.style,
 3447      size: this.size,
 3448      textSize: this.textSize,
 3449      color: this.color,
 3450      phantom: this.phantom,
 3451      font: this.font,
 3452      fontFamily: this.fontFamily,
 3453      fontWeight: this.fontWeight,
 3454      fontShape: this.fontShape,
 3455      maxSize: this.maxSize,
 3456      minRuleThickness: this.minRuleThickness
 3457    };
 3458
 3459    for (var key in extension) {
 3460      if (extension.hasOwnProperty(key)) {
 3461        data[key] = extension[key];
 3462      }
 3463    }
 3464
 3465    return new Options(data);
 3466  }
 3467  /**
 3468   * Return an options object with the given style. If `this.style === style`,
 3469   * returns `this`.
 3470   */
 3471
 3472
 3473  havingStyle(style) {
 3474    if (this.style === style) {
 3475      return this;
 3476    } else {
 3477      return this.extend({
 3478        style: style,
 3479        size: sizeAtStyle(this.textSize, style)
 3480      });
 3481    }
 3482  }
 3483  /**
 3484   * Return an options object with a cramped version of the current style. If
 3485   * the current style is cramped, returns `this`.
 3486   */
 3487
 3488
 3489  havingCrampedStyle() {
 3490    return this.havingStyle(this.style.cramp());
 3491  }
 3492  /**
 3493   * Return an options object with the given size and in at least `\textstyle`.
 3494   * Returns `this` if appropriate.
 3495   */
 3496
 3497
 3498  havingSize(size) {
 3499    if (this.size === size && this.textSize === size) {
 3500      return this;
 3501    } else {
 3502      return this.extend({
 3503        style: this.style.text(),
 3504        size: size,
 3505        textSize: size,
 3506        sizeMultiplier: sizeMultipliers[size - 1]
 3507      });
 3508    }
 3509  }
 3510  /**
 3511   * Like `this.havingSize(BASESIZE).havingStyle(style)`. If `style` is omitted,
 3512   * changes to at least `\textstyle`.
 3513   */
 3514
 3515
 3516  havingBaseStyle(style) {
 3517    style = style || this.style.text();
 3518    var wantSize = sizeAtStyle(Options.BASESIZE, style);
 3519
 3520    if (this.size === wantSize && this.textSize === Options.BASESIZE && this.style === style) {
 3521      return this;
 3522    } else {
 3523      return this.extend({
 3524        style: style,
 3525        size: wantSize
 3526      });
 3527    }
 3528  }
 3529  /**
 3530   * Remove the effect of sizing changes such as \Huge.
 3531   * Keep the effect of the current style, such as \scriptstyle.
 3532   */
 3533
 3534
 3535  havingBaseSizing() {
 3536    var size;
 3537
 3538    switch (this.style.id) {
 3539      case 4:
 3540      case 5:
 3541        size = 3; // normalsize in scriptstyle
 3542
 3543        break;
 3544
 3545      case 6:
 3546      case 7:
 3547        size = 1; // normalsize in scriptscriptstyle
 3548
 3549        break;
 3550
 3551      default:
 3552        size = 6;
 3553      // normalsize in textstyle or displaystyle
 3554    }
 3555
 3556    return this.extend({
 3557      style: this.style.text(),
 3558      size: size
 3559    });
 3560  }
 3561  /**
 3562   * Create a new options object with the given color.
 3563   */
 3564
 3565
 3566  withColor(color) {
 3567    return this.extend({
 3568      color: color
 3569    });
 3570  }
 3571  /**
 3572   * Create a new options object with "phantom" set to true.
 3573   */
 3574
 3575
 3576  withPhantom() {
 3577    return this.extend({
 3578      phantom: true
 3579    });
 3580  }
 3581  /**
 3582   * Creates a new options object with the given math font or old text font.
 3583   * @type {[type]}
 3584   */
 3585
 3586
 3587  withFont(font) {
 3588    return this.extend({
 3589      font
 3590    });
 3591  }
 3592  /**
 3593   * Create a new options objects with the given fontFamily.
 3594   */
 3595
 3596
 3597  withTextFontFamily(fontFamily) {
 3598    return this.extend({
 3599      fontFamily,
 3600      font: ""
 3601    });
 3602  }
 3603  /**
 3604   * Creates a new options object with the given font weight
 3605   */
 3606
 3607
 3608  withTextFontWeight(fontWeight) {
 3609    return this.extend({
 3610      fontWeight,
 3611      font: ""
 3612    });
 3613  }
 3614  /**
 3615   * Creates a new options object with the given font weight
 3616   */
 3617
 3618
 3619  withTextFontShape(fontShape) {
 3620    return this.extend({
 3621      fontShape,
 3622      font: ""
 3623    });
 3624  }
 3625  /**
 3626   * Return the CSS sizing classes required to switch from enclosing options
 3627   * `oldOptions` to `this`. Returns an array of classes.
 3628   */
 3629
 3630
 3631  sizingClasses(oldOptions) {
 3632    if (oldOptions.size !== this.size) {
 3633      return ["sizing", "reset-size" + oldOptions.size, "size" + this.size];
 3634    } else {
 3635      return [];
 3636    }
 3637  }
 3638  /**
 3639   * Return the CSS sizing classes required to switch to the base size. Like
 3640   * `this.havingSize(BASESIZE).sizingClasses(this)`.
 3641   */
 3642
 3643
 3644  baseSizingClasses() {
 3645    if (this.size !== Options.BASESIZE) {
 3646      return ["sizing", "reset-size" + this.size, "size" + Options.BASESIZE];
 3647    } else {
 3648      return [];
 3649    }
 3650  }
 3651  /**
 3652   * Return the font metrics for this size.
 3653   */
 3654
 3655
 3656  fontMetrics() {
 3657    if (!this._fontMetrics) {
 3658      this._fontMetrics = getGlobalMetrics(this.size);
 3659    }
 3660
 3661    return this._fontMetrics;
 3662  }
 3663  /**
 3664   * Gets the CSS color of the current options object
 3665   */
 3666
 3667
 3668  getColor() {
 3669    if (this.phantom) {
 3670      return "transparent";
 3671    } else {
 3672      return this.color;
 3673    }
 3674  }
 3675
 3676}
 3677
 3678Options.BASESIZE = 6;
 3679
 3680/**
 3681 * This file does conversion between units.  In particular, it provides
 3682 * calculateSize to convert other units into ems.
 3683 */
 3684// Thus, multiplying a length by this number converts the length from units
 3685// into pts.  Dividing the result by ptPerEm gives the number of ems
 3686// *assuming* a font size of ptPerEm (normal size, normal style).
 3687
 3688var ptPerUnit = {
 3689  // https://en.wikibooks.org/wiki/LaTeX/Lengths and
 3690  // https://tex.stackexchange.com/a/8263
 3691  "pt": 1,
 3692  // TeX point
 3693  "mm": 7227 / 2540,
 3694  // millimeter
 3695  "cm": 7227 / 254,
 3696  // centimeter
 3697  "in": 72.27,
 3698  // inch
 3699  "bp": 803 / 800,
 3700  // big (PostScript) points
 3701  "pc": 12,
 3702  // pica
 3703  "dd": 1238 / 1157,
 3704  // didot
 3705  "cc": 14856 / 1157,
 3706  // cicero (12 didot)
 3707  "nd": 685 / 642,
 3708  // new didot
 3709  "nc": 1370 / 107,
 3710  // new cicero (12 new didot)
 3711  "sp": 1 / 65536,
 3712  // scaled point (TeX's internal smallest unit)
 3713  // https://tex.stackexchange.com/a/41371
 3714  "px": 803 / 800 // \pdfpxdimen defaults to 1 bp in pdfTeX and LuaTeX
 3715
 3716}; // Dictionary of relative units, for fast validity testing.
 3717
 3718var relativeUnit = {
 3719  "ex": true,
 3720  "em": true,
 3721  "mu": true
 3722};
 3723
 3724/**
 3725 * Determine whether the specified unit (either a string defining the unit
 3726 * or a "size" parse node containing a unit field) is valid.
 3727 */
 3728var validUnit = function validUnit(unit) {
 3729  if (typeof unit !== "string") {
 3730    unit = unit.unit;
 3731  }
 3732
 3733  return unit in ptPerUnit || unit in relativeUnit || unit === "ex";
 3734};
 3735/*
 3736 * Convert a "size" parse node (with numeric "number" and string "unit" fields,
 3737 * as parsed by functions.js argType "size") into a CSS em value for the
 3738 * current style/scale.  `options` gives the current options.
 3739 */
 3740
 3741var calculateSize = function calculateSize(sizeValue, options) {
 3742  var scale;
 3743
 3744  if (sizeValue.unit in ptPerUnit) {
 3745    // Absolute units
 3746    scale = ptPerUnit[sizeValue.unit] // Convert unit to pt
 3747    / options.fontMetrics().ptPerEm // Convert pt to CSS em
 3748    / options.sizeMultiplier; // Unscale to make absolute units
 3749  } else if (sizeValue.unit === "mu") {
 3750    // `mu` units scale with scriptstyle/scriptscriptstyle.
 3751    scale = options.fontMetrics().cssEmPerMu;
 3752  } else {
 3753    // Other relative units always refer to the *textstyle* font
 3754    // in the current size.
 3755    var unitOptions;
 3756
 3757    if (options.style.isTight()) {
 3758      // isTight() means current style is script/scriptscript.
 3759      unitOptions = options.havingStyle(options.style.text());
 3760    } else {
 3761      unitOptions = options;
 3762    } // TODO: In TeX these units are relative to the quad of the current
 3763    // *text* font, e.g. cmr10. KaTeX instead uses values from the
 3764    // comparably-sized *Computer Modern symbol* font. At 10pt, these
 3765    // match. At 7pt and 5pt, they differ: cmr7=1.138894, cmsy7=1.170641;
 3766    // cmr5=1.361133, cmsy5=1.472241. Consider $\scriptsize a\kern1emb$.
 3767    // TeX \showlists shows a kern of 1.13889 * fontsize;
 3768    // KaTeX shows a kern of 1.171 * fontsize.
 3769
 3770
 3771    if (sizeValue.unit === "ex") {
 3772      scale = unitOptions.fontMetrics().xHeight;
 3773    } else if (sizeValue.unit === "em") {
 3774      scale = unitOptions.fontMetrics().quad;
 3775    } else {
 3776      throw new ParseError("Invalid unit: '" + sizeValue.unit + "'");
 3777    }
 3778
 3779    if (unitOptions !== options) {
 3780      scale *= unitOptions.sizeMultiplier / options.sizeMultiplier;
 3781    }
 3782  }
 3783
 3784  return Math.min(sizeValue.number * scale, options.maxSize);
 3785};
 3786/**
 3787 * Round `n` to 4 decimal places, or to the nearest 1/10,000th em. See
 3788 * https://github.com/KaTeX/KaTeX/pull/2460.
 3789 */
 3790
 3791var makeEm = function makeEm(n) {
 3792  return +n.toFixed(4) + "em";
 3793};
 3794
 3795/**
 3796 * These objects store the data about the DOM nodes we create, as well as some
 3797 * extra data. They can then be transformed into real DOM nodes with the
 3798 * `toNode` function or HTML markup using `toMarkup`. They are useful for both
 3799 * storing extra properties on the nodes, as well as providing a way to easily
 3800 * work with the DOM.
 3801 *
 3802 * Similar functions for working with MathML nodes exist in mathMLTree.js.
 3803 *
 3804 * TODO: refactor `span` and `anchor` into common superclass when
 3805 * target environments support class inheritance
 3806 */
 3807
 3808/**
 3809 * Create an HTML className based on a list of classes. In addition to joining
 3810 * with spaces, we also remove empty classes.
 3811 */
 3812var createClass = function createClass(classes) {
 3813  return classes.filter(cls => cls).join(" ");
 3814};
 3815
 3816var initNode = function initNode(classes, options, style) {
 3817  this.classes = classes || [];
 3818  this.attributes = {};
 3819  this.height = 0;
 3820  this.depth = 0;
 3821  this.maxFontSize = 0;
 3822  this.style = style || {};
 3823
 3824  if (options) {
 3825    if (options.style.isTight()) {
 3826      this.classes.push("mtight");
 3827    }
 3828
 3829    var color = options.getColor();
 3830
 3831    if (color) {
 3832      this.style.color = color;
 3833    }
 3834  }
 3835};
 3836/**
 3837 * Convert into an HTML node
 3838 */
 3839
 3840
 3841var toNode = function toNode(tagName) {
 3842  var node = document.createElement(tagName); // Apply the class
 3843
 3844  node.className = createClass(this.classes); // Apply inline styles
 3845
 3846  for (var style in this.style) {
 3847    if (this.style.hasOwnProperty(style)) {
 3848      // $FlowFixMe Flow doesn't seem to understand span.style's type.
 3849      node.style[style] = this.style[style];
 3850    }
 3851  } // Apply attributes
 3852
 3853
 3854  for (var attr in this.attributes) {
 3855    if (this.attributes.hasOwnProperty(attr)) {
 3856      node.setAttribute(attr, this.attributes[attr]);
 3857    }
 3858  } // Append the children, also as HTML nodes
 3859
 3860
 3861  for (var i = 0; i < this.children.length; i++) {
 3862    node.appendChild(this.children[i].toNode());
 3863  }
 3864
 3865  return node;
 3866};
 3867/**
 3868 * Convert into an HTML markup string
 3869 */
 3870
 3871
 3872var toMarkup = function toMarkup(tagName) {
 3873  var markup = "<" + tagName; // Add the class
 3874
 3875  if (this.classes.length) {
 3876    markup += " class=\"" + utils.escape(createClass(this.classes)) + "\"";
 3877  }
 3878
 3879  var styles = ""; // Add the styles, after hyphenation
 3880
 3881  for (var style in this.style) {
 3882    if (this.style.hasOwnProperty(style)) {
 3883      styles += utils.hyphenate(style) + ":" + this.style[style] + ";";
 3884    }
 3885  }
 3886
 3887  if (styles) {
 3888    markup += " style=\"" + utils.escape(styles) + "\"";
 3889  } // Add the attributes
 3890
 3891
 3892  for (var attr in this.attributes) {
 3893    if (this.attributes.hasOwnProperty(attr)) {
 3894      markup += " " + attr + "=\"" + utils.escape(this.attributes[attr]) + "\"";
 3895    }
 3896  }
 3897
 3898  markup += ">"; // Add the markup of the children, also as markup
 3899
 3900  for (var i = 0; i < this.children.length; i++) {
 3901    markup += this.children[i].toMarkup();
 3902  }
 3903
 3904  markup += "</" + tagName + ">";
 3905  return markup;
 3906}; // Making the type below exact with all optional fields doesn't work due to
 3907// - https://github.com/facebook/flow/issues/4582
 3908// - https://github.com/facebook/flow/issues/5688
 3909// However, since *all* fields are optional, $Shape<> works as suggested in 5688
 3910// above.
 3911// This type does not include all CSS properties. Additional properties should
 3912// be added as needed.
 3913
 3914
 3915/**
 3916 * This node represents a span node, with a className, a list of children, and
 3917 * an inline style. It also contains information about its height, depth, and
 3918 * maxFontSize.
 3919 *
 3920 * Represents two types with different uses: SvgSpan to wrap an SVG and DomSpan
 3921 * otherwise. This typesafety is important when HTML builders access a span's
 3922 * children.
 3923 */
 3924class Span {
 3925  constructor(classes, children, options, style) {
 3926    this.children = void 0;
 3927    this.attributes = void 0;
 3928    this.classes = void 0;
 3929    this.height = void 0;
 3930    this.depth = void 0;
 3931    this.width = void 0;
 3932    this.maxFontSize = void 0;
 3933    this.style = void 0;
 3934    initNode.call(this, classes, options, style);
 3935    this.children = children || [];
 3936  }
 3937  /**
 3938   * Sets an arbitrary attribute on the span. Warning: use this wisely. Not
 3939   * all browsers support attributes the same, and having too many custom
 3940   * attributes is probably bad.
 3941   */
 3942
 3943
 3944  setAttribute(attribute, value) {
 3945    this.attributes[attribute] = value;
 3946  }
 3947
 3948  hasClass(className) {
 3949    return utils.contains(this.classes, className);
 3950  }
 3951
 3952  toNode() {
 3953    return toNode.call(this, "span");
 3954  }
 3955
 3956  toMarkup() {
 3957    return toMarkup.call(this, "span");
 3958  }
 3959
 3960}
 3961/**
 3962 * This node represents an anchor (<a>) element with a hyperlink.  See `span`
 3963 * for further details.
 3964 */
 3965
 3966class Anchor {
 3967  constructor(href, classes, children, options) {
 3968    this.children = void 0;
 3969    this.attributes = void 0;
 3970    this.classes = void 0;
 3971    this.height = void 0;
 3972    this.depth = void 0;
 3973    this.maxFontSize = void 0;
 3974    this.style = void 0;
 3975    initNode.call(this, classes, options);
 3976    this.children = children || [];
 3977    this.setAttribute('href', href);
 3978  }
 3979
 3980  setAttribute(attribute, value) {
 3981    this.attributes[attribute] = value;
 3982  }
 3983
 3984  hasClass(className) {
 3985    return utils.contains(this.classes, className);
 3986  }
 3987
 3988  toNode() {
 3989    return toNode.call(this, "a");
 3990  }
 3991
 3992  toMarkup() {
 3993    return toMarkup.call(this, "a");
 3994  }
 3995
 3996}
 3997/**
 3998 * This node represents an image embed (<img>) element.
 3999 */
 4000
 4001class Img {
 4002  constructor(src, alt, style) {
 4003    this.src = void 0;
 4004    this.alt = void 0;
 4005    this.classes = void 0;
 4006    this.height = void 0;
 4007    this.depth = void 0;
 4008    this.maxFontSize = void 0;
 4009    this.style = void 0;
 4010    this.alt = alt;
 4011    this.src = src;
 4012    this.classes = ["mord"];
 4013    this.style = style;
 4014  }
 4015
 4016  hasClass(className) {
 4017    return utils.contains(this.classes, className);
 4018  }
 4019
 4020  toNode() {
 4021    var node = document.createElement("img");
 4022    node.src = this.src;
 4023    node.alt = this.alt;
 4024    node.className = "mord"; // Apply inline styles
 4025
 4026    for (var style in this.style) {
 4027      if (this.style.hasOwnProperty(style)) {
 4028        // $FlowFixMe
 4029        node.style[style] = this.style[style];
 4030      }
 4031    }
 4032
 4033    return node;
 4034  }
 4035
 4036  toMarkup() {
 4037    var markup = "<img  src='" + this.src + " 'alt='" + this.alt + "' "; // Add the styles, after hyphenation
 4038
 4039    var styles = "";
 4040
 4041    for (var style in this.style) {
 4042      if (this.style.hasOwnProperty(style)) {
 4043        styles += utils.hyphenate(style) + ":" + this.style[style] + ";";
 4044      }
 4045    }
 4046
 4047    if (styles) {
 4048      markup += " style=\"" + utils.escape(styles) + "\"";
 4049    }
 4050
 4051    markup += "'/>";
 4052    return markup;
 4053  }
 4054
 4055}
 4056var iCombinations = {
 4057  'î': '\u0131\u0302',
 4058  'ï': '\u0131\u0308',
 4059  'í': '\u0131\u0301',
 4060  // 'ī': '\u0131\u0304', // enable when we add Extended Latin
 4061  'ì': '\u0131\u0300'
 4062};
 4063/**
 4064 * A symbol node contains information about a single symbol. It either renders
 4065 * to a single text node, or a span with a single text node in it, depending on
 4066 * whether it has CSS classes, styles, or needs italic correction.
 4067 */
 4068
 4069class SymbolNode {
 4070  constructor(text, height, depth, italic, skew, width, classes, style) {
 4071    this.text = void 0;
 4072    this.height = void 0;
 4073    this.depth = void 0;
 4074    this.italic = void 0;
 4075    this.skew = void 0;
 4076    this.width = void 0;
 4077    this.maxFontSize = void 0;
 4078    this.classes = void 0;
 4079    this.style = void 0;
 4080    this.text = text;
 4081    this.height = height || 0;
 4082    this.depth = depth || 0;
 4083    this.italic = italic || 0;
 4084    this.skew = skew || 0;
 4085    this.width = width || 0;
 4086    this.classes = classes || [];
 4087    this.style = style || {};
 4088    this.maxFontSize = 0; // Mark text from non-Latin scripts with specific classes so that we
 4089    // can specify which fonts to use.  This allows us to render these
 4090    // characters with a serif font in situations where the browser would
 4091    // either default to a sans serif or render a placeholder character.
 4092    // We use CSS class names like cjk_fallback, hangul_fallback and
 4093    // brahmic_fallback. See ./unicodeScripts.js for the set of possible
 4094    // script names
 4095
 4096    var script = scriptFromCodepoint(this.text.charCodeAt(0));
 4097
 4098    if (script) {
 4099      this.classes.push(script + "_fallback");
 4100    }
 4101
 4102    if (/[îïíì]/.test(this.text)) {
 4103      // add ī when we add Extended Latin
 4104      this.text = iCombinations[this.text];
 4105    }
 4106  }
 4107
 4108  hasClass(className) {
 4109    return utils.contains(this.classes, className);
 4110  }
 4111  /**
 4112   * Creates a text node or span from a symbol node. Note that a span is only
 4113   * created if it is needed.
 4114   */
 4115
 4116
 4117  toNode() {
 4118    var node = document.createTextNode(this.text);
 4119    var span = null;
 4120
 4121    if (this.italic > 0) {
 4122      span = document.createElement("span");
 4123      span.style.marginRight = makeEm(this.italic);
 4124    }
 4125
 4126    if (this.classes.length > 0) {
 4127      span = span || document.createElement("span");
 4128      span.className = createClass(this.classes);
 4129    }
 4130
 4131    for (var style in this.style) {
 4132      if (this.style.hasOwnProperty(style)) {
 4133        span = span || document.createElement("span"); // $FlowFixMe Flow doesn't seem to understand span.style's type.
 4134
 4135        span.style[style] = this.style[style];
 4136      }
 4137    }
 4138
 4139    if (span) {
 4140      span.appendChild(node);
 4141      return span;
 4142    } else {
 4143      return node;
 4144    }
 4145  }
 4146  /**
 4147   * Creates markup for a symbol node.
 4148   */
 4149
 4150
 4151  toMarkup() {
 4152    // TODO(alpert): More duplication than I'd like from
 4153    // span.prototype.toMarkup and symbolNode.prototype.toNode...
 4154    var needsSpan = false;
 4155    var markup = "<span";
 4156
 4157    if (this.classes.length) {
 4158      needsSpan = true;
 4159      markup += " class=\"";
 4160      markup += utils.escape(createClass(this.classes));
 4161      markup += "\"";
 4162    }
 4163
 4164    var styles = "";
 4165
 4166    if (this.italic > 0) {
 4167      styles += "margin-right:" + this.italic + "em;";
 4168    }
 4169
 4170    for (var style in this.style) {
 4171      if (this.style.hasOwnProperty(style)) {
 4172        styles += utils.hyphenate(style) + ":" + this.style[style] + ";";
 4173      }
 4174    }
 4175
 4176    if (styles) {
 4177      needsSpan = true;
 4178      markup += " style=\"" + utils.escape(styles) + "\"";
 4179    }
 4180
 4181    var escaped = utils.escape(this.text);
 4182
 4183    if (needsSpan) {
 4184      markup += ">";
 4185      markup += escaped;
 4186      markup += "</span>";
 4187      return markup;
 4188    } else {
 4189      return escaped;
 4190    }
 4191  }
 4192
 4193}
 4194/**
 4195 * SVG nodes are used to render stretchy wide elements.
 4196 */
 4197
 4198class SvgNode {
 4199  constructor(children, attributes) {
 4200    this.children = void 0;
 4201    this.attributes = void 0;
 4202    this.children = children || [];
 4203    this.attributes = attributes || {};
 4204  }
 4205
 4206  toNode() {
 4207    var svgNS = "http://www.w3.org/2000/svg";
 4208    var node = document.createElementNS(svgNS, "svg"); // Apply attributes
 4209
 4210    for (var attr in this.attributes) {
 4211      if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
 4212        node.setAttribute(attr, this.attributes[attr]);
 4213      }
 4214    }
 4215
 4216    for (var i = 0; i < this.children.length; i++) {
 4217      node.appendChild(this.children[i].toNode());
 4218    }
 4219
 4220    return node;
 4221  }
 4222
 4223  toMarkup() {
 4224    var markup = "<svg xmlns=\"http://www.w3.org/2000/svg\""; // Apply attributes
 4225
 4226    for (var attr in this.attributes) {
 4227      if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
 4228        markup += " " + attr + "='" + this.attributes[attr] + "'";
 4229      }
 4230    }
 4231
 4232    markup += ">";
 4233
 4234    for (var i = 0; i < this.children.length; i++) {
 4235      markup += this.children[i].toMarkup();
 4236    }
 4237
 4238    markup += "</svg>";
 4239    return markup;
 4240  }
 4241
 4242}
 4243class PathNode {
 4244  constructor(pathName, alternate) {
 4245    this.pathName = void 0;
 4246    this.alternate = void 0;
 4247    this.pathName = pathName;
 4248    this.alternate = alternate; // Used only for \sqrt, \phase, & tall delims
 4249  }
 4250
 4251  toNode() {
 4252    var svgNS = "http://www.w3.org/2000/svg";
 4253    var node = document.createElementNS(svgNS, "path");
 4254
 4255    if (this.alternate) {
 4256      node.setAttribute("d", this.alternate);
 4257    } else {
 4258      node.setAttribute("d", path[this.pathName]);
 4259    }
 4260
 4261    return node;
 4262  }
 4263
 4264  toMarkup() {
 4265    if (this.alternate) {
 4266      return "<path d='" + this.alternate + "'/>";
 4267    } else {
 4268      return "<path d='" + path[this.pathName] + "'/>";
 4269    }
 4270  }
 4271
 4272}
 4273class LineNode {
 4274  constructor(attributes) {
 4275    this.attributes = void 0;
 4276    this.attributes = attributes || {};
 4277  }
 4278
 4279  toNode() {
 4280    var svgNS = "http://www.w3.org/2000/svg";
 4281    var node = document.createElementNS(svgNS, "line"); // Apply attributes
 4282
 4283    for (var attr in this.attributes) {
 4284      if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
 4285        node.setAttribute(attr, this.attributes[attr]);
 4286      }
 4287    }
 4288
 4289    return node;
 4290  }
 4291
 4292  toMarkup() {
 4293    var markup = "<line";
 4294
 4295    for (var attr in this.attributes) {
 4296      if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
 4297        markup += " " + attr + "='" + this.attributes[attr] + "'";
 4298      }
 4299    }
 4300
 4301    markup += "/>";
 4302    return markup;
 4303  }
 4304
 4305}
 4306function assertSymbolDomNode(group) {
 4307  if (group instanceof SymbolNode) {
 4308    return group;
 4309  } else {
 4310    throw new Error("Expected symbolNode but got " + String(group) + ".");
 4311  }
 4312}
 4313function assertSpan(group) {
 4314  if (group instanceof Span) {
 4315    return group;
 4316  } else {
 4317    throw new Error("Expected span<HtmlDomNode> but got " + String(group) + ".");
 4318  }
 4319}
 4320
 4321/**
 4322 * This file holds a list of all no-argument functions and single-character
 4323 * symbols (like 'a' or ';').
 4324 *
 4325 * For each of the symbols, there are three properties they can have:
 4326 * - font (required): the font to be used for this symbol. Either "main" (the
 4327     normal font), or "ams" (the ams fonts).
 4328 * - group (required): the ParseNode group type the symbol should have (i.e.
 4329     "textord", "mathord", etc).
 4330     See https://github.com/KaTeX/KaTeX/wiki/Examining-TeX#group-types
 4331 * - replace: the character that this symbol or function should be
 4332 *   replaced with (i.e. "\phi" has a replace value of "\u03d5", the phi
 4333 *   character in the main font).
 4334 *
 4335 * The outermost map in the table indicates what mode the symbols should be
 4336 * accepted in (e.g. "math" or "text").
 4337 */
 4338// Some of these have a "-token" suffix since these are also used as `ParseNode`
 4339// types for raw text tokens, and we want to avoid conflicts with higher-level
 4340// `ParseNode` types. These `ParseNode`s are constructed within `Parser` by
 4341// looking up the `symbols` map.
 4342var ATOMS = {
 4343  "bin": 1,
 4344  "close": 1,
 4345  "inner": 1,
 4346  "open": 1,
 4347  "punct": 1,
 4348  "rel": 1
 4349};
 4350var NON_ATOMS = {
 4351  "accent-token": 1,
 4352  "mathord": 1,
 4353  "op-token": 1,
 4354  "spacing": 1,
 4355  "textord": 1
 4356};
 4357var symbols = {
 4358  "math": {},
 4359  "text": {}
 4360};
 4361/** `acceptUnicodeChar = true` is only applicable if `replace` is set. */
 4362
 4363function defineSymbol(mode, font, group, replace, name, acceptUnicodeChar) {
 4364  symbols[mode][name] = {
 4365    font,
 4366    group,
 4367    replace
 4368  };
 4369
 4370  if (acceptUnicodeChar && replace) {
 4371    symbols[mode][replace] = symbols[mode][name];
 4372  }
 4373} // Some abbreviations for commonly used strings.
 4374// This helps minify the code, and also spotting typos using jshint.
 4375// modes:
 4376
 4377var math = "math";
 4378var text = "text"; // fonts:
 4379
 4380var main = "main";
 4381var ams = "ams"; // groups:
 4382
 4383var accent = "accent-token";
 4384var bin = "bin";
 4385var close = "close";
 4386var inner = "inner";
 4387var mathord = "mathord";
 4388var op = "op-token";
 4389var open = "open";
 4390var punct = "punct";
 4391var rel = "rel";
 4392var spacing = "spacing";
 4393var textord = "textord"; // Now comes the symbol table
 4394// Relation Symbols
 4395
 4396defineSymbol(math, main, rel, "\u2261", "\\equiv", true);
 4397defineSymbol(math, main, rel, "\u227a", "\\prec", true);
 4398defineSymbol(math, main, rel, "\u227b", "\\succ", true);
 4399defineSymbol(math, main, rel, "\u223c", "\\sim", true);
 4400defineSymbol(math, main, rel, "\u22a5", "\\perp");
 4401defineSymbol(math, main, rel, "\u2aaf", "\\preceq", true);
 4402defineSymbol(math, main, rel, "\u2ab0", "\\succeq", true);
 4403defineSymbol(math, main, rel, "\u2243", "\\simeq", true);
 4404defineSymbol(math, main, rel, "\u2223", "\\mid", true);
 4405defineSymbol(math, main, rel, "\u226a", "\\ll", true);
 4406defineSymbol(math, main, rel, "\u226b", "\\gg", true);
 4407defineSymbol(math, main, rel, "\u224d", "\\asymp", true);
 4408defineSymbol(math, main, rel, "\u2225", "\\parallel");
 4409defineSymbol(math, main, rel, "\u22c8", "\\bowtie", true);
 4410defineSymbol(math, main, rel, "\u2323", "\\smile", true);
 4411defineSymbol(math, main, rel, "\u2291", "\\sqsubseteq", true);
 4412defineSymbol(math, main, rel, "\u2292", "\\sqsupseteq", true);
 4413defineSymbol(math, main, rel, "\u2250", "\\doteq", true);
 4414defineSymbol(math, main, rel, "\u2322", "\\frown", true);
 4415defineSymbol(math, main, rel, "\u220b", "\\ni", true);
 4416defineSymbol(math, main, rel, "\u221d", "\\propto", true);
 4417defineSymbol(math, main, rel, "\u22a2", "\\vdash", true);
 4418defineSymbol(math, main, rel, "\u22a3", "\\dashv", true);
 4419defineSymbol(math, main, rel, "\u220b", "\\owns"); // Punctuation
 4420
 4421defineSymbol(math, main, punct, "\u002e", "\\ldotp");
 4422defineSymbol(math, main, punct, "\u22c5", "\\cdotp"); // Misc Symbols
 4423
 4424defineSymbol(math, main, textord, "\u0023", "\\#");
 4425defineSymbol(text, main, textord, "\u0023", "\\#");
 4426defineSymbol(math, main, textord, "\u0026", "\\&");
 4427defineSymbol(text, main, textord, "\u0026", "\\&");
 4428defineSymbol(math, main, textord, "\u2135", "\\aleph", true);
 4429defineSymbol(math, main, textord, "\u2200", "\\forall", true);
 4430defineSymbol(math, main, textord, "\u210f", "\\hbar", true);
 4431defineSymbol(math, main, textord, "\u2203", "\\exists", true);
 4432defineSymbol(math, main, textord, "\u2207", "\\nabla", true);
 4433defineSymbol(math, main, textord, "\u266d", "\\flat", true);
 4434defineSymbol(math, main, textord, "\u2113", "\\ell", true);
 4435defineSymbol(math, main, textord, "\u266e", "\\natural", true);
 4436defineSymbol(math, main, textord, "\u2663", "\\clubsuit", true);
 4437defineSymbol(math, main, textord, "\u2118", "\\wp", true);
 4438defineSymbol(math, main, textord, "\u266f", "\\sharp", true);
 4439defineSymbol(math, main, textord, "\u2662", "\\diamondsuit", true);
 4440defineSymbol(math, main, textord, "\u211c", "\\Re", true);
 4441defineSymbol(math, main, textord, "\u2661", "\\heartsuit", true);
 4442defineSymbol(math, main, textord, "\u2111", "\\Im", true);
 4443defineSymbol(math, main, textord, "\u2660", "\\spadesuit", true);
 4444defineSymbol(math, main, textord, "\u00a7", "\\S", true);
 4445defineSymbol(text, main, textord, "\u00a7", "\\S");
 4446defineSymbol(math, main, textord, "\u00b6", "\\P", true);
 4447defineSymbol(text, main, textord, "\u00b6", "\\P"); // Math and Text
 4448
 4449defineSymbol(math, main, textord, "\u2020", "\\dag");
 4450defineSymbol(text, main, textord, "\u2020", "\\dag");
 4451defineSymbol(text, main, textord, "\u2020", "\\textdagger");
 4452defineSymbol(math, main, textord, "\u2021", "\\ddag");
 4453defineSymbol(text, main, textord, "\u2021", "\\ddag");
 4454defineSymbol(text, main, textord, "\u2021", "\\textdaggerdbl"); // Large Delimiters
 4455
 4456defineSymbol(math, main, close, "\u23b1", "\\rmoustache", true);
 4457defineSymbol(math, main, open, "\u23b0", "\\lmoustache", true);
 4458defineSymbol(math, main, close, "\u27ef", "\\rgroup", true);
 4459defineSymbol(math, main, open, "\u27ee", "\\lgroup", true); // Binary Operators
 4460
 4461defineSymbol(math, main, bin, "\u2213", "\\mp", true);
 4462defineSymbol(math, main, bin, "\u2296", "\\ominus", true);
 4463defineSymbol(math, main, bin, "\u228e", "\\uplus", true);
 4464defineSymbol(math, main, bin, "\u2293", "\\sqcap", true);
 4465defineSymbol(math, main, bin, "\u2217", "\\ast");
 4466defineSymbol(math, main, bin, "\u2294", "\\sqcup", true);
 4467defineSymbol(math, main, bin, "\u25ef", "\\bigcirc", true);
 4468defineSymbol(math, main, bin, "\u2219", "\\bullet", true);
 4469defineSymbol(math, main, bin, "\u2021", "\\ddagger");
 4470defineSymbol(math, main, bin, "\u2240", "\\wr", true);
 4471defineSymbol(math, main, bin, "\u2a3f", "\\amalg");
 4472defineSymbol(math, main, bin, "\u0026", "\\And"); // from amsmath
 4473// Arrow Symbols
 4474
 4475defineSymbol(math, main, rel, "\u27f5", "\\longleftarrow", true);
 4476defineSymbol(math, main, rel, "\u21d0", "\\Leftarrow", true);
 4477defineSymbol(math, main, rel, "\u27f8", "\\Longleftarrow", true);
 4478defineSymbol(math, main, rel, "\u27f6", "\\longrightarrow", true);
 4479defineSymbol(math, main, rel, "\u21d2", "\\Rightarrow", true);
 4480defineSymbol(math, main, rel, "\u27f9", "\\Longrightarrow", true);
 4481defineSymbol(math, main, rel, "\u2194", "\\leftrightarrow", true);
 4482defineSymbol(math, main, rel, "\u27f7", "\\longleftrightarrow", true);
 4483defineSymbol(math, main, rel, "\u21d4", "\\Leftrightarrow", true);
 4484defineSymbol(math, main, rel, "\u27fa", "\\Longleftrightarrow", true);
 4485defineSymbol(math, main, rel, "\u21a6", "\\mapsto", true);
 4486defineSymbol(math, main, rel, "\u27fc", "\\longmapsto", true);
 4487defineSymbol(math, main, rel, "\u2197", "\\nearrow", true);
 4488defineSymbol(math, main, rel, "\u21a9", "\\hookleftarrow", true);
 4489defineSymbol(math, main, rel, "\u21aa", "\\hookrightarrow", true);
 4490defineSymbol(math, main, rel, "\u2198", "\\searrow", true);
 4491defineSymbol(math, main, rel, "\u21bc", "\\leftharpoonup", true);
 4492defineSymbol(math, main, rel, "\u21c0", "\\rightharpoonup", true);
 4493defineSymbol(math, main, rel, "\u2199", "\\swarrow", true);
 4494defineSymbol(math, main, rel, "\u21bd", "\\leftharpoondown", true);
 4495defineSymbol(math, main, rel, "\u21c1", "\\rightharpoondown", true);
 4496defineSymbol(math, main, rel, "\u2196", "\\nwarrow", true);
 4497defineSymbol(math, main, rel, "\u21cc", "\\rightleftharpoons", true); // AMS Negated Binary Relations
 4498
 4499defineSymbol(math, ams, rel, "\u226e", "\\nless", true); // Symbol names preceeded by "@" each have a corresponding macro.
 4500
 4501defineSymbol(math, ams, rel, "\ue010", "\\@nleqslant");
 4502defineSymbol(math, ams, rel, "\ue011", "\\@nleqq");
 4503defineSymbol(math, ams, rel, "\u2a87", "\\lneq", true);
 4504defineSymbol(math, ams, rel, "\u2268", "\\lneqq", true);
 4505defineSymbol(math, ams, rel, "\ue00c", "\\@lvertneqq");
 4506defineSymbol(math, ams, rel, "\u22e6", "\\lnsim", true);
 4507defineSymbol(math, ams, rel, "\u2a89", "\\lnapprox", true);
 4508defineSymbol(math, ams, rel, "\u2280", "\\nprec", true); // unicode-math maps \u22e0 to \npreccurlyeq. We'll use the AMS synonym.
 4509
 4510defineSymbol(math, ams, rel, "\u22e0", "\\npreceq", true);
 4511defineSymbol(math, ams, rel, "\u22e8", "\\precnsim", true);
 4512defineSymbol(math, ams, rel, "\u2ab9", "\\precnapprox", true);
 4513defineSymbol(math, ams, rel, "\u2241", "\\nsim", true);
 4514defineSymbol(math, ams, rel, "\ue006", "\\@nshortmid");
 4515defineSymbol(math, ams, rel, "\u2224", "\\nmid", true);
 4516defineSymbol(math, ams, rel, "\u22ac", "\\nvdash", true);
 4517defineSymbol(math, ams, rel, "\u22ad", "\\nvDash", true);
 4518defineSymbol(math, ams, rel, "\u22ea", "\\ntriangleleft");
 4519defineSymbol(math, ams, rel, "\u22ec", "\\ntrianglelefteq", true);
 4520defineSymbol(math, ams, rel, "\u228a", "\\subsetneq", true);
 4521defineSymbol(math, ams, rel, "\ue01a", "\\@varsubsetneq");
 4522defineSymbol(math, ams, rel, "\u2acb", "\\subsetneqq", true);
 4523defineSymbol(math, ams, rel, "\ue017", "\\@varsubsetneqq");
 4524defineSymbol(math, ams, rel, "\u226f", "\\ngtr", true);
 4525defineSymbol(math, ams, rel, "\ue00f", "\\@ngeqslant");
 4526defineSymbol(math, ams, rel, "\ue00e", "\\@ngeqq");
 4527defineSymbol(math, ams, rel, "\u2a88", "\\gneq", true);
 4528defineSymbol(math, ams, rel, "\u2269", "\\gneqq", true);
 4529defineSymbol(math, ams, rel, "\ue00d", "\\@gvertneqq");
 4530defineSymbol(math, ams, rel, "\u22e7", "\\gnsim", true);
 4531defineSymbol(math, ams, rel, "\u2a8a", "\\gnapprox", true);
 4532defineSymbol(math, ams, rel, "\u2281", "\\nsucc", true); // unicode-math maps \u22e1 to \nsucccurlyeq. We'll use the AMS synonym.
 4533
 4534defineSymbol(math, ams, rel, "\u22e1", "\\nsucceq", true);
 4535defineSymbol(math, ams, rel, "\u22e9", "\\succnsim", true);
 4536defineSymbol(math, ams, rel, "\u2aba", "\\succnapprox", true); // unicode-math maps \u2246 to \simneqq. We'll use the AMS synonym.
 4537
 4538defineSymbol(math, ams, rel, "\u2246", "\\ncong", true);
 4539defineSymbol(math, ams, rel, "\ue007", "\\@nshortparallel");
 4540defineSymbol(math, ams, rel, "\u2226", "\\nparallel", true);
 4541defineSymbol(math, ams, rel, "\u22af", "\\nVDash", true);
 4542defineSymbol(math, ams, rel, "\u22eb", "\\ntriangleright");
 4543defineSymbol(math, ams, rel, "\u22ed", "\\ntrianglerighteq", true);
 4544defineSymbol(math, ams, rel, "\ue018", "\\@nsupseteqq");
 4545defineSymbol(math, ams, rel, "\u228b", "\\supsetneq", true);
 4546defineSymbol(math, ams, rel, "\ue01b", "\\@varsupsetneq");
 4547defineSymbol(math, ams, rel, "\u2acc", "\\supsetneqq", true);
 4548defineSymbol(math, ams, rel, "\ue019", "\\@varsupsetneqq");
 4549defineSymbol(math, ams, rel, "\u22ae", "\\nVdash", true);
 4550defineSymbol(math, ams, rel, "\u2ab5", "\\precneqq", true);
 4551defineSymbol(math, ams, rel, "\u2ab6", "\\succneqq", true);
 4552defineSymbol(math, ams, rel, "\ue016", "\\@nsubseteqq");
 4553defineSymbol(math, ams, bin, "\u22b4", "\\unlhd");
 4554defineSymbol(math, ams, bin, "\u22b5", "\\unrhd"); // AMS Negated Arrows
 4555
 4556defineSymbol(math, ams, rel, "\u219a", "\\nleftarrow", true);
 4557defineSymbol(math, ams, rel, "\u219b", "\\nrightarrow", true);
 4558defineSymbol(math, ams, rel, "\u21cd", "\\nLeftarrow", true);
 4559defineSymbol(math, ams, rel, "\u21cf", "\\nRightarrow", true);
 4560defineSymbol(math, ams, rel, "\u21ae", "\\nleftrightarrow", true);
 4561defineSymbol(math, ams, rel, "\u21ce", "\\nLeftrightarrow", true); // AMS Misc
 4562
 4563defineSymbol(math, ams, rel, "\u25b3", "\\vartriangle");
 4564defineSymbol(math, ams, textord, "\u210f", "\\hslash");
 4565defineSymbol(math, ams, textord, "\u25bd", "\\triangledown");
 4566defineSymbol(math, ams, textord, "\u25ca", "\\lozenge");
 4567defineSymbol(math, ams, textord, "\u24c8", "\\circledS");
 4568defineSymbol(math, ams, textord, "\u00ae", "\\circledR");
 4569defineSymbol(text, ams, textord, "\u00ae", "\\circledR");
 4570defineSymbol(math, ams, textord, "\u2221", "\\measuredangle", true);
 4571defineSymbol(math, ams, textord, "\u2204", "\\nexists");
 4572defineSymbol(math, ams, textord, "\u2127", "\\mho");
 4573defineSymbol(math, ams, textord, "\u2132", "\\Finv", true);
 4574defineSymbol(math, ams, textord, "\u2141", "\\Game", true);
 4575defineSymbol(math, ams, textord, "\u2035", "\\backprime");
 4576defineSymbol(math, ams, textord, "\u25b2", "\\blacktriangle");
 4577defineSymbol(math, ams, textord, "\u25bc", "\\blacktriangledown");
 4578defineSymbol(math, ams, textord, "\u25a0", "\\blacksquare");
 4579defineSymbol(math, ams, textord, "\u29eb", "\\blacklozenge");
 4580defineSymbol(math, ams, textord, "\u2605", "\\bigstar");
 4581defineSymbol(math, ams, textord, "\u2222", "\\sphericalangle", true);
 4582defineSymbol(math, ams, textord, "\u2201", "\\complement", true); // unicode-math maps U+F0 to \matheth. We map to AMS function \eth
 4583
 4584defineSymbol(math, ams, textord, "\u00f0", "\\eth", true);
 4585defineSymbol(text, main, textord, "\u00f0", "\u00f0");
 4586defineSymbol(math, ams, textord, "\u2571", "\\diagup");
 4587defineSymbol(math, ams, textord, "\u2572", "\\diagdown");
 4588defineSymbol(math, ams, textord, "\u25a1", "\\square");
 4589defineSymbol(math, ams, textord, "\u25a1", "\\Box");
 4590defineSymbol(math, ams, textord, "\u25ca", "\\Diamond"); // unicode-math maps U+A5 to \mathyen. We map to AMS function \yen
 4591
 4592defineSymbol(math, ams, textord, "\u00a5", "\\yen", true);
 4593defineSymbol(text, ams, textord, "\u00a5", "\\yen", true);
 4594defineSymbol(math, ams, textord, "\u2713", "\\checkmark", true);
 4595defineSymbol(text, ams, textord, "\u2713", "\\checkmark"); // AMS Hebrew
 4596
 4597defineSymbol(math, ams, textord, "\u2136", "\\beth", true);
 4598defineSymbol(math, ams, textord, "\u2138", "\\daleth", true);
 4599defineSymbol(math, ams, textord, "\u2137", "\\gimel", true); // AMS Greek
 4600
 4601defineSymbol(math, ams, textord, "\u03dd", "\\digamma", true);
 4602defineSymbol(math, ams, textord, "\u03f0", "\\varkappa"); // AMS Delimiters
 4603
 4604defineSymbol(math, ams, open, "\u250c", "\\@ulcorner", true);
 4605defineSymbol(math, ams, close, "\u2510", "\\@urcorner", true);
 4606defineSymbol(math, ams, open, "\u2514", "\\@llcorner", true);
 4607defineSymbol(math, ams, close, "\u2518", "\\@lrcorner", true); // AMS Binary Relations
 4608
 4609defineSymbol(math, ams, rel, "\u2266", "\\leqq", true);
 4610defineSymbol(math, ams, rel, "\u2a7d", "\\leqslant", true);
 4611defineSymbol(math, ams, rel, "\u2a95", "\\eqslantless", true);
 4612defineSymbol(math, ams, rel, "\u2272", "\\lesssim", true);
 4613defineSymbol(math, ams, rel, "\u2a85", "\\lessapprox", true);
 4614defineSymbol(math, ams, rel, "\u224a", "\\approxeq", true);
 4615defineSymbol(math, ams, bin, "\u22d6", "\\lessdot");
 4616defineSymbol(math, ams, rel, "\u22d8", "\\lll", true);
 4617defineSymbol(math, ams, rel, "\u2276", "\\lessgtr", true);
 4618defineSymbol(math, ams, rel, "\u22da", "\\lesseqgtr", true);
 4619defineSymbol(math, ams, rel, "\u2a8b", "\\lesseqqgtr", true);
 4620defineSymbol(math, ams, rel, "\u2251", "\\doteqdot");
 4621defineSymbol(math, ams, rel, "\u2253", "\\risingdotseq", true);
 4622defineSymbol(math, ams, rel, "\u2252", "\\fallingdotseq", true);
 4623defineSymbol(math, ams, rel, "\u223d", "\\backsim", true);
 4624defineSymbol(math, ams, rel, "\u22cd", "\\backsimeq", true);
 4625defineSymbol(math, ams, rel, "\u2ac5", "\\subseteqq", true);
 4626defineSymbol(math, ams, rel, "\u22d0", "\\Subset", true);
 4627defineSymbol(math, ams, rel, "\u228f", "\\sqsubset", true);
 4628defineSymbol(math, ams, rel, "\u227c", "\\preccurlyeq", true);
 4629defineSymbol(math, ams, rel, "\u22de", "\\curlyeqprec", true);
 4630defineSymbol(math, ams, rel, "\u227e", "\\precsim", true);
 4631defineSymbol(math, ams, rel, "\u2ab7", "\\precapprox", true);
 4632defineSymbol(math, ams, rel, "\u22b2", "\\vartriangleleft");
 4633defineSymbol(math, ams, rel, "\u22b4", "\\trianglelefteq");
 4634defineSymbol(math, ams, rel, "\u22a8", "\\vDash", true);
 4635defineSymbol(math, ams, rel, "\u22aa", "\\Vvdash", true);
 4636defineSymbol(math, ams, rel, "\u2323", "\\smallsmile");
 4637defineSymbol(math, ams, rel, "\u2322", "\\smallfrown");
 4638defineSymbol(math, ams, rel, "\u224f", "\\bumpeq", true);
 4639defineSymbol(math, ams, rel, "\u224e", "\\Bumpeq", true);
 4640defineSymbol(math, ams, rel, "\u2267", "\\geqq", true);
 4641defineSymbol(math, ams, rel, "\u2a7e", "\\geqslant", true);
 4642defineSymbol(math, ams, rel, "\u2a96", "\\eqslantgtr", true);
 4643defineSymbol(math, ams, rel, "\u2273", "\\gtrsim", true);
 4644defineSymbol(math, ams, rel, "\u2a86", "\\gtrapprox", true);
 4645defineSymbol(math, ams, bin, "\u22d7", "\\gtrdot");
 4646defineSymbol(math, ams, rel, "\u22d9", "\\ggg", true);
 4647defineSymbol(math, ams, rel, "\u2277", "\\gtrless", true);
 4648defineSymbol(math, ams, rel, "\u22db", "\\gtreqless", true);
 4649defineSymbol(math, ams, rel, "\u2a8c", "\\gtreqqless", true);
 4650defineSymbol(math, ams, rel, "\u2256", "\\eqcirc", true);
 4651defineSymbol(math, ams, rel, "\u2257", "\\circeq", true);
 4652defineSymbol(math, ams, rel, "\u225c", "\\triangleq", true);
 4653defineSymbol(math, ams, rel, "\u223c", "\\thicksim");
 4654defineSymbol(math, ams, rel, "\u2248", "\\thickapprox");
 4655defineSymbol(math, ams, rel, "\u2ac6", "\\supseteqq", true);
 4656defineSymbol(math, ams, rel, "\u22d1", "\\Supset", true);
 4657defineSymbol(math, ams, rel, "\u2290", "\\sqsupset", true);
 4658defineSymbol(math, ams, rel, "\u227d", "\\succcurlyeq", true);
 4659defineSymbol(math, ams, rel, "\u22df", "\\curlyeqsucc", true);
 4660defineSymbol(math, ams, rel, "\u227f", "\\succsim", true);
 4661defineSymbol(math, ams, rel, "\u2ab8", "\\succapprox", true);
 4662defineSymbol(math, ams, rel, "\u22b3", "\\vartriangleright");
 4663defineSymbol(math, ams, rel, "\u22b5", "\\trianglerighteq");
 4664defineSymbol(math, ams, rel, "\u22a9", "\\Vdash", true);
 4665defineSymbol(math, ams, rel, "\u2223", "\\shortmid");
 4666defineSymbol(math, ams, rel, "\u2225", "\\shortparallel");
 4667defineSymbol(math, ams, rel, "\u226c", "\\between", true);
 4668defineSymbol(math, ams, rel, "\u22d4", "\\pitchfork", true);
 4669defineSymbol(math, ams, rel, "\u221d", "\\varpropto");
 4670defineSymbol(math, ams, rel, "\u25c0", "\\blacktriangleleft"); // unicode-math says that \therefore is a mathord atom.
 4671// We kept the amssymb atom type, which is rel.
 4672
 4673defineSymbol(math, ams, rel, "\u2234", "\\therefore", true);
 4674defineSymbol(math, ams, rel, "\u220d", "\\backepsilon");
 4675defineSymbol(math, ams, rel, "\u25b6", "\\blacktriangleright"); // unicode-math says that \because is a mathord atom.
 4676// We kept the amssymb atom type, which is rel.
 4677
 4678defineSymbol(math, ams, rel, "\u2235", "\\because", true);
 4679defineSymbol(math, ams, rel, "\u22d8", "\\llless");
 4680defineSymbol(math, ams, rel, "\u22d9", "\\gggtr");
 4681defineSymbol(math, ams, bin, "\u22b2", "\\lhd");
 4682defineSymbol(math, ams, bin, "\u22b3", "\\rhd");
 4683defineSymbol(math, ams, rel, "\u2242", "\\eqsim", true);
 4684defineSymbol(math, main, rel, "\u22c8", "\\Join");
 4685defineSymbol(math, ams, rel, "\u2251", "\\Doteq", true); // AMS Binary Operators
 4686
 4687defineSymbol(math, ams, bin, "\u2214", "\\dotplus", true);
 4688defineSymbol(math, ams, bin, "\u2216", "\\smallsetminus");
 4689defineSymbol(math, ams, bin, "\u22d2", "\\Cap", true);
 4690defineSymbol(math, ams, bin, "\u22d3", "\\Cup", true);
 4691defineSymbol(math, ams, bin, "\u2a5e", "\\doublebarwedge", true);
 4692defineSymbol(math, ams, bin, "\u229f", "\\boxminus", true);
 4693defineSymbol(math, ams, bin, "\u229e", "\\boxplus", true);
 4694defineSymbol(math, ams, bin, "\u22c7", "\\divideontimes", true);
 4695defineSymbol(math, ams, bin, "\u22c9", "\\ltimes", true);
 4696defineSymbol(math, ams, bin, "\u22ca", "\\rtimes", true);
 4697defineSymbol(math, ams, bin, "\u22cb", "\\leftthreetimes", true);
 4698defineSymbol(math, ams, bin, "\u22cc", "\\rightthreetimes", true);
 4699defineSymbol(math, ams, bin, "\u22cf", "\\curlywedge", true);
 4700defineSymbol(math, ams, bin, "\u22ce", "\\curlyvee", true);
 4701defineSymbol(math, ams, bin, "\u229d", "\\circleddash", true);
 4702defineSymbol(math, ams, bin, "\u229b", "\\circledast", true);
 4703defineSymbol(math, ams, bin, "\u22c5", "\\centerdot");
 4704defineSymbol(math, ams, bin, "\u22ba", "\\intercal", true);
 4705defineSymbol(math, ams, bin, "\u22d2", "\\doublecap");
 4706defineSymbol(math, ams, bin, "\u22d3", "\\doublecup");
 4707defineSymbol(math, ams, bin, "\u22a0", "\\boxtimes", true); // AMS Arrows
 4708// Note: unicode-math maps \u21e2 to their own function \rightdasharrow.
 4709// We'll map it to AMS function \dashrightarrow. It produces the same atom.
 4710
 4711defineSymbol(math, ams, rel, "\u21e2", "\\dashrightarrow", true); // unicode-math maps \u21e0 to \leftdasharrow. We'll use the AMS synonym.
 4712
 4713defineSymbol(math, ams, rel, "\u21e0", "\\dashleftarrow", true);
 4714defineSymbol(math, ams, rel, "\u21c7", "\\leftleftarrows", true);
 4715defineSymbol(math, ams, rel, "\u21c6", "\\leftrightarrows", true);
 4716defineSymbol(math, ams, rel, "\u21da", "\\Lleftarrow", true);
 4717defineSymbol(math, ams, rel, "\u219e", "\\twoheadleftarrow", true);
 4718defineSymbol(math, ams, rel, "\u21a2", "\\leftarrowtail", true);
 4719defineSymbol(math, ams, rel, "\u21ab", "\\looparrowleft", true);
 4720defineSymbol(math, ams, rel, "\u21cb", "\\leftrightharpoons", true);
 4721defineSymbol(math, ams, rel, "\u21b6", "\\curvearrowleft", true); // unicode-math maps \u21ba to \acwopencirclearrow. We'll use the AMS synonym.
 4722
 4723defineSymbol(math, ams, rel, "\u21ba", "\\circlearrowleft", true);
 4724defineSymbol(math, ams, rel, "\u21b0", "\\Lsh", true);
 4725defineSymbol(math, ams, rel, "\u21c8", "\\upuparrows", true);
 4726defineSymbol(math, ams, rel, "\u21bf", "\\upharpoonleft", true);
 4727defineSymbol(math, ams, rel, "\u21c3", "\\downharpoonleft", true);
 4728defineSymbol(math, main, rel, "\u22b6", "\\origof", true); // not in font
 4729
 4730defineSymbol(math, main, rel, "\u22b7", "\\imageof", true); // not in font
 4731
 4732defineSymbol(math, ams, rel, "\u22b8", "\\multimap", true);
 4733defineSymbol(math, ams, rel, "\u21ad", "\\leftrightsquigarrow", true);
 4734defineSymbol(math, ams, rel, "\u21c9", "\\rightrightarrows", true);
 4735defineSymbol(math, ams, rel, "\u21c4", "\\rightleftarrows", true);
 4736defineSymbol(math, ams, rel, "\u21a0", "\\twoheadrightarrow", true);
 4737defineSymbol(math, ams, rel, "\u21a3", "\\rightarrowtail", true);
 4738defineSymbol(math, ams, rel, "\u21ac", "\\looparrowright", true);
 4739defineSymbol(math, ams, rel, "\u21b7", "\\curvearrowright", true); // unicode-math maps \u21bb to \cwopencirclearrow. We'll use the AMS synonym.
 4740
 4741defineSymbol(math, ams, rel, "\u21bb", "\\circlearrowright", true);
 4742defineSymbol(math, ams, rel, "\u21b1", "\\Rsh", true);
 4743defineSymbol(math, ams, rel, "\u21ca", "\\downdownarrows", true);
 4744defineSymbol(math, ams, rel, "\u21be", "\\upharpoonright", true);
 4745defineSymbol(math, ams, rel, "\u21c2", "\\downharpoonright", true);
 4746defineSymbol(math, ams, rel, "\u21dd", "\\rightsquigarrow", true);
 4747defineSymbol(math, ams, rel, "\u21dd", "\\leadsto");
 4748defineSymbol(math, ams, rel, "\u21db", "\\Rrightarrow", true);
 4749defineSymbol(math, ams, rel, "\u21be", "\\restriction");
 4750defineSymbol(math, main, textord, "\u2018", "`");
 4751defineSymbol(math, main, textord, "$", "\\$");
 4752defineSymbol(text, main, textord, "$", "\\$");
 4753defineSymbol(text, main, textord, "$", "\\textdollar");
 4754defineSymbol(math, main, textord, "%", "\\%");
 4755defineSymbol(text, main, textord, "%", "\\%");
 4756defineSymbol(math, main, textord, "_", "\\_");
 4757defineSymbol(text, main, textord, "_", "\\_");
 4758defineSymbol(text, main, textord, "_", "\\textunderscore");
 4759defineSymbol(math, main, textord, "\u2220", "\\angle", true);
 4760defineSymbol(math, main, textord, "\u221e", "\\infty", true);
 4761defineSymbol(math, main, textord, "\u2032", "\\prime");
 4762defineSymbol(math, main, textord, "\u25b3", "\\triangle");
 4763defineSymbol(math, main, textord, "\u0393", "\\Gamma", true);
 4764defineSymbol(math, main, textord, "\u0394", "\\Delta", true);
 4765defineSymbol(math, main, textord, "\u0398", "\\Theta", true);
 4766defineSymbol(math, main, textord, "\u039b", "\\Lambda", true);
 4767defineSymbol(math, main, textord, "\u039e", "\\Xi", true);
 4768defineSymbol(math, main, textord, "\u03a0", "\\Pi", true);
 4769defineSymbol(math, main, textord, "\u03a3", "\\Sigma", true);
 4770defineSymbol(math, main, textord, "\u03a5", "\\Upsilon", true);
 4771defineSymbol(math, main, textord, "\u03a6", "\\Phi", true);
 4772defineSymbol(math, main, textord, "\u03a8", "\\Psi", true);
 4773defineSymbol(math, main, textord, "\u03a9", "\\Omega", true);
 4774defineSymbol(math, main, textord, "A", "\u0391");
 4775defineSymbol(math, main, textord, "B", "\u0392");
 4776defineSymbol(math, main, textord, "E", "\u0395");
 4777defineSymbol(math, main, textord, "Z", "\u0396");
 4778defineSymbol(math, main, textord, "H", "\u0397");
 4779defineSymbol(math, main, textord, "I", "\u0399");
 4780defineSymbol(math, main, textord, "K", "\u039A");
 4781defineSymbol(math, main, textord, "M", "\u039C");
 4782defineSymbol(math, main, textord, "N", "\u039D");
 4783defineSymbol(math, main, textord, "O", "\u039F");
 4784defineSymbol(math, main, textord, "P", "\u03A1");
 4785defineSymbol(math, main, textord, "T", "\u03A4");
 4786defineSymbol(math, main, textord, "X", "\u03A7");
 4787defineSymbol(math, main, textord, "\u00ac", "\\neg", true);
 4788defineSymbol(math, main, textord, "\u00ac", "\\lnot");
 4789defineSymbol(math, main, textord, "\u22a4", "\\top");
 4790defineSymbol(math, main, textord, "\u22a5", "\\bot");
 4791defineSymbol(math, main, textord, "\u2205", "\\emptyset");
 4792defineSymbol(math, ams, textord, "\u2205", "\\varnothing");
 4793defineSymbol(math, main, mathord, "\u03b1", "\\alpha", true);
 4794defineSymbol(math, main, mathord, "\u03b2", "\\beta", true);
 4795defineSymbol(math, main, mathord, "\u03b3", "\\gamma", true);
 4796defineSymbol(math, main, mathord, "\u03b4", "\\delta", true);
 4797defineSymbol(math, main, mathord, "\u03f5", "\\epsilon", true);
 4798defineSymbol(math, main, mathord, "\u03b6", "\\zeta", true);
 4799defineSymbol(math, main, mathord, "\u03b7", "\\eta", true);
 4800defineSymbol(math, main, mathord, "\u03b8", "\\theta", true);
 4801defineSymbol(math, main, mathord, "\u03b9", "\\iota", true);
 4802defineSymbol(math, main, mathord, "\u03ba", "\\kappa", true);
 4803defineSymbol(math, main, mathord, "\u03bb", "\\lambda", true);
 4804defineSymbol(math, main, mathord, "\u03bc", "\\mu", true);
 4805defineSymbol(math, main, mathord, "\u03bd", "\\nu", true);
 4806defineSymbol(math, main, mathord, "\u03be", "\\xi", true);
 4807defineSymbol(math, main, mathord, "\u03bf", "\\omicron", true);
 4808defineSymbol(math, main, mathord, "\u03c0", "\\pi", true);
 4809defineSymbol(math, main, mathord, "\u03c1", "\\rho", true);
 4810defineSymbol(math, main, mathord, "\u03c3", "\\sigma", true);
 4811defineSymbol(math, main, mathord, "\u03c4", "\\tau", true);
 4812defineSymbol(math, main, mathord, "\u03c5", "\\upsilon", true);
 4813defineSymbol(math, main, mathord, "\u03d5", "\\phi", true);
 4814defineSymbol(math, main, mathord, "\u03c7", "\\chi", true);
 4815defineSymbol(math, main, mathord, "\u03c8", "\\psi", true);
 4816defineSymbol(math, main, mathord, "\u03c9", "\\omega", true);
 4817defineSymbol(math, main, mathord, "\u03b5", "\\varepsilon", true);
 4818defineSymbol(math, main, mathord, "\u03d1", "\\vartheta", true);
 4819defineSymbol(math, main, mathord, "\u03d6", "\\varpi", true);
 4820defineSymbol(math, main, mathord, "\u03f1", "\\varrho", true);
 4821defineSymbol(math, main, mathord, "\u03c2", "\\varsigma", true);
 4822defineSymbol(math, main, mathord, "\u03c6", "\\varphi", true);
 4823defineSymbol(math, main, bin, "\u2217", "*", true);
 4824defineSymbol(math, main, bin, "+", "+");
 4825defineSymbol(math, main, bin, "\u2212", "-", true);
 4826defineSymbol(math, main, bin, "\u22c5", "\\cdot", true);
 4827defineSymbol(math, main, bin, "\u2218", "\\circ", true);
 4828defineSymbol(math, main, bin, "\u00f7", "\\div", true);
 4829defineSymbol(math, main, bin, "\u00b1", "\\pm", true);
 4830defineSymbol(math, main, bin, "\u00d7", "\\times", true);
 4831defineSymbol(math, main, bin, "\u2229", "\\cap", true);
 4832defineSymbol(math, main, bin, "\u222a", "\\cup", true);
 4833defineSymbol(math, main, bin, "\u2216", "\\setminus", true);
 4834defineSymbol(math, main, bin, "\u2227", "\\land");
 4835defineSymbol(math, main, bin, "\u2228", "\\lor");
 4836defineSymbol(math, main, bin, "\u2227", "\\wedge", true);
 4837defineSymbol(math, main, bin, "\u2228", "\\vee", true);
 4838defineSymbol(math, main, textord, "\u221a", "\\surd");
 4839defineSymbol(math, main, open, "\u27e8", "\\langle", true);
 4840defineSymbol(math, main, open, "\u2223", "\\lvert");
 4841defineSymbol(math, main, open, "\u2225", "\\lVert");
 4842defineSymbol(math, main, close, "?", "?");
 4843defineSymbol(math, main, close, "!", "!");
 4844defineSymbol(math, main, close, "\u27e9", "\\rangle", true);
 4845defineSymbol(math, main, close, "\u2223", "\\rvert");
 4846defineSymbol(math, main, close, "\u2225", "\\rVert");
 4847defineSymbol(math, main, rel, "=", "=");
 4848defineSymbol(math, main, rel, ":", ":");
 4849defineSymbol(math, main, rel, "\u2248", "\\approx", true);
 4850defineSymbol(math, main, rel, "\u2245", "\\cong", true);
 4851defineSymbol(math, main, rel, "\u2265", "\\ge");
 4852defineSymbol(math, main, rel, "\u2265", "\\geq", true);
 4853defineSymbol(math, main, rel, "\u2190", "\\gets");
 4854defineSymbol(math, main, rel, ">", "\\gt", true);
 4855defineSymbol(math, main, rel, "\u2208", "\\in", true);
 4856defineSymbol(math, main, rel, "\ue020", "\\@not");
 4857defineSymbol(math, main, rel, "\u2282", "\\subset", true);
 4858defineSymbol(math, main, rel, "\u2283", "\\supset", true);
 4859defineSymbol(math, main, rel, "\u2286", "\\subseteq", true);
 4860defineSymbol(math, main, rel, "\u2287", "\\supseteq", true);
 4861defineSymbol(math, ams, rel, "\u2288", "\\nsubseteq", true);
 4862defineSymbol(math, ams, rel, "\u2289", "\\nsupseteq", true);
 4863defineSymbol(math, main, rel, "\u22a8", "\\models");
 4864defineSymbol(math, main, rel, "\u2190", "\\leftarrow", true);
 4865defineSymbol(math, main, rel, "\u2264", "\\le");
 4866defineSymbol(math, main, rel, "\u2264", "\\leq", true);
 4867defineSymbol(math, main, rel, "<", "\\lt", true);
 4868defineSymbol(math, main, rel, "\u2192", "\\rightarrow", true);
 4869defineSymbol(math, main, rel, "\u2192", "\\to");
 4870defineSymbol(math, ams, rel, "\u2271", "\\ngeq", true);
 4871defineSymbol(math, ams, rel, "\u2270", "\\nleq", true);
 4872defineSymbol(math, main, spacing, "\u00a0", "\\ ");
 4873defineSymbol(math, main, spacing, "\u00a0", "\\space"); // Ref: LaTeX Source 2e: \DeclareRobustCommand{\nobreakspace}{%
 4874
 4875defineSymbol(math, main, spacing, "\u00a0", "\\nobreakspace");
 4876defineSymbol(text, main, spacing, "\u00a0", "\\ ");
 4877defineSymbol(text, main, spacing, "\u00a0", " ");
 4878defineSymbol(text, main, spacing, "\u00a0", "\\space");
 4879defineSymbol(text, main, spacing, "\u00a0", "\\nobreakspace");
 4880defineSymbol(math, main, spacing, null, "\\nobreak");
 4881defineSymbol(math, main, spacing, null, "\\allowbreak");
 4882defineSymbol(math, main, punct, ",", ",");
 4883defineSymbol(math, main, punct, ";", ";");
 4884defineSymbol(math, ams, bin, "\u22bc", "\\barwedge", true);
 4885defineSymbol(math, ams, bin, "\u22bb", "\\veebar", true);
 4886defineSymbol(math, main, bin, "\u2299", "\\odot", true);
 4887defineSymbol(math, main, bin, "\u2295", "\\oplus", true);
 4888defineSymbol(math, main, bin, "\u2297", "\\otimes", true);
 4889defineSymbol(math, main, textord, "\u2202", "\\partial", true);
 4890defineSymbol(math, main, bin, "\u2298", "\\oslash", true);
 4891defineSymbol(math, ams, bin, "\u229a", "\\circledcirc", true);
 4892defineSymbol(math, ams, bin, "\u22a1", "\\boxdot", true);
 4893defineSymbol(math, main, bin, "\u25b3", "\\bigtriangleup");
 4894defineSymbol(math, main, bin, "\u25bd", "\\bigtriangledown");
 4895defineSymbol(math, main, bin, "\u2020", "\\dagger");
 4896defineSymbol(math, main, bin, "\u22c4", "\\diamond");
 4897defineSymbol(math, main, bin, "\u22c6", "\\star");
 4898defineSymbol(math, main, bin, "\u25c3", "\\triangleleft");
 4899defineSymbol(math, main, bin, "\u25b9", "\\triangleright");
 4900defineSymbol(math, main, open, "{", "\\{");
 4901defineSymbol(text, main, textord, "{", "\\{");
 4902defineSymbol(text, main, textord, "{", "\\textbraceleft");
 4903defineSymbol(math, main, close, "}", "\\}");
 4904defineSymbol(text, main, textord, "}", "\\}");
 4905defineSymbol(text, main, textord, "}", "\\textbraceright");
 4906defineSymbol(math, main, open, "{", "\\lbrace");
 4907defineSymbol(math, main, close, "}", "\\rbrace");
 4908defineSymbol(math, main, open, "[", "\\lbrack", true);
 4909defineSymbol(text, main, textord, "[", "\\lbrack", true);
 4910defineSymbol(math, main, close, "]", "\\rbrack", true);
 4911defineSymbol(text, main, textord, "]", "\\rbrack", true);
 4912defineSymbol(math, main, open, "(", "\\lparen", true);
 4913defineSymbol(math, main, close, ")", "\\rparen", true);
 4914defineSymbol(text, main, textord, "<", "\\textless", true); // in T1 fontenc
 4915
 4916defineSymbol(text, main, textord, ">", "\\textgreater", true); // in T1 fontenc
 4917
 4918defineSymbol(math, main, open, "\u230a", "\\lfloor", true);
 4919defineSymbol(math, main, close, "\u230b", "\\rfloor", true);
 4920defineSymbol(math, main, open, "\u2308", "\\lceil", true);
 4921defineSymbol(math, main, close, "\u2309", "\\rceil", true);
 4922defineSymbol(math, main, textord, "\\", "\\backslash");
 4923defineSymbol(math, main, textord, "\u2223", "|");
 4924defineSymbol(math, main, textord, "\u2223", "\\vert");
 4925defineSymbol(text, main, textord, "|", "\\textbar", true); // in T1 fontenc
 4926
 4927defineSymbol(math, main, textord, "\u2225", "\\|");
 4928defineSymbol(math, main, textord, "\u2225", "\\Vert");
 4929defineSymbol(text, main, textord, "\u2225", "\\textbardbl");
 4930defineSymbol(text, main, textord, "~", "\\textasciitilde");
 4931defineSymbol(text, main, textord, "\\", "\\textbackslash");
 4932defineSymbol(text, main, textord, "^", "\\textasciicircum");
 4933defineSymbol(math, main, rel, "\u2191", "\\uparrow", true);
 4934defineSymbol(math, main, rel, "\u21d1", "\\Uparrow", true);
 4935defineSymbol(math, main, rel, "\u2193", "\\downarrow", true);
 4936defineSymbol(math, main, rel, "\u21d3", "\\Downarrow", true);
 4937defineSymbol(math, main, rel, "\u2195", "\\updownarrow", true);
 4938defineSymbol(math, main, rel, "\u21d5", "\\Updownarrow", true);
 4939defineSymbol(math, main, op, "\u2210", "\\coprod");
 4940defineSymbol(math, main, op, "\u22c1", "\\bigvee");
 4941defineSymbol(math, main, op, "\u22c0", "\\bigwedge");
 4942defineSymbol(math, main, op, "\u2a04", "\\biguplus");
 4943defineSymbol(math, main, op, "\u22c2", "\\bigcap");
 4944defineSymbol(math, main, op, "\u22c3", "\\bigcup");
 4945defineSymbol(math, main, op, "\u222b", "\\int");
 4946defineSymbol(math, main, op, "\u222b", "\\intop");
 4947defineSymbol(math, main, op, "\u222c", "\\iint");
 4948defineSymbol(math, main, op, "\u222d", "\\iiint");
 4949defineSymbol(math, main, op, "\u220f", "\\prod");
 4950defineSymbol(math, main, op, "\u2211", "\\sum");
 4951defineSymbol(math, main, op, "\u2a02", "\\bigotimes");
 4952defineSymbol(math, main, op, "\u2a01", "\\bigoplus");
 4953defineSymbol(math, main, op, "\u2a00", "\\bigodot");
 4954defineSymbol(math, main, op, "\u222e", "\\oint");
 4955defineSymbol(math, main, op, "\u222f", "\\oiint");
 4956defineSymbol(math, main, op, "\u2230", "\\oiiint");
 4957defineSymbol(math, main, op, "\u2a06", "\\bigsqcup");
 4958defineSymbol(math, main, op, "\u222b", "\\smallint");
 4959defineSymbol(text, main, inner, "\u2026", "\\textellipsis");
 4960defineSymbol(math, main, inner, "\u2026", "\\mathellipsis");
 4961defineSymbol(text, main, inner, "\u2026", "\\ldots", true);
 4962defineSymbol(math, main, inner, "\u2026", "\\ldots", true);
 4963defineSymbol(math, main, inner, "\u22ef", "\\@cdots", true);
 4964defineSymbol(math, main, inner, "\u22f1", "\\ddots", true);
 4965defineSymbol(math, main, textord, "\u22ee", "\\varvdots"); // \vdots is a macro
 4966
 4967defineSymbol(math, main, accent, "\u02ca", "\\acute");
 4968defineSymbol(math, main, accent, "\u02cb", "\\grave");
 4969defineSymbol(math, main, accent, "\u00a8", "\\ddot");
 4970defineSymbol(math, main, accent, "\u007e", "\\tilde");
 4971defineSymbol(math, main, accent, "\u02c9", "\\bar");
 4972defineSymbol(math, main, accent, "\u02d8", "\\breve");
 4973defineSymbol(math, main, accent, "\u02c7", "\\check");
 4974defineSymbol(math, main, accent, "\u005e", "\\hat");
 4975defineSymbol(math, main, accent, "\u20d7", "\\vec");
 4976defineSymbol(math, main, accent, "\u02d9", "\\dot");
 4977defineSymbol(math, main, accent, "\u02da", "\\mathring"); // \imath and \jmath should be invariant to \mathrm, \mathbf, etc., so use PUA
 4978
 4979defineSymbol(math, main, mathord, "\ue131", "\\@imath");
 4980defineSymbol(math, main, mathord, "\ue237", "\\@jmath");
 4981defineSymbol(math, main, textord, "\u0131", "\u0131");
 4982defineSymbol(math, main, textord, "\u0237", "\u0237");
 4983defineSymbol(text, main, textord, "\u0131", "\\i", true);
 4984defineSymbol(text, main, textord, "\u0237", "\\j", true);
 4985defineSymbol(text, main, textord, "\u00df", "\\ss", true);
 4986defineSymbol(text, main, textord, "\u00e6", "\\ae", true);
 4987defineSymbol(text, main, textord, "\u0153", "\\oe", true);
 4988defineSymbol(text, main, textord, "\u00f8", "\\o", true);
 4989defineSymbol(text, main, textord, "\u00c6", "\\AE", true);
 4990defineSymbol(text, main, textord, "\u0152", "\\OE", true);
 4991defineSymbol(text, main, textord, "\u00d8", "\\O", true);
 4992defineSymbol(text, main, accent, "\u02ca", "\\'"); // acute
 4993
 4994defineSymbol(text, main, accent, "\u02cb", "\\`"); // grave
 4995
 4996defineSymbol(text, main, accent, "\u02c6", "\\^"); // circumflex
 4997
 4998defineSymbol(text, main, accent, "\u02dc", "\\~"); // tilde
 4999
 5000defineSymbol(text, main, accent, "\u02c9", "\\="); // macron
 5001
 5002defineSymbol(text, main, accent, "\u02d8", "\\u"); // breve
 5003
 5004defineSymbol(text, main, accent, "\u02d9", "\\."); // dot above
 5005
 5006defineSymbol(text, main, accent, "\u00b8", "\\c"); // cedilla
 5007
 5008defineSymbol(text, main, accent, "\u02da", "\\r"); // ring above
 5009
 5010defineSymbol(text, main, accent, "\u02c7", "\\v"); // caron
 5011
 5012defineSymbol(text, main, accent, "\u00a8", '\\"'); // diaresis
 5013
 5014defineSymbol(text, main, accent, "\u02dd", "\\H"); // double acute
 5015
 5016defineSymbol(text, main, accent, "\u25ef", "\\textcircled"); // \bigcirc glyph
 5017// These ligatures are detected and created in Parser.js's `formLigatures`.
 5018
 5019var ligatures = {
 5020  "--": true,
 5021  "---": true,
 5022  "``": true,
 5023  "''": true
 5024};
 5025defineSymbol(text, main, textord, "\u2013", "--", true);
 5026defineSymbol(text, main, textord, "\u2013", "\\textendash");
 5027defineSymbol(text, main, textord, "\u2014", "---", true);
 5028defineSymbol(text, main, textord, "\u2014", "\\textemdash");
 5029defineSymbol(text, main, textord, "\u2018", "`", true);
 5030defineSymbol(text, main, textord, "\u2018", "\\textquoteleft");
 5031defineSymbol(text, main, textord, "\u2019", "'", true);
 5032defineSymbol(text, main, textord, "\u2019", "\\textquoteright");
 5033defineSymbol(text, main, textord, "\u201c", "``", true);
 5034defineSymbol(text, main, textord, "\u201c", "\\textquotedblleft");
 5035defineSymbol(text, main, textord, "\u201d", "''", true);
 5036defineSymbol(text, main, textord, "\u201d", "\\textquotedblright"); //  \degree from gensymb package
 5037
 5038defineSymbol(math, main, textord, "\u00b0", "\\degree", true);
 5039defineSymbol(text, main, textord, "\u00b0", "\\degree"); // \textdegree from inputenc package
 5040
 5041defineSymbol(text, main, textord, "\u00b0", "\\textdegree", true); // TODO: In LaTeX, \pounds can generate a different character in text and math
 5042// mode, but among our fonts, only Main-Regular defines this character "163".
 5043
 5044defineSymbol(math, main, textord, "\u00a3", "\\pounds");
 5045defineSymbol(math, main, textord, "\u00a3", "\\mathsterling", true);
 5046defineSymbol(text, main, textord, "\u00a3", "\\pounds");
 5047defineSymbol(text, main, textord, "\u00a3", "\\textsterling", true);
 5048defineSymbol(math, ams, textord, "\u2720", "\\maltese");
 5049defineSymbol(text, ams, textord, "\u2720", "\\maltese"); // There are lots of symbols which are the same, so we add them in afterwards.
 5050// All of these are textords in math mode
 5051
 5052var mathTextSymbols = "0123456789/@.\"";
 5053
 5054for (var i = 0; i < mathTextSymbols.length; i++) {
 5055  var ch = mathTextSymbols.charAt(i);
 5056  defineSymbol(math, main, textord, ch, ch);
 5057} // All of these are textords in text mode
 5058
 5059
 5060var textSymbols = "0123456789!@*()-=+\";:?/.,";
 5061
 5062for (var _i = 0; _i < textSymbols.length; _i++) {
 5063  var _ch = textSymbols.charAt(_i);
 5064
 5065  defineSymbol(text, main, textord, _ch, _ch);
 5066} // All of these are textords in text mode, and mathords in math mode
 5067
 5068
 5069var letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
 5070
 5071for (var _i2 = 0; _i2 < letters.length; _i2++) {
 5072  var _ch2 = letters.charAt(_i2);
 5073
 5074  defineSymbol(math, main, mathord, _ch2, _ch2);
 5075  defineSymbol(text, main, textord, _ch2, _ch2);
 5076} // Blackboard bold and script letters in Unicode range
 5077
 5078
 5079defineSymbol(math, ams, textord, "C", "\u2102"); // blackboard bold
 5080
 5081defineSymbol(text, ams, textord, "C", "\u2102");
 5082defineSymbol(math, ams, textord, "H", "\u210D");
 5083defineSymbol(text, ams, textord, "H", "\u210D");
 5084defineSymbol(math, ams, textord, "N", "\u2115");
 5085defineSymbol(text, ams, textord, "N", "\u2115");
 5086defineSymbol(math, ams, textord, "P", "\u2119");
 5087defineSymbol(text, ams, textord, "P", "\u2119");
 5088defineSymbol(math, ams, textord, "Q", "\u211A");
 5089defineSymbol(text, ams, textord, "Q", "\u211A");
 5090defineSymbol(math, ams, textord, "R", "\u211D");
 5091defineSymbol(text, ams, textord, "R", "\u211D");
 5092defineSymbol(math, ams, textord, "Z", "\u2124");
 5093defineSymbol(text, ams, textord, "Z", "\u2124");
 5094defineSymbol(math, main, mathord, "h", "\u210E"); // italic h, Planck constant
 5095
 5096defineSymbol(text, main, mathord, "h", "\u210E"); // The next loop loads wide (surrogate pair) characters.
 5097// We support some letters in the Unicode range U+1D400 to U+1D7FF,
 5098// Mathematical Alphanumeric Symbols.
 5099// Some editors do not deal well with wide characters. So don't write the
 5100// string into this file. Instead, create the string from the surrogate pair.
 5101
 5102var wideChar = "";
 5103
 5104for (var _i3 = 0; _i3 < letters.length; _i3++) {
 5105  var _ch3 = letters.charAt(_i3); // The hex numbers in the next line are a surrogate pair.
 5106  // 0xD835 is the high surrogate for all letters in the range we support.
 5107  // 0xDC00 is the low surrogate for bold A.
 5108
 5109
 5110  wideChar = String.fromCharCode(0xD835, 0xDC00 + _i3); // A-Z a-z bold
 5111
 5112  defineSymbol(math, main, mathord, _ch3, wideChar);
 5113  defineSymbol(text, main, textord, _ch3, wideChar);
 5114  wideChar = String.fromCharCode(0xD835, 0xDC34 + _i3); // A-Z a-z italic
 5115
 5116  defineSymbol(math, main, mathord, _ch3, wideChar);
 5117  defineSymbol(text, main, textord, _ch3, wideChar);
 5118  wideChar = String.fromCharCode(0xD835, 0xDC68 + _i3); // A-Z a-z bold italic
 5119
 5120  defineSymbol(math, main, mathord, _ch3, wideChar);
 5121  defineSymbol(text, main, textord, _ch3, wideChar);
 5122  wideChar = String.fromCharCode(0xD835, 0xDD04 + _i3); // A-Z a-z Fractur
 5123
 5124  defineSymbol(math, main, mathord, _ch3, wideChar);
 5125  defineSymbol(text, main, textord, _ch3, wideChar);
 5126  wideChar = String.fromCharCode(0xD835, 0xDDA0 + _i3); // A-Z a-z sans-serif
 5127
 5128  defineSymbol(math, main, mathord, _ch3, wideChar);
 5129  defineSymbol(text, main, textord, _ch3, wideChar);
 5130  wideChar = String.fromCharCode(0xD835, 0xDDD4 + _i3); // A-Z a-z sans bold
 5131
 5132  defineSymbol(math, main, mathord, _ch3, wideChar);
 5133  defineSymbol(text, main, textord, _ch3, wideChar);
 5134  wideChar = String.fromCharCode(0xD835, 0xDE08 + _i3); // A-Z a-z sans italic
 5135
 5136  defineSymbol(math, main, mathord, _ch3, wideChar);
 5137  defineSymbol(text, main, textord, _ch3, wideChar);
 5138  wideChar = String.fromCharCode(0xD835, 0xDE70 + _i3); // A-Z a-z monospace
 5139
 5140  defineSymbol(math, main, mathord, _ch3, wideChar);
 5141  defineSymbol(text, main, textord, _ch3, wideChar);
 5142
 5143  if (_i3 < 26) {
 5144    // KaTeX fonts have only capital letters for blackboard bold and script.
 5145    // See exception for k below.
 5146    wideChar = String.fromCharCode(0xD835, 0xDD38 + _i3); // A-Z double struck
 5147
 5148    defineSymbol(math, main, mathord, _ch3, wideChar);
 5149    defineSymbol(text, main, textord, _ch3, wideChar);
 5150    wideChar = String.fromCharCode(0xD835, 0xDC9C + _i3); // A-Z script
 5151
 5152    defineSymbol(math, main, mathord, _ch3, wideChar);
 5153    defineSymbol(text, main, textord, _ch3, wideChar);
 5154  } // TODO: Add bold script when it is supported by a KaTeX font.
 5155
 5156} // "k" is the only double struck lower case letter in the KaTeX fonts.
 5157
 5158
 5159wideChar = String.fromCharCode(0xD835, 0xDD5C); // k double struck
 5160
 5161defineSymbol(math, main, mathord, "k", wideChar);
 5162defineSymbol(text, main, textord, "k", wideChar); // Next, some wide character numerals
 5163
 5164for (var _i4 = 0; _i4 < 10; _i4++) {
 5165  var _ch4 = _i4.toString();
 5166
 5167  wideChar = String.fromCharCode(0xD835, 0xDFCE + _i4); // 0-9 bold
 5168
 5169  defineSymbol(math, main, mathord, _ch4, wideChar);
 5170  defineSymbol(text, main, textord, _ch4, wideChar);
 5171  wideChar = String.fromCharCode(0xD835, 0xDFE2 + _i4); // 0-9 sans serif
 5172
 5173  defineSymbol(math, main, mathord, _ch4, wideChar);
 5174  defineSymbol(text, main, textord, _ch4, wideChar);
 5175  wideChar = String.fromCharCode(0xD835, 0xDFEC + _i4); // 0-9 bold sans
 5176
 5177  defineSymbol(math, main, mathord, _ch4, wideChar);
 5178  defineSymbol(text, main, textord, _ch4, wideChar);
 5179  wideChar = String.fromCharCode(0xD835, 0xDFF6 + _i4); // 0-9 monospace
 5180
 5181  defineSymbol(math, main, mathord, _ch4, wideChar);
 5182  defineSymbol(text, main, textord, _ch4, wideChar);
 5183} // We add these Latin-1 letters as symbols for backwards-compatibility,
 5184// but they are not actually in the font, nor are they supported by the
 5185// Unicode accent mechanism, so they fall back to Times font and look ugly.
 5186// TODO(edemaine): Fix this.
 5187
 5188
 5189var extraLatin = "\u00d0\u00de\u00fe";
 5190
 5191for (var _i5 = 0; _i5 < extraLatin.length; _i5++) {
 5192  var _ch5 = extraLatin.charAt(_i5);
 5193
 5194  defineSymbol(math, main, mathord, _ch5, _ch5);
 5195  defineSymbol(text, main, textord, _ch5, _ch5);
 5196}
 5197
 5198/**
 5199 * This file provides support for Unicode range U+1D400 to U+1D7FF,
 5200 * Mathematical Alphanumeric Symbols.
 5201 *
 5202 * Function wideCharacterFont takes a wide character as input and returns
 5203 * the font information necessary to render it properly.
 5204 */
 5205/**
 5206 * Data below is from https://www.unicode.org/charts/PDF/U1D400.pdf
 5207 * That document sorts characters into groups by font type, say bold or italic.
 5208 *
 5209 * In the arrays below, each subarray consists three elements:
 5210 *      * The CSS class of that group when in math mode.
 5211 *      * The CSS class of that group when in text mode.
 5212 *      * The font name, so that KaTeX can get font metrics.
 5213 */
 5214
 5215var wideLatinLetterData = [["mathbf", "textbf", "Main-Bold"], // A-Z bold upright
 5216["mathbf", "textbf", "Main-Bold"], // a-z bold upright
 5217["mathnormal", "textit", "Math-Italic"], // A-Z italic
 5218["mathnormal", "textit", "Math-Italic"], // a-z italic
 5219["boldsymbol", "boldsymbol", "Main-BoldItalic"], // A-Z bold italic
 5220["boldsymbol", "boldsymbol", "Main-BoldItalic"], // a-z bold italic
 5221// Map fancy A-Z letters to script, not calligraphic.
 5222// This aligns with unicode-math and math fonts (except Cambria Math).
 5223["mathscr", "textscr", "Script-Regular"], // A-Z script
 5224["", "", ""], // a-z script.  No font
 5225["", "", ""], // A-Z bold script. No font
 5226["", "", ""], // a-z bold script. No font
 5227["mathfrak", "textfrak", "Fraktur-Regular"], // A-Z Fraktur
 5228["mathfrak", "textfrak", "Fraktur-Regular"], // a-z Fraktur
 5229["mathbb", "textbb", "AMS-Regular"], // A-Z double-struck
 5230["mathbb", "textbb", "AMS-Regular"], // k double-struck
 5231["", "", ""], // A-Z bold Fraktur No font metrics
 5232["", "", ""], // a-z bold Fraktur.   No font.
 5233["mathsf", "textsf", "SansSerif-Regular"], // A-Z sans-serif
 5234["mathsf", "textsf", "SansSerif-Regular"], // a-z sans-serif
 5235["mathboldsf", "textboldsf", "SansSerif-Bold"], // A-Z bold sans-serif
 5236["mathboldsf", "textboldsf", "SansSerif-Bold"], // a-z bold sans-serif
 5237["mathitsf", "textitsf", "SansSerif-Italic"], // A-Z italic sans-serif
 5238["mathitsf", "textitsf", "SansSerif-Italic"], // a-z italic sans-serif
 5239["", "", ""], // A-Z bold italic sans. No font
 5240["", "", ""], // a-z bold italic sans. No font
 5241["mathtt", "texttt", "Typewriter-Regular"], // A-Z monospace
 5242["mathtt", "texttt", "Typewriter-Regular"] // a-z monospace
 5243];
 5244var wideNumeralData = [["mathbf", "textbf", "Main-Bold"], // 0-9 bold
 5245["", "", ""], // 0-9 double-struck. No KaTeX font.
 5246["mathsf", "textsf", "SansSerif-Regular"], // 0-9 sans-serif
 5247["mathboldsf", "textboldsf", "SansSerif-Bold"], // 0-9 bold sans-serif
 5248["mathtt", "texttt", "Typewriter-Regular"] // 0-9 monospace
 5249];
 5250var wideCharacterFont = function wideCharacterFont(wideChar, mode) {
 5251  // IE doesn't support codePointAt(). So work with the surrogate pair.
 5252  var H = wideChar.charCodeAt(0); // high surrogate
 5253
 5254  var L = wideChar.charCodeAt(1); // low surrogate
 5255
 5256  var codePoint = (H - 0xD800) * 0x400 + (L - 0xDC00) + 0x10000;
 5257  var j = mode === "math" ? 0 : 1; // column index for CSS class.
 5258
 5259  if (0x1D400 <= codePoint && codePoint < 0x1D6A4) {
 5260    // wideLatinLetterData contains exactly 26 chars on each row.
 5261    // So we can calculate the relevant row. No traverse necessary.
 5262    var i = Math.floor((codePoint - 0x1D400) / 26);
 5263    return [wideLatinLetterData[i][2], wideLatinLetterData[i][j]];
 5264  } else if (0x1D7CE <= codePoint && codePoint <= 0x1D7FF) {
 5265    // Numerals, ten per row.
 5266    var _i = Math.floor((codePoint - 0x1D7CE) / 10);
 5267
 5268    return [wideNumeralData[_i][2], wideNumeralData[_i][j]];
 5269  } else if (codePoint === 0x1D6A5 || codePoint === 0x1D6A6) {
 5270    // dotless i or j
 5271    return [wideLatinLetterData[0][2], wideLatinLetterData[0][j]];
 5272  } else if (0x1D6A6 < codePoint && codePoint < 0x1D7CE) {
 5273    // Greek letters. Not supported, yet.
 5274    return ["", ""];
 5275  } else {
 5276    // We don't support any wide characters outside 1D400–1D7FF.
 5277    throw new ParseError("Unsupported character: " + wideChar);
 5278  }
 5279};
 5280
 5281/* eslint no-console:0 */
 5282
 5283/**
 5284 * Looks up the given symbol in fontMetrics, after applying any symbol
 5285 * replacements defined in symbol.js
 5286 */
 5287var lookupSymbol = function lookupSymbol(value, // TODO(#963): Use a union type for this.
 5288fontName, mode) {
 5289  // Replace the value with its replaced value from symbol.js
 5290  if (symbols[mode][value] && symbols[mode][value].replace) {
 5291    value = symbols[mode][value].replace;
 5292  }
 5293
 5294  return {
 5295    value: value,
 5296    metrics: getCharacterMetrics(value, fontName, mode)
 5297  };
 5298};
 5299/**
 5300 * Makes a symbolNode after translation via the list of symbols in symbols.js.
 5301 * Correctly pulls out metrics for the character, and optionally takes a list of
 5302 * classes to be attached to the node.
 5303 *
 5304 * TODO: make argument order closer to makeSpan
 5305 * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which
 5306 * should if present come first in `classes`.
 5307 * TODO(#953): Make `options` mandatory and always pass it in.
 5308 */
 5309
 5310
 5311var makeSymbol = function makeSymbol(value, fontName, mode, options, classes) {
 5312  var lookup = lookupSymbol(value, fontName, mode);
 5313  var metrics = lookup.metrics;
 5314  value = lookup.value;
 5315  var symbolNode;
 5316
 5317  if (metrics) {
 5318    var italic = metrics.italic;
 5319
 5320    if (mode === "text" || options && options.font === "mathit") {
 5321      italic = 0;
 5322    }
 5323
 5324    symbolNode = new SymbolNode(value, metrics.height, metrics.depth, italic, metrics.skew, metrics.width, classes);
 5325  } else {
 5326    // TODO(emily): Figure out a good way to only print this in development
 5327    typeof console !== "undefined" && console.warn("No character metrics " + ("for '" + value + "' in style '" + fontName + "' and mode '" + mode + "'"));
 5328    symbolNode = new SymbolNode(value, 0, 0, 0, 0, 0, classes);
 5329  }
 5330
 5331  if (options) {
 5332    symbolNode.maxFontSize = options.sizeMultiplier;
 5333
 5334    if (options.style.isTight()) {
 5335      symbolNode.classes.push("mtight");
 5336    }
 5337
 5338    var color = options.getColor();
 5339
 5340    if (color) {
 5341      symbolNode.style.color = color;
 5342    }
 5343  }
 5344
 5345  return symbolNode;
 5346};
 5347/**
 5348 * Makes a symbol in Main-Regular or AMS-Regular.
 5349 * Used for rel, bin, open, close, inner, and punct.
 5350 */
 5351
 5352
 5353var mathsym = function mathsym(value, mode, options, classes) {
 5354  if (classes === void 0) {
 5355    classes = [];
 5356  }
 5357
 5358  // Decide what font to render the symbol in by its entry in the symbols
 5359  // table.
 5360  // Have a special case for when the value = \ because the \ is used as a
 5361  // textord in unsupported command errors but cannot be parsed as a regular
 5362  // text ordinal and is therefore not present as a symbol in the symbols
 5363  // table for text, as well as a special case for boldsymbol because it
 5364  // can be used for bold + and -
 5365  if (options.font === "boldsymbol" && lookupSymbol(value, "Main-Bold", mode).metrics) {
 5366    return makeSymbol(value, "Main-Bold", mode, options, classes.concat(["mathbf"]));
 5367  } else if (value === "\\" || symbols[mode][value].font === "main") {
 5368    return makeSymbol(value, "Main-Regular", mode, options, classes);
 5369  } else {
 5370    return makeSymbol(value, "AMS-Regular", mode, options, classes.concat(["amsrm"]));
 5371  }
 5372};
 5373/**
 5374 * Determines which of the two font names (Main-Bold and Math-BoldItalic) and
 5375 * corresponding style tags (mathbf or boldsymbol) to use for font "boldsymbol",
 5376 * depending on the symbol.  Use this function instead of fontMap for font
 5377 * "boldsymbol".
 5378 */
 5379
 5380
 5381var boldsymbol = function boldsymbol(value, mode, options, classes, type) {
 5382  if (type !== "textord" && lookupSymbol(value, "Math-BoldItalic", mode).metrics) {
 5383    return {
 5384      fontName: "Math-BoldItalic",
 5385      fontClass: "boldsymbol"
 5386    };
 5387  } else {
 5388    // Some glyphs do not exist in Math-BoldItalic so we need to use
 5389    // Main-Bold instead.
 5390    return {
 5391      fontName: "Main-Bold",
 5392      fontClass: "mathbf"
 5393    };
 5394  }
 5395};
 5396/**
 5397 * Makes either a mathord or textord in the correct font and color.
 5398 */
 5399
 5400
 5401var makeOrd = function makeOrd(group, options, type) {
 5402  var mode = group.mode;
 5403  var text = group.text;
 5404  var classes = ["mord"]; // Math mode or Old font (i.e. \rm)
 5405
 5406  var isFont = mode === "math" || mode === "text" && options.font;
 5407  var fontOrFamily = isFont ? options.font : options.fontFamily;
 5408
 5409  if (text.charCodeAt(0) === 0xD835) {
 5410    // surrogate pairs get special treatment
 5411    var [wideFontName, wideFontClass] = wideCharacterFont(text, mode);
 5412    return makeSymbol(text, wideFontName, mode, options, classes.concat(wideFontClass));
 5413  } else if (fontOrFamily) {
 5414    var fontName;
 5415    var fontClasses;
 5416
 5417    if (fontOrFamily === "boldsymbol") {
 5418      var fontData = boldsymbol(text, mode, options, classes, type);
 5419      fontName = fontData.fontName;
 5420      fontClasses = [fontData.fontClass];
 5421    } else if (isFont) {
 5422      fontName = fontMap[fontOrFamily].fontName;
 5423      fontClasses = [fontOrFamily];
 5424    } else {
 5425      fontName = retrieveTextFontName(fontOrFamily, options.fontWeight, options.fontShape);
 5426      fontClasses = [fontOrFamily, options.fontWeight, options.fontShape];
 5427    }
 5428
 5429    if (lookupSymbol(text, fontName, mode).metrics) {
 5430      return makeSymbol(text, fontName, mode, options, classes.concat(fontClasses));
 5431    } else if (ligatures.hasOwnProperty(text) && fontName.substr(0, 10) === "Typewriter") {
 5432      // Deconstruct ligatures in monospace fonts (\texttt, \tt).
 5433      var parts = [];
 5434
 5435      for (var i = 0; i < text.length; i++) {
 5436        parts.push(makeSymbol(text[i], fontName, mode, options, classes.concat(fontClasses)));
 5437      }
 5438
 5439      return makeFragment(parts);
 5440    }
 5441  } // Makes a symbol in the default font for mathords and textords.
 5442
 5443
 5444  if (type === "mathord") {
 5445    return makeSymbol(text, "Math-Italic", mode, options, classes.concat(["mathnormal"]));
 5446  } else if (type === "textord") {
 5447    var font = symbols[mode][text] && symbols[mode][text].font;
 5448
 5449    if (font === "ams") {
 5450      var _fontName = retrieveTextFontName("amsrm", options.fontWeight, options.fontShape);
 5451
 5452      return makeSymbol(text, _fontName, mode, options, classes.concat("amsrm", options.fontWeight, options.fontShape));
 5453    } else if (font === "main" || !font) {
 5454      var _fontName2 = retrieveTextFontName("textrm", options.fontWeight, options.fontShape);
 5455
 5456      return makeSymbol(text, _fontName2, mode, options, classes.concat(options.fontWeight, options.fontShape));
 5457    } else {
 5458      // fonts added by plugins
 5459      var _fontName3 = retrieveTextFontName(font, options.fontWeight, options.fontShape); // We add font name as a css class
 5460
 5461
 5462      return makeSymbol(text, _fontName3, mode, options, classes.concat(_fontName3, options.fontWeight, options.fontShape));
 5463    }
 5464  } else {
 5465    throw new Error("unexpected type: " + type + " in makeOrd");
 5466  }
 5467};
 5468/**
 5469 * Returns true if subsequent symbolNodes have the same classes, skew, maxFont,
 5470 * and styles.
 5471 */
 5472
 5473
 5474var canCombine = (prev, next) => {
 5475  if (createClass(prev.classes) !== createClass(next.classes) || prev.skew !== next.skew || prev.maxFontSize !== next.maxFontSize) {
 5476    return false;
 5477  } // If prev and next both are just "mbin"s or "mord"s we don't combine them
 5478  // so that the proper spacing can be preserved.
 5479
 5480
 5481  if (prev.classes.length === 1) {
 5482    var cls = prev.classes[0];
 5483
 5484    if (cls === "mbin" || cls === "mord") {
 5485      return false;
 5486    }
 5487  }
 5488
 5489  for (var style in prev.style) {
 5490    if (prev.style.hasOwnProperty(style) && prev.style[style] !== next.style[style]) {
 5491      return false;
 5492    }
 5493  }
 5494
 5495  for (var _style in next.style) {
 5496    if (next.style.hasOwnProperty(_style) && prev.style[_style] !== next.style[_style]) {
 5497      return false;
 5498    }
 5499  }
 5500
 5501  return true;
 5502};
 5503/**
 5504 * Combine consecutive domTree.symbolNodes into a single symbolNode.
 5505 * Note: this function mutates the argument.
 5506 */
 5507
 5508
 5509var tryCombineChars = chars => {
 5510  for (var i = 0; i < chars.length - 1; i++) {
 5511    var prev = chars[i];
 5512    var next = chars[i + 1];
 5513
 5514    if (prev instanceof SymbolNode && next instanceof SymbolNode && canCombine(prev, next)) {
 5515      prev.text += next.text;
 5516      prev.height = Math.max(prev.height, next.height);
 5517      prev.depth = Math.max(prev.depth, next.depth); // Use the last character's italic correction since we use
 5518      // it to add padding to the right of the span created from
 5519      // the combined characters.
 5520
 5521      prev.italic = next.italic;
 5522      chars.splice(i + 1, 1);
 5523      i--;
 5524    }
 5525  }
 5526
 5527  return chars;
 5528};
 5529/**
 5530 * Calculate the height, depth, and maxFontSize of an element based on its
 5531 * children.
 5532 */
 5533
 5534
 5535var sizeElementFromChildren = function sizeElementFromChildren(elem) {
 5536  var height = 0;
 5537  var depth = 0;
 5538  var maxFontSize = 0;
 5539
 5540  for (var i = 0; i < elem.children.length; i++) {
 5541    var child = elem.children[i];
 5542
 5543    if (child.height > height) {
 5544      height = child.height;
 5545    }
 5546
 5547    if (child.depth > depth) {
 5548      depth = child.depth;
 5549    }
 5550
 5551    if (child.maxFontSize > maxFontSize) {
 5552      maxFontSize = child.maxFontSize;
 5553    }
 5554  }
 5555
 5556  elem.height = height;
 5557  elem.depth = depth;
 5558  elem.maxFontSize = maxFontSize;
 5559};
 5560/**
 5561 * Makes a span with the given list of classes, list of children, and options.
 5562 *
 5563 * TODO(#953): Ensure that `options` is always provided (currently some call
 5564 * sites don't pass it) and make the type below mandatory.
 5565 * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which
 5566 * should if present come first in `classes`.
 5567 */
 5568
 5569
 5570var makeSpan$2 = function makeSpan(classes, children, options, style) {
 5571  var span = new Span(classes, children, options, style);
 5572  sizeElementFromChildren(span);
 5573  return span;
 5574}; // SVG one is simpler -- doesn't require height, depth, max-font setting.
 5575// This is also a separate method for typesafety.
 5576
 5577
 5578var makeSvgSpan = (classes, children, options, style) => new Span(classes, children, options, style);
 5579
 5580var makeLineSpan = function makeLineSpan(className, options, thickness) {
 5581  var line = makeSpan$2([className], [], options);
 5582  line.height = Math.max(thickness || options.fontMetrics().defaultRuleThickness, options.minRuleThickness);
 5583  line.style.borderBottomWidth = makeEm(line.height);
 5584  line.maxFontSize = 1.0;
 5585  return line;
 5586};
 5587/**
 5588 * Makes an anchor with the given href, list of classes, list of children,
 5589 * and options.
 5590 */
 5591
 5592
 5593var makeAnchor = function makeAnchor(href, classes, children, options) {
 5594  var anchor = new Anchor(href, classes, children, options);
 5595  sizeElementFromChildren(anchor);
 5596  return anchor;
 5597};
 5598/**
 5599 * Makes a document fragment with the given list of children.
 5600 */
 5601
 5602
 5603var makeFragment = function makeFragment(children) {
 5604  var fragment = new DocumentFragment(children);
 5605  sizeElementFromChildren(fragment);
 5606  return fragment;
 5607};
 5608/**
 5609 * Wraps group in a span if it's a document fragment, allowing to apply classes
 5610 * and styles
 5611 */
 5612
 5613
 5614var wrapFragment = function wrapFragment(group, options) {
 5615  if (group instanceof DocumentFragment) {
 5616    return makeSpan$2([], [group], options);
 5617  }
 5618
 5619  return group;
 5620}; // These are exact object types to catch typos in the names of the optional fields.
 5621
 5622
 5623// Computes the updated `children` list and the overall depth.
 5624//
 5625// This helper function for makeVList makes it easier to enforce type safety by
 5626// allowing early exits (returns) in the logic.
 5627var getVListChildrenAndDepth = function getVListChildrenAndDepth(params) {
 5628  if (params.positionType === "individualShift") {
 5629    var oldChildren = params.children;
 5630    var children = [oldChildren[0]]; // Add in kerns to the list of params.children to get each element to be
 5631    // shifted to the correct specified shift
 5632
 5633    var _depth = -oldChildren[0].shift - oldChildren[0].elem.depth;
 5634
 5635    var currPos = _depth;
 5636
 5637    for (var i = 1; i < oldChildren.length; i++) {
 5638      var diff = -oldChildren[i].shift - currPos - oldChildren[i].elem.depth;
 5639      var size = diff - (oldChildren[i - 1].elem.height + oldChildren[i - 1].elem.depth);
 5640      currPos = currPos + diff;
 5641      children.push({
 5642        type: "kern",
 5643        size
 5644      });
 5645      children.push(oldChildren[i]);
 5646    }
 5647
 5648    return {
 5649      children,
 5650      depth: _depth
 5651    };
 5652  }
 5653
 5654  var depth;
 5655
 5656  if (params.positionType === "top") {
 5657    // We always start at the bottom, so calculate the bottom by adding up
 5658    // all the sizes
 5659    var bottom = params.positionData;
 5660
 5661    for (var _i = 0; _i < params.children.length; _i++) {
 5662      var child = params.children[_i];
 5663      bottom -= child.type === "kern" ? child.size : child.elem.height + child.elem.depth;
 5664    }
 5665
 5666    depth = bottom;
 5667  } else if (params.positionType === "bottom") {
 5668    depth = -params.positionData;
 5669  } else {
 5670    var firstChild = params.children[0];
 5671
 5672    if (firstChild.type !== "elem") {
 5673      throw new Error('First child must have type "elem".');
 5674    }
 5675
 5676    if (params.positionType === "shift") {
 5677      depth = -firstChild.elem.depth - params.positionData;
 5678    } else if (params.positionType === "firstBaseline") {
 5679      depth = -firstChild.elem.depth;
 5680    } else {
 5681      throw new Error("Invalid positionType " + params.positionType + ".");
 5682    }
 5683  }
 5684
 5685  return {
 5686    children: params.children,
 5687    depth
 5688  };
 5689};
 5690/**
 5691 * Makes a vertical list by stacking elements and kerns on top of each other.
 5692 * Allows for many different ways of specifying the positioning method.
 5693 *
 5694 * See VListParam documentation above.
 5695 */
 5696
 5697
 5698var makeVList = function makeVList(params, options) {
 5699  var {
 5700    children,
 5701    depth
 5702  } = getVListChildrenAndDepth(params); // Create a strut that is taller than any list item. The strut is added to
 5703  // each item, where it will determine the item's baseline. Since it has
 5704  // `overflow:hidden`, the strut's top edge will sit on the item's line box's
 5705  // top edge and the strut's bottom edge will sit on the item's baseline,
 5706  // with no additional line-height spacing. This allows the item baseline to
 5707  // be positioned precisely without worrying about font ascent and
 5708  // line-height.
 5709
 5710  var pstrutSize = 0;
 5711
 5712  for (var i = 0; i < children.length; i++) {
 5713    var child = children[i];
 5714
 5715    if (child.type === "elem") {
 5716      var elem = child.elem;
 5717      pstrutSize = Math.max(pstrutSize, elem.maxFontSize, elem.height);
 5718    }
 5719  }
 5720
 5721  pstrutSize += 2;
 5722  var pstrut = makeSpan$2(["pstrut"], []);
 5723  pstrut.style.height = makeEm(pstrutSize); // Create a new list of actual children at the correct offsets
 5724
 5725  var realChildren = [];
 5726  var minPos = depth;
 5727  var maxPos = depth;
 5728  var currPos = depth;
 5729
 5730  for (var _i2 = 0; _i2 < children.length; _i2++) {
 5731    var _child = children[_i2];
 5732
 5733    if (_child.type === "kern") {
 5734      currPos += _child.size;
 5735    } else {
 5736      var _elem = _child.elem;
 5737      var classes = _child.wrapperClasses || [];
 5738      var style = _child.wrapperStyle || {};
 5739      var childWrap = makeSpan$2(classes, [pstrut, _elem], undefined, style);
 5740      childWrap.style.top = makeEm(-pstrutSize - currPos - _elem.depth);
 5741
 5742      if (_child.marginLeft) {
 5743        childWrap.style.marginLeft = _child.marginLeft;
 5744      }
 5745
 5746      if (_child.marginRight) {
 5747        childWrap.style.marginRight = _child.marginRight;
 5748      }
 5749
 5750      realChildren.push(childWrap);
 5751      currPos += _elem.height + _elem.depth;
 5752    }
 5753
 5754    minPos = Math.min(minPos, currPos);
 5755    maxPos = Math.max(maxPos, currPos);
 5756  } // The vlist contents go in a table-cell with `vertical-align:bottom`.
 5757  // This cell's bottom edge will determine the containing table's baseline
 5758  // without overly expanding the containing line-box.
 5759
 5760
 5761  var vlist = makeSpan$2(["vlist"], realChildren);
 5762  vlist.style.height = makeEm(maxPos); // A second row is used if necessary to represent the vlist's depth.
 5763
 5764  var rows;
 5765
 5766  if (minPos < 0) {
 5767    // We will define depth in an empty span with display: table-cell.
 5768    // It should render with the height that we define. But Chrome, in
 5769    // contenteditable mode only, treats that span as if it contains some
 5770    // text content. And that min-height over-rides our desired height.
 5771    // So we put another empty span inside the depth strut span.
 5772    var emptySpan = makeSpan$2([], []);
 5773    var depthStrut = makeSpan$2(["vlist"], [emptySpan]);
 5774    depthStrut.style.height = makeEm(-minPos); // Safari wants the first row to have inline content; otherwise it
 5775    // puts the bottom of the *second* row on the baseline.
 5776
 5777    var topStrut = makeSpan$2(["vlist-s"], [new SymbolNode("\u200b")]);
 5778    rows = [makeSpan$2(["vlist-r"], [vlist, topStrut]), makeSpan$2(["vlist-r"], [depthStrut])];
 5779  } else {
 5780    rows = [makeSpan$2(["vlist-r"], [vlist])];
 5781  }
 5782
 5783  var vtable = makeSpan$2(["vlist-t"], rows);
 5784
 5785  if (rows.length === 2) {
 5786    vtable.classes.push("vlist-t2");
 5787  }
 5788
 5789  vtable.height = maxPos;
 5790  vtable.depth = -minPos;
 5791  return vtable;
 5792}; // Glue is a concept from TeX which is a flexible space between elements in
 5793// either a vertical or horizontal list. In KaTeX, at least for now, it's
 5794// static space between elements in a horizontal layout.
 5795
 5796
 5797var makeGlue = (measurement, options) => {
 5798  // Make an empty span for the space
 5799  var rule = makeSpan$2(["mspace"], [], options);
 5800  var size = calculateSize(measurement, options);
 5801  rule.style.marginRight = makeEm(size);
 5802  return rule;
 5803}; // Takes font options, and returns the appropriate fontLookup name
 5804
 5805
 5806var retrieveTextFontName = function retrieveTextFontName(fontFamily, fontWeight, fontShape) {
 5807  var baseFontName = "";
 5808
 5809  switch (fontFamily) {
 5810    case "amsrm":
 5811      baseFontName = "AMS";
 5812      break;
 5813
 5814    case "textrm":
 5815      baseFontName = "Main";
 5816      break;
 5817
 5818    case "textsf":
 5819      baseFontName = "SansSerif";
 5820      break;
 5821
 5822    case "texttt":
 5823      baseFontName = "Typewriter";
 5824      break;
 5825
 5826    default:
 5827      baseFontName = fontFamily;
 5828    // use fonts added by a plugin
 5829  }
 5830
 5831  var fontStylesName;
 5832
 5833  if (fontWeight === "textbf" && fontShape === "textit") {
 5834    fontStylesName = "BoldItalic";
 5835  } else if (fontWeight === "textbf") {
 5836    fontStylesName = "Bold";
 5837  } else if (fontWeight === "textit") {
 5838    fontStylesName = "Italic";
 5839  } else {
 5840    fontStylesName = "Regular";
 5841  }
 5842
 5843  return baseFontName + "-" + fontStylesName;
 5844};
 5845/**
 5846 * Maps TeX font commands to objects containing:
 5847 * - variant: string used for "mathvariant" attribute in buildMathML.js
 5848 * - fontName: the "style" parameter to fontMetrics.getCharacterMetrics
 5849 */
 5850// A map between tex font commands an MathML mathvariant attribute values
 5851
 5852
 5853var fontMap = {
 5854  // styles
 5855  "mathbf": {
 5856    variant: "bold",
 5857    fontName: "Main-Bold"
 5858  },
 5859  "mathrm": {
 5860    variant: "normal",
 5861    fontName: "Main-Regular"
 5862  },
 5863  "textit": {
 5864    variant: "italic",
 5865    fontName: "Main-Italic"
 5866  },
 5867  "mathit": {
 5868    variant: "italic",
 5869    fontName: "Main-Italic"
 5870  },
 5871  "mathnormal": {
 5872    variant: "italic",
 5873    fontName: "Math-Italic"
 5874  },
 5875  // "boldsymbol" is missing because they require the use of multiple fonts:
 5876  // Math-BoldItalic and Main-Bold.  This is handled by a special case in
 5877  // makeOrd which ends up calling boldsymbol.
 5878  // families
 5879  "mathbb": {
 5880    variant: "double-struck",
 5881    fontName: "AMS-Regular"
 5882  },
 5883  "mathcal": {
 5884    variant: "script",
 5885    fontName: "Caligraphic-Regular"
 5886  },
 5887  "mathfrak": {
 5888    variant: "fraktur",
 5889    fontName: "Fraktur-Regular"
 5890  },
 5891  "mathscr": {
 5892    variant: "script",
 5893    fontName: "Script-Regular"
 5894  },
 5895  "mathsf": {
 5896    variant: "sans-serif",
 5897    fontName: "SansSerif-Regular"
 5898  },
 5899  "mathtt": {
 5900    variant: "monospace",
 5901    fontName: "Typewriter-Regular"
 5902  }
 5903};
 5904var svgData = {
 5905  //   path, width, height
 5906  vec: ["vec", 0.471, 0.714],
 5907  // values from the font glyph
 5908  oiintSize1: ["oiintSize1", 0.957, 0.499],
 5909  // oval to overlay the integrand
 5910  oiintSize2: ["oiintSize2", 1.472, 0.659],
 5911  oiiintSize1: ["oiiintSize1", 1.304, 0.499],
 5912  oiiintSize2: ["oiiintSize2", 1.98, 0.659]
 5913};
 5914
 5915var staticSvg = function staticSvg(value, options) {
 5916  // Create a span with inline SVG for the element.
 5917  var [pathName, width, height] = svgData[value];
 5918  var path = new PathNode(pathName);
 5919  var svgNode = new SvgNode([path], {
 5920    "width": makeEm(width),
 5921    "height": makeEm(height),
 5922    // Override CSS rule `.katex svg { width: 100% }`
 5923    "style": "width:" + makeEm(width),
 5924    "viewBox": "0 0 " + 1000 * width + " " + 1000 * height,
 5925    "preserveAspectRatio": "xMinYMin"
 5926  });
 5927  var span = makeSvgSpan(["overlay"], [svgNode], options);
 5928  span.height = height;
 5929  span.style.height = makeEm(height);
 5930  span.style.width = makeEm(width);
 5931  return span;
 5932};
 5933
 5934var buildCommon = {
 5935  fontMap,
 5936  makeSymbol,
 5937  mathsym,
 5938  makeSpan: makeSpan$2,
 5939  makeSvgSpan,
 5940  makeLineSpan,
 5941  makeAnchor,
 5942  makeFragment,
 5943  wrapFragment,
 5944  makeVList,
 5945  makeOrd,
 5946  makeGlue,
 5947  staticSvg,
 5948  svgData,
 5949  tryCombineChars
 5950};
 5951
 5952/**
 5953 * Describes spaces between different classes of atoms.
 5954 */
 5955var thinspace = {
 5956  number: 3,
 5957  unit: "mu"
 5958};
 5959var mediumspace = {
 5960  number: 4,
 5961  unit: "mu"
 5962};
 5963var thickspace = {
 5964  number: 5,
 5965  unit: "mu"
 5966}; // Making the type below exact with all optional fields doesn't work due to
 5967// - https://github.com/facebook/flow/issues/4582
 5968// - https://github.com/facebook/flow/issues/5688
 5969// However, since *all* fields are optional, $Shape<> works as suggested in 5688
 5970// above.
 5971
 5972// Spacing relationships for display and text styles
 5973var spacings = {
 5974  mord: {
 5975    mop: thinspace,
 5976    mbin: mediumspace,
 5977    mrel: thickspace,
 5978    minner: thinspace
 5979  },
 5980  mop: {
 5981    mord: thinspace,
 5982    mop: thinspace,
 5983    mrel: thickspace,
 5984    minner: thinspace
 5985  },
 5986  mbin: {
 5987    mord: mediumspace,
 5988    mop: mediumspace,
 5989    mopen: mediumspace,
 5990    minner: mediumspace
 5991  },
 5992  mrel: {
 5993    mord: thickspace,
 5994    mop: thickspace,
 5995    mopen: thickspace,
 5996    minner: thickspace
 5997  },
 5998  mopen: {},
 5999  mclose: {
 6000    mop: thinspace,
 6001    mbin: mediumspace,
 6002    mrel: thickspace,
 6003    minner: thinspace
 6004  },
 6005  mpunct: {
 6006    mord: thinspace,
 6007    mop: thinspace,
 6008    mrel: thickspace,
 6009    mopen: thinspace,
 6010    mclose: thinspace,
 6011    mpunct: thinspace,
 6012    minner: thinspace
 6013  },
 6014  minner: {
 6015    mord: thinspace,
 6016    mop: thinspace,
 6017    mbin: mediumspace,
 6018    mrel: thickspace,
 6019    mopen: thinspace,
 6020    mpunct: thinspace,
 6021    minner: thinspace
 6022  }
 6023}; // Spacing relationships for script and scriptscript styles
 6024
 6025var tightSpacings = {
 6026  mord: {
 6027    mop: thinspace
 6028  },
 6029  mop: {
 6030    mord: thinspace,
 6031    mop: thinspace
 6032  },
 6033  mbin: {},
 6034  mrel: {},
 6035  mopen: {},
 6036  mclose: {
 6037    mop: thinspace
 6038  },
 6039  mpunct: {},
 6040  minner: {
 6041    mop: thinspace
 6042  }
 6043};
 6044
 6045/** Context provided to function handlers for error messages. */
 6046// Note: reverse the order of the return type union will cause a flow error.
 6047// See https://github.com/facebook/flow/issues/3663.
 6048// More general version of `HtmlBuilder` for nodes (e.g. \sum, accent types)
 6049// whose presence impacts super/subscripting. In this case, ParseNode<"supsub">
 6050// delegates its HTML building to the HtmlBuilder corresponding to these nodes.
 6051
 6052/**
 6053 * Final function spec for use at parse time.
 6054 * This is almost identical to `FunctionPropSpec`, except it
 6055 * 1. includes the function handler, and
 6056 * 2. requires all arguments except argTypes.
 6057 * It is generated by `defineFunction()` below.
 6058 */
 6059
 6060/**
 6061 * All registered functions.
 6062 * `functions.js` just exports this same dictionary again and makes it public.
 6063 * `Parser.js` requires this dictionary.
 6064 */
 6065var _functions = {};
 6066/**
 6067 * All HTML builders. Should be only used in the `define*` and the `build*ML`
 6068 * functions.
 6069 */
 6070
 6071var _htmlGroupBuilders = {};
 6072/**
 6073 * All MathML builders. Should be only used in the `define*` and the `build*ML`
 6074 * functions.
 6075 */
 6076
 6077var _mathmlGroupBuilders = {};
 6078function defineFunction(_ref) {
 6079  var {
 6080    type,
 6081    names,
 6082    props,
 6083    handler,
 6084    htmlBuilder,
 6085    mathmlBuilder
 6086  } = _ref;
 6087  // Set default values of functions
 6088  var data = {
 6089    type,
 6090    numArgs: props.numArgs,
 6091    argTypes: props.argTypes,
 6092    allowedInArgument: !!props.allowedInArgument,
 6093    allowedInText: !!props.allowedInText,
 6094    allowedInMath: props.allowedInMath === undefined ? true : props.allowedInMath,
 6095    numOptionalArgs: props.numOptionalArgs || 0,
 6096    infix: !!props.infix,
 6097    primitive: !!props.primitive,
 6098    handler: handler
 6099  };
 6100
 6101  for (var i = 0; i < names.length; ++i) {
 6102    _functions[names[i]] = data;
 6103  }
 6104
 6105  if (type) {
 6106    if (htmlBuilder) {
 6107      _htmlGroupBuilders[type] = htmlBuilder;
 6108    }
 6109
 6110    if (mathmlBuilder) {
 6111      _mathmlGroupBuilders[type] = mathmlBuilder;
 6112    }
 6113  }
 6114}
 6115/**
 6116 * Use this to register only the HTML and MathML builders for a function (e.g.
 6117 * if the function's ParseNode is generated in Parser.js rather than via a
 6118 * stand-alone handler provided to `defineFunction`).
 6119 */
 6120
 6121function defineFunctionBuilders(_ref2) {
 6122  var {
 6123    type,
 6124    htmlBuilder,
 6125    mathmlBuilder
 6126  } = _ref2;
 6127  defineFunction({
 6128    type,
 6129    names: [],
 6130    props: {
 6131      numArgs: 0
 6132    },
 6133
 6134    handler() {
 6135      throw new Error('Should never be called.');
 6136    },
 6137
 6138    htmlBuilder,
 6139    mathmlBuilder
 6140  });
 6141}
 6142var normalizeArgument = function normalizeArgument(arg) {
 6143  return arg.type === "ordgroup" && arg.body.length === 1 ? arg.body[0] : arg;
 6144}; // Since the corresponding buildHTML/buildMathML function expects a
 6145// list of elements, we normalize for different kinds of arguments
 6146
 6147var ordargument = function ordargument(arg) {
 6148  return arg.type === "ordgroup" ? arg.body : [arg];
 6149};
 6150
 6151/**
 6152 * This file does the main work of building a domTree structure from a parse
 6153 * tree. The entry point is the `buildHTML` function, which takes a parse tree.
 6154 * Then, the buildExpression, buildGroup, and various groupBuilders functions
 6155 * are called, to produce a final HTML tree.
 6156 */
 6157var makeSpan$1 = buildCommon.makeSpan; // Binary atoms (first class `mbin`) change into ordinary atoms (`mord`)
 6158// depending on their surroundings. See TeXbook pg. 442-446, Rules 5 and 6,
 6159// and the text before Rule 19.
 6160
 6161var binLeftCanceller = ["leftmost", "mbin", "mopen", "mrel", "mop", "mpunct"];
 6162var binRightCanceller = ["rightmost", "mrel", "mclose", "mpunct"];
 6163var styleMap$1 = {
 6164  "display": Style$1.DISPLAY,
 6165  "text": Style$1.TEXT,
 6166  "script": Style$1.SCRIPT,
 6167  "scriptscript": Style$1.SCRIPTSCRIPT
 6168};
 6169var DomEnum = {
 6170  mord: "mord",
 6171  mop: "mop",
 6172  mbin: "mbin",
 6173  mrel: "mrel",
 6174  mopen: "mopen",
 6175  mclose: "mclose",
 6176  mpunct: "mpunct",
 6177  minner: "minner"
 6178};
 6179
 6180/**
 6181 * Take a list of nodes, build them in order, and return a list of the built
 6182 * nodes. documentFragments are flattened into their contents, so the
 6183 * returned list contains no fragments. `isRealGroup` is true if `expression`
 6184 * is a real group (no atoms will be added on either side), as opposed to
 6185 * a partial group (e.g. one created by \color). `surrounding` is an array
 6186 * consisting type of nodes that will be added to the left and right.
 6187 */
 6188var buildExpression$1 = function buildExpression(expression, options, isRealGroup, surrounding) {
 6189  if (surrounding === void 0) {
 6190    surrounding = [null, null];
 6191  }
 6192
 6193  // Parse expressions into `groups`.
 6194  var groups = [];
 6195
 6196  for (var i = 0; i < expression.length; i++) {
 6197    var output = buildGroup$1(expression[i], options);
 6198
 6199    if (output instanceof DocumentFragment) {
 6200      var children = output.children;
 6201      groups.push(...children);
 6202    } else {
 6203      groups.push(output);
 6204    }
 6205  } // Combine consecutive domTree.symbolNodes into a single symbolNode.
 6206
 6207
 6208  buildCommon.tryCombineChars(groups); // If `expression` is a partial group, let the parent handle spacings
 6209  // to avoid processing groups multiple times.
 6210
 6211  if (!isRealGroup) {
 6212    return groups;
 6213  }
 6214
 6215  var glueOptions = options;
 6216
 6217  if (expression.length === 1) {
 6218    var node = expression[0];
 6219
 6220    if (node.type === "sizing") {
 6221      glueOptions = options.havingSize(node.size);
 6222    } else if (node.type === "styling") {
 6223      glueOptions = options.havingStyle(styleMap$1[node.style]);
 6224    }
 6225  } // Dummy spans for determining spacings between surrounding atoms.
 6226  // If `expression` has no atoms on the left or right, class "leftmost"
 6227  // or "rightmost", respectively, is used to indicate it.
 6228
 6229
 6230  var dummyPrev = makeSpan$1([surrounding[0] || "leftmost"], [], options);
 6231  var dummyNext = makeSpan$1([surrounding[1] || "rightmost"], [], options); // TODO: These code assumes that a node's math class is the first element
 6232  // of its `classes` array. A later cleanup should ensure this, for
 6233  // instance by changing the signature of `makeSpan`.
 6234  // Before determining what spaces to insert, perform bin cancellation.
 6235  // Binary operators change to ordinary symbols in some contexts.
 6236
 6237  var isRoot = isRealGroup === "root";
 6238  traverseNonSpaceNodes(groups, (node, prev) => {
 6239    var prevType = prev.classes[0];
 6240    var type = node.classes[0];
 6241
 6242    if (prevType === "mbin" && utils.contains(binRightCanceller, type)) {
 6243      prev.classes[0] = "mord";
 6244    } else if (type === "mbin" && utils.contains(binLeftCanceller, prevType)) {
 6245      node.classes[0] = "mord";
 6246    }
 6247  }, {
 6248    node: dummyPrev
 6249  }, dummyNext, isRoot);
 6250  traverseNonSpaceNodes(groups, (node, prev) => {
 6251    var prevType = getTypeOfDomTree(prev);
 6252    var type = getTypeOfDomTree(node); // 'mtight' indicates that the node is script or scriptscript style.
 6253
 6254    var space = prevType && type ? node.hasClass("mtight") ? tightSpacings[prevType][type] : spacings[prevType][type] : null;
 6255
 6256    if (space) {
 6257      // Insert glue (spacing) after the `prev`.
 6258      return buildCommon.makeGlue(space, glueOptions);
 6259    }
 6260  }, {
 6261    node: dummyPrev
 6262  }, dummyNext, isRoot);
 6263  return groups;
 6264}; // Depth-first traverse non-space `nodes`, calling `callback` with the current and
 6265// previous node as arguments, optionally returning a node to insert after the
 6266// previous node. `prev` is an object with the previous node and `insertAfter`
 6267// function to insert after it. `next` is a node that will be added to the right.
 6268// Used for bin cancellation and inserting spacings.
 6269
 6270var traverseNonSpaceNodes = function traverseNonSpaceNodes(nodes, callback, prev, next, isRoot) {
 6271  if (next) {
 6272    // temporarily append the right node, if exists
 6273    nodes.push(next);
 6274  }
 6275
 6276  var i = 0;
 6277
 6278  for (; i < nodes.length; i++) {
 6279    var node = nodes[i];
 6280    var partialGroup = checkPartialGroup(node);
 6281
 6282    if (partialGroup) {
 6283      // Recursive DFS
 6284      // $FlowFixMe: make nodes a $ReadOnlyArray by returning a new array
 6285      traverseNonSpaceNodes(partialGroup.children, callback, prev, null, isRoot);
 6286      continue;
 6287    } // Ignore explicit spaces (e.g., \;, \,) when determining what implicit
 6288    // spacing should go between atoms of different classes
 6289
 6290
 6291    var nonspace = !node.hasClass("mspace");
 6292
 6293    if (nonspace) {
 6294      var result = callback(node, prev.node);
 6295
 6296      if (result) {
 6297        if (prev.insertAfter) {
 6298          prev.insertAfter(result);
 6299        } else {
 6300          // insert at front
 6301          nodes.unshift(result);
 6302          i++;
 6303        }
 6304      }
 6305    }
 6306
 6307    if (nonspace) {
 6308      prev.node = node;
 6309    } else if (isRoot && node.hasClass("newline")) {
 6310      prev.node = makeSpan$1(["leftmost"]); // treat like beginning of line
 6311    }
 6312
 6313    prev.insertAfter = (index => n => {
 6314      nodes.splice(index + 1, 0, n);
 6315      i++;
 6316    })(i);
 6317  }
 6318
 6319  if (next) {
 6320    nodes.pop();
 6321  }
 6322}; // Check if given node is a partial group, i.e., does not affect spacing around.
 6323
 6324
 6325var checkPartialGroup = function checkPartialGroup(node) {
 6326  if (node instanceof DocumentFragment || node instanceof Anchor || node instanceof Span && node.hasClass("enclosing")) {
 6327    return node;
 6328  }
 6329
 6330  return null;
 6331}; // Return the outermost node of a domTree.
 6332
 6333
 6334var getOutermostNode = function getOutermostNode(node, side) {
 6335  var partialGroup = checkPartialGroup(node);
 6336
 6337  if (partialGroup) {
 6338    var children = partialGroup.children;
 6339
 6340    if (children.length) {
 6341      if (side === "right") {
 6342        return getOutermostNode(children[children.length - 1], "right");
 6343      } else if (side === "left") {
 6344        return getOutermostNode(children[0], "left");
 6345      }
 6346    }
 6347  }
 6348
 6349  return node;
 6350}; // Return math atom class (mclass) of a domTree.
 6351// If `side` is given, it will get the type of the outermost node at given side.
 6352
 6353
 6354var getTypeOfDomTree = function getTypeOfDomTree(node, side) {
 6355  if (!node) {
 6356    return null;
 6357  }
 6358
 6359  if (side) {
 6360    node = getOutermostNode(node, side);
 6361  } // This makes a lot of assumptions as to where the type of atom
 6362  // appears.  We should do a better job of enforcing this.
 6363
 6364
 6365  return DomEnum[node.classes[0]] || null;
 6366};
 6367var makeNullDelimiter = function makeNullDelimiter(options, classes) {
 6368  var moreClasses = ["nulldelimiter"].concat(options.baseSizingClasses());
 6369  return makeSpan$1(classes.concat(moreClasses));
 6370};
 6371/**
 6372 * buildGroup is the function that takes a group and calls the correct groupType
 6373 * function for it. It also handles the interaction of size and style changes
 6374 * between parents and children.
 6375 */
 6376
 6377var buildGroup$1 = function buildGroup(group, options, baseOptions) {
 6378  if (!group) {
 6379    return makeSpan$1();
 6380  }
 6381
 6382  if (_htmlGroupBuilders[group.type]) {
 6383    // Call the groupBuilders function
 6384    // $FlowFixMe
 6385    var groupNode = _htmlGroupBuilders[group.type](group, options); // If the size changed between the parent and the current group, account
 6386    // for that size difference.
 6387
 6388    if (baseOptions && options.size !== baseOptions.size) {
 6389      groupNode = makeSpan$1(options.sizingClasses(baseOptions), [groupNode], options);
 6390      var multiplier = options.sizeMultiplier / baseOptions.sizeMultiplier;
 6391      groupNode.height *= multiplier;
 6392      groupNode.depth *= multiplier;
 6393    }
 6394
 6395    return groupNode;
 6396  } else {
 6397    throw new ParseError("Got group of unknown type: '" + group.type + "'");
 6398  }
 6399};
 6400/**
 6401 * Combine an array of HTML DOM nodes (e.g., the output of `buildExpression`)
 6402 * into an unbreakable HTML node of class .base, with proper struts to
 6403 * guarantee correct vertical extent.  `buildHTML` calls this repeatedly to
 6404 * make up the entire expression as a sequence of unbreakable units.
 6405 */
 6406
 6407function buildHTMLUnbreakable(children, options) {
 6408  // Compute height and depth of this chunk.
 6409  var body = makeSpan$1(["base"], children, options); // Add strut, which ensures that the top of the HTML element falls at
 6410  // the height of the expression, and the bottom of the HTML element
 6411  // falls at the depth of the expression.
 6412
 6413  var strut = makeSpan$1(["strut"]);
 6414  strut.style.height = makeEm(body.height + body.depth);
 6415
 6416  if (body.depth) {
 6417    strut.style.verticalAlign = makeEm(-body.depth);
 6418  }
 6419
 6420  body.children.unshift(strut);
 6421  return body;
 6422}
 6423/**
 6424 * Take an entire parse tree, and build it into an appropriate set of HTML
 6425 * nodes.
 6426 */
 6427
 6428
 6429function buildHTML(tree, options) {
 6430  // Strip off outer tag wrapper for processing below.
 6431  var tag = null;
 6432
 6433  if (tree.length === 1 && tree[0].type === "tag") {
 6434    tag = tree[0].tag;
 6435    tree = tree[0].body;
 6436  } // Build the expression contained in the tree
 6437
 6438
 6439  var expression = buildExpression$1(tree, options, "root");
 6440  var eqnNum;
 6441
 6442  if (expression.length === 2 && expression[1].hasClass("tag")) {
 6443    // An environment with automatic equation numbers, e.g. {gather}.
 6444    eqnNum = expression.pop();
 6445  }
 6446
 6447  var children = []; // Create one base node for each chunk between potential line breaks.
 6448  // The TeXBook [p.173] says "A formula will be broken only after a
 6449  // relation symbol like $=$ or $<$ or $\rightarrow$, or after a binary
 6450  // operation symbol like $+$ or $-$ or $\times$, where the relation or
 6451  // binary operation is on the ``outer level'' of the formula (i.e., not
 6452  // enclosed in {...} and not part of an \over construction)."
 6453
 6454  var parts = [];
 6455
 6456  for (var i = 0; i < expression.length; i++) {
 6457    parts.push(expression[i]);
 6458
 6459    if (expression[i].hasClass("mbin") || expression[i].hasClass("mrel") || expression[i].hasClass("allowbreak")) {
 6460      // Put any post-operator glue on same line as operator.
 6461      // Watch for \nobreak along the way, and stop at \newline.
 6462      var nobreak = false;
 6463
 6464      while (i < expression.length - 1 && expression[i + 1].hasClass("mspace") && !expression[i + 1].hasClass("newline")) {
 6465        i++;
 6466        parts.push(expression[i]);
 6467
 6468        if (expression[i].hasClass("nobreak")) {
 6469          nobreak = true;
 6470        }
 6471      } // Don't allow break if \nobreak among the post-operator glue.
 6472
 6473
 6474      if (!nobreak) {
 6475        children.push(buildHTMLUnbreakable(parts, options));
 6476        parts = [];
 6477      }
 6478    } else if (expression[i].hasClass("newline")) {
 6479      // Write the line except the newline
 6480      parts.pop();
 6481
 6482      if (parts.length > 0) {
 6483        children.push(buildHTMLUnbreakable(parts, options));
 6484        parts = [];
 6485      } // Put the newline at the top level
 6486
 6487
 6488      children.push(expression[i]);
 6489    }
 6490  }
 6491
 6492  if (parts.length > 0) {
 6493    children.push(buildHTMLUnbreakable(parts, options));
 6494  } // Now, if there was a tag, build it too and append it as a final child.
 6495
 6496
 6497  var tagChild;
 6498
 6499  if (tag) {
 6500    tagChild = buildHTMLUnbreakable(buildExpression$1(tag, options, true));
 6501    tagChild.classes = ["tag"];
 6502    children.push(tagChild);
 6503  } else if (eqnNum) {
 6504    children.push(eqnNum);
 6505  }
 6506
 6507  var htmlNode = makeSpan$1(["katex-html"], children);
 6508  htmlNode.setAttribute("aria-hidden", "true"); // Adjust the strut of the tag to be the maximum height of all children
 6509  // (the height of the enclosing htmlNode) for proper vertical alignment.
 6510
 6511  if (tagChild) {
 6512    var strut = tagChild.children[0];
 6513    strut.style.height = makeEm(htmlNode.height + htmlNode.depth);
 6514
 6515    if (htmlNode.depth) {
 6516      strut.style.verticalAlign = makeEm(-htmlNode.depth);
 6517    }
 6518  }
 6519
 6520  return htmlNode;
 6521}
 6522
 6523/**
 6524 * These objects store data about MathML nodes. This is the MathML equivalent
 6525 * of the types in domTree.js. Since MathML handles its own rendering, and
 6526 * since we're mainly using MathML to improve accessibility, we don't manage
 6527 * any of the styling state that the plain DOM nodes do.
 6528 *
 6529 * The `toNode` and `toMarkup` functions work simlarly to how they do in
 6530 * domTree.js, creating namespaced DOM nodes and HTML text markup respectively.
 6531 */
 6532function newDocumentFragment(children) {
 6533  return new DocumentFragment(children);
 6534}
 6535/**
 6536 * This node represents a general purpose MathML node of any type. The
 6537 * constructor requires the type of node to create (for example, `"mo"` or
 6538 * `"mspace"`, corresponding to `<mo>` and `<mspace>` tags).
 6539 */
 6540
 6541class MathNode {
 6542  constructor(type, children, classes) {
 6543    this.type = void 0;
 6544    this.attributes = void 0;
 6545    this.children = void 0;
 6546    this.classes = void 0;
 6547    this.type = type;
 6548    this.attributes = {};
 6549    this.children = children || [];
 6550    this.classes = classes || [];
 6551  }
 6552  /**
 6553   * Sets an attribute on a MathML node. MathML depends on attributes to convey a
 6554   * semantic content, so this is used heavily.
 6555   */
 6556
 6557
 6558  setAttribute(name, value) {
 6559    this.attributes[name] = value;
 6560  }
 6561  /**
 6562   * Gets an attribute on a MathML node.
 6563   */
 6564
 6565
 6566  getAttribute(name) {
 6567    return this.attributes[name];
 6568  }
 6569  /**
 6570   * Converts the math node into a MathML-namespaced DOM element.
 6571   */
 6572
 6573
 6574  toNode() {
 6575    var node = document.createElementNS("http://www.w3.org/1998/Math/MathML", this.type);
 6576
 6577    for (var attr in this.attributes) {
 6578      if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
 6579        node.setAttribute(attr, this.attributes[attr]);
 6580      }
 6581    }
 6582
 6583    if (this.classes.length > 0) {
 6584      node.className = createClass(this.classes);
 6585    }
 6586
 6587    for (var i = 0; i < this.children.length; i++) {
 6588      node.appendChild(this.children[i].toNode());
 6589    }
 6590
 6591    return node;
 6592  }
 6593  /**
 6594   * Converts the math node into an HTML markup string.
 6595   */
 6596
 6597
 6598  toMarkup() {
 6599    var markup = "<" + this.type; // Add the attributes
 6600
 6601    for (var attr in this.attributes) {
 6602      if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
 6603        markup += " " + attr + "=\"";
 6604        markup += utils.escape(this.attributes[attr]);
 6605        markup += "\"";
 6606      }
 6607    }
 6608
 6609    if (this.classes.length > 0) {
 6610      markup += " class =\"" + utils.escape(createClass(this.classes)) + "\"";
 6611    }
 6612
 6613    markup += ">";
 6614
 6615    for (var i = 0; i < this.children.length; i++) {
 6616      markup += this.children[i].toMarkup();
 6617    }
 6618
 6619    markup += "</" + this.type + ">";
 6620    return markup;
 6621  }
 6622  /**
 6623   * Converts the math node into a string, similar to innerText, but escaped.
 6624   */
 6625
 6626
 6627  toText() {
 6628    return this.children.map(child => child.toText()).join("");
 6629  }
 6630
 6631}
 6632/**
 6633 * This node represents a piece of text.
 6634 */
 6635
 6636class TextNode {
 6637  constructor(text) {
 6638    this.text = void 0;
 6639    this.text = text;
 6640  }
 6641  /**
 6642   * Converts the text node into a DOM text node.
 6643   */
 6644
 6645
 6646  toNode() {
 6647    return document.createTextNode(this.text);
 6648  }
 6649  /**
 6650   * Converts the text node into escaped HTML markup
 6651   * (representing the text itself).
 6652   */
 6653
 6654
 6655  toMarkup() {
 6656    return utils.escape(this.toText());
 6657  }
 6658  /**
 6659   * Converts the text node into a string
 6660   * (representing the text iteself).
 6661   */
 6662
 6663
 6664  toText() {
 6665    return this.text;
 6666  }
 6667
 6668}
 6669/**
 6670 * This node represents a space, but may render as <mspace.../> or as text,
 6671 * depending on the width.
 6672 */
 6673
 6674class SpaceNode {
 6675  /**
 6676   * Create a Space node with width given in CSS ems.
 6677   */
 6678  constructor(width) {
 6679    this.width = void 0;
 6680    this.character = void 0;
 6681    this.width = width; // See https://www.w3.org/TR/2000/WD-MathML2-20000328/chapter6.html
 6682    // for a table of space-like characters.  We use Unicode
 6683    // representations instead of &LongNames; as it's not clear how to
 6684    // make the latter via document.createTextNode.
 6685
 6686    if (width >= 0.05555 && width <= 0.05556) {
 6687      this.character = "\u200a"; // &VeryThinSpace;
 6688    } else if (width >= 0.1666 && width <= 0.1667) {
 6689      this.character = "\u2009"; // &ThinSpace;
 6690    } else if (width >= 0.2222 && width <= 0.2223) {
 6691      this.character = "\u2005"; // &MediumSpace;
 6692    } else if (width >= 0.2777 && width <= 0.2778) {
 6693      this.character = "\u2005\u200a"; // &ThickSpace;
 6694    } else if (width >= -0.05556 && width <= -0.05555) {
 6695      this.character = "\u200a\u2063"; // &NegativeVeryThinSpace;
 6696    } else if (width >= -0.1667 && width <= -0.1666) {
 6697      this.character = "\u2009\u2063"; // &NegativeThinSpace;
 6698    } else if (width >= -0.2223 && width <= -0.2222) {
 6699      this.character = "\u205f\u2063"; // &NegativeMediumSpace;
 6700    } else if (width >= -0.2778 && width <= -0.2777) {
 6701      this.character = "\u2005\u2063"; // &NegativeThickSpace;
 6702    } else {
 6703      this.character = null;
 6704    }
 6705  }
 6706  /**
 6707   * Converts the math node into a MathML-namespaced DOM element.
 6708   */
 6709
 6710
 6711  toNode() {
 6712    if (this.character) {
 6713      return document.createTextNode(this.character);
 6714    } else {
 6715      var node = document.createElementNS("http://www.w3.org/1998/Math/MathML", "mspace");
 6716      node.setAttribute("width", makeEm(this.width));
 6717      return node;
 6718    }
 6719  }
 6720  /**
 6721   * Converts the math node into an HTML markup string.
 6722   */
 6723
 6724
 6725  toMarkup() {
 6726    if (this.character) {
 6727      return "<mtext>" + this.character + "</mtext>";
 6728    } else {
 6729      return "<mspace width=\"" + makeEm(this.width) + "\"/>";
 6730    }
 6731  }
 6732  /**
 6733   * Converts the math node into a string, similar to innerText.
 6734   */
 6735
 6736
 6737  toText() {
 6738    if (this.character) {
 6739      return this.character;
 6740    } else {
 6741      return " ";
 6742    }
 6743  }
 6744
 6745}
 6746
 6747var mathMLTree = {
 6748  MathNode,
 6749  TextNode,
 6750  SpaceNode,
 6751  newDocumentFragment
 6752};
 6753
 6754/**
 6755 * This file converts a parse tree into a cooresponding MathML tree. The main
 6756 * entry point is the `buildMathML` function, which takes a parse tree from the
 6757 * parser.
 6758 */
 6759
 6760/**
 6761 * Takes a symbol and converts it into a MathML text node after performing
 6762 * optional replacement from symbols.js.
 6763 */
 6764var makeText = function makeText(text, mode, options) {
 6765  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"))) {
 6766    text = symbols[mode][text].replace;
 6767  }
 6768
 6769  return new mathMLTree.TextNode(text);
 6770};
 6771/**
 6772 * Wrap the given array of nodes in an <mrow> node if needed, i.e.,
 6773 * unless the array has length 1.  Always returns a single node.
 6774 */
 6775
 6776var makeRow = function makeRow(body) {
 6777  if (body.length === 1) {
 6778    return body[0];
 6779  } else {
 6780    return new mathMLTree.MathNode("mrow", body);
 6781  }
 6782};
 6783/**
 6784 * Returns the math variant as a string or null if none is required.
 6785 */
 6786
 6787var getVariant = function getVariant(group, options) {
 6788  // Handle \text... font specifiers as best we can.
 6789  // MathML has a limited list of allowable mathvariant specifiers; see
 6790  // https://www.w3.org/TR/MathML3/chapter3.html#presm.commatt
 6791  if (options.fontFamily === "texttt") {
 6792    return "monospace";
 6793  } else if (options.fontFamily === "textsf") {
 6794    if (options.fontShape === "textit" && options.fontWeight === "textbf") {
 6795      return "sans-serif-bold-italic";
 6796    } else if (options.fontShape === "textit") {
 6797      return "sans-serif-italic";
 6798    } else if (options.fontWeight === "textbf") {
 6799      return "bold-sans-serif";
 6800    } else {
 6801      return "sans-serif";
 6802    }
 6803  } else if (options.fontShape === "textit" && options.fontWeight === "textbf") {
 6804    return "bold-italic";
 6805  } else if (options.fontShape === "textit") {
 6806    return "italic";
 6807  } else if (options.fontWeight === "textbf") {
 6808    return "bold";
 6809  }
 6810
 6811  var font = options.font;
 6812
 6813  if (!font || font === "mathnormal") {
 6814    return null;
 6815  }
 6816
 6817  var mode = group.mode;
 6818
 6819  if (font === "mathit") {
 6820    return "italic";
 6821  } else if (font === "boldsymbol") {
 6822    return group.type === "textord" ? "bold" : "bold-italic";
 6823  } else if (font === "mathbf") {
 6824    return "bold";
 6825  } else if (font === "mathbb") {
 6826    return "double-struck";
 6827  } else if (font === "mathfrak") {
 6828    return "fraktur";
 6829  } else if (font === "mathscr" || font === "mathcal") {
 6830    // MathML makes no distinction between script and caligrahpic
 6831    return "script";
 6832  } else if (font === "mathsf") {
 6833    return "sans-serif";
 6834  } else if (font === "mathtt") {
 6835    return "monospace";
 6836  }
 6837
 6838  var text = group.text;
 6839
 6840  if (utils.contains(["\\imath", "\\jmath"], text)) {
 6841    return null;
 6842  }
 6843
 6844  if (symbols[mode][text] && symbols[mode][text].replace) {
 6845    text = symbols[mode][text].replace;
 6846  }
 6847
 6848  var fontName = buildCommon.fontMap[font].fontName;
 6849
 6850  if (getCharacterMetrics(text, fontName, mode)) {
 6851    return buildCommon.fontMap[font].variant;
 6852  }
 6853
 6854  return null;
 6855};
 6856/**
 6857 * Takes a list of nodes, builds them, and returns a list of the generated
 6858 * MathML nodes.  Also combine consecutive <mtext> outputs into a single
 6859 * <mtext> tag.
 6860 */
 6861
 6862var buildExpression = function buildExpression(expression, options, isOrdgroup) {
 6863  if (expression.length === 1) {
 6864    var group = buildGroup(expression[0], options);
 6865
 6866    if (isOrdgroup && group instanceof MathNode && group.type === "mo") {
 6867      // When TeX writers want to suppress spacing on an operator,
 6868      // they often put the operator by itself inside braces.
 6869      group.setAttribute("lspace", "0em");
 6870      group.setAttribute("rspace", "0em");
 6871    }
 6872
 6873    return [group];
 6874  }
 6875
 6876  var groups = [];
 6877  var lastGroup;
 6878
 6879  for (var i = 0; i < expression.length; i++) {
 6880    var _group = buildGroup(expression[i], options);
 6881
 6882    if (_group instanceof MathNode && lastGroup instanceof MathNode) {
 6883      // Concatenate adjacent <mtext>s
 6884      if (_group.type === 'mtext' && lastGroup.type === 'mtext' && _group.getAttribute('mathvariant') === lastGroup.getAttribute('mathvariant')) {
 6885        lastGroup.children.push(..._group.children);
 6886        continue; // Concatenate adjacent <mn>s
 6887      } else if (_group.type === 'mn' && lastGroup.type === 'mn') {
 6888        lastGroup.children.push(..._group.children);
 6889        continue; // Concatenate <mn>...</mn> followed by <mi>.</mi>
 6890      } else if (_group.type === 'mi' && _group.children.length === 1 && lastGroup.type === 'mn') {
 6891        var child = _group.children[0];
 6892
 6893        if (child instanceof TextNode && child.text === '.') {
 6894          lastGroup.children.push(..._group.children);
 6895          continue;
 6896        }
 6897      } else if (lastGroup.type === 'mi' && lastGroup.children.length === 1) {
 6898        var lastChild = lastGroup.children[0];
 6899
 6900        if (lastChild instanceof TextNode && lastChild.text === '\u0338' && (_group.type === 'mo' || _group.type === 'mi' || _group.type === 'mn')) {
 6901          var _child = _group.children[0];
 6902
 6903          if (_child instanceof TextNode && _child.text.length > 0) {
 6904            // Overlay with combining character long solidus
 6905            _child.text = _child.text.slice(0, 1) + "\u0338" + _child.text.slice(1);
 6906            groups.pop();
 6907          }
 6908        }
 6909      }
 6910    }
 6911
 6912    groups.push(_group);
 6913    lastGroup = _group;
 6914  }
 6915
 6916  return groups;
 6917};
 6918/**
 6919 * Equivalent to buildExpression, but wraps the elements in an <mrow>
 6920 * if there's more than one.  Returns a single node instead of an array.
 6921 */
 6922
 6923var buildExpressionRow = function buildExpressionRow(expression, options, isOrdgroup) {
 6924  return makeRow(buildExpression(expression, options, isOrdgroup));
 6925};
 6926/**
 6927 * Takes a group from the parser and calls the appropriate groupBuilders function
 6928 * on it to produce a MathML node.
 6929 */
 6930
 6931var buildGroup = function buildGroup(group, options) {
 6932  if (!group) {
 6933    return new mathMLTree.MathNode("mrow");
 6934  }
 6935
 6936  if (_mathmlGroupBuilders[group.type]) {
 6937    // Call the groupBuilders function
 6938    // $FlowFixMe
 6939    var result = _mathmlGroupBuilders[group.type](group, options); // $FlowFixMe
 6940
 6941    return result;
 6942  } else {
 6943    throw new ParseError("Got group of unknown type: '" + group.type + "'");
 6944  }
 6945};
 6946/**
 6947 * Takes a full parse tree and settings and builds a MathML representation of
 6948 * it. In particular, we put the elements from building the parse tree into a
 6949 * <semantics> tag so we can also include that TeX source as an annotation.
 6950 *
 6951 * Note that we actually return a domTree element with a `<math>` inside it so
 6952 * we can do appropriate styling.
 6953 */
 6954
 6955function buildMathML(tree, texExpression, options, isDisplayMode, forMathmlOnly) {
 6956  var expression = buildExpression(tree, options); // TODO: Make a pass thru the MathML similar to buildHTML.traverseNonSpaceNodes
 6957  // and add spacing nodes. This is necessary only adjacent to math operators
 6958  // like \sin or \lim or to subsup elements that contain math operators.
 6959  // MathML takes care of the other spacing issues.
 6960  // Wrap up the expression in an mrow so it is presented in the semantics
 6961  // tag correctly, unless it's a single <mrow> or <mtable>.
 6962
 6963  var wrapper;
 6964
 6965  if (expression.length === 1 && expression[0] instanceof MathNode && utils.contains(["mrow", "mtable"], expression[0].type)) {
 6966    wrapper = expression[0];
 6967  } else {
 6968    wrapper = new mathMLTree.MathNode("mrow", expression);
 6969  } // Build a TeX annotation of the source
 6970
 6971
 6972  var annotation = new mathMLTree.MathNode("annotation", [new mathMLTree.TextNode(texExpression)]);
 6973  annotation.setAttribute("encoding", "application/x-tex");
 6974  var semantics = new mathMLTree.MathNode("semantics", [wrapper, annotation]);
 6975  var math = new mathMLTree.MathNode("math", [semantics]);
 6976  math.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML");
 6977
 6978  if (isDisplayMode) {
 6979    math.setAttribute("display", "block");
 6980  } // You can't style <math> nodes, so we wrap the node in a span.
 6981  // NOTE: The span class is not typed to have <math> nodes as children, and
 6982  // we don't want to make the children type more generic since the children
 6983  // of span are expected to have more fields in `buildHtml` contexts.
 6984
 6985
 6986  var wrapperClass = forMathmlOnly ? "katex" : "katex-mathml"; // $FlowFixMe
 6987
 6988  return buildCommon.makeSpan([wrapperClass], [math]);
 6989}
 6990
 6991var optionsFromSettings = function optionsFromSettings(settings) {
 6992  return new Options({
 6993    style: settings.displayMode ? Style$1.DISPLAY : Style$1.TEXT,
 6994    maxSize: settings.maxSize,
 6995    minRuleThickness: settings.minRuleThickness
 6996  });
 6997};
 6998
 6999var displayWrap = function displayWrap(node, settings) {
 7000  if (settings.displayMode) {
 7001    var classes = ["katex-display"];
 7002
 7003    if (settings.leqno) {
 7004      classes.push("leqno");
 7005    }
 7006
 7007    if (settings.fleqn) {
 7008      classes.push("fleqn");
 7009    }
 7010
 7011    node = buildCommon.makeSpan(classes, [node]);
 7012  }
 7013
 7014  return node;
 7015};
 7016
 7017var buildTree = function buildTree(tree, expression, settings) {
 7018  var options = optionsFromSettings(settings);
 7019  var katexNode;
 7020
 7021  if (settings.output === "mathml") {
 7022    return buildMathML(tree, expression, options, settings.displayMode, true);
 7023  } else if (settings.output === "html") {
 7024    var htmlNode = buildHTML(tree, options);
 7025    katexNode = buildCommon.makeSpan(["katex"], [htmlNode]);
 7026  } else {
 7027    var mathMLNode = buildMathML(tree, expression, options, settings.displayMode, false);
 7028
 7029    var _htmlNode = buildHTML(tree, options);
 7030
 7031    katexNode = buildCommon.makeSpan(["katex"], [mathMLNode, _htmlNode]);
 7032  }
 7033
 7034  return displayWrap(katexNode, settings);
 7035};
 7036var buildHTMLTree = function buildHTMLTree(tree, expression, settings) {
 7037  var options = optionsFromSettings(settings);
 7038  var htmlNode = buildHTML(tree, options);
 7039  var katexNode = buildCommon.makeSpan(["katex"], [htmlNode]);
 7040  return displayWrap(katexNode, settings);
 7041};
 7042
 7043/**
 7044 * This file provides support to buildMathML.js and buildHTML.js
 7045 * for stretchy wide elements rendered from SVG files
 7046 * and other CSS trickery.
 7047 */
 7048var stretchyCodePoint = {
 7049  widehat: "^",
 7050  widecheck: "ˇ",
 7051  widetilde: "~",
 7052  utilde: "~",
 7053  overleftarrow: "\u2190",
 7054  underleftarrow: "\u2190",
 7055  xleftarrow: "\u2190",
 7056  overrightarrow: "\u2192",
 7057  underrightarrow: "\u2192",
 7058  xrightarrow: "\u2192",
 7059  underbrace: "\u23df",
 7060  overbrace: "\u23de",
 7061  overgroup: "\u23e0",
 7062  undergroup: "\u23e1",
 7063  overleftrightarrow: "\u2194",
 7064  underleftrightarrow: "\u2194",
 7065  xleftrightarrow: "\u2194",
 7066  Overrightarrow: "\u21d2",
 7067  xRightarrow: "\u21d2",
 7068  overleftharpoon: "\u21bc",
 7069  xleftharpoonup: "\u21bc",
 7070  overrightharpoon: "\u21c0",
 7071  xrightharpoonup: "\u21c0",
 7072  xLeftarrow: "\u21d0",
 7073  xLeftrightarrow: "\u21d4",
 7074  xhookleftarrow: "\u21a9",
 7075  xhookrightarrow: "\u21aa",
 7076  xmapsto: "\u21a6",
 7077  xrightharpoondown: "\u21c1",
 7078  xleftharpoondown: "\u21bd",
 7079  xrightleftharpoons: "\u21cc",
 7080  xleftrightharpoons: "\u21cb",
 7081  xtwoheadleftarrow: "\u219e",
 7082  xtwoheadrightarrow: "\u21a0",
 7083  xlongequal: "=",
 7084  xtofrom: "\u21c4",
 7085  xrightleftarrows: "\u21c4",
 7086  xrightequilibrium: "\u21cc",
 7087  // Not a perfect match.
 7088  xleftequilibrium: "\u21cb",
 7089  // None better available.
 7090  "\\cdrightarrow": "\u2192",
 7091  "\\cdleftarrow": "\u2190",
 7092  "\\cdlongequal": "="
 7093};
 7094
 7095var mathMLnode = function mathMLnode(label) {
 7096  var node = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode(stretchyCodePoint[label.replace(/^\\/, '')])]);
 7097  node.setAttribute("stretchy", "true");
 7098  return node;
 7099}; // Many of the KaTeX SVG images have been adapted from glyphs in KaTeX fonts.
 7100// Copyright (c) 2009-2010, Design Science, Inc. (<www.mathjax.org>)
 7101// Copyright (c) 2014-2017 Khan Academy (<www.khanacademy.org>)
 7102// Licensed under the SIL Open Font License, Version 1.1.
 7103// See \nhttp://scripts.sil.org/OFL
 7104// Very Long SVGs
 7105//    Many of the KaTeX stretchy wide elements use a long SVG image and an
 7106//    overflow: hidden tactic to achieve a stretchy image while avoiding
 7107//    distortion of arrowheads or brace corners.
 7108//    The SVG typically contains a very long (400 em) arrow.
 7109//    The SVG is in a container span that has overflow: hidden, so the span
 7110//    acts like a window that exposes only part of the  SVG.
 7111//    The SVG always has a longer, thinner aspect ratio than the container span.
 7112//    After the SVG fills 100% of the height of the container span,
 7113//    there is a long arrow shaft left over. That left-over shaft is not shown.
 7114//    Instead, it is sliced off because the span's CSS has overflow: hidden.
 7115//    Thus, the reader sees an arrow that matches the subject matter width
 7116//    without distortion.
 7117//    Some functions, such as \cancel, need to vary their aspect ratio. These
 7118//    functions do not get the overflow SVG treatment.
 7119// Second Brush Stroke
 7120//    Low resolution monitors struggle to display images in fine detail.
 7121//    So browsers apply anti-aliasing. A long straight arrow shaft therefore
 7122//    will sometimes appear as if it has a blurred edge.
 7123//    To mitigate this, these SVG files contain a second "brush-stroke" on the
 7124//    arrow shafts. That is, a second long thin rectangular SVG path has been
 7125//    written directly on top of each arrow shaft. This reinforcement causes
 7126//    some of the screen pixels to display as black instead of the anti-aliased
 7127//    gray pixel that a  single path would generate. So we get arrow shafts
 7128//    whose edges appear to be sharper.
 7129// In the katexImagesData object just below, the dimensions all
 7130// correspond to path geometry inside the relevant SVG.
 7131// For example, \overrightarrow uses the same arrowhead as glyph U+2192
 7132// from the KaTeX Main font. The scaling factor is 1000.
 7133// That is, inside the font, that arrowhead is 522 units tall, which
 7134// corresponds to 0.522 em inside the document.
 7135
 7136
 7137var katexImagesData = {
 7138  //   path(s), minWidth, height, align
 7139  overrightarrow: [["rightarrow"], 0.888, 522, "xMaxYMin"],
 7140  overleftarrow: [["leftarrow"], 0.888, 522, "xMinYMin"],
 7141  underrightarrow: [["rightarrow"], 0.888, 522, "xMaxYMin"],
 7142  underleftarrow: [["leftarrow"], 0.888, 522, "xMinYMin"],
 7143  xrightarrow: [["rightarrow"], 1.469, 522, "xMaxYMin"],
 7144  "\\cdrightarrow": [["rightarrow"], 3.0, 522, "xMaxYMin"],
 7145  // CD minwwidth2.5pc
 7146  xleftarrow: [["leftarrow"], 1.469, 522, "xMinYMin"],
 7147  "\\cdleftarrow": [["leftarrow"], 3.0, 522, "xMinYMin"],
 7148  Overrightarrow: [["doublerightarrow"], 0.888, 560, "xMaxYMin"],
 7149  xRightarrow: [["doublerightarrow"], 1.526, 560, "xMaxYMin"],
 7150  xLeftarrow: [["doubleleftarrow"], 1.526, 560, "xMinYMin"],
 7151  overleftharpoon: [["leftharpoon"], 0.888, 522, "xMinYMin"],
 7152  xleftharpoonup: [["leftharpoon"], 0.888, 522, "xMinYMin"],
 7153  xleftharpoondown: [["leftharpoondown"], 0.888, 522, "xMinYMin"],
 7154  overrightharpoon: [["rightharpoon"], 0.888, 522, "xMaxYMin"],
 7155  xrightharpoonup: [["rightharpoon"], 0.888, 522, "xMaxYMin"],
 7156  xrightharpoondown: [["rightharpoondown"], 0.888, 522, "xMaxYMin"],
 7157  xlongequal: [["longequal"], 0.888, 334, "xMinYMin"],
 7158  "\\cdlongequal": [["longequal"], 3.0, 334, "xMinYMin"],
 7159  xtwoheadleftarrow: [["twoheadleftarrow"], 0.888, 334, "xMinYMin"],
 7160  xtwoheadrightarrow: [["twoheadrightarrow"], 0.888, 334, "xMaxYMin"],
 7161  overleftrightarrow: [["leftarrow", "rightarrow"], 0.888, 522],
 7162  overbrace: [["leftbrace", "midbrace", "rightbrace"], 1.6, 548],
 7163  underbrace: [["leftbraceunder", "midbraceunder", "rightbraceunder"], 1.6, 548],
 7164  underleftrightarrow: [["leftarrow", "rightarrow"], 0.888, 522],
 7165  xleftrightarrow: [["leftarrow", "rightarrow"], 1.75, 522],
 7166  xLeftrightarrow: [["doubleleftarrow", "doublerightarrow"], 1.75, 560],
 7167  xrightleftharpoons: [["leftharpoondownplus", "rightharpoonplus"], 1.75, 716],
 7168  xleftrightharpoons: [["leftharpoonplus", "rightharpoondownplus"], 1.75, 716],
 7169  xhookleftarrow: [["leftarrow", "righthook"], 1.08, 522],
 7170  xhookrightarrow: [["lefthook", "rightarrow"], 1.08, 522],
 7171  overlinesegment: [["leftlinesegment", "rightlinesegment"], 0.888, 522],
 7172  underlinesegment: [["leftlinesegment", "rightlinesegment"], 0.888, 522],
 7173  overgroup: [["leftgroup", "rightgroup"], 0.888, 342],
 7174  undergroup: [["leftgroupunder", "rightgroupunder"], 0.888, 342],
 7175  xmapsto: [["leftmapsto", "rightarrow"], 1.5, 522],
 7176  xtofrom: [["leftToFrom", "rightToFrom"], 1.75, 528],
 7177  // The next three arrows are from the mhchem package.
 7178  // In mhchem.sty, min-length is 2.0em. But these arrows might appear in the
 7179  // document as \xrightarrow or \xrightleftharpoons. Those have
 7180  // min-length = 1.75em, so we set min-length on these next three to match.
 7181  xrightleftarrows: [["baraboveleftarrow", "rightarrowabovebar"], 1.75, 901],
 7182  xrightequilibrium: [["baraboveshortleftharpoon", "rightharpoonaboveshortbar"], 1.75, 716],
 7183  xleftequilibrium: [["shortbaraboveleftharpoon", "shortrightharpoonabovebar"], 1.75, 716]
 7184};
 7185
 7186var groupLength = function groupLength(arg) {
 7187  if (arg.type === "ordgroup") {
 7188    return arg.body.length;
 7189  } else {
 7190    return 1;
 7191  }
 7192};
 7193
 7194var svgSpan = function svgSpan(group, options) {
 7195  // Create a span with inline SVG for the element.
 7196  function buildSvgSpan_() {
 7197    var viewBoxWidth = 400000; // default
 7198
 7199    var label = group.label.substr(1);
 7200
 7201    if (utils.contains(["widehat", "widecheck", "widetilde", "utilde"], label)) {
 7202      // Each type in the `if` statement corresponds to one of the ParseNode
 7203      // types below. This narrowing is required to access `grp.base`.
 7204      // $FlowFixMe
 7205      var grp = group; // There are four SVG images available for each function.
 7206      // Choose a taller image when there are more characters.
 7207
 7208      var numChars = groupLength(grp.base);
 7209      var viewBoxHeight;
 7210      var pathName;
 7211
 7212      var _height;
 7213
 7214      if (numChars > 5) {
 7215        if (label === "widehat" || label === "widecheck") {
 7216          viewBoxHeight = 420;
 7217          viewBoxWidth = 2364;
 7218          _height = 0.42;
 7219          pathName = label + "4";
 7220        } else {
 7221          viewBoxHeight = 312;
 7222          viewBoxWidth = 2340;
 7223          _height = 0.34;
 7224          pathName = "tilde4";
 7225        }
 7226      } else {
 7227        var imgIndex = [1, 1, 2, 2, 3, 3][numChars];
 7228
 7229        if (label === "widehat" || label === "widecheck") {
 7230          viewBoxWidth = [0, 1062, 2364, 2364, 2364][imgIndex];
 7231          viewBoxHeight = [0, 239, 300, 360, 420][imgIndex];
 7232          _height = [0, 0.24, 0.3, 0.3, 0.36, 0.42][imgIndex];
 7233          pathName = label + imgIndex;
 7234        } else {
 7235          viewBoxWidth = [0, 600, 1033, 2339, 2340][imgIndex];
 7236          viewBoxHeight = [0, 260, 286, 306, 312][imgIndex];
 7237          _height = [0, 0.26, 0.286, 0.3, 0.306, 0.34][imgIndex];
 7238          pathName = "tilde" + imgIndex;
 7239        }
 7240      }
 7241
 7242      var path = new PathNode(pathName);
 7243      var svgNode = new SvgNode([path], {
 7244        "width": "100%",
 7245        "height": makeEm(_height),
 7246        "viewBox": "0 0 " + viewBoxWidth + " " + viewBoxHeight,
 7247        "preserveAspectRatio": "none"
 7248      });
 7249      return {
 7250        span: buildCommon.makeSvgSpan([], [svgNode], options),
 7251        minWidth: 0,
 7252        height: _height
 7253      };
 7254    } else {
 7255      var spans = [];
 7256      var data = katexImagesData[label];
 7257      var [paths, _minWidth, _viewBoxHeight] = data;
 7258
 7259      var _height2 = _viewBoxHeight / 1000;
 7260
 7261      var numSvgChildren = paths.length;
 7262      var widthClasses;
 7263      var aligns;
 7264
 7265      if (numSvgChildren === 1) {
 7266        // $FlowFixMe: All these cases must be of the 4-tuple type.
 7267        var align1 = data[3];
 7268        widthClasses = ["hide-tail"];
 7269        aligns = [align1];
 7270      } else if (numSvgChildren === 2) {
 7271        widthClasses = ["halfarrow-left", "halfarrow-right"];
 7272        aligns = ["xMinYMin", "xMaxYMin"];
 7273      } else if (numSvgChildren === 3) {
 7274        widthClasses = ["brace-left", "brace-center", "brace-right"];
 7275        aligns = ["xMinYMin", "xMidYMin", "xMaxYMin"];
 7276      } else {
 7277        throw new Error("Correct katexImagesData or update code here to support\n                    " + numSvgChildren + " children.");
 7278      }
 7279
 7280      for (var i = 0; i < numSvgChildren; i++) {
 7281        var _path = new PathNode(paths[i]);
 7282
 7283        var _svgNode = new SvgNode([_path], {
 7284          "width": "400em",
 7285          "height": makeEm(_height2),
 7286          "viewBox": "0 0 " + viewBoxWidth + " " + _viewBoxHeight,
 7287          "preserveAspectRatio": aligns[i] + " slice"
 7288        });
 7289
 7290        var _span = buildCommon.makeSvgSpan([widthClasses[i]], [_svgNode], options);
 7291
 7292        if (numSvgChildren === 1) {
 7293          return {
 7294            span: _span,
 7295            minWidth: _minWidth,
 7296            height: _height2
 7297          };
 7298        } else {
 7299          _span.style.height = makeEm(_height2);
 7300          spans.push(_span);
 7301        }
 7302      }
 7303
 7304      return {
 7305        span: buildCommon.makeSpan(["stretchy"], spans, options),
 7306        minWidth: _minWidth,
 7307        height: _height2
 7308      };
 7309    }
 7310  } // buildSvgSpan_()
 7311
 7312
 7313  var {
 7314    span,
 7315    minWidth,
 7316    height
 7317  } = buildSvgSpan_(); // Note that we are returning span.depth = 0.
 7318  // Any adjustments relative to the baseline must be done in buildHTML.
 7319
 7320  span.height = height;
 7321  span.style.height = makeEm(height);
 7322
 7323  if (minWidth > 0) {
 7324    span.style.minWidth = makeEm(minWidth);
 7325  }
 7326
 7327  return span;
 7328};
 7329
 7330var encloseSpan = function encloseSpan(inner, label, topPad, bottomPad, options) {
 7331  // Return an image span for \cancel, \bcancel, \xcancel, \fbox, or \angl
 7332  var img;
 7333  var totalHeight = inner.height + inner.depth + topPad + bottomPad;
 7334
 7335  if (/fbox|color|angl/.test(label)) {
 7336    img = buildCommon.makeSpan(["stretchy", label], [], options);
 7337
 7338    if (label === "fbox") {
 7339      var color = options.color && options.getColor();
 7340
 7341      if (color) {
 7342        img.style.borderColor = color;
 7343      }
 7344    }
 7345  } else {
 7346    // \cancel, \bcancel, or \xcancel
 7347    // Since \cancel's SVG is inline and it omits the viewBox attribute,
 7348    // its stroke-width will not vary with span area.
 7349    var lines = [];
 7350
 7351    if (/^[bx]cancel$/.test(label)) {
 7352      lines.push(new LineNode({
 7353        "x1": "0",
 7354        "y1": "0",
 7355        "x2": "100%",
 7356        "y2": "100%",
 7357        "stroke-width": "0.046em"
 7358      }));
 7359    }
 7360
 7361    if (/^x?cancel$/.test(label)) {
 7362      lines.push(new LineNode({
 7363        "x1": "0",
 7364        "y1": "100%",
 7365        "x2": "100%",
 7366        "y2": "0",
 7367        "stroke-width": "0.046em"
 7368      }));
 7369    }
 7370
 7371    var svgNode = new SvgNode(lines, {
 7372      "width": "100%",
 7373      "height": makeEm(totalHeight)
 7374    });
 7375    img = buildCommon.makeSvgSpan([], [svgNode], options);
 7376  }
 7377
 7378  img.height = totalHeight;
 7379  img.style.height = makeEm(totalHeight);
 7380  return img;
 7381};
 7382
 7383var stretchy = {
 7384  encloseSpan,
 7385  mathMLnode,
 7386  svgSpan
 7387};
 7388
 7389/**
 7390 * Asserts that the node is of the given type and returns it with stricter
 7391 * typing. Throws if the node's type does not match.
 7392 */
 7393function assertNodeType(node, type) {
 7394  if (!node || node.type !== type) {
 7395    throw new Error("Expected node of type " + type + ", but got " + (node ? "node of type " + node.type : String(node)));
 7396  } // $FlowFixMe, >=0.125
 7397
 7398
 7399  return node;
 7400}
 7401/**
 7402 * Returns the node more strictly typed iff it is of the given type. Otherwise,
 7403 * returns null.
 7404 */
 7405
 7406function assertSymbolNodeType(node) {
 7407  var typedNode = checkSymbolNodeType(node);
 7408
 7409  if (!typedNode) {
 7410    throw new Error("Expected node of symbol group type, but got " + (node ? "node of type " + node.type : String(node)));
 7411  }
 7412
 7413  return typedNode;
 7414}
 7415/**
 7416 * Returns the node more strictly typed iff it is of the given type. Otherwise,
 7417 * returns null.
 7418 */
 7419
 7420function checkSymbolNodeType(node) {
 7421  if (node && (node.type === "atom" || NON_ATOMS.hasOwnProperty(node.type))) {
 7422    // $FlowFixMe
 7423    return node;
 7424  }
 7425
 7426  return null;
 7427}
 7428
 7429// NOTE: Unlike most `htmlBuilder`s, this one handles not only "accent", but
 7430// also "supsub" since an accent can affect super/subscripting.
 7431var htmlBuilder$a = (grp, options) => {
 7432  // Accents are handled in the TeXbook pg. 443, rule 12.
 7433  var base;
 7434  var group;
 7435  var supSubGroup;
 7436
 7437  if (grp && grp.type === "supsub") {
 7438    // If our base is a character box, and we have superscripts and
 7439    // subscripts, the supsub will defer to us. In particular, we want
 7440    // to attach the superscripts and subscripts to the inner body (so
 7441    // that the position of the superscripts and subscripts won't be
 7442    // affected by the height of the accent). We accomplish this by
 7443    // sticking the base of the accent into the base of the supsub, and
 7444    // rendering that, while keeping track of where the accent is.
 7445    // The real accent group is the base of the supsub group
 7446    group = assertNodeType(grp.base, "accent"); // The character box is the base of the accent group
 7447
 7448    base = group.base; // Stick the character box into the base of the supsub group
 7449
 7450    grp.base = base; // Rerender the supsub group with its new base, and store that
 7451    // result.
 7452
 7453    supSubGroup = assertSpan(buildGroup$1(grp, options)); // reset original base
 7454
 7455    grp.base = group;
 7456  } else {
 7457    group = assertNodeType(grp, "accent");
 7458    base = group.base;
 7459  } // Build the base group
 7460
 7461
 7462  var body = buildGroup$1(base, options.havingCrampedStyle()); // Does the accent need to shift for the skew of a character?
 7463
 7464  var mustShift = group.isShifty && utils.isCharacterBox(base); // Calculate the skew of the accent. This is based on the line "If the
 7465  // nucleus is not a single character, let s = 0; otherwise set s to the
 7466  // kern amount for the nucleus followed by the \skewchar of its font."
 7467  // Note that our skew metrics are just the kern between each character
 7468  // and the skewchar.
 7469
 7470  var skew = 0;
 7471
 7472  if (mustShift) {
 7473    // If the base is a character box, then we want the skew of the
 7474    // innermost character. To do that, we find the innermost character:
 7475    var baseChar = utils.getBaseElem(base); // Then, we render its group to get the symbol inside it
 7476
 7477    var baseGroup = buildGroup$1(baseChar, options.havingCrampedStyle()); // Finally, we pull the skew off of the symbol.
 7478
 7479    skew = assertSymbolDomNode(baseGroup).skew; // Note that we now throw away baseGroup, because the layers we
 7480    // removed with getBaseElem might contain things like \color which
 7481    // we can't get rid of.
 7482    // TODO(emily): Find a better way to get the skew
 7483  }
 7484
 7485  var accentBelow = group.label === "\\c"; // calculate the amount of space between the body and the accent
 7486
 7487  var clearance = accentBelow ? body.height + body.depth : Math.min(body.height, options.fontMetrics().xHeight); // Build the accent
 7488
 7489  var accentBody;
 7490
 7491  if (!group.isStretchy) {
 7492    var accent;
 7493    var width;
 7494
 7495    if (group.label === "\\vec") {
 7496      // Before version 0.9, \vec used the combining font glyph U+20D7.
 7497      // But browsers, especially Safari, are not consistent in how they
 7498      // render combining characters when not preceded by a character.
 7499      // So now we use an SVG.
 7500      // If Safari reforms, we should consider reverting to the glyph.
 7501      accent = buildCommon.staticSvg("vec", options);
 7502      width = buildCommon.svgData.vec[1];
 7503    } else {
 7504      accent = buildCommon.makeOrd({
 7505        mode: group.mode,
 7506        text: group.label
 7507      }, options, "textord");
 7508      accent = assertSymbolDomNode(accent); // Remove the italic correction of the accent, because it only serves to
 7509      // shift the accent over to a place we don't want.
 7510
 7511      accent.italic = 0;
 7512      width = accent.width;
 7513
 7514      if (accentBelow) {
 7515        clearance += accent.depth;
 7516      }
 7517    }
 7518
 7519    accentBody = buildCommon.makeSpan(["accent-body"], [accent]); // "Full" accents expand the width of the resulting symbol to be
 7520    // at least the width of the accent, and overlap directly onto the
 7521    // character without any vertical offset.
 7522
 7523    var accentFull = group.label === "\\textcircled";
 7524
 7525    if (accentFull) {
 7526      accentBody.classes.push('accent-full');
 7527      clearance = body.height;
 7528    } // Shift the accent over by the skew.
 7529
 7530
 7531    var left = skew; // CSS defines `.katex .accent .accent-body:not(.accent-full) { width: 0 }`
 7532    // so that the accent doesn't contribute to the bounding box.
 7533    // We need to shift the character by its width (effectively half
 7534    // its width) to compensate.
 7535
 7536    if (!accentFull) {
 7537      left -= width / 2;
 7538    }
 7539
 7540    accentBody.style.left = makeEm(left); // \textcircled uses the \bigcirc glyph, so it needs some
 7541    // vertical adjustment to match LaTeX.
 7542
 7543    if (group.label === "\\textcircled") {
 7544      accentBody.style.top = ".2em";
 7545    }
 7546
 7547    accentBody = buildCommon.makeVList({
 7548      positionType: "firstBaseline",
 7549      children: [{
 7550        type: "elem",
 7551        elem: body
 7552      }, {
 7553        type: "kern",
 7554        size: -clearance
 7555      }, {
 7556        type: "elem",
 7557        elem: accentBody
 7558      }]
 7559    }, options);
 7560  } else {
 7561    accentBody = stretchy.svgSpan(group, options);
 7562    accentBody = buildCommon.makeVList({
 7563      positionType: "firstBaseline",
 7564      children: [{
 7565        type: "elem",
 7566        elem: body
 7567      }, {
 7568        type: "elem",
 7569        elem: accentBody,
 7570        wrapperClasses: ["svg-align"],
 7571        wrapperStyle: skew > 0 ? {
 7572          width: "calc(100% - " + makeEm(2 * skew) + ")",
 7573          marginLeft: makeEm(2 * skew)
 7574        } : undefined
 7575      }]
 7576    }, options);
 7577  }
 7578
 7579  var accentWrap = buildCommon.makeSpan(["mord", "accent"], [accentBody], options);
 7580
 7581  if (supSubGroup) {
 7582    // Here, we replace the "base" child of the supsub with our newly
 7583    // generated accent.
 7584    supSubGroup.children[0] = accentWrap; // Since we don't rerun the height calculation after replacing the
 7585    // accent, we manually recalculate height.
 7586
 7587    supSubGroup.height = Math.max(accentWrap.height, supSubGroup.height); // Accents should always be ords, even when their innards are not.
 7588
 7589    supSubGroup.classes[0] = "mord";
 7590    return supSubGroup;
 7591  } else {
 7592    return accentWrap;
 7593  }
 7594};
 7595
 7596var mathmlBuilder$9 = (group, options) => {
 7597  var accentNode = group.isStretchy ? stretchy.mathMLnode(group.label) : new mathMLTree.MathNode("mo", [makeText(group.label, group.mode)]);
 7598  var node = new mathMLTree.MathNode("mover", [buildGroup(group.base, options), accentNode]);
 7599  node.setAttribute("accent", "true");
 7600  return node;
 7601};
 7602
 7603var NON_STRETCHY_ACCENT_REGEX = new RegExp(["\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve", "\\check", "\\hat", "\\vec", "\\dot", "\\mathring"].map(accent => "\\" + accent).join("|")); // Accents
 7604
 7605defineFunction({
 7606  type: "accent",
 7607  names: ["\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve", "\\check", "\\hat", "\\vec", "\\dot", "\\mathring", "\\widecheck", "\\widehat", "\\widetilde", "\\overrightarrow", "\\overleftarrow", "\\Overrightarrow", "\\overleftrightarrow", "\\overgroup", "\\overlinesegment", "\\overleftharpoon", "\\overrightharpoon"],
 7608  props: {
 7609    numArgs: 1
 7610  },
 7611  handler: (context, args) => {
 7612    var base = normalizeArgument(args[0]);
 7613    var isStretchy = !NON_STRETCHY_ACCENT_REGEX.test(context.funcName);
 7614    var isShifty = !isStretchy || context.funcName === "\\widehat" || context.funcName === "\\widetilde" || context.funcName === "\\widecheck";
 7615    return {
 7616      type: "accent",
 7617      mode: context.parser.mode,
 7618      label: context.funcName,
 7619      isStretchy: isStretchy,
 7620      isShifty: isShifty,
 7621      base: base
 7622    };
 7623  },
 7624  htmlBuilder: htmlBuilder$a,
 7625  mathmlBuilder: mathmlBuilder$9
 7626}); // Text-mode accents
 7627
 7628defineFunction({
 7629  type: "accent",
 7630  names: ["\\'", "\\`", "\\^", "\\~", "\\=", "\\u", "\\.", '\\"', "\\c", "\\r", "\\H", "\\v", "\\textcircled"],
 7631  props: {
 7632    numArgs: 1,
 7633    allowedInText: true,
 7634    allowedInMath: true,
 7635    // unless in strict mode
 7636    argTypes: ["primitive"]
 7637  },
 7638  handler: (context, args) => {
 7639    var base = args[0];
 7640    var mode = context.parser.mode;
 7641
 7642    if (mode === "math") {
 7643      context.parser.settings.reportNonstrict("mathVsTextAccents", "LaTeX's accent " + context.funcName + " works only in text mode");
 7644      mode = "text";
 7645    }
 7646
 7647    return {
 7648      type: "accent",
 7649      mode: mode,
 7650      label: context.funcName,
 7651      isStretchy: false,
 7652      isShifty: true,
 7653      base: base
 7654    };
 7655  },
 7656  htmlBuilder: htmlBuilder$a,
 7657  mathmlBuilder: mathmlBuilder$9
 7658});
 7659
 7660// Horizontal overlap functions
 7661defineFunction({
 7662  type: "accentUnder",
 7663  names: ["\\underleftarrow", "\\underrightarrow", "\\underleftrightarrow", "\\undergroup", "\\underlinesegment", "\\utilde"],
 7664  props: {
 7665    numArgs: 1
 7666  },
 7667  handler: (_ref, args) => {
 7668    var {
 7669      parser,
 7670      funcName
 7671    } = _ref;
 7672    var base = args[0];
 7673    return {
 7674      type: "accentUnder",
 7675      mode: parser.mode,
 7676      label: funcName,
 7677      base: base
 7678    };
 7679  },
 7680  htmlBuilder: (group, options) => {
 7681    // Treat under accents much like underlines.
 7682    var innerGroup = buildGroup$1(group.base, options);
 7683    var accentBody = stretchy.svgSpan(group, options);
 7684    var kern = group.label === "\\utilde" ? 0.12 : 0; // Generate the vlist, with the appropriate kerns
 7685
 7686    var vlist = buildCommon.makeVList({
 7687      positionType: "top",
 7688      positionData: innerGroup.height,
 7689      children: [{
 7690        type: "elem",
 7691        elem: accentBody,
 7692        wrapperClasses: ["svg-align"]
 7693      }, {
 7694        type: "kern",
 7695        size: kern
 7696      }, {
 7697        type: "elem",
 7698        elem: innerGroup
 7699      }]
 7700    }, options);
 7701    return buildCommon.makeSpan(["mord", "accentunder"], [vlist], options);
 7702  },
 7703  mathmlBuilder: (group, options) => {
 7704    var accentNode = stretchy.mathMLnode(group.label);
 7705    var node = new mathMLTree.MathNode("munder", [buildGroup(group.base, options), accentNode]);
 7706    node.setAttribute("accentunder", "true");
 7707    return node;
 7708  }
 7709});
 7710
 7711// Helper function
 7712var paddedNode = group => {
 7713  var node = new mathMLTree.MathNode("mpadded", group ? [group] : []);
 7714  node.setAttribute("width", "+0.6em");
 7715  node.setAttribute("lspace", "0.3em");
 7716  return node;
 7717}; // Stretchy arrows with an optional argument
 7718
 7719
 7720defineFunction({
 7721  type: "xArrow",
 7722  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.
 7723  // Direct use of these functions is discouraged and may break someday.
 7724  "\\xrightleftarrows", "\\xrightequilibrium", "\\xleftequilibrium", // The next 3 functions are here only to support the {CD} environment.
 7725  "\\\\cdrightarrow", "\\\\cdleftarrow", "\\\\cdlongequal"],
 7726  props: {
 7727    numArgs: 1,
 7728    numOptionalArgs: 1
 7729  },
 7730
 7731  handler(_ref, args, optArgs) {
 7732    var {
 7733      parser,
 7734      funcName
 7735    } = _ref;
 7736    return {
 7737      type: "xArrow",
 7738      mode: parser.mode,
 7739      label: funcName,
 7740      body: args[0],
 7741      below: optArgs[0]
 7742    };
 7743  },
 7744
 7745  // Flow is unable to correctly infer the type of `group`, even though it's
 7746  // unamibiguously determined from the passed-in `type` above.
 7747  htmlBuilder(group, options) {
 7748    var style = options.style; // Build the argument groups in the appropriate style.
 7749    // Ref: amsmath.dtx:   \hbox{$\scriptstyle\mkern#3mu{#6}\mkern#4mu$}%
 7750    // Some groups can return document fragments.  Handle those by wrapping
 7751    // them in a span.
 7752
 7753    var newOptions = options.havingStyle(style.sup());
 7754    var upperGroup = buildCommon.wrapFragment(buildGroup$1(group.body, newOptions, options), options);
 7755    var arrowPrefix = group.label.slice(0, 2) === "\\x" ? "x" : "cd";
 7756    upperGroup.classes.push(arrowPrefix + "-arrow-pad");
 7757    var lowerGroup;
 7758
 7759    if (group.below) {
 7760      // Build the lower group
 7761      newOptions = options.havingStyle(style.sub());
 7762      lowerGroup = buildCommon.wrapFragment(buildGroup$1(group.below, newOptions, options), options);
 7763      lowerGroup.classes.push(arrowPrefix + "-arrow-pad");
 7764    }
 7765
 7766    var arrowBody = stretchy.svgSpan(group, options); // Re shift: Note that stretchy.svgSpan returned arrowBody.depth = 0.
 7767    // The point we want on the math axis is at 0.5 * arrowBody.height.
 7768
 7769    var arrowShift = -options.fontMetrics().axisHeight + 0.5 * arrowBody.height; // 2 mu kern. Ref: amsmath.dtx: #7\if0#2\else\mkern#2mu\fi
 7770
 7771    var upperShift = -options.fontMetrics().axisHeight - 0.5 * arrowBody.height - 0.111; // 0.111 em = 2 mu
 7772
 7773    if (upperGroup.depth > 0.25 || group.label === "\\xleftequilibrium") {
 7774      upperShift -= upperGroup.depth; // shift up if depth encroaches
 7775    } // Generate the vlist
 7776
 7777
 7778    var vlist;
 7779
 7780    if (lowerGroup) {
 7781      var lowerShift = -options.fontMetrics().axisHeight + lowerGroup.height + 0.5 * arrowBody.height + 0.111;
 7782      vlist = buildCommon.makeVList({
 7783        positionType: "individualShift",
 7784        children: [{
 7785          type: "elem",
 7786          elem: upperGroup,
 7787          shift: upperShift
 7788        }, {
 7789          type: "elem",
 7790          elem: arrowBody,
 7791          shift: arrowShift
 7792        }, {
 7793          type: "elem",
 7794          elem: lowerGroup,
 7795          shift: lowerShift
 7796        }]
 7797      }, options);
 7798    } else {
 7799      vlist = buildCommon.makeVList({
 7800        positionType: "individualShift",
 7801        children: [{
 7802          type: "elem",
 7803          elem: upperGroup,
 7804          shift: upperShift
 7805        }, {
 7806          type: "elem",
 7807          elem: arrowBody,
 7808          shift: arrowShift
 7809        }]
 7810      }, options);
 7811    } // $FlowFixMe: Replace this with passing "svg-align" into makeVList.
 7812
 7813
 7814    vlist.children[0].children[0].children[1].classes.push("svg-align");
 7815    return buildCommon.makeSpan(["mrel", "x-arrow"], [vlist], options);
 7816  },
 7817
 7818  mathmlBuilder(group, options) {
 7819    var arrowNode = stretchy.mathMLnode(group.label);
 7820    arrowNode.setAttribute("minsize", group.label.charAt(0) === "x" ? "1.75em" : "3.0em");
 7821    var node;
 7822
 7823    if (group.body) {
 7824      var upperNode = paddedNode(buildGroup(group.body, options));
 7825
 7826      if (group.below) {
 7827        var lowerNode = paddedNode(buildGroup(group.below, options));
 7828        node = new mathMLTree.MathNode("munderover", [arrowNode, lowerNode, upperNode]);
 7829      } else {
 7830        node = new mathMLTree.MathNode("mover", [arrowNode, upperNode]);
 7831      }
 7832    } else if (group.below) {
 7833      var _lowerNode = paddedNode(buildGroup(group.below, options));
 7834
 7835      node = new mathMLTree.MathNode("munder", [arrowNode, _lowerNode]);
 7836    } else {
 7837      // This should never happen.
 7838      // Parser.js throws an error if there is no argument.
 7839      node = paddedNode();
 7840      node = new mathMLTree.MathNode("mover", [arrowNode, node]);
 7841    }
 7842
 7843    return node;
 7844  }
 7845
 7846});
 7847
 7848var cdArrowFunctionName = {
 7849  ">": "\\\\cdrightarrow",
 7850  "<": "\\\\cdleftarrow",
 7851  "=": "\\\\cdlongequal",
 7852  "A": "\\uparrow",
 7853  "V": "\\downarrow",
 7854  "|": "\\Vert",
 7855  ".": "no arrow"
 7856};
 7857
 7858var newCell = () => {
 7859  // Create an empty cell, to be filled below with parse nodes.
 7860  // The parseTree from this module must be constructed like the
 7861  // one created by parseArray(), so an empty CD cell must
 7862  // be a ParseNode<"styling">. And CD is always displaystyle.
 7863  // So these values are fixed and flow can do implicit typing.
 7864  return {
 7865    type: "styling",
 7866    body: [],
 7867    mode: "math",
 7868    style: "display"
 7869  };
 7870};
 7871
 7872var isStartOfArrow = node => {
 7873  return node.type === "textord" && node.text === "@";
 7874};
 7875
 7876var isLabelEnd = (node, endChar) => {
 7877  return (node.type === "mathord" || node.type === "atom") && node.text === endChar;
 7878};
 7879
 7880function cdArrow(arrowChar, labels, parser) {
 7881  // Return a parse tree of an arrow and its labels.
 7882  // This acts in a way similar to a macro expansion.
 7883  var funcName = cdArrowFunctionName[arrowChar];
 7884
 7885  switch (funcName) {
 7886    case "\\\\cdrightarrow":
 7887    case "\\\\cdleftarrow":
 7888      return parser.callFunction(funcName, [labels[0]], [labels[1]]);
 7889
 7890    case "\\uparrow":
 7891    case "\\downarrow":
 7892      {
 7893        var leftLabel = parser.callFunction("\\\\cdleft", [labels[0]], []);
 7894        var bareArrow = {
 7895          type: "atom",
 7896          text: funcName,
 7897          mode: "math",
 7898          family: "rel"
 7899        };
 7900        var sizedArrow = parser.callFunction("\\Big", [bareArrow], []);
 7901        var rightLabel = parser.callFunction("\\\\cdright", [labels[1]], []);
 7902        var arrowGroup = {
 7903          type: "ordgroup",
 7904          mode: "math",
 7905          body: [leftLabel, sizedArrow, rightLabel]
 7906        };
 7907        return parser.callFunction("\\\\cdparent", [arrowGroup], []);
 7908      }
 7909
 7910    case "\\\\cdlongequal":
 7911      return parser.callFunction("\\\\cdlongequal", [], []);
 7912
 7913    case "\\Vert":
 7914      {
 7915        var arrow = {
 7916          type: "textord",
 7917          text: "\\Vert",
 7918          mode: "math"
 7919        };
 7920        return parser.callFunction("\\Big", [arrow], []);
 7921      }
 7922
 7923    default:
 7924      return {
 7925        type: "textord",
 7926        text: " ",
 7927        mode: "math"
 7928      };
 7929  }
 7930}
 7931
 7932function parseCD(parser) {
 7933  // Get the array's parse nodes with \\ temporarily mapped to \cr.
 7934  var parsedRows = [];
 7935  parser.gullet.beginGroup();
 7936  parser.gullet.macros.set("\\cr", "\\\\\\relax");
 7937  parser.gullet.beginGroup();
 7938
 7939  while (true) {
 7940    // eslint-disable-line no-constant-condition
 7941    // Get the parse nodes for the next row.
 7942    parsedRows.push(parser.parseExpression(false, "\\\\"));
 7943    parser.gullet.endGroup();
 7944    parser.gullet.beginGroup();
 7945    var next = parser.fetch().text;
 7946
 7947    if (next === "&" || next === "\\\\") {
 7948      parser.consume();
 7949    } else if (next === "\\end") {
 7950      if (parsedRows[parsedRows.length - 1].length === 0) {
 7951        parsedRows.pop(); // final row ended in \\
 7952      }
 7953
 7954      break;
 7955    } else {
 7956      throw new ParseError("Expected \\\\ or \\cr or \\end", parser.nextToken);
 7957    }
 7958  }
 7959
 7960  var row = [];
 7961  var body = [row]; // Loop thru the parse nodes. Collect them into cells and arrows.
 7962
 7963  for (var i = 0; i < parsedRows.length; i++) {
 7964    // Start a new row.
 7965    var rowNodes = parsedRows[i]; // Create the first cell.
 7966
 7967    var cell = newCell();
 7968
 7969    for (var j = 0; j < rowNodes.length; j++) {
 7970      if (!isStartOfArrow(rowNodes[j])) {
 7971        // If a parseNode is not an arrow, it goes into a cell.
 7972        cell.body.push(rowNodes[j]);
 7973      } else {
 7974        // Parse node j is an "@", the start of an arrow.
 7975        // Before starting on the arrow, push the cell into `row`.
 7976        row.push(cell); // Now collect parseNodes into an arrow.
 7977        // The character after "@" defines the arrow type.
 7978
 7979        j += 1;
 7980        var arrowChar = assertSymbolNodeType(rowNodes[j]).text; // Create two empty label nodes. We may or may not use them.
 7981
 7982        var labels = new Array(2);
 7983        labels[0] = {
 7984          type: "ordgroup",
 7985          mode: "math",
 7986          body: []
 7987        };
 7988        labels[1] = {
 7989          type: "ordgroup",
 7990          mode: "math",
 7991          body: []
 7992        }; // Process the arrow.
 7993
 7994        if ("=|.".indexOf(arrowChar) > -1) ; else if ("<>AV".indexOf(arrowChar) > -1) {
 7995          // Four arrows, `@>>>`, `@<<<`, `@AAA`, and `@VVV`, each take
 7996          // two optional labels. E.g. the right-point arrow syntax is
 7997          // really:  @>{optional label}>{optional label}>
 7998          // Collect parseNodes into labels.
 7999          for (var labelNum = 0; labelNum < 2; labelNum++) {
 8000            var inLabel = true;
 8001
 8002            for (var k = j + 1; k < rowNodes.length; k++) {
 8003              if (isLabelEnd(rowNodes[k], arrowChar)) {
 8004                inLabel = false;
 8005                j = k;
 8006                break;
 8007              }
 8008
 8009              if (isStartOfArrow(rowNodes[k])) {
 8010                throw new ParseError("Missing a " + arrowChar + " character to complete a CD arrow.", rowNodes[k]);
 8011              }
 8012
 8013              labels[labelNum].body.push(rowNodes[k]);
 8014            }
 8015
 8016            if (inLabel) {
 8017              // isLabelEnd never returned a true.
 8018              throw new ParseError("Missing a " + arrowChar + " character to complete a CD arrow.", rowNodes[j]);
 8019            }
 8020          }
 8021        } else {
 8022          throw new ParseError("Expected one of \"<>AV=|.\" after @", rowNodes[j]);
 8023        } // Now join the arrow to its labels.
 8024
 8025
 8026        var arrow = cdArrow(arrowChar, labels, parser); // Wrap the arrow in  ParseNode<"styling">.
 8027        // This is done to match parseArray() behavior.
 8028
 8029        var wrappedArrow = {
 8030          type: "styling",
 8031          body: [arrow],
 8032          mode: "math",
 8033          style: "display" // CD is always displaystyle.
 8034
 8035        };
 8036        row.push(wrappedArrow); // In CD's syntax, cells are implicit. That is, everything that
 8037        // is not an arrow gets collected into a cell. So create an empty
 8038        // cell now. It will collect upcoming parseNodes.
 8039
 8040        cell = newCell();
 8041      }
 8042    }
 8043
 8044    if (i % 2 === 0) {
 8045      // Even-numbered rows consist of: cell, arrow, cell, arrow, ... cell
 8046      // The last cell is not yet pushed into `row`, so:
 8047      row.push(cell);
 8048    } else {
 8049      // Odd-numbered rows consist of: vert arrow, empty cell, ... vert arrow
 8050      // Remove the empty cell that was placed at the beginning of `row`.
 8051      row.shift();
 8052    }
 8053
 8054    row = [];
 8055    body.push(row);
 8056  } // End row group
 8057
 8058
 8059  parser.gullet.endGroup(); // End array group defining \\
 8060
 8061  parser.gullet.endGroup(); // define column separation.
 8062
 8063  var cols = new Array(body[0].length).fill({
 8064    type: "align",
 8065    align: "c",
 8066    pregap: 0.25,
 8067    // CD package sets \enskip between columns.
 8068    postgap: 0.25 // So pre and post each get half an \enskip, i.e. 0.25em.
 8069
 8070  });
 8071  return {
 8072    type: "array",
 8073    mode: "math",
 8074    body,
 8075    arraystretch: 1,
 8076    addJot: true,
 8077    rowGaps: [null],
 8078    cols,
 8079    colSeparationType: "CD",
 8080    hLinesBeforeRow: new Array(body.length + 1).fill([])
 8081  };
 8082} // The functions below are not available for general use.
 8083// They are here only for internal use by the {CD} environment in placing labels
 8084// next to vertical arrows.
 8085// We don't need any such functions for horizontal arrows because we can reuse
 8086// the functionality that already exists for extensible arrows.
 8087
 8088defineFunction({
 8089  type: "cdlabel",
 8090  names: ["\\\\cdleft", "\\\\cdright"],
 8091  props: {
 8092    numArgs: 1
 8093  },
 8094
 8095  handler(_ref, args) {
 8096    var {
 8097      parser,
 8098      funcName
 8099    } = _ref;
 8100    return {
 8101      type: "cdlabel",
 8102      mode: parser.mode,
 8103      side: funcName.slice(4),
 8104      label: args[0]
 8105    };
 8106  },
 8107
 8108  htmlBuilder(group, options) {
 8109    var newOptions = options.havingStyle(options.style.sup());
 8110    var label = buildCommon.wrapFragment(buildGroup$1(group.label, newOptions, options), options);
 8111    label.classes.push("cd-label-" + group.side);
 8112    label.style.bottom = makeEm(0.8 - label.depth); // Zero out label height & depth, so vertical align of arrow is set
 8113    // by the arrow height, not by the label.
 8114
 8115    label.height = 0;
 8116    label.depth = 0;
 8117    return label;
 8118  },
 8119
 8120  mathmlBuilder(group, options) {
 8121    var label = new mathMLTree.MathNode("mrow", [buildGroup(group.label, options)]);
 8122    label = new mathMLTree.MathNode("mpadded", [label]);
 8123    label.setAttribute("width", "0");
 8124
 8125    if (group.side === "left") {
 8126      label.setAttribute("lspace", "-1width");
 8127    } // We have to guess at vertical alignment. We know the arrow is 1.8em tall,
 8128    // But we don't know the height or depth of the label.
 8129
 8130
 8131    label.setAttribute("voffset", "0.7em");
 8132    label = new mathMLTree.MathNode("mstyle", [label]);
 8133    label.setAttribute("displaystyle", "false");
 8134    label.setAttribute("scriptlevel", "1");
 8135    return label;
 8136  }
 8137
 8138});
 8139defineFunction({
 8140  type: "cdlabelparent",
 8141  names: ["\\\\cdparent"],
 8142  props: {
 8143    numArgs: 1
 8144  },
 8145
 8146  handler(_ref2, args) {
 8147    var {
 8148      parser
 8149    } = _ref2;
 8150    return {
 8151      type: "cdlabelparent",
 8152      mode: parser.mode,
 8153      fragment: args[0]
 8154    };
 8155  },
 8156
 8157  htmlBuilder(group, options) {
 8158    // Wrap the vertical arrow and its labels.
 8159    // The parent gets position: relative. The child gets position: absolute.
 8160    // So CSS can locate the label correctly.
 8161    var parent = buildCommon.wrapFragment(buildGroup$1(group.fragment, options), options);
 8162    parent.classes.push("cd-vert-arrow");
 8163    return parent;
 8164  },
 8165
 8166  mathmlBuilder(group, options) {
 8167    return new mathMLTree.MathNode("mrow", [buildGroup(group.fragment, options)]);
 8168  }
 8169
 8170});
 8171
 8172// {123} and converts into symbol with code 123.  It is used by the *macro*
 8173// \char defined in macros.js.
 8174
 8175defineFunction({
 8176  type: "textord",
 8177  names: ["\\@char"],
 8178  props: {
 8179    numArgs: 1,
 8180    allowedInText: true
 8181  },
 8182
 8183  handler(_ref, args) {
 8184    var {
 8185      parser
 8186    } = _ref;
 8187    var arg = assertNodeType(args[0], "ordgroup");
 8188    var group = arg.body;
 8189    var number = "";
 8190
 8191    for (var i = 0; i < group.length; i++) {
 8192      var node = assertNodeType(group[i], "textord");
 8193      number += node.text;
 8194    }
 8195
 8196    var code = parseInt(number);
 8197    var text;
 8198
 8199    if (isNaN(code)) {
 8200      throw new ParseError("\\@char has non-numeric argument " + number); // If we drop IE support, the following code could be replaced with
 8201      // text = String.fromCodePoint(code)
 8202    } else if (code < 0 || code >= 0x10ffff) {
 8203      throw new ParseError("\\@char with invalid code point " + number);
 8204    } else if (code <= 0xffff) {
 8205      text = String.fromCharCode(code);
 8206    } else {
 8207      // Astral code point; split into surrogate halves
 8208      code -= 0x10000;
 8209      text = String.fromCharCode((code >> 10) + 0xd800, (code & 0x3ff) + 0xdc00);
 8210    }
 8211
 8212    return {
 8213      type: "textord",
 8214      mode: parser.mode,
 8215      text: text
 8216    };
 8217  }
 8218
 8219});
 8220
 8221var htmlBuilder$9 = (group, options) => {
 8222  var elements = buildExpression$1(group.body, options.withColor(group.color), false); // \color isn't supposed to affect the type of the elements it contains.
 8223  // To accomplish this, we wrap the results in a fragment, so the inner
 8224  // elements will be able to directly interact with their neighbors. For
 8225  // example, `\color{red}{2 +} 3` has the same spacing as `2 + 3`
 8226
 8227  return buildCommon.makeFragment(elements);
 8228};
 8229
 8230var mathmlBuilder$8 = (group, options) => {
 8231  var inner = buildExpression(group.body, options.withColor(group.color));
 8232  var node = new mathMLTree.MathNode("mstyle", inner);
 8233  node.setAttribute("mathcolor", group.color);
 8234  return node;
 8235};
 8236
 8237defineFunction({
 8238  type: "color",
 8239  names: ["\\textcolor"],
 8240  props: {
 8241    numArgs: 2,
 8242    allowedInText: true,
 8243    argTypes: ["color", "original"]
 8244  },
 8245
 8246  handler(_ref, args) {
 8247    var {
 8248      parser
 8249    } = _ref;
 8250    var color = assertNodeType(args[0], "color-token").color;
 8251    var body = args[1];
 8252    return {
 8253      type: "color",
 8254      mode: parser.mode,
 8255      color,
 8256      body: ordargument(body)
 8257    };
 8258  },
 8259
 8260  htmlBuilder: htmlBuilder$9,
 8261  mathmlBuilder: mathmlBuilder$8
 8262});
 8263defineFunction({
 8264  type: "color",
 8265  names: ["\\color"],
 8266  props: {
 8267    numArgs: 1,
 8268    allowedInText: true,
 8269    argTypes: ["color"]
 8270  },
 8271
 8272  handler(_ref2, args) {
 8273    var {
 8274      parser,
 8275      breakOnTokenText
 8276    } = _ref2;
 8277    var color = assertNodeType(args[0], "color-token").color; // Set macro \current@color in current namespace to store the current
 8278    // color, mimicking the behavior of color.sty.
 8279    // This is currently used just to correctly color a \right
 8280    // that follows a \color command.
 8281
 8282    parser.gullet.macros.set("\\current@color", color); // Parse out the implicit body that should be colored.
 8283
 8284    var body = parser.parseExpression(true, breakOnTokenText);
 8285    return {
 8286      type: "color",
 8287      mode: parser.mode,
 8288      color,
 8289      body
 8290    };
 8291  },
 8292
 8293  htmlBuilder: htmlBuilder$9,
 8294  mathmlBuilder: mathmlBuilder$8
 8295});
 8296
 8297// Row breaks within tabular environments, and line breaks at top level
 8298
 8299defineFunction({
 8300  type: "cr",
 8301  names: ["\\\\"],
 8302  props: {
 8303    numArgs: 0,
 8304    numOptionalArgs: 1,
 8305    argTypes: ["size"],
 8306    allowedInText: true
 8307  },
 8308
 8309  handler(_ref, args, optArgs) {
 8310    var {
 8311      parser
 8312    } = _ref;
 8313    var size = optArgs[0];
 8314    var newLine = !parser.settings.displayMode || !parser.settings.useStrictBehavior("newLineInDisplayMode", "In LaTeX, \\\\ or \\newline " + "does nothing in display mode");
 8315    return {
 8316      type: "cr",
 8317      mode: parser.mode,
 8318      newLine,
 8319      size: size && assertNodeType(size, "size").value
 8320    };
 8321  },
 8322
 8323  // The following builders are called only at the top level,
 8324  // not within tabular/array environments.
 8325  htmlBuilder(group, options) {
 8326    var span = buildCommon.makeSpan(["mspace"], [], options);
 8327
 8328    if (group.newLine) {
 8329      span.classes.push("newline");
 8330
 8331      if (group.size) {
 8332        span.style.marginTop = makeEm(calculateSize(group.size, options));
 8333      }
 8334    }
 8335
 8336    return span;
 8337  },
 8338
 8339  mathmlBuilder(group, options) {
 8340    var node = new mathMLTree.MathNode("mspace");
 8341
 8342    if (group.newLine) {
 8343      node.setAttribute("linebreak", "newline");
 8344
 8345      if (group.size) {
 8346        node.setAttribute("height", makeEm(calculateSize(group.size, options)));
 8347      }
 8348    }
 8349
 8350    return node;
 8351  }
 8352
 8353});
 8354
 8355var globalMap = {
 8356  "\\global": "\\global",
 8357  "\\long": "\\\\globallong",
 8358  "\\\\globallong": "\\\\globallong",
 8359  "\\def": "\\gdef",
 8360  "\\gdef": "\\gdef",
 8361  "\\edef": "\\xdef",
 8362  "\\xdef": "\\xdef",
 8363  "\\let": "\\\\globallet",
 8364  "\\futurelet": "\\\\globalfuture"
 8365};
 8366
 8367var checkControlSequence = tok => {
 8368  var name = tok.text;
 8369
 8370  if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) {
 8371    throw new ParseError("Expected a control sequence", tok);
 8372  }
 8373
 8374  return name;
 8375};
 8376
 8377var getRHS = parser => {
 8378  var tok = parser.gullet.popToken();
 8379
 8380  if (tok.text === "=") {
 8381    // consume optional equals
 8382    tok = parser.gullet.popToken();
 8383
 8384    if (tok.text === " ") {
 8385      // consume one optional space
 8386      tok = parser.gullet.popToken();
 8387    }
 8388  }
 8389
 8390  return tok;
 8391};
 8392
 8393var letCommand = (parser, name, tok, global) => {
 8394  var macro = parser.gullet.macros.get(tok.text);
 8395
 8396  if (macro == null) {
 8397    // don't expand it later even if a macro with the same name is defined
 8398    // e.g., \let\foo=\frac \def\frac{\relax} \frac12
 8399    tok.noexpand = true;
 8400    macro = {
 8401      tokens: [tok],
 8402      numArgs: 0,
 8403      // reproduce the same behavior in expansion
 8404      unexpandable: !parser.gullet.isExpandable(tok.text)
 8405    };
 8406  }
 8407
 8408  parser.gullet.macros.set(name, macro, global);
 8409}; // <assignment> -> <non-macro assignment>|<macro assignment>
 8410// <non-macro assignment> -> <simple assignment>|\global<non-macro assignment>
 8411// <macro assignment> -> <definition>|<prefix><macro assignment>
 8412// <prefix> -> \global|\long|\outer
 8413
 8414
 8415defineFunction({
 8416  type: "internal",
 8417  names: ["\\global", "\\long", "\\\\globallong" // can’t be entered directly
 8418  ],
 8419  props: {
 8420    numArgs: 0,
 8421    allowedInText: true
 8422  },
 8423
 8424  handler(_ref) {
 8425    var {
 8426      parser,
 8427      funcName
 8428    } = _ref;
 8429    parser.consumeSpaces();
 8430    var token = parser.fetch();
 8431
 8432    if (globalMap[token.text]) {
 8433      // KaTeX doesn't have \par, so ignore \long
 8434      if (funcName === "\\global" || funcName === "\\\\globallong") {
 8435        token.text = globalMap[token.text];
 8436      }
 8437
 8438      return assertNodeType(parser.parseFunction(), "internal");
 8439    }
 8440
 8441    throw new ParseError("Invalid token after macro prefix", token);
 8442  }
 8443
 8444}); // Basic support for macro definitions: \def, \gdef, \edef, \xdef
 8445// <definition> -> <def><control sequence><definition text>
 8446// <def> -> \def|\gdef|\edef|\xdef
 8447// <definition text> -> <parameter text><left brace><balanced text><right brace>
 8448
 8449defineFunction({
 8450  type: "internal",
 8451  names: ["\\def", "\\gdef", "\\edef", "\\xdef"],
 8452  props: {
 8453    numArgs: 0,
 8454    allowedInText: true,
 8455    primitive: true
 8456  },
 8457
 8458  handler(_ref2) {
 8459    var {
 8460      parser,
 8461      funcName
 8462    } = _ref2;
 8463    var tok = parser.gullet.popToken();
 8464    var name = tok.text;
 8465
 8466    if (/^(?:[\\{}$&#^_]|EOF)$/.test(name)) {
 8467      throw new ParseError("Expected a control sequence", tok);
 8468    }
 8469
 8470    var numArgs = 0;
 8471    var insert;
 8472    var delimiters = [[]]; // <parameter text> contains no braces
 8473
 8474    while (parser.gullet.future().text !== "{") {
 8475      tok = parser.gullet.popToken();
 8476
 8477      if (tok.text === "#") {
 8478        // If the very last character of the <parameter text> is #, so that
 8479        // this # is immediately followed by {, TeX will behave as if the {
 8480        // had been inserted at the right end of both the parameter text
 8481        // and the replacement text.
 8482        if (parser.gullet.future().text === "{") {
 8483          insert = parser.gullet.future();
 8484          delimiters[numArgs].push("{");
 8485          break;
 8486        } // A parameter, the first appearance of # must be followed by 1,
 8487        // the next by 2, and so on; up to nine #’s are allowed
 8488
 8489
 8490        tok = parser.gullet.popToken();
 8491
 8492        if (!/^[1-9]$/.test(tok.text)) {
 8493          throw new ParseError("Invalid argument number \"" + tok.text + "\"");
 8494        }
 8495
 8496        if (parseInt(tok.text) !== numArgs + 1) {
 8497          throw new ParseError("Argument number \"" + tok.text + "\" out of order");
 8498        }
 8499
 8500        numArgs++;
 8501        delimiters.push([]);
 8502      } else if (tok.text === "EOF") {
 8503        throw new ParseError("Expected a macro definition");
 8504      } else {
 8505        delimiters[numArgs].push(tok.text);
 8506      }
 8507    } // replacement text, enclosed in '{' and '}' and properly nested
 8508
 8509
 8510    var {
 8511      tokens
 8512    } = parser.gullet.consumeArg();
 8513
 8514    if (insert) {
 8515      tokens.unshift(insert);
 8516    }
 8517
 8518    if (funcName === "\\edef" || funcName === "\\xdef") {
 8519      tokens = parser.gullet.expandTokens(tokens);
 8520      tokens.reverse(); // to fit in with stack order
 8521    } // Final arg is the expansion of the macro
 8522
 8523
 8524    parser.gullet.macros.set(name, {
 8525      tokens,
 8526      numArgs,
 8527      delimiters
 8528    }, funcName === globalMap[funcName]);
 8529    return {
 8530      type: "internal",
 8531      mode: parser.mode
 8532    };
 8533  }
 8534
 8535}); // <simple assignment> -> <let assignment>
 8536// <let assignment> -> \futurelet<control sequence><token><token>
 8537//     | \let<control sequence><equals><one optional space><token>
 8538// <equals> -> <optional spaces>|<optional spaces>=
 8539
 8540defineFunction({
 8541  type: "internal",
 8542  names: ["\\let", "\\\\globallet" // can’t be entered directly
 8543  ],
 8544  props: {
 8545    numArgs: 0,
 8546    allowedInText: true,
 8547    primitive: true
 8548  },
 8549
 8550  handler(_ref3) {
 8551    var {
 8552      parser,
 8553      funcName
 8554    } = _ref3;
 8555    var name = checkControlSequence(parser.gullet.popToken());
 8556    parser.gullet.consumeSpaces();
 8557    var tok = getRHS(parser);
 8558    letCommand(parser, name, tok, funcName === "\\\\globallet");
 8559    return {
 8560      type: "internal",
 8561      mode: parser.mode
 8562    };
 8563  }
 8564
 8565}); // ref: https://www.tug.org/TUGboat/tb09-3/tb22bechtolsheim.pdf
 8566
 8567defineFunction({
 8568  type: "internal",
 8569  names: ["\\futurelet", "\\\\globalfuture" // can’t be entered directly
 8570  ],
 8571  props: {
 8572    numArgs: 0,
 8573    allowedInText: true,
 8574    primitive: true
 8575  },
 8576
 8577  handler(_ref4) {
 8578    var {
 8579      parser,
 8580      funcName
 8581    } = _ref4;
 8582    var name = checkControlSequence(parser.gullet.popToken());
 8583    var middle = parser.gullet.popToken();
 8584    var tok = parser.gullet.popToken();
 8585    letCommand(parser, name, tok, funcName === "\\\\globalfuture");
 8586    parser.gullet.pushToken(tok);
 8587    parser.gullet.pushToken(middle);
 8588    return {
 8589      type: "internal",
 8590      mode: parser.mode
 8591    };
 8592  }
 8593
 8594});
 8595
 8596/**
 8597 * This file deals with creating delimiters of various sizes. The TeXbook
 8598 * discusses these routines on page 441-442, in the "Another subroutine sets box
 8599 * x to a specified variable delimiter" paragraph.
 8600 *
 8601 * There are three main routines here. `makeSmallDelim` makes a delimiter in the
 8602 * normal font, but in either text, script, or scriptscript style.
 8603 * `makeLargeDelim` makes a delimiter in textstyle, but in one of the Size1,
 8604 * Size2, Size3, or Size4 fonts. `makeStackedDelim` makes a delimiter out of
 8605 * smaller pieces that are stacked on top of one another.
 8606 *
 8607 * The functions take a parameter `center`, which determines if the delimiter
 8608 * should be centered around the axis.
 8609 *
 8610 * Then, there are three exposed functions. `sizedDelim` makes a delimiter in
 8611 * one of the given sizes. This is used for things like `\bigl`.
 8612 * `customSizedDelim` makes a delimiter with a given total height+depth. It is
 8613 * called in places like `\sqrt`. `leftRightDelim` makes an appropriate
 8614 * delimiter which surrounds an expression of a given height an depth. It is
 8615 * used in `\left` and `\right`.
 8616 */
 8617
 8618/**
 8619 * Get the metrics for a given symbol and font, after transformation (i.e.
 8620 * after following replacement from symbols.js)
 8621 */
 8622var getMetrics = function getMetrics(symbol, font, mode) {
 8623  var replace = symbols.math[symbol] && symbols.math[symbol].replace;
 8624  var metrics = getCharacterMetrics(replace || symbol, font, mode);
 8625
 8626  if (!metrics) {
 8627    throw new Error("Unsupported symbol " + symbol + " and font size " + font + ".");
 8628  }
 8629
 8630  return metrics;
 8631};
 8632/**
 8633 * Puts a delimiter span in a given style, and adds appropriate height, depth,
 8634 * and maxFontSizes.
 8635 */
 8636
 8637
 8638var styleWrap = function styleWrap(delim, toStyle, options, classes) {
 8639  var newOptions = options.havingBaseStyle(toStyle);
 8640  var span = buildCommon.makeSpan(classes.concat(newOptions.sizingClasses(options)), [delim], options);
 8641  var delimSizeMultiplier = newOptions.sizeMultiplier / options.sizeMultiplier;
 8642  span.height *= delimSizeMultiplier;
 8643  span.depth *= delimSizeMultiplier;
 8644  span.maxFontSize = newOptions.sizeMultiplier;
 8645  return span;
 8646};
 8647
 8648var centerSpan = function centerSpan(span, options, style) {
 8649  var newOptions = options.havingBaseStyle(style);
 8650  var shift = (1 - options.sizeMultiplier / newOptions.sizeMultiplier) * options.fontMetrics().axisHeight;
 8651  span.classes.push("delimcenter");
 8652  span.style.top = makeEm(shift);
 8653  span.height -= shift;
 8654  span.depth += shift;
 8655};
 8656/**
 8657 * Makes a small delimiter. This is a delimiter that comes in the Main-Regular
 8658 * font, but is restyled to either be in textstyle, scriptstyle, or
 8659 * scriptscriptstyle.
 8660 */
 8661
 8662
 8663var makeSmallDelim = function makeSmallDelim(delim, style, center, options, mode, classes) {
 8664  var text = buildCommon.makeSymbol(delim, "Main-Regular", mode, options);
 8665  var span = styleWrap(text, style, options, classes);
 8666
 8667  if (center) {
 8668    centerSpan(span, options, style);
 8669  }
 8670
 8671  return span;
 8672};
 8673/**
 8674 * Builds a symbol in the given font size (note size is an integer)
 8675 */
 8676
 8677
 8678var mathrmSize = function mathrmSize(value, size, mode, options) {
 8679  return buildCommon.makeSymbol(value, "Size" + size + "-Regular", mode, options);
 8680};
 8681/**
 8682 * Makes a large delimiter. This is a delimiter that comes in the Size1, Size2,
 8683 * Size3, or Size4 fonts. It is always rendered in textstyle.
 8684 */
 8685
 8686
 8687var makeLargeDelim = function makeLargeDelim(delim, size, center, options, mode, classes) {
 8688  var inner = mathrmSize(delim, size, mode, options);
 8689  var span = styleWrap(buildCommon.makeSpan(["delimsizing", "size" + size], [inner], options), Style$1.TEXT, options, classes);
 8690
 8691  if (center) {
 8692    centerSpan(span, options, Style$1.TEXT);
 8693  }
 8694
 8695  return span;
 8696};
 8697/**
 8698 * Make a span from a font glyph with the given offset and in the given font.
 8699 * This is used in makeStackedDelim to make the stacking pieces for the delimiter.
 8700 */
 8701
 8702
 8703var makeGlyphSpan = function makeGlyphSpan(symbol, font, mode) {
 8704  var sizeClass; // Apply the correct CSS class to choose the right font.
 8705
 8706  if (font === "Size1-Regular") {
 8707    sizeClass = "delim-size1";
 8708  } else
 8709    /* if (font === "Size4-Regular") */
 8710    {
 8711      sizeClass = "delim-size4";
 8712    }
 8713
 8714  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
 8715  // in the appropriate tag that VList uses.
 8716
 8717  return {
 8718    type: "elem",
 8719    elem: corner
 8720  };
 8721};
 8722
 8723var makeInner = function makeInner(ch, height, options) {
 8724  // Create a span with inline SVG for the inner part of a tall stacked delimiter.
 8725  var width = fontMetricsData['Size4-Regular'][ch.charCodeAt(0)] ? fontMetricsData['Size4-Regular'][ch.charCodeAt(0)][4] : fontMetricsData['Size1-Regular'][ch.charCodeAt(0)][4];
 8726  var path = new PathNode("inner", innerPath(ch, Math.round(1000 * height)));
 8727  var svgNode = new SvgNode([path], {
 8728    "width": makeEm(width),
 8729    "height": makeEm(height),
 8730    // Override CSS rule `.katex svg { width: 100% }`
 8731    "style": "width:" + makeEm(width),
 8732    "viewBox": "0 0 " + 1000 * width + " " + Math.round(1000 * height),
 8733    "preserveAspectRatio": "xMinYMin"
 8734  });
 8735  var span = buildCommon.makeSvgSpan([], [svgNode], options);
 8736  span.height = height;
 8737  span.style.height = makeEm(height);
 8738  span.style.width = makeEm(width);
 8739  return {
 8740    type: "elem",
 8741    elem: span
 8742  };
 8743}; // Helpers for makeStackedDelim
 8744
 8745
 8746var lapInEms = 0.008;
 8747var lap = {
 8748  type: "kern",
 8749  size: -1 * lapInEms
 8750};
 8751var verts = ["|", "\\lvert", "\\rvert", "\\vert"];
 8752var doubleVerts = ["\\|", "\\lVert", "\\rVert", "\\Vert"];
 8753/**
 8754 * Make a stacked delimiter out of a given delimiter, with the total height at
 8755 * least `heightTotal`. This routine is mentioned on page 442 of the TeXbook.
 8756 */
 8757
 8758var makeStackedDelim = function makeStackedDelim(delim, heightTotal, center, options, mode, classes) {
 8759  // There are four parts, the top, an optional middle, a repeated part, and a
 8760  // bottom.
 8761  var top;
 8762  var middle;
 8763  var repeat;
 8764  var bottom;
 8765  top = repeat = bottom = delim;
 8766  middle = null; // Also keep track of what font the delimiters are in
 8767
 8768  var font = "Size1-Regular"; // We set the parts and font based on the symbol. Note that we use
 8769  // '\u23d0' instead of '|' and '\u2016' instead of '\\|' for the
 8770  // repeats of the arrows
 8771
 8772  if (delim === "\\uparrow") {
 8773    repeat = bottom = "\u23d0";
 8774  } else if (delim === "\\Uparrow") {
 8775    repeat = bottom = "\u2016";
 8776  } else if (delim === "\\downarrow") {
 8777    top = repeat = "\u23d0";
 8778  } else if (delim === "\\Downarrow") {
 8779    top = repeat = "\u2016";
 8780  } else if (delim === "\\updownarrow") {
 8781    top = "\\uparrow";
 8782    repeat = "\u23d0";
 8783    bottom = "\\downarrow";
 8784  } else if (delim === "\\Updownarrow") {
 8785    top = "\\Uparrow";
 8786    repeat = "\u2016";
 8787    bottom = "\\Downarrow";
 8788  } else if (utils.contains(verts, delim)) {
 8789    repeat = "\u2223";
 8790  } else if (utils.contains(doubleVerts, delim)) {
 8791    repeat = "\u2225";
 8792  } else if (delim === "[" || delim === "\\lbrack") {
 8793    top = "\u23a1";
 8794    repeat = "\u23a2";
 8795    bottom = "\u23a3";
 8796    font = "Size4-Regular";
 8797  } else if (delim === "]" || delim === "\\rbrack") {
 8798    top = "\u23a4";
 8799    repeat = "\u23a5";
 8800    bottom = "\u23a6";
 8801    font = "Size4-Regular";
 8802  } else if (delim === "\\lfloor" || delim === "\u230a") {
 8803    repeat = top = "\u23a2";
 8804    bottom = "\u23a3";
 8805    font = "Size4-Regular";
 8806  } else if (delim === "\\lceil" || delim === "\u2308") {
 8807    top = "\u23a1";
 8808    repeat = bottom = "\u23a2";
 8809    font = "Size4-Regular";
 8810  } else if (delim === "\\rfloor" || delim === "\u230b") {
 8811    repeat = top = "\u23a5";
 8812    bottom = "\u23a6";
 8813    font = "Size4-Regular";
 8814  } else if (delim === "\\rceil" || delim === "\u2309") {
 8815    top = "\u23a4";
 8816    repeat = bottom = "\u23a5";
 8817    font = "Size4-Regular";
 8818  } else if (delim === "(" || delim === "\\lparen") {
 8819    top = "\u239b";
 8820    repeat = "\u239c";
 8821    bottom = "\u239d";
 8822    font = "Size4-Regular";
 8823  } else if (delim === ")" || delim === "\\rparen") {
 8824    top = "\u239e";
 8825    repeat = "\u239f";
 8826    bottom = "\u23a0";
 8827    font = "Size4-Regular";
 8828  } else if (delim === "\\{" || delim === "\\lbrace") {
 8829    top = "\u23a7";
 8830    middle = "\u23a8";
 8831    bottom = "\u23a9";
 8832    repeat = "\u23aa";
 8833    font = "Size4-Regular";
 8834  } else if (delim === "\\}" || delim === "\\rbrace") {
 8835    top = "\u23ab";
 8836    middle = "\u23ac";
 8837    bottom = "\u23ad";
 8838    repeat = "\u23aa";
 8839    font = "Size4-Regular";
 8840  } else if (delim === "\\lgroup" || delim === "\u27ee") {
 8841    top = "\u23a7";
 8842    bottom = "\u23a9";
 8843    repeat = "\u23aa";
 8844    font = "Size4-Regular";
 8845  } else if (delim === "\\rgroup" || delim === "\u27ef") {
 8846    top = "\u23ab";
 8847    bottom = "\u23ad";
 8848    repeat = "\u23aa";
 8849    font = "Size4-Regular";
 8850  } else if (delim === "\\lmoustache" || delim === "\u23b0") {
 8851    top = "\u23a7";
 8852    bottom = "\u23ad";
 8853    repeat = "\u23aa";
 8854    font = "Size4-Regular";
 8855  } else if (delim === "\\rmoustache" || delim === "\u23b1") {
 8856    top = "\u23ab";
 8857    bottom = "\u23a9";
 8858    repeat = "\u23aa";
 8859    font = "Size4-Regular";
 8860  } // Get the metrics of the four sections
 8861
 8862
 8863  var topMetrics = getMetrics(top, font, mode);
 8864  var topHeightTotal = topMetrics.height + topMetrics.depth;
 8865  var repeatMetrics = getMetrics(repeat, font, mode);
 8866  var repeatHeightTotal = repeatMetrics.height + repeatMetrics.depth;
 8867  var bottomMetrics = getMetrics(bottom, font, mode);
 8868  var bottomHeightTotal = bottomMetrics.height + bottomMetrics.depth;
 8869  var middleHeightTotal = 0;
 8870  var middleFactor = 1;
 8871
 8872  if (middle !== null) {
 8873    var middleMetrics = getMetrics(middle, font, mode);
 8874    middleHeightTotal = middleMetrics.height + middleMetrics.depth;
 8875    middleFactor = 2; // repeat symmetrically above and below middle
 8876  } // Calcuate the minimal height that the delimiter can have.
 8877  // It is at least the size of the top, bottom, and optional middle combined.
 8878
 8879
 8880  var minHeight = topHeightTotal + bottomHeightTotal + middleHeightTotal; // Compute the number of copies of the repeat symbol we will need
 8881
 8882  var repeatCount = Math.max(0, Math.ceil((heightTotal - minHeight) / (middleFactor * repeatHeightTotal))); // Compute the total height of the delimiter including all the symbols
 8883
 8884  var realHeightTotal = minHeight + repeatCount * middleFactor * repeatHeightTotal; // The center of the delimiter is placed at the center of the axis. Note
 8885  // that in this context, "center" means that the delimiter should be
 8886  // centered around the axis in the current style, while normally it is
 8887  // centered around the axis in textstyle.
 8888
 8889  var axisHeight = options.fontMetrics().axisHeight;
 8890
 8891  if (center) {
 8892    axisHeight *= options.sizeMultiplier;
 8893  } // Calculate the depth
 8894
 8895
 8896  var depth = realHeightTotal / 2 - axisHeight; // Now, we start building the pieces that will go into the vlist
 8897  // Keep a list of the pieces of the stacked delimiter
 8898
 8899  var stack = []; // Add the bottom symbol
 8900
 8901  stack.push(makeGlyphSpan(bottom, font, mode));
 8902  stack.push(lap); // overlap
 8903
 8904  if (middle === null) {
 8905    // The middle section will be an SVG. Make it an extra 0.016em tall.
 8906    // We'll overlap by 0.008em at top and bottom.
 8907    var innerHeight = realHeightTotal - topHeightTotal - bottomHeightTotal + 2 * lapInEms;
 8908    stack.push(makeInner(repeat, innerHeight, options));
 8909  } else {
 8910    // When there is a middle bit, we need the middle part and two repeated
 8911    // sections
 8912    var _innerHeight = (realHeightTotal - topHeightTotal - bottomHeightTotal - middleHeightTotal) / 2 + 2 * lapInEms;
 8913
 8914    stack.push(makeInner(repeat, _innerHeight, options)); // Now insert the middle of the brace.
 8915
 8916    stack.push(lap);
 8917    stack.push(makeGlyphSpan(middle, font, mode));
 8918    stack.push(lap);
 8919    stack.push(makeInner(repeat, _innerHeight, options));
 8920  } // Add the top symbol
 8921
 8922
 8923  stack.push(lap);
 8924  stack.push(makeGlyphSpan(top, font, mode)); // Finally, build the vlist
 8925
 8926  var newOptions = options.havingBaseStyle(Style$1.TEXT);
 8927  var inner = buildCommon.makeVList({
 8928    positionType: "bottom",
 8929    positionData: depth,
 8930    children: stack
 8931  }, newOptions);
 8932  return styleWrap(buildCommon.makeSpan(["delimsizing", "mult"], [inner], newOptions), Style$1.TEXT, options, classes);
 8933}; // All surds have 0.08em padding above the viniculum inside the SVG.
 8934// That keeps browser span height rounding error from pinching the line.
 8935
 8936
 8937var vbPad = 80; // padding above the surd, measured inside the viewBox.
 8938
 8939var emPad = 0.08; // padding, in ems, measured in the document.
 8940
 8941var sqrtSvg = function sqrtSvg(sqrtName, height, viewBoxHeight, extraViniculum, options) {
 8942  var path = sqrtPath(sqrtName, extraViniculum, viewBoxHeight);
 8943  var pathNode = new PathNode(sqrtName, path);
 8944  var svg = new SvgNode([pathNode], {
 8945    // Note: 1000:1 ratio of viewBox to document em width.
 8946    "width": "400em",
 8947    "height": makeEm(height),
 8948    "viewBox": "0 0 400000 " + viewBoxHeight,
 8949    "preserveAspectRatio": "xMinYMin slice"
 8950  });
 8951  return buildCommon.makeSvgSpan(["hide-tail"], [svg], options);
 8952};
 8953/**
 8954 * Make a sqrt image of the given height,
 8955 */
 8956
 8957
 8958var makeSqrtImage = function makeSqrtImage(height, options) {
 8959  // Define a newOptions that removes the effect of size changes such as \Huge.
 8960  // We don't pick different a height surd for \Huge. For it, we scale up.
 8961  var newOptions = options.havingBaseSizing(); // Pick the desired surd glyph from a sequence of surds.
 8962
 8963  var delim = traverseSequence("\\surd", height * newOptions.sizeMultiplier, stackLargeDelimiterSequence, newOptions);
 8964  var sizeMultiplier = newOptions.sizeMultiplier; // default
 8965  // The standard sqrt SVGs each have a 0.04em thick viniculum.
 8966  // If Settings.minRuleThickness is larger than that, we add extraViniculum.
 8967
 8968  var extraViniculum = Math.max(0, options.minRuleThickness - options.fontMetrics().sqrtRuleThickness); // Create a span containing an SVG image of a sqrt symbol.
 8969
 8970  var span;
 8971  var spanHeight = 0;
 8972  var texHeight = 0;
 8973  var viewBoxHeight = 0;
 8974  var advanceWidth; // We create viewBoxes with 80 units of "padding" above each surd.
 8975  // Then browser rounding error on the parent span height will not
 8976  // encroach on the ink of the viniculum. But that padding is not
 8977  // included in the TeX-like `height` used for calculation of
 8978  // vertical alignment. So texHeight = span.height < span.style.height.
 8979
 8980  if (delim.type === "small") {
 8981    // Get an SVG that is derived from glyph U+221A in font KaTeX-Main.
 8982    // 1000 unit normal glyph height.
 8983    viewBoxHeight = 1000 + 1000 * extraViniculum + vbPad;
 8984
 8985    if (height < 1.0) {
 8986      sizeMultiplier = 1.0; // mimic a \textfont radical
 8987    } else if (height < 1.4) {
 8988      sizeMultiplier = 0.7; // mimic a \scriptfont radical
 8989    }
 8990
 8991    spanHeight = (1.0 + extraViniculum + emPad) / sizeMultiplier;
 8992    texHeight = (1.00 + extraViniculum) / sizeMultiplier;
 8993    span = sqrtSvg("sqrtMain", spanHeight, viewBoxHeight, extraViniculum, options);
 8994    span.style.minWidth = "0.853em";
 8995    advanceWidth = 0.833 / sizeMultiplier; // from the font.
 8996  } else if (delim.type === "large") {
 8997    // These SVGs come from fonts: KaTeX_Size1, _Size2, etc.
 8998    viewBoxHeight = (1000 + vbPad) * sizeToMaxHeight[delim.size];
 8999    texHeight = (sizeToMaxHeight[delim.size] + extraViniculum) / sizeMultiplier;
 9000    spanHeight = (sizeToMaxHeight[delim.size] + extraViniculum + emPad) / sizeMultiplier;
 9001    span = sqrtSvg("sqrtSize" + delim.size, spanHeight, viewBoxHeight, extraViniculum, options);
 9002    span.style.minWidth = "1.02em";
 9003    advanceWidth = 1.0 / sizeMultiplier; // 1.0 from the font.
 9004  } else {
 9005    // Tall sqrt. In TeX, this would be stacked using multiple glyphs.
 9006    // We'll use a single SVG to accomplish the same thing.
 9007    spanHeight = height + extraViniculum + emPad;
 9008    texHeight = height + extraViniculum;
 9009    viewBoxHeight = Math.floor(1000 * height + extraViniculum) + vbPad;
 9010    span = sqrtSvg("sqrtTall", spanHeight, viewBoxHeight, extraViniculum, options);
 9011    span.style.minWidth = "0.742em";
 9012    advanceWidth = 1.056;
 9013  }
 9014
 9015  span.height = texHeight;
 9016  span.style.height = makeEm(spanHeight);
 9017  return {
 9018    span,
 9019    advanceWidth,
 9020    // Calculate the actual line width.
 9021    // This actually should depend on the chosen font -- e.g. \boldmath
 9022    // should use the thicker surd symbols from e.g. KaTeX_Main-Bold, and
 9023    // have thicker rules.
 9024    ruleWidth: (options.fontMetrics().sqrtRuleThickness + extraViniculum) * sizeMultiplier
 9025  };
 9026}; // There are three kinds of delimiters, delimiters that stack when they become
 9027// too large
 9028
 9029
 9030var stackLargeDelimiters = ["(", "\\lparen", ")", "\\rparen", "[", "\\lbrack", "]", "\\rbrack", "\\{", "\\lbrace", "\\}", "\\rbrace", "\\lfloor", "\\rfloor", "\u230a", "\u230b", "\\lceil", "\\rceil", "\u2308", "\u2309", "\\surd"]; // delimiters that always stack
 9031
 9032var 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
 9033
 9034var stackNeverDelimiters = ["<", ">", "\\langle", "\\rangle", "/", "\\backslash", "\\lt", "\\gt"]; // Metrics of the different sizes. Found by looking at TeX's output of
 9035// $\bigl| // \Bigl| \biggl| \Biggl| \showlists$
 9036// Used to create stacked delimiters of appropriate sizes in makeSizedDelim.
 9037
 9038var sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0];
 9039/**
 9040 * Used to create a delimiter of a specific size, where `size` is 1, 2, 3, or 4.
 9041 */
 9042
 9043var makeSizedDelim = function makeSizedDelim(delim, size, options, mode, classes) {
 9044  // < and > turn into \langle and \rangle in delimiters
 9045  if (delim === "<" || delim === "\\lt" || delim === "\u27e8") {
 9046    delim = "\\langle";
 9047  } else if (delim === ">" || delim === "\\gt" || delim === "\u27e9") {
 9048    delim = "\\rangle";
 9049  } // Sized delimiters are never centered.
 9050
 9051
 9052  if (utils.contains(stackLargeDelimiters, delim) || utils.contains(stackNeverDelimiters, delim)) {
 9053    return makeLargeDelim(delim, size, false, options, mode, classes);
 9054  } else if (utils.contains(stackAlwaysDelimiters, delim)) {
 9055    return makeStackedDelim(delim, sizeToMaxHeight[size], false, options, mode, classes);
 9056  } else {
 9057    throw new ParseError("Illegal delimiter: '" + delim + "'");
 9058  }
 9059};
 9060/**
 9061 * There are three different sequences of delimiter sizes that the delimiters
 9062 * follow depending on the kind of delimiter. This is used when creating custom
 9063 * sized delimiters to decide whether to create a small, large, or stacked
 9064 * delimiter.
 9065 *
 9066 * In real TeX, these sequences aren't explicitly defined, but are instead
 9067 * defined inside the font metrics. Since there are only three sequences that
 9068 * are possible for the delimiters that TeX defines, it is easier to just encode
 9069 * them explicitly here.
 9070 */
 9071
 9072
 9073// Delimiters that never stack try small delimiters and large delimiters only
 9074var stackNeverDelimiterSequence = [{
 9075  type: "small",
 9076  style: Style$1.SCRIPTSCRIPT
 9077}, {
 9078  type: "small",
 9079  style: Style$1.SCRIPT
 9080}, {
 9081  type: "small",
 9082  style: Style$1.TEXT
 9083}, {
 9084  type: "large",
 9085  size: 1
 9086}, {
 9087  type: "large",
 9088  size: 2
 9089}, {
 9090  type: "large",
 9091  size: 3
 9092}, {
 9093  type: "large",
 9094  size: 4
 9095}]; // Delimiters that always stack try the small delimiters first, then stack
 9096
 9097var stackAlwaysDelimiterSequence = [{
 9098  type: "small",
 9099  style: Style$1.SCRIPTSCRIPT
 9100}, {
 9101  type: "small",
 9102  style: Style$1.SCRIPT
 9103}, {
 9104  type: "small",
 9105  style: Style$1.TEXT
 9106}, {
 9107  type: "stack"
 9108}]; // Delimiters that stack when large try the small and then large delimiters, and
 9109// stack afterwards
 9110
 9111var stackLargeDelimiterSequence = [{
 9112  type: "small",
 9113  style: Style$1.SCRIPTSCRIPT
 9114}, {
 9115  type: "small",
 9116  style: Style$1.SCRIPT
 9117}, {
 9118  type: "small",
 9119  style: Style$1.TEXT
 9120}, {
 9121  type: "large",
 9122  size: 1
 9123}, {
 9124  type: "large",
 9125  size: 2
 9126}, {
 9127  type: "large",
 9128  size: 3
 9129}, {
 9130  type: "large",
 9131  size: 4
 9132}, {
 9133  type: "stack"
 9134}];
 9135/**
 9136 * Get the font used in a delimiter based on what kind of delimiter it is.
 9137 * TODO(#963) Use more specific font family return type once that is introduced.
 9138 */
 9139
 9140var delimTypeToFont = function delimTypeToFont(type) {
 9141  if (type.type === "small") {
 9142    return "Main-Regular";
 9143  } else if (type.type === "large") {
 9144    return "Size" + type.size + "-Regular";
 9145  } else if (type.type === "stack") {
 9146    return "Size4-Regular";
 9147  } else {
 9148    throw new Error("Add support for delim type '" + type.type + "' here.");
 9149  }
 9150};
 9151/**
 9152 * Traverse a sequence of types of delimiters to decide what kind of delimiter
 9153 * should be used to create a delimiter of the given height+depth.
 9154 */
 9155
 9156
 9157var traverseSequence = function traverseSequence(delim, height, sequence, options) {
 9158  // Here, we choose the index we should start at in the sequences. In smaller
 9159  // sizes (which correspond to larger numbers in style.size) we start earlier
 9160  // in the sequence. Thus, scriptscript starts at index 3-3=0, script starts
 9161  // at index 3-2=1, text starts at 3-1=2, and display starts at min(2,3-0)=2
 9162  var start = Math.min(2, 3 - options.style.size);
 9163
 9164  for (var i = start; i < sequence.length; i++) {
 9165    if (sequence[i].type === "stack") {
 9166      // This is always the last delimiter, so we just break the loop now.
 9167      break;
 9168    }
 9169
 9170    var metrics = getMetrics(delim, delimTypeToFont(sequence[i]), "math");
 9171    var heightDepth = metrics.height + metrics.depth; // Small delimiters are scaled down versions of the same font, so we
 9172    // account for the style change size.
 9173
 9174    if (sequence[i].type === "small") {
 9175      var newOptions = options.havingBaseStyle(sequence[i].style);
 9176      heightDepth *= newOptions.sizeMultiplier;
 9177    } // Check if the delimiter at this size works for the given height.
 9178
 9179
 9180    if (heightDepth > height) {
 9181      return sequence[i];
 9182    }
 9183  } // If we reached the end of the sequence, return the last sequence element.
 9184
 9185
 9186  return sequence[sequence.length - 1];
 9187};
 9188/**
 9189 * Make a delimiter of a given height+depth, with optional centering. Here, we
 9190 * traverse the sequences, and create a delimiter that the sequence tells us to.
 9191 */
 9192
 9193
 9194var makeCustomSizedDelim = function makeCustomSizedDelim(delim, height, center, options, mode, classes) {
 9195  if (delim === "<" || delim === "\\lt" || delim === "\u27e8") {
 9196    delim = "\\langle";
 9197  } else if (delim === ">" || delim === "\\gt" || delim === "\u27e9") {
 9198    delim = "\\rangle";
 9199  } // Decide what sequence to use
 9200
 9201
 9202  var sequence;
 9203
 9204  if (utils.contains(stackNeverDelimiters, delim)) {
 9205    sequence = stackNeverDelimiterSequence;
 9206  } else if (utils.contains(stackLargeDelimiters, delim)) {
 9207    sequence = stackLargeDelimiterSequence;
 9208  } else {
 9209    sequence = stackAlwaysDelimiterSequence;
 9210  } // Look through the sequence
 9211
 9212
 9213  var delimType = traverseSequence(delim, height, sequence, options); // Get the delimiter from font glyphs.
 9214  // Depending on the sequence element we decided on, call the
 9215  // appropriate function.
 9216
 9217  if (delimType.type === "small") {
 9218    return makeSmallDelim(delim, delimType.style, center, options, mode, classes);
 9219  } else if (delimType.type === "large") {
 9220    return makeLargeDelim(delim, delimType.size, center, options, mode, classes);
 9221  } else
 9222    /* if (delimType.type === "stack") */
 9223    {
 9224      return makeStackedDelim(delim, height, center, options, mode, classes);
 9225    }
 9226};
 9227/**
 9228 * Make a delimiter for use with `\left` and `\right`, given a height and depth
 9229 * of an expression that the delimiters surround.
 9230 */
 9231
 9232
 9233var makeLeftRightDelim = function makeLeftRightDelim(delim, height, depth, options, mode, classes) {
 9234  // We always center \left/\right delimiters, so the axis is always shifted
 9235  var axisHeight = options.fontMetrics().axisHeight * options.sizeMultiplier; // Taken from TeX source, tex.web, function make_left_right
 9236
 9237  var delimiterFactor = 901;
 9238  var delimiterExtend = 5.0 / options.fontMetrics().ptPerEm;
 9239  var maxDistFromAxis = Math.max(height - axisHeight, depth + axisHeight);
 9240  var totalHeight = Math.max( // In real TeX, calculations are done using integral values which are
 9241  // 65536 per pt, or 655360 per em. So, the division here truncates in
 9242  // TeX but doesn't here, producing different results. If we wanted to
 9243  // exactly match TeX's calculation, we could do
 9244  //   Math.floor(655360 * maxDistFromAxis / 500) *
 9245  //    delimiterFactor / 655360
 9246  // (To see the difference, compare
 9247  //    x^{x^{\left(\rule{0.1em}{0.68em}\right)}}
 9248  // in TeX and KaTeX)
 9249  maxDistFromAxis / 500 * delimiterFactor, 2 * maxDistFromAxis - delimiterExtend); // Finally, we defer to `makeCustomSizedDelim` with our calculated total
 9250  // height
 9251
 9252  return makeCustomSizedDelim(delim, totalHeight, true, options, mode, classes);
 9253};
 9254
 9255var delimiter = {
 9256  sqrtImage: makeSqrtImage,
 9257  sizedDelim: makeSizedDelim,
 9258  sizeToMaxHeight: sizeToMaxHeight,
 9259  customSizedDelim: makeCustomSizedDelim,
 9260  leftRightDelim: makeLeftRightDelim
 9261};
 9262
 9263// Extra data needed for the delimiter handler down below
 9264var delimiterSizes = {
 9265  "\\bigl": {
 9266    mclass: "mopen",
 9267    size: 1
 9268  },
 9269  "\\Bigl": {
 9270    mclass: "mopen",
 9271    size: 2
 9272  },
 9273  "\\biggl": {
 9274    mclass: "mopen",
 9275    size: 3
 9276  },
 9277  "\\Biggl": {
 9278    mclass: "mopen",
 9279    size: 4
 9280  },
 9281  "\\bigr": {
 9282    mclass: "mclose",
 9283    size: 1
 9284  },
 9285  "\\Bigr": {
 9286    mclass: "mclose",
 9287    size: 2
 9288  },
 9289  "\\biggr": {
 9290    mclass: "mclose",
 9291    size: 3
 9292  },
 9293  "\\Biggr": {
 9294    mclass: "mclose",
 9295    size: 4
 9296  },
 9297  "\\bigm": {
 9298    mclass: "mrel",
 9299    size: 1
 9300  },
 9301  "\\Bigm": {
 9302    mclass: "mrel",
 9303    size: 2
 9304  },
 9305  "\\biggm": {
 9306    mclass: "mrel",
 9307    size: 3
 9308  },
 9309  "\\Biggm": {
 9310    mclass: "mrel",
 9311    size: 4
 9312  },
 9313  "\\big": {
 9314    mclass: "mord",
 9315    size: 1
 9316  },
 9317  "\\Big": {
 9318    mclass: "mord",
 9319    size: 2
 9320  },
 9321  "\\bigg": {
 9322    mclass: "mord",
 9323    size: 3
 9324  },
 9325  "\\Bigg": {
 9326    mclass: "mord",
 9327    size: 4
 9328  }
 9329};
 9330var 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", "."];
 9331
 9332// Delimiter functions
 9333function checkDelimiter(delim, context) {
 9334  var symDelim = checkSymbolNodeType(delim);
 9335
 9336  if (symDelim && utils.contains(delimiters, symDelim.text)) {
 9337    return symDelim;
 9338  } else if (symDelim) {
 9339    throw new ParseError("Invalid delimiter '" + symDelim.text + "' after '" + context.funcName + "'", delim);
 9340  } else {
 9341    throw new ParseError("Invalid delimiter type '" + delim.type + "'", delim);
 9342  }
 9343}
 9344
 9345defineFunction({
 9346  type: "delimsizing",
 9347  names: ["\\bigl", "\\Bigl", "\\biggl", "\\Biggl", "\\bigr", "\\Bigr", "\\biggr", "\\Biggr", "\\bigm", "\\Bigm", "\\biggm", "\\Biggm", "\\big", "\\Big", "\\bigg", "\\Bigg"],
 9348  props: {
 9349    numArgs: 1,
 9350    argTypes: ["primitive"]
 9351  },
 9352  handler: (context, args) => {
 9353    var delim = checkDelimiter(args[0], context);
 9354    return {
 9355      type: "delimsizing",
 9356      mode: context.parser.mode,
 9357      size: delimiterSizes[context.funcName].size,
 9358      mclass: delimiterSizes[context.funcName].mclass,
 9359      delim: delim.text
 9360    };
 9361  },
 9362  htmlBuilder: (group, options) => {
 9363    if (group.delim === ".") {
 9364      // Empty delimiters still count as elements, even though they don't
 9365      // show anything.
 9366      return buildCommon.makeSpan([group.mclass]);
 9367    } // Use delimiter.sizedDelim to generate the delimiter.
 9368
 9369
 9370    return delimiter.sizedDelim(group.delim, group.size, options, group.mode, [group.mclass]);
 9371  },
 9372  mathmlBuilder: group => {
 9373    var children = [];
 9374
 9375    if (group.delim !== ".") {
 9376      children.push(makeText(group.delim, group.mode));
 9377    }
 9378
 9379    var node = new mathMLTree.MathNode("mo", children);
 9380
 9381    if (group.mclass === "mopen" || group.mclass === "mclose") {
 9382      // Only some of the delimsizing functions act as fences, and they
 9383      // return "mopen" or "mclose" mclass.
 9384      node.setAttribute("fence", "true");
 9385    } else {
 9386      // Explicitly disable fencing if it's not a fence, to override the
 9387      // defaults.
 9388      node.setAttribute("fence", "false");
 9389    }
 9390
 9391    node.setAttribute("stretchy", "true");
 9392    var size = makeEm(delimiter.sizeToMaxHeight[group.size]);
 9393    node.setAttribute("minsize", size);
 9394    node.setAttribute("maxsize", size);
 9395    return node;
 9396  }
 9397});
 9398
 9399function assertParsed(group) {
 9400  if (!group.body) {
 9401    throw new Error("Bug: The leftright ParseNode wasn't fully parsed.");
 9402  }
 9403}
 9404
 9405defineFunction({
 9406  type: "leftright-right",
 9407  names: ["\\right"],
 9408  props: {
 9409    numArgs: 1,
 9410    primitive: true
 9411  },
 9412  handler: (context, args) => {
 9413    // \left case below triggers parsing of \right in
 9414    //   `const right = parser.parseFunction();`
 9415    // uses this return value.
 9416    var color = context.parser.gullet.macros.get("\\current@color");
 9417
 9418    if (color && typeof color !== "string") {
 9419      throw new ParseError("\\current@color set to non-string in \\right");
 9420    }
 9421
 9422    return {
 9423      type: "leftright-right",
 9424      mode: context.parser.mode,
 9425      delim: checkDelimiter(args[0], context).text,
 9426      color // undefined if not set via \color
 9427
 9428    };
 9429  }
 9430});
 9431defineFunction({
 9432  type: "leftright",
 9433  names: ["\\left"],
 9434  props: {
 9435    numArgs: 1,
 9436    primitive: true
 9437  },
 9438  handler: (context, args) => {
 9439    var delim = checkDelimiter(args[0], context);
 9440    var parser = context.parser; // Parse out the implicit body
 9441
 9442    ++parser.leftrightDepth; // parseExpression stops before '\\right'
 9443
 9444    var body = parser.parseExpression(false);
 9445    --parser.leftrightDepth; // Check the next token
 9446
 9447    parser.expect("\\right", false);
 9448    var right = assertNodeType(parser.parseFunction(), "leftright-right");
 9449    return {
 9450      type: "leftright",
 9451      mode: parser.mode,
 9452      body,
 9453      left: delim.text,
 9454      right: right.delim,
 9455      rightColor: right.color
 9456    };
 9457  },
 9458  htmlBuilder: (group, options) => {
 9459    assertParsed(group); // Build the inner expression
 9460
 9461    var inner = buildExpression$1(group.body, options, true, ["mopen", "mclose"]);
 9462    var innerHeight = 0;
 9463    var innerDepth = 0;
 9464    var hadMiddle = false; // Calculate its height and depth
 9465
 9466    for (var i = 0; i < inner.length; i++) {
 9467      // Property `isMiddle` not defined on `span`. See comment in
 9468      // "middle"'s htmlBuilder.
 9469      // $FlowFixMe
 9470      if (inner[i].isMiddle) {
 9471        hadMiddle = true;
 9472      } else {
 9473        innerHeight = Math.max(inner[i].height, innerHeight);
 9474        innerDepth = Math.max(inner[i].depth, innerDepth);
 9475      }
 9476    } // The size of delimiters is the same, regardless of what style we are
 9477    // in. Thus, to correctly calculate the size of delimiter we need around
 9478    // a group, we scale down the inner size based on the size.
 9479
 9480
 9481    innerHeight *= options.sizeMultiplier;
 9482    innerDepth *= options.sizeMultiplier;
 9483    var leftDelim;
 9484
 9485    if (group.left === ".") {
 9486      // Empty delimiters in \left and \right make null delimiter spaces.
 9487      leftDelim = makeNullDelimiter(options, ["mopen"]);
 9488    } else {
 9489      // Otherwise, use leftRightDelim to generate the correct sized
 9490      // delimiter.
 9491      leftDelim = delimiter.leftRightDelim(group.left, innerHeight, innerDepth, options, group.mode, ["mopen"]);
 9492    } // Add it to the beginning of the expression
 9493
 9494
 9495    inner.unshift(leftDelim); // Handle middle delimiters
 9496
 9497    if (hadMiddle) {
 9498      for (var _i = 1; _i < inner.length; _i++) {
 9499        var middleDelim = inner[_i]; // Property `isMiddle` not defined on `span`. See comment in
 9500        // "middle"'s htmlBuilder.
 9501        // $FlowFixMe
 9502
 9503        var isMiddle = middleDelim.isMiddle;
 9504
 9505        if (isMiddle) {
 9506          // Apply the options that were active when \middle was called
 9507          inner[_i] = delimiter.leftRightDelim(isMiddle.delim, innerHeight, innerDepth, isMiddle.options, group.mode, []);
 9508        }
 9509      }
 9510    }
 9511
 9512    var rightDelim; // Same for the right delimiter, but using color specified by \color
 9513
 9514    if (group.right === ".") {
 9515      rightDelim = makeNullDelimiter(options, ["mclose"]);
 9516    } else {
 9517      var colorOptions = group.rightColor ? options.withColor(group.rightColor) : options;
 9518      rightDelim = delimiter.leftRightDelim(group.right, innerHeight, innerDepth, colorOptions, group.mode, ["mclose"]);
 9519    } // Add it to the end of the expression.
 9520
 9521
 9522    inner.push(rightDelim);
 9523    return buildCommon.makeSpan(["minner"], inner, options);
 9524  },
 9525  mathmlBuilder: (group, options) => {
 9526    assertParsed(group);
 9527    var inner = buildExpression(group.body, options);
 9528
 9529    if (group.left !== ".") {
 9530      var leftNode = new mathMLTree.MathNode("mo", [makeText(group.left, group.mode)]);
 9531      leftNode.setAttribute("fence", "true");
 9532      inner.unshift(leftNode);
 9533    }
 9534
 9535    if (group.right !== ".") {
 9536      var rightNode = new mathMLTree.MathNode("mo", [makeText(group.right, group.mode)]);
 9537      rightNode.setAttribute("fence", "true");
 9538
 9539      if (group.rightColor) {
 9540        rightNode.setAttribute("mathcolor", group.rightColor);
 9541      }
 9542
 9543      inner.push(rightNode);
 9544    }
 9545
 9546    return makeRow(inner);
 9547  }
 9548});
 9549defineFunction({
 9550  type: "middle",
 9551  names: ["\\middle"],
 9552  props: {
 9553    numArgs: 1,
 9554    primitive: true
 9555  },
 9556  handler: (context, args) => {
 9557    var delim = checkDelimiter(args[0], context);
 9558
 9559    if (!context.parser.leftrightDepth) {
 9560      throw new ParseError("\\middle without preceding \\left", delim);
 9561    }
 9562
 9563    return {
 9564      type: "middle",
 9565      mode: context.parser.mode,
 9566      delim: delim.text
 9567    };
 9568  },
 9569  htmlBuilder: (group, options) => {
 9570    var middleDelim;
 9571
 9572    if (group.delim === ".") {
 9573      middleDelim = makeNullDelimiter(options, []);
 9574    } else {
 9575      middleDelim = delimiter.sizedDelim(group.delim, 1, options, group.mode, []);
 9576      var isMiddle = {
 9577        delim: group.delim,
 9578        options
 9579      }; // Property `isMiddle` not defined on `span`. It is only used in
 9580      // this file above.
 9581      // TODO: Fix this violation of the `span` type and possibly rename
 9582      // things since `isMiddle` sounds like a boolean, but is a struct.
 9583      // $FlowFixMe
 9584
 9585      middleDelim.isMiddle = isMiddle;
 9586    }
 9587
 9588    return middleDelim;
 9589  },
 9590  mathmlBuilder: (group, options) => {
 9591    // A Firefox \middle will strech a character vertically only if it
 9592    // is in the fence part of the operator dictionary at:
 9593    // https://www.w3.org/TR/MathML3/appendixc.html.
 9594    // So we need to avoid U+2223 and use plain "|" instead.
 9595    var textNode = group.delim === "\\vert" || group.delim === "|" ? makeText("|", "text") : makeText(group.delim, group.mode);
 9596    var middleNode = new mathMLTree.MathNode("mo", [textNode]);
 9597    middleNode.setAttribute("fence", "true"); // MathML gives 5/18em spacing to each <mo> element.
 9598    // \middle should get delimiter spacing instead.
 9599
 9600    middleNode.setAttribute("lspace", "0.05em");
 9601    middleNode.setAttribute("rspace", "0.05em");
 9602    return middleNode;
 9603  }
 9604});
 9605
 9606var htmlBuilder$8 = (group, options) => {
 9607  // \cancel, \bcancel, \xcancel, \sout, \fbox, \colorbox, \fcolorbox, \phase
 9608  // Some groups can return document fragments.  Handle those by wrapping
 9609  // them in a span.
 9610  var inner = buildCommon.wrapFragment(buildGroup$1(group.body, options), options);
 9611  var label = group.label.substr(1);
 9612  var scale = options.sizeMultiplier;
 9613  var img;
 9614  var imgShift = 0; // In the LaTeX cancel package, line geometry is slightly different
 9615  // depending on whether the subject is wider than it is tall, or vice versa.
 9616  // We don't know the width of a group, so as a proxy, we test if
 9617  // the subject is a single character. This captures most of the
 9618  // subjects that should get the "tall" treatment.
 9619
 9620  var isSingleChar = utils.isCharacterBox(group.body);
 9621
 9622  if (label === "sout") {
 9623    img = buildCommon.makeSpan(["stretchy", "sout"]);
 9624    img.height = options.fontMetrics().defaultRuleThickness / scale;
 9625    imgShift = -0.5 * options.fontMetrics().xHeight;
 9626  } else if (label === "phase") {
 9627    // Set a couple of dimensions from the steinmetz package.
 9628    var lineWeight = calculateSize({
 9629      number: 0.6,
 9630      unit: "pt"
 9631    }, options);
 9632    var clearance = calculateSize({
 9633      number: 0.35,
 9634      unit: "ex"
 9635    }, options); // Prevent size changes like \Huge from affecting line thickness
 9636
 9637    var newOptions = options.havingBaseSizing();
 9638    scale = scale / newOptions.sizeMultiplier;
 9639    var angleHeight = inner.height + inner.depth + lineWeight + clearance; // Reserve a left pad for the angle.
 9640
 9641    inner.style.paddingLeft = makeEm(angleHeight / 2 + lineWeight); // Create an SVG
 9642
 9643    var viewBoxHeight = Math.floor(1000 * angleHeight * scale);
 9644    var path = phasePath(viewBoxHeight);
 9645    var svgNode = new SvgNode([new PathNode("phase", path)], {
 9646      "width": "400em",
 9647      "height": makeEm(viewBoxHeight / 1000),
 9648      "viewBox": "0 0 400000 " + viewBoxHeight,
 9649      "preserveAspectRatio": "xMinYMin slice"
 9650    }); // Wrap it in a span with overflow: hidden.
 9651
 9652    img = buildCommon.makeSvgSpan(["hide-tail"], [svgNode], options);
 9653    img.style.height = makeEm(angleHeight);
 9654    imgShift = inner.depth + lineWeight + clearance;
 9655  } else {
 9656    // Add horizontal padding
 9657    if (/cancel/.test(label)) {
 9658      if (!isSingleChar) {
 9659        inner.classes.push("cancel-pad");
 9660      }
 9661    } else if (label === "angl") {
 9662      inner.classes.push("anglpad");
 9663    } else {
 9664      inner.classes.push("boxpad");
 9665    } // Add vertical padding
 9666
 9667
 9668    var topPad = 0;
 9669    var bottomPad = 0;
 9670    var ruleThickness = 0; // ref: cancel package: \advance\totalheight2\p@ % "+2"
 9671
 9672    if (/box/.test(label)) {
 9673      ruleThickness = Math.max(options.fontMetrics().fboxrule, // default
 9674      options.minRuleThickness // User override.
 9675      );
 9676      topPad = options.fontMetrics().fboxsep + (label === "colorbox" ? 0 : ruleThickness);
 9677      bottomPad = topPad;
 9678    } else if (label === "angl") {
 9679      ruleThickness = Math.max(options.fontMetrics().defaultRuleThickness, options.minRuleThickness);
 9680      topPad = 4 * ruleThickness; // gap = 3 × line, plus the line itself.
 9681
 9682      bottomPad = Math.max(0, 0.25 - inner.depth);
 9683    } else {
 9684      topPad = isSingleChar ? 0.2 : 0;
 9685      bottomPad = topPad;
 9686    }
 9687
 9688    img = stretchy.encloseSpan(inner, label, topPad, bottomPad, options);
 9689
 9690    if (/fbox|boxed|fcolorbox/.test(label)) {
 9691      img.style.borderStyle = "solid";
 9692      img.style.borderWidth = makeEm(ruleThickness);
 9693    } else if (label === "angl" && ruleThickness !== 0.049) {
 9694      img.style.borderTopWidth = makeEm(ruleThickness);
 9695      img.style.borderRightWidth = makeEm(ruleThickness);
 9696    }
 9697
 9698    imgShift = inner.depth + bottomPad;
 9699
 9700    if (group.backgroundColor) {
 9701      img.style.backgroundColor = group.backgroundColor;
 9702
 9703      if (group.borderColor) {
 9704        img.style.borderColor = group.borderColor;
 9705      }
 9706    }
 9707  }
 9708
 9709  var vlist;
 9710
 9711  if (group.backgroundColor) {
 9712    vlist = buildCommon.makeVList({
 9713      positionType: "individualShift",
 9714      children: [// Put the color background behind inner;
 9715      {
 9716        type: "elem",
 9717        elem: img,
 9718        shift: imgShift
 9719      }, {
 9720        type: "elem",
 9721        elem: inner,
 9722        shift: 0
 9723      }]
 9724    }, options);
 9725  } else {
 9726    var classes = /cancel|phase/.test(label) ? ["svg-align"] : [];
 9727    vlist = buildCommon.makeVList({
 9728      positionType: "individualShift",
 9729      children: [// Write the \cancel stroke on top of inner.
 9730      {
 9731        type: "elem",
 9732        elem: inner,
 9733        shift: 0
 9734      }, {
 9735        type: "elem",
 9736        elem: img,
 9737        shift: imgShift,
 9738        wrapperClasses: classes
 9739      }]
 9740    }, options);
 9741  }
 9742
 9743  if (/cancel/.test(label)) {
 9744    // The cancel package documentation says that cancel lines add their height
 9745    // to the expression, but tests show that isn't how it actually works.
 9746    vlist.height = inner.height;
 9747    vlist.depth = inner.depth;
 9748  }
 9749
 9750  if (/cancel/.test(label) && !isSingleChar) {
 9751    // cancel does not create horiz space for its line extension.
 9752    return buildCommon.makeSpan(["mord", "cancel-lap"], [vlist], options);
 9753  } else {
 9754    return buildCommon.makeSpan(["mord"], [vlist], options);
 9755  }
 9756};
 9757
 9758var mathmlBuilder$7 = (group, options) => {
 9759  var fboxsep = 0;
 9760  var node = new mathMLTree.MathNode(group.label.indexOf("colorbox") > -1 ? "mpadded" : "menclose", [buildGroup(group.body, options)]);
 9761
 9762  switch (group.label) {
 9763    case "\\cancel":
 9764      node.setAttribute("notation", "updiagonalstrike");
 9765      break;
 9766
 9767    case "\\bcancel":
 9768      node.setAttribute("notation", "downdiagonalstrike");
 9769      break;
 9770
 9771    case "\\phase":
 9772      node.setAttribute("notation", "phasorangle");
 9773      break;
 9774
 9775    case "\\sout":
 9776      node.setAttribute("notation", "horizontalstrike");
 9777      break;
 9778
 9779    case "\\fbox":
 9780      node.setAttribute("notation", "box");
 9781      break;
 9782
 9783    case "\\angl":
 9784      node.setAttribute("notation", "actuarial");
 9785      break;
 9786
 9787    case "\\fcolorbox":
 9788    case "\\colorbox":
 9789      // <menclose> doesn't have a good notation option. So use <mpadded>
 9790      // instead. Set some attributes that come included with <menclose>.
 9791      fboxsep = options.fontMetrics().fboxsep * options.fontMetrics().ptPerEm;
 9792      node.setAttribute("width", "+" + 2 * fboxsep + "pt");
 9793      node.setAttribute("height", "+" + 2 * fboxsep + "pt");
 9794      node.setAttribute("lspace", fboxsep + "pt"); //
 9795
 9796      node.setAttribute("voffset", fboxsep + "pt");
 9797
 9798      if (group.label === "\\fcolorbox") {
 9799        var thk = Math.max(options.fontMetrics().fboxrule, // default
 9800        options.minRuleThickness // user override
 9801        );
 9802        node.setAttribute("style", "border: " + thk + "em solid " + String(group.borderColor));
 9803      }
 9804
 9805      break;
 9806
 9807    case "\\xcancel":
 9808      node.setAttribute("notation", "updiagonalstrike downdiagonalstrike");
 9809      break;
 9810  }
 9811
 9812  if (group.backgroundColor) {
 9813    node.setAttribute("mathbackground", group.backgroundColor);
 9814  }
 9815
 9816  return node;
 9817};
 9818
 9819defineFunction({
 9820  type: "enclose",
 9821  names: ["\\colorbox"],
 9822  props: {
 9823    numArgs: 2,
 9824    allowedInText: true,
 9825    argTypes: ["color", "text"]
 9826  },
 9827
 9828  handler(_ref, args, optArgs) {
 9829    var {
 9830      parser,
 9831      funcName
 9832    } = _ref;
 9833    var color = assertNodeType(args[0], "color-token").color;
 9834    var body = args[1];
 9835    return {
 9836      type: "enclose",
 9837      mode: parser.mode,
 9838      label: funcName,
 9839      backgroundColor: color,
 9840      body
 9841    };
 9842  },
 9843
 9844  htmlBuilder: htmlBuilder$8,
 9845  mathmlBuilder: mathmlBuilder$7
 9846});
 9847defineFunction({
 9848  type: "enclose",
 9849  names: ["\\fcolorbox"],
 9850  props: {
 9851    numArgs: 3,
 9852    allowedInText: true,
 9853    argTypes: ["color", "color", "text"]
 9854  },
 9855
 9856  handler(_ref2, args, optArgs) {
 9857    var {
 9858      parser,
 9859      funcName
 9860    } = _ref2;
 9861    var borderColor = assertNodeType(args[0], "color-token").color;
 9862    var backgroundColor = assertNodeType(args[1], "color-token").color;
 9863    var body = args[2];
 9864    return {
 9865      type: "enclose",
 9866      mode: parser.mode,
 9867      label: funcName,
 9868      backgroundColor,
 9869      borderColor,
 9870      body
 9871    };
 9872  },
 9873
 9874  htmlBuilder: htmlBuilder$8,
 9875  mathmlBuilder: mathmlBuilder$7
 9876});
 9877defineFunction({
 9878  type: "enclose",
 9879  names: ["\\fbox"],
 9880  props: {
 9881    numArgs: 1,
 9882    argTypes: ["hbox"],
 9883    allowedInText: true
 9884  },
 9885
 9886  handler(_ref3, args) {
 9887    var {
 9888      parser
 9889    } = _ref3;
 9890    return {
 9891      type: "enclose",
 9892      mode: parser.mode,
 9893      label: "\\fbox",
 9894      body: args[0]
 9895    };
 9896  }
 9897
 9898});
 9899defineFunction({
 9900  type: "enclose",
 9901  names: ["\\cancel", "\\bcancel", "\\xcancel", "\\sout", "\\phase"],
 9902  props: {
 9903    numArgs: 1
 9904  },
 9905
 9906  handler(_ref4, args) {
 9907    var {
 9908      parser,
 9909      funcName
 9910    } = _ref4;
 9911    var body = args[0];
 9912    return {
 9913      type: "enclose",
 9914      mode: parser.mode,
 9915      label: funcName,
 9916      body
 9917    };
 9918  },
 9919
 9920  htmlBuilder: htmlBuilder$8,
 9921  mathmlBuilder: mathmlBuilder$7
 9922});
 9923defineFunction({
 9924  type: "enclose",
 9925  names: ["\\angl"],
 9926  props: {
 9927    numArgs: 1,
 9928    argTypes: ["hbox"],
 9929    allowedInText: false
 9930  },
 9931
 9932  handler(_ref5, args) {
 9933    var {
 9934      parser
 9935    } = _ref5;
 9936    return {
 9937      type: "enclose",
 9938      mode: parser.mode,
 9939      label: "\\angl",
 9940      body: args[0]
 9941    };
 9942  }
 9943
 9944});
 9945
 9946/**
 9947 * All registered environments.
 9948 * `environments.js` exports this same dictionary again and makes it public.
 9949 * `Parser.js` requires this dictionary via `environments.js`.
 9950 */
 9951var _environments = {};
 9952function defineEnvironment(_ref) {
 9953  var {
 9954    type,
 9955    names,
 9956    props,
 9957    handler,
 9958    htmlBuilder,
 9959    mathmlBuilder
 9960  } = _ref;
 9961  // Set default values of environments.
 9962  var data = {
 9963    type,
 9964    numArgs: props.numArgs || 0,
 9965    allowedInText: false,
 9966    numOptionalArgs: 0,
 9967    handler
 9968  };
 9969
 9970  for (var i = 0; i < names.length; ++i) {
 9971    // TODO: The value type of _environments should be a type union of all
 9972    // possible `EnvSpec<>` possibilities instead of `EnvSpec<*>`, which is
 9973    // an existential type.
 9974    _environments[names[i]] = data;
 9975  }
 9976
 9977  if (htmlBuilder) {
 9978    _htmlGroupBuilders[type] = htmlBuilder;
 9979  }
 9980
 9981  if (mathmlBuilder) {
 9982    _mathmlGroupBuilders[type] = mathmlBuilder;
 9983  }
 9984}
 9985
 9986/**
 9987 * All registered global/built-in macros.
 9988 * `macros.js` exports this same dictionary again and makes it public.
 9989 * `Parser.js` requires this dictionary via `macros.js`.
 9990 */
 9991var _macros = {}; // This function might one day accept an additional argument and do more things.
 9992
 9993function defineMacro(name, body) {
 9994  _macros[name] = body;
 9995}
 9996
 9997// Helper functions
 9998function getHLines(parser) {
 9999  // Return an array. The array length = number of hlines.
10000  // Each element in the array tells if the line is dashed.
10001  var hlineInfo = [];
10002  parser.consumeSpaces();
10003  var nxt = parser.fetch().text;
10004
10005  while (nxt === "\\hline" || nxt === "\\hdashline") {
10006    parser.consume();
10007    hlineInfo.push(nxt === "\\hdashline");
10008    parser.consumeSpaces();
10009    nxt = parser.fetch().text;
10010  }
10011
10012  return hlineInfo;
10013}
10014
10015var validateAmsEnvironmentContext = context => {
10016  var settings = context.parser.settings;
10017
10018  if (!settings.displayMode) {
10019    throw new ParseError("{" + context.envName + "} can be used only in" + " display mode.");
10020  }
10021}; // autoTag (an argument to parseArray) can be one of three values:
10022// * undefined: Regular (not-top-level) array; no tags on each row
10023// * true: Automatic equation numbering, overridable by \tag
10024// * false: Tags allowed on each row, but no automatic numbering
10025// This function *doesn't* work with the "split" environment name.
10026
10027
10028function getAutoTag(name) {
10029  if (name.indexOf("ed") === -1) {
10030    return name.indexOf("*") === -1;
10031  } // return undefined;
10032
10033}
10034/**
10035 * Parse the body of the environment, with rows delimited by \\ and
10036 * columns delimited by &, and create a nested list in row-major order
10037 * with one group per cell.  If given an optional argument style
10038 * ("text", "display", etc.), then each cell is cast into that style.
10039 */
10040
10041
10042function parseArray(parser, _ref, style) {
10043  var {
10044    hskipBeforeAndAfter,
10045    addJot,
10046    cols,
10047    arraystretch,
10048    colSeparationType,
10049    autoTag,
10050    singleRow,
10051    emptySingleRow,
10052    maxNumCols,
10053    leqno
10054  } = _ref;
10055  parser.gullet.beginGroup();
10056
10057  if (!singleRow) {
10058    // \cr is equivalent to \\ without the optional size argument (see below)
10059    // TODO: provide helpful error when \cr is used outside array environment
10060    parser.gullet.macros.set("\\cr", "\\\\\\relax");
10061  } // Get current arraystretch if it's not set by the environment
10062
10063
10064  if (!arraystretch) {
10065    var stretch = parser.gullet.expandMacroAsText("\\arraystretch");
10066
10067    if (stretch == null) {
10068      // Default \arraystretch from lttab.dtx
10069      arraystretch = 1;
10070    } else {
10071      arraystretch = parseFloat(stretch);
10072
10073      if (!arraystretch || arraystretch < 0) {
10074        throw new ParseError("Invalid \\arraystretch: " + stretch);
10075      }
10076    }
10077  } // Start group for first cell
10078
10079
10080  parser.gullet.beginGroup();
10081  var row = [];
10082  var body = [row];
10083  var rowGaps = [];
10084  var hLinesBeforeRow = [];
10085  var tags = autoTag != null ? [] : undefined; // amsmath uses \global\@eqnswtrue and \global\@eqnswfalse to represent
10086  // whether this row should have an equation number.  Simulate this with
10087  // a \@eqnsw macro set to 1 or 0.
10088
10089  function beginRow() {
10090    if (autoTag) {
10091      parser.gullet.macros.set("\\@eqnsw", "1", true);
10092    }
10093  }
10094
10095  function endRow() {
10096    if (tags) {
10097      if (parser.gullet.macros.get("\\df@tag")) {
10098        tags.push(parser.subparse([new Token("\\df@tag")]));
10099        parser.gullet.macros.set("\\df@tag", undefined, true);
10100      } else {
10101        tags.push(Boolean(autoTag) && parser.gullet.macros.get("\\@eqnsw") === "1");
10102      }
10103    }
10104  }
10105
10106  beginRow(); // Test for \hline at the top of the array.
10107
10108  hLinesBeforeRow.push(getHLines(parser));
10109
10110  while (true) {
10111    // eslint-disable-line no-constant-condition
10112    // Parse each cell in its own group (namespace)
10113    var cell = parser.parseExpression(false, singleRow ? "\\end" : "\\\\");
10114    parser.gullet.endGroup();
10115    parser.gullet.beginGroup();
10116    cell = {
10117      type: "ordgroup",
10118      mode: parser.mode,
10119      body: cell
10120    };
10121
10122    if (style) {
10123      cell = {
10124        type: "styling",
10125        mode: parser.mode,
10126        style,
10127        body: [cell]
10128      };
10129    }
10130
10131    row.push(cell);
10132    var next = parser.fetch().text;
10133
10134    if (next === "&") {
10135      if (maxNumCols && row.length === maxNumCols) {
10136        if (singleRow || colSeparationType) {
10137          // {equation} or {split}
10138          throw new ParseError("Too many tab characters: &", parser.nextToken);
10139        } else {
10140          // {array} environment
10141          parser.settings.reportNonstrict("textEnv", "Too few columns " + "specified in the {array} column argument.");
10142        }
10143      }
10144
10145      parser.consume();
10146    } else if (next === "\\end") {
10147      endRow(); // Arrays terminate newlines with `\crcr` which consumes a `\cr` if
10148      // the last line is empty.  However, AMS environments keep the
10149      // empty row if it's the only one.
10150      // NOTE: Currently, `cell` is the last item added into `row`.
10151
10152      if (row.length === 1 && cell.type === "styling" && cell.body[0].body.length === 0 && (body.length > 1 || !emptySingleRow)) {
10153        body.pop();
10154      }
10155
10156      if (hLinesBeforeRow.length < body.length + 1) {
10157        hLinesBeforeRow.push([]);
10158      }
10159
10160      break;
10161    } else if (next === "\\\\") {
10162      parser.consume();
10163      var size = void 0; // \def\Let@{\let\\\math@cr}
10164      // \def\math@cr{...\math@cr@}
10165      // \def\math@cr@{\new@ifnextchar[\math@cr@@{\math@cr@@[\z@]}}
10166      // \def\math@cr@@[#1]{...\math@cr@@@...}
10167      // \def\math@cr@@@{\cr}
10168
10169      if (parser.gullet.future().text !== " ") {
10170        size = parser.parseSizeGroup(true);
10171      }
10172
10173      rowGaps.push(size ? size.value : null);
10174      endRow(); // check for \hline(s) following the row separator
10175
10176      hLinesBeforeRow.push(getHLines(parser));
10177      row = [];
10178      body.push(row);
10179      beginRow();
10180    } else {
10181      throw new ParseError("Expected & or \\\\ or \\cr or \\end", parser.nextToken);
10182    }
10183  } // End cell group
10184
10185
10186  parser.gullet.endGroup(); // End array group defining \cr
10187
10188  parser.gullet.endGroup();
10189  return {
10190    type: "array",
10191    mode: parser.mode,
10192    addJot,
10193    arraystretch,
10194    body,
10195    cols,
10196    rowGaps,
10197    hskipBeforeAndAfter,
10198    hLinesBeforeRow,
10199    colSeparationType,
10200    tags,
10201    leqno
10202  };
10203} // Decides on a style for cells in an array according to whether the given
10204// environment name starts with the letter 'd'.
10205
10206
10207function dCellStyle(envName) {
10208  if (envName.substr(0, 1) === "d") {
10209    return "display";
10210  } else {
10211    return "text";
10212  }
10213}
10214
10215var htmlBuilder$7 = function htmlBuilder(group, options) {
10216  var r;
10217  var c;
10218  var nr = group.body.length;
10219  var hLinesBeforeRow = group.hLinesBeforeRow;
10220  var nc = 0;
10221  var body = new Array(nr);
10222  var hlines = [];
10223  var ruleThickness = Math.max( // From LaTeX \showthe\arrayrulewidth. Equals 0.04 em.
10224  options.fontMetrics().arrayRuleWidth, options.minRuleThickness // User override.
10225  ); // Horizontal spacing
10226
10227  var pt = 1 / options.fontMetrics().ptPerEm;
10228  var arraycolsep = 5 * pt; // default value, i.e. \arraycolsep in article.cls
10229
10230  if (group.colSeparationType && group.colSeparationType === "small") {
10231    // We're in a {smallmatrix}. Default column space is \thickspace,
10232    // i.e. 5/18em = 0.2778em, per amsmath.dtx for {smallmatrix}.
10233    // But that needs adjustment because LaTeX applies \scriptstyle to the
10234    // entire array, including the colspace, but this function applies
10235    // \scriptstyle only inside each element.
10236    var localMultiplier = options.havingStyle(Style$1.SCRIPT).sizeMultiplier;
10237    arraycolsep = 0.2778 * (localMultiplier / options.sizeMultiplier);
10238  } // Vertical spacing
10239
10240
10241  var baselineskip = group.colSeparationType === "CD" ? calculateSize({
10242    number: 3,
10243    unit: "ex"
10244  }, options) : 12 * pt; // see size10.clo
10245  // Default \jot from ltmath.dtx
10246  // TODO(edemaine): allow overriding \jot via \setlength (#687)
10247
10248  var jot = 3 * pt;
10249  var arrayskip = group.arraystretch * baselineskip;
10250  var arstrutHeight = 0.7 * arrayskip; // \strutbox in ltfsstrc.dtx and
10251
10252  var arstrutDepth = 0.3 * arrayskip; // \@arstrutbox in lttab.dtx
10253
10254  var totalHeight = 0; // Set a position for \hline(s) at the top of the array, if any.
10255
10256  function setHLinePos(hlinesInGap) {
10257    for (var i = 0; i < hlinesInGap.length; ++i) {
10258      if (i > 0) {
10259        totalHeight += 0.25;
10260      }
10261
10262      hlines.push({
10263        pos: totalHeight,
10264        isDashed: hlinesInGap[i]
10265      });
10266    }
10267  }
10268
10269  setHLinePos(hLinesBeforeRow[0]);
10270
10271  for (r = 0; r < group.body.length; ++r) {
10272    var inrow = group.body[r];
10273    var height = arstrutHeight; // \@array adds an \@arstrut
10274
10275    var depth = arstrutDepth; // to each tow (via the template)
10276
10277    if (nc < inrow.length) {
10278      nc = inrow.length;
10279    }
10280
10281    var outrow = new Array(inrow.length);
10282
10283    for (c = 0; c < inrow.length; ++c) {
10284      var elt = buildGroup$1(inrow[c], options);
10285
10286      if (depth < elt.depth) {
10287        depth = elt.depth;
10288      }
10289
10290      if (height < elt.height) {
10291        height = elt.height;
10292      }
10293
10294      outrow[c] = elt;
10295    }
10296
10297    var rowGap = group.rowGaps[r];
10298    var gap = 0;
10299
10300    if (rowGap) {
10301      gap = calculateSize(rowGap, options);
10302
10303      if (gap > 0) {
10304        // \@argarraycr
10305        gap += arstrutDepth;
10306
10307        if (depth < gap) {
10308          depth = gap; // \@xargarraycr
10309        }
10310
10311        gap = 0;
10312      }
10313    } // In AMS multiline environments such as aligned and gathered, rows
10314    // correspond to lines that have additional \jot added to the
10315    // \baselineskip via \openup.
10316
10317
10318    if (group.addJot) {
10319      depth += jot;
10320    }
10321
10322    outrow.height = height;
10323    outrow.depth = depth;
10324    totalHeight += height;
10325    outrow.pos = totalHeight;
10326    totalHeight += depth + gap; // \@yargarraycr
10327
10328    body[r] = outrow; // Set a position for \hline(s), if any.
10329
10330    setHLinePos(hLinesBeforeRow[r + 1]);
10331  }
10332
10333  var offset = totalHeight / 2 + options.fontMetrics().axisHeight;
10334  var colDescriptions = group.cols || [];
10335  var cols = [];
10336  var colSep;
10337  var colDescrNum;
10338  var tagSpans = [];
10339
10340  if (group.tags && group.tags.some(tag => tag)) {
10341    // An environment with manual tags and/or automatic equation numbers.
10342    // Create node(s), the latter of which trigger CSS counter increment.
10343    for (r = 0; r < nr; ++r) {
10344      var rw = body[r];
10345      var shift = rw.pos - offset;
10346      var tag = group.tags[r];
10347      var tagSpan = void 0;
10348
10349      if (tag === true) {
10350        // automatic numbering
10351        tagSpan = buildCommon.makeSpan(["eqn-num"], [], options);
10352      } else if (tag === false) {
10353        // \nonumber/\notag or starred environment
10354        tagSpan = buildCommon.makeSpan([], [], options);
10355      } else {
10356        // manual \tag
10357        tagSpan = buildCommon.makeSpan([], buildExpression$1(tag, options, true), options);
10358      }
10359
10360      tagSpan.depth = rw.depth;
10361      tagSpan.height = rw.height;
10362      tagSpans.push({
10363        type: "elem",
10364        elem: tagSpan,
10365        shift
10366      });
10367    }
10368  }
10369
10370  for (c = 0, colDescrNum = 0; // Continue while either there are more columns or more column
10371  // descriptions, so trailing separators don't get lost.
10372  c < nc || colDescrNum < colDescriptions.length; ++c, ++colDescrNum) {
10373    var colDescr = colDescriptions[colDescrNum] || {};
10374    var firstSeparator = true;
10375
10376    while (colDescr.type === "separator") {
10377      // If there is more than one separator in a row, add a space
10378      // between them.
10379      if (!firstSeparator) {
10380        colSep = buildCommon.makeSpan(["arraycolsep"], []);
10381        colSep.style.width = makeEm(options.fontMetrics().doubleRuleSep);
10382        cols.push(colSep);
10383      }
10384
10385      if (colDescr.separator === "|" || colDescr.separator === ":") {
10386        var lineType = colDescr.separator === "|" ? "solid" : "dashed";
10387        var separator = buildCommon.makeSpan(["vertical-separator"], [], options);
10388        separator.style.height = makeEm(totalHeight);
10389        separator.style.borderRightWidth = makeEm(ruleThickness);
10390        separator.style.borderRightStyle = lineType;
10391        separator.style.margin = "0 " + makeEm(-ruleThickness / 2);
10392
10393        var _shift = totalHeight - offset;
10394
10395        if (_shift) {
10396          separator.style.verticalAlign = makeEm(-_shift);
10397        }
10398
10399        cols.push(separator);
10400      } else {
10401        throw new ParseError("Invalid separator type: " + colDescr.separator);
10402      }
10403
10404      colDescrNum++;
10405      colDescr = colDescriptions[colDescrNum] || {};
10406      firstSeparator = false;
10407    }
10408
10409    if (c >= nc) {
10410      continue;
10411    }
10412
10413    var sepwidth = void 0;
10414
10415    if (c > 0 || group.hskipBeforeAndAfter) {
10416      sepwidth = utils.deflt(colDescr.pregap, arraycolsep);
10417
10418      if (sepwidth !== 0) {
10419        colSep = buildCommon.makeSpan(["arraycolsep"], []);
10420        colSep.style.width = makeEm(sepwidth);
10421        cols.push(colSep);
10422      }
10423    }
10424
10425    var col = [];
10426
10427    for (r = 0; r < nr; ++r) {
10428      var row = body[r];
10429      var elem = row[c];
10430
10431      if (!elem) {
10432        continue;
10433      }
10434
10435      var _shift2 = row.pos - offset;
10436
10437      elem.depth = row.depth;
10438      elem.height = row.height;
10439      col.push({
10440        type: "elem",
10441        elem: elem,
10442        shift: _shift2
10443      });
10444    }
10445
10446    col = buildCommon.makeVList({
10447      positionType: "individualShift",
10448      children: col
10449    }, options);
10450    col = buildCommon.makeSpan(["col-align-" + (colDescr.align || "c")], [col]);
10451    cols.push(col);
10452
10453    if (c < nc - 1 || group.hskipBeforeAndAfter) {
10454      sepwidth = utils.deflt(colDescr.postgap, arraycolsep);
10455
10456      if (sepwidth !== 0) {
10457        colSep = buildCommon.makeSpan(["arraycolsep"], []);
10458        colSep.style.width = makeEm(sepwidth);
10459        cols.push(colSep);
10460      }
10461    }
10462  }
10463
10464  body = buildCommon.makeSpan(["mtable"], cols); // Add \hline(s), if any.
10465
10466  if (hlines.length > 0) {
10467    var line = buildCommon.makeLineSpan("hline", options, ruleThickness);
10468    var dashes = buildCommon.makeLineSpan("hdashline", options, ruleThickness);
10469    var vListElems = [{
10470      type: "elem",
10471      elem: body,
10472      shift: 0
10473    }];
10474
10475    while (hlines.length > 0) {
10476      var hline = hlines.pop();
10477      var lineShift = hline.pos - offset;
10478
10479      if (hline.isDashed) {
10480        vListElems.push({
10481          type: "elem",
10482          elem: dashes,
10483          shift: lineShift
10484        });
10485      } else {
10486        vListElems.push({
10487          type: "elem",
10488          elem: line,
10489          shift: lineShift
10490        });
10491      }
10492    }
10493
10494    body = buildCommon.makeVList({
10495      positionType: "individualShift",
10496      children: vListElems
10497    }, options);
10498  }
10499
10500  if (tagSpans.length === 0) {
10501    return buildCommon.makeSpan(["mord"], [body], options);
10502  } else {
10503    var eqnNumCol = buildCommon.makeVList({
10504      positionType: "individualShift",
10505      children: tagSpans
10506    }, options);
10507    eqnNumCol = buildCommon.makeSpan(["tag"], [eqnNumCol], options);
10508    return buildCommon.makeFragment([body, eqnNumCol]);
10509  }
10510};
10511
10512var alignMap = {
10513  c: "center ",
10514  l: "left ",
10515  r: "right "
10516};
10517
10518var mathmlBuilder$6 = function mathmlBuilder(group, options) {
10519  var tbl = [];
10520  var glue = new mathMLTree.MathNode("mtd", [], ["mtr-glue"]);
10521  var tag = new mathMLTree.MathNode("mtd", [], ["mml-eqn-num"]);
10522
10523  for (var i = 0; i < group.body.length; i++) {
10524    var rw = group.body[i];
10525    var row = [];
10526
10527    for (var j = 0; j < rw.length; j++) {
10528      row.push(new mathMLTree.MathNode("mtd", [buildGroup(rw[j], options)]));
10529    }
10530
10531    if (group.tags && group.tags[i]) {
10532      row.unshift(glue);
10533      row.push(glue);
10534
10535      if (group.leqno) {
10536        row.unshift(tag);
10537      } else {
10538        row.push(tag);
10539      }
10540    }
10541
10542    tbl.push(new mathMLTree.MathNode("mtr", row));
10543  }
10544
10545  var table = new mathMLTree.MathNode("mtable", tbl); // Set column alignment, row spacing, column spacing, and
10546  // array lines by setting attributes on the table element.
10547  // Set the row spacing. In MathML, we specify a gap distance.
10548  // We do not use rowGap[] because MathML automatically increases
10549  // cell height with the height/depth of the element content.
10550  // LaTeX \arraystretch multiplies the row baseline-to-baseline distance.
10551  // We simulate this by adding (arraystretch - 1)em to the gap. This
10552  // does a reasonable job of adjusting arrays containing 1 em tall content.
10553  // The 0.16 and 0.09 values are found emprically. They produce an array
10554  // similar to LaTeX and in which content does not interfere with \hines.
10555
10556  var gap = group.arraystretch === 0.5 ? 0.1 // {smallmatrix}, {subarray}
10557  : 0.16 + group.arraystretch - 1 + (group.addJot ? 0.09 : 0);
10558  table.setAttribute("rowspacing", makeEm(gap)); // MathML table lines go only between cells.
10559  // To place a line on an edge we'll use <menclose>, if necessary.
10560
10561  var menclose = "";
10562  var align = "";
10563
10564  if (group.cols && group.cols.length > 0) {
10565    // Find column alignment, column spacing, and  vertical lines.
10566    var cols = group.cols;
10567    var columnLines = "";
10568    var prevTypeWasAlign = false;
10569    var iStart = 0;
10570    var iEnd = cols.length;
10571
10572    if (cols[0].type === "separator") {
10573      menclose += "top ";
10574      iStart = 1;
10575    }
10576
10577    if (cols[cols.length - 1].type === "separator") {
10578      menclose += "bottom ";
10579      iEnd -= 1;
10580    }
10581
10582    for (var _i = iStart; _i < iEnd; _i++) {
10583      if (cols[_i].type === "align") {
10584        align += alignMap[cols[_i].align];
10585
10586        if (prevTypeWasAlign) {
10587          columnLines += "none ";
10588        }
10589
10590        prevTypeWasAlign = true;
10591      } else if (cols[_i].type === "separator") {
10592        // MathML accepts only single lines between cells.
10593        // So we read only the first of consecutive separators.
10594        if (prevTypeWasAlign) {
10595          columnLines += cols[_i].separator === "|" ? "solid " : "dashed ";
10596          prevTypeWasAlign = false;
10597        }
10598      }
10599    }
10600
10601    table.setAttribute("columnalign", align.trim());
10602
10603    if (/[sd]/.test(columnLines)) {
10604      table.setAttribute("columnlines", columnLines.trim());
10605    }
10606  } // Set column spacing.
10607
10608
10609  if (group.colSeparationType === "align") {
10610    var _cols = group.cols || [];
10611
10612    var spacing = "";
10613
10614    for (var _i2 = 1; _i2 < _cols.length; _i2++) {
10615      spacing += _i2 % 2 ? "0em " : "1em ";
10616    }
10617
10618    table.setAttribute("columnspacing", spacing.trim());
10619  } else if (group.colSeparationType === "alignat" || group.colSeparationType === "gather") {
10620    table.setAttribute("columnspacing", "0em");
10621  } else if (group.colSeparationType === "small") {
10622    table.setAttribute("columnspacing", "0.2778em");
10623  } else if (group.colSeparationType === "CD") {
10624    table.setAttribute("columnspacing", "0.5em");
10625  } else {
10626    table.setAttribute("columnspacing", "1em");
10627  } // Address \hline and \hdashline
10628
10629
10630  var rowLines = "";
10631  var hlines = group.hLinesBeforeRow;
10632  menclose += hlines[0].length > 0 ? "left " : "";
10633  menclose += hlines[hlines.length - 1].length > 0 ? "right " : "";
10634
10635  for (var _i3 = 1; _i3 < hlines.length - 1; _i3++) {
10636    rowLines += hlines[_i3].length === 0 ? "none " // MathML accepts only a single line between rows. Read one element.
10637    : hlines[_i3][0] ? "dashed " : "solid ";
10638  }
10639
10640  if (/[sd]/.test(rowLines)) {
10641    table.setAttribute("rowlines", rowLines.trim());
10642  }
10643
10644  if (menclose !== "") {
10645    table = new mathMLTree.MathNode("menclose", [table]);
10646    table.setAttribute("notation", menclose.trim());
10647  }
10648
10649  if (group.arraystretch && group.arraystretch < 1) {
10650    // A small array. Wrap in scriptstyle so row gap is not too large.
10651    table = new mathMLTree.MathNode("mstyle", [table]);
10652    table.setAttribute("scriptlevel", "1");
10653  }
10654
10655  return table;
10656}; // Convenience function for align, align*, aligned, alignat, alignat*, alignedat.
10657
10658
10659var alignedHandler = function alignedHandler(context, args) {
10660  if (context.envName.indexOf("ed") === -1) {
10661    validateAmsEnvironmentContext(context);
10662  }
10663
10664  var cols = [];
10665  var separationType = context.envName.indexOf("at") > -1 ? "alignat" : "align";
10666  var isSplit = context.envName === "split";
10667  var res = parseArray(context.parser, {
10668    cols,
10669    addJot: true,
10670    autoTag: isSplit ? undefined : getAutoTag(context.envName),
10671    emptySingleRow: true,
10672    colSeparationType: separationType,
10673    maxNumCols: isSplit ? 2 : undefined,
10674    leqno: context.parser.settings.leqno
10675  }, "display"); // Determining number of columns.
10676  // 1. If the first argument is given, we use it as a number of columns,
10677  //    and makes sure that each row doesn't exceed that number.
10678  // 2. Otherwise, just count number of columns = maximum number
10679  //    of cells in each row ("aligned" mode -- isAligned will be true).
10680  //
10681  // At the same time, prepend empty group {} at beginning of every second
10682  // cell in each row (starting with second cell) so that operators become
10683  // binary.  This behavior is implemented in amsmath's \start@aligned.
10684
10685  var numMaths;
10686  var numCols = 0;
10687  var emptyGroup = {
10688    type: "ordgroup",
10689    mode: context.mode,
10690    body: []
10691  };
10692
10693  if (args[0] && args[0].type === "ordgroup") {
10694    var arg0 = "";
10695
10696    for (var i = 0; i < args[0].body.length; i++) {
10697      var textord = assertNodeType(args[0].body[i], "textord");
10698      arg0 += textord.text;
10699    }
10700
10701    numMaths = Number(arg0);
10702    numCols = numMaths * 2;
10703  }
10704
10705  var isAligned = !numCols;
10706  res.body.forEach(function (row) {
10707    for (var _i4 = 1; _i4 < row.length; _i4 += 2) {
10708      // Modify ordgroup node within styling node
10709      var styling = assertNodeType(row[_i4], "styling");
10710      var ordgroup = assertNodeType(styling.body[0], "ordgroup");
10711      ordgroup.body.unshift(emptyGroup);
10712    }
10713
10714    if (!isAligned) {
10715      // Case 1
10716      var curMaths = row.length / 2;
10717
10718      if (numMaths < curMaths) {
10719        throw new ParseError("Too many math in a row: " + ("expected " + numMaths + ", but got " + curMaths), row[0]);
10720      }
10721    } else if (numCols < row.length) {
10722      // Case 2
10723      numCols = row.length;
10724    }
10725  }); // Adjusting alignment.
10726  // In aligned mode, we add one \qquad between columns;
10727  // otherwise we add nothing.
10728
10729  for (var _i5 = 0; _i5 < numCols; ++_i5) {
10730    var align = "r";
10731    var pregap = 0;
10732
10733    if (_i5 % 2 === 1) {
10734      align = "l";
10735    } else if (_i5 > 0 && isAligned) {
10736      // "aligned" mode.
10737      pregap = 1; // add one \quad
10738    }
10739
10740    cols[_i5] = {
10741      type: "align",
10742      align: align,
10743      pregap: pregap,
10744      postgap: 0
10745    };
10746  }
10747
10748  res.colSeparationType = isAligned ? "align" : "alignat";
10749  return res;
10750}; // Arrays are part of LaTeX, defined in lttab.dtx so its documentation
10751// is part of the source2e.pdf file of LaTeX2e source documentation.
10752// {darray} is an {array} environment where cells are set in \displaystyle,
10753// as defined in nccmath.sty.
10754
10755
10756defineEnvironment({
10757  type: "array",
10758  names: ["array", "darray"],
10759  props: {
10760    numArgs: 1
10761  },
10762
10763  handler(context, args) {
10764    // Since no types are specified above, the two possibilities are
10765    // - The argument is wrapped in {} or [], in which case Parser's
10766    //   parseGroup() returns an "ordgroup" wrapping some symbol node.
10767    // - The argument is a bare symbol node.
10768    var symNode = checkSymbolNodeType(args[0]);
10769    var colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body;
10770    var cols = colalign.map(function (nde) {
10771      var node = assertSymbolNodeType(nde);
10772      var ca = node.text;
10773
10774      if ("lcr".indexOf(ca) !== -1) {
10775        return {
10776          type: "align",
10777          align: ca
10778        };
10779      } else if (ca === "|") {
10780        return {
10781          type: "separator",
10782          separator: "|"
10783        };
10784      } else if (ca === ":") {
10785        return {
10786          type: "separator",
10787          separator: ":"
10788        };
10789      }
10790
10791      throw new ParseError("Unknown column alignment: " + ca, nde);
10792    });
10793    var res = {
10794      cols,
10795      hskipBeforeAndAfter: true,
10796      // \@preamble in lttab.dtx
10797      maxNumCols: cols.length
10798    };
10799    return parseArray(context.parser, res, dCellStyle(context.envName));
10800  },
10801
10802  htmlBuilder: htmlBuilder$7,
10803  mathmlBuilder: mathmlBuilder$6
10804}); // The matrix environments of amsmath builds on the array environment
10805// of LaTeX, which is discussed above.
10806// The mathtools package adds starred versions of the same environments.
10807// These have an optional argument to choose left|center|right justification.
10808
10809defineEnvironment({
10810  type: "array",
10811  names: ["matrix", "pmatrix", "bmatrix", "Bmatrix", "vmatrix", "Vmatrix", "matrix*", "pmatrix*", "bmatrix*", "Bmatrix*", "vmatrix*", "Vmatrix*"],
10812  props: {
10813    numArgs: 0
10814  },
10815
10816  handler(context) {
10817    var delimiters = {
10818      "matrix": null,
10819      "pmatrix": ["(", ")"],
10820      "bmatrix": ["[", "]"],
10821      "Bmatrix": ["\\{", "\\}"],
10822      "vmatrix": ["|", "|"],
10823      "Vmatrix": ["\\Vert", "\\Vert"]
10824    }[context.envName.replace("*", "")]; // \hskip -\arraycolsep in amsmath
10825
10826    var colAlign = "c";
10827    var payload = {
10828      hskipBeforeAndAfter: false,
10829      cols: [{
10830        type: "align",
10831        align: colAlign
10832      }]
10833    };
10834
10835    if (context.envName.charAt(context.envName.length - 1) === "*") {
10836      // It's one of the mathtools starred functions.
10837      // Parse the optional alignment argument.
10838      var parser = context.parser;
10839      parser.consumeSpaces();
10840
10841      if (parser.fetch().text === "[") {
10842        parser.consume();
10843        parser.consumeSpaces();
10844        colAlign = parser.fetch().text;
10845
10846        if ("lcr".indexOf(colAlign) === -1) {
10847          throw new ParseError("Expected l or c or r", parser.nextToken);
10848        }
10849
10850        parser.consume();
10851        parser.consumeSpaces();
10852        parser.expect("]");
10853        parser.consume();
10854        payload.cols = [{
10855          type: "align",
10856          align: colAlign
10857        }];
10858      }
10859    }
10860
10861    var res = parseArray(context.parser, payload, dCellStyle(context.envName)); // Populate cols with the correct number of column alignment specs.
10862
10863    var numCols = Math.max(0, ...res.body.map(row => row.length));
10864    res.cols = new Array(numCols).fill({
10865      type: "align",
10866      align: colAlign
10867    });
10868    return delimiters ? {
10869      type: "leftright",
10870      mode: context.mode,
10871      body: [res],
10872      left: delimiters[0],
10873      right: delimiters[1],
10874      rightColor: undefined // \right uninfluenced by \color in array
10875
10876    } : res;
10877  },
10878
10879  htmlBuilder: htmlBuilder$7,
10880  mathmlBuilder: mathmlBuilder$6
10881});
10882defineEnvironment({
10883  type: "array",
10884  names: ["smallmatrix"],
10885  props: {
10886    numArgs: 0
10887  },
10888
10889  handler(context) {
10890    var payload = {
10891      arraystretch: 0.5
10892    };
10893    var res = parseArray(context.parser, payload, "script");
10894    res.colSeparationType = "small";
10895    return res;
10896  },
10897
10898  htmlBuilder: htmlBuilder$7,
10899  mathmlBuilder: mathmlBuilder$6
10900});
10901defineEnvironment({
10902  type: "array",
10903  names: ["subarray"],
10904  props: {
10905    numArgs: 1
10906  },
10907
10908  handler(context, args) {
10909    // Parsing of {subarray} is similar to {array}
10910    var symNode = checkSymbolNodeType(args[0]);
10911    var colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body;
10912    var cols = colalign.map(function (nde) {
10913      var node = assertSymbolNodeType(nde);
10914      var ca = node.text; // {subarray} only recognizes "l" & "c"
10915
10916      if ("lc".indexOf(ca) !== -1) {
10917        return {
10918          type: "align",
10919          align: ca
10920        };
10921      }
10922
10923      throw new ParseError("Unknown column alignment: " + ca, nde);
10924    });
10925
10926    if (cols.length > 1) {
10927      throw new ParseError("{subarray} can contain only one column");
10928    }
10929
10930    var res = {
10931      cols,
10932      hskipBeforeAndAfter: false,
10933      arraystretch: 0.5
10934    };
10935    res = parseArray(context.parser, res, "script");
10936
10937    if (res.body.length > 0 && res.body[0].length > 1) {
10938      throw new ParseError("{subarray} can contain only one column");
10939    }
10940
10941    return res;
10942  },
10943
10944  htmlBuilder: htmlBuilder$7,
10945  mathmlBuilder: mathmlBuilder$6
10946}); // A cases environment (in amsmath.sty) is almost equivalent to
10947// \def\arraystretch{1.2}%
10948// \left\{\begin{array}{@{}l@{\quad}l@{}} … \end{array}\right.
10949// {dcases} is a {cases} environment where cells are set in \displaystyle,
10950// as defined in mathtools.sty.
10951// {rcases} is another mathtools environment. It's brace is on the right side.
10952
10953defineEnvironment({
10954  type: "array",
10955  names: ["cases", "dcases", "rcases", "drcases"],
10956  props: {
10957    numArgs: 0
10958  },
10959
10960  handler(context) {
10961    var payload = {
10962      arraystretch: 1.2,
10963      cols: [{
10964        type: "align",
10965        align: "l",
10966        pregap: 0,
10967        // TODO(kevinb) get the current style.
10968        // For now we use the metrics for TEXT style which is what we were
10969        // doing before.  Before attempting to get the current style we
10970        // should look at TeX's behavior especially for \over and matrices.
10971        postgap: 1.0
10972        /* 1em quad */
10973
10974      }, {
10975        type: "align",
10976        align: "l",
10977        pregap: 0,
10978        postgap: 0
10979      }]
10980    };
10981    var res = parseArray(context.parser, payload, dCellStyle(context.envName));
10982    return {
10983      type: "leftright",
10984      mode: context.mode,
10985      body: [res],
10986      left: context.envName.indexOf("r") > -1 ? "." : "\\{",
10987      right: context.envName.indexOf("r") > -1 ? "\\}" : ".",
10988      rightColor: undefined
10989    };
10990  },
10991
10992  htmlBuilder: htmlBuilder$7,
10993  mathmlBuilder: mathmlBuilder$6
10994}); // In the align environment, one uses ampersands, &, to specify number of
10995// columns in each row, and to locate spacing between each column.
10996// align gets automatic numbering. align* and aligned do not.
10997// The alignedat environment can be used in math mode.
10998// Note that we assume \nomallineskiplimit to be zero,
10999// so that \strut@ is the same as \strut.
11000
11001defineEnvironment({
11002  type: "array",
11003  names: ["align", "align*", "aligned", "split"],
11004  props: {
11005    numArgs: 0
11006  },
11007  handler: alignedHandler,
11008  htmlBuilder: htmlBuilder$7,
11009  mathmlBuilder: mathmlBuilder$6
11010}); // A gathered environment is like an array environment with one centered
11011// column, but where rows are considered lines so get \jot line spacing
11012// and contents are set in \displaystyle.
11013
11014defineEnvironment({
11015  type: "array",
11016  names: ["gathered", "gather", "gather*"],
11017  props: {
11018    numArgs: 0
11019  },
11020
11021  handler(context) {
11022    if (utils.contains(["gather", "gather*"], context.envName)) {
11023      validateAmsEnvironmentContext(context);
11024    }
11025
11026    var res = {
11027      cols: [{
11028        type: "align",
11029        align: "c"
11030      }],
11031      addJot: true,
11032      colSeparationType: "gather",
11033      autoTag: getAutoTag(context.envName),
11034      emptySingleRow: true,
11035      leqno: context.parser.settings.leqno
11036    };
11037    return parseArray(context.parser, res, "display");
11038  },
11039
11040  htmlBuilder: htmlBuilder$7,
11041  mathmlBuilder: mathmlBuilder$6
11042}); // alignat environment is like an align environment, but one must explicitly
11043// specify maximum number of columns in each row, and can adjust spacing between
11044// each columns.
11045
11046defineEnvironment({
11047  type: "array",
11048  names: ["alignat", "alignat*", "alignedat"],
11049  props: {
11050    numArgs: 1
11051  },
11052  handler: alignedHandler,
11053  htmlBuilder: htmlBuilder$7,
11054  mathmlBuilder: mathmlBuilder$6
11055});
11056defineEnvironment({
11057  type: "array",
11058  names: ["equation", "equation*"],
11059  props: {
11060    numArgs: 0
11061  },
11062
11063  handler(context) {
11064    validateAmsEnvironmentContext(context);
11065    var res = {
11066      autoTag: getAutoTag(context.envName),
11067      emptySingleRow: true,
11068      singleRow: true,
11069      maxNumCols: 1,
11070      leqno: context.parser.settings.leqno
11071    };
11072    return parseArray(context.parser, res, "display");
11073  },
11074
11075  htmlBuilder: htmlBuilder$7,
11076  mathmlBuilder: mathmlBuilder$6
11077});
11078defineEnvironment({
11079  type: "array",
11080  names: ["CD"],
11081  props: {
11082    numArgs: 0
11083  },
11084
11085  handler(context) {
11086    validateAmsEnvironmentContext(context);
11087    return parseCD(context.parser);
11088  },
11089
11090  htmlBuilder: htmlBuilder$7,
11091  mathmlBuilder: mathmlBuilder$6
11092});
11093defineMacro("\\nonumber", "\\gdef\\@eqnsw{0}");
11094defineMacro("\\notag", "\\nonumber"); // Catch \hline outside array environment
11095
11096defineFunction({
11097  type: "text",
11098  // Doesn't matter what this is.
11099  names: ["\\hline", "\\hdashline"],
11100  props: {
11101    numArgs: 0,
11102    allowedInText: true,
11103    allowedInMath: true
11104  },
11105
11106  handler(context, args) {
11107    throw new ParseError(context.funcName + " valid only within array environment");
11108  }
11109
11110});
11111
11112var environments = _environments;
11113
11114// defineEnvironment definitions.
11115
11116defineFunction({
11117  type: "environment",
11118  names: ["\\begin", "\\end"],
11119  props: {
11120    numArgs: 1,
11121    argTypes: ["text"]
11122  },
11123
11124  handler(_ref, args) {
11125    var {
11126      parser,
11127      funcName
11128    } = _ref;
11129    var nameGroup = args[0];
11130
11131    if (nameGroup.type !== "ordgroup") {
11132      throw new ParseError("Invalid environment name", nameGroup);
11133    }
11134
11135    var envName = "";
11136
11137    for (var i = 0; i < nameGroup.body.length; ++i) {
11138      envName += assertNodeType(nameGroup.body[i], "textord").text;
11139    }
11140
11141    if (funcName === "\\begin") {
11142      // begin...end is similar to left...right
11143      if (!environments.hasOwnProperty(envName)) {
11144        throw new ParseError("No such environment: " + envName, nameGroup);
11145      } // Build the environment object. Arguments and other information will
11146      // be made available to the begin and end methods using properties.
11147
11148
11149      var env = environments[envName];
11150      var {
11151        args: _args,
11152        optArgs
11153      } = parser.parseArguments("\\begin{" + envName + "}", env);
11154      var context = {
11155        mode: parser.mode,
11156        envName,
11157        parser
11158      };
11159      var result = env.handler(context, _args, optArgs);
11160      parser.expect("\\end", false);
11161      var endNameToken = parser.nextToken;
11162      var end = assertNodeType(parser.parseFunction(), "environment");
11163
11164      if (end.name !== envName) {
11165        throw new ParseError("Mismatch: \\begin{" + envName + "} matched by \\end{" + end.name + "}", endNameToken);
11166      } // $FlowFixMe, "environment" handler returns an environment ParseNode
11167
11168
11169      return result;
11170    }
11171
11172    return {
11173      type: "environment",
11174      mode: parser.mode,
11175      name: envName,
11176      nameGroup
11177    };
11178  }
11179
11180});
11181
11182var makeSpan = buildCommon.makeSpan;
11183
11184function htmlBuilder$6(group, options) {
11185  var elements = buildExpression$1(group.body, options, true);
11186  return makeSpan([group.mclass], elements, options);
11187}
11188
11189function mathmlBuilder$5(group, options) {
11190  var node;
11191  var inner = buildExpression(group.body, options);
11192
11193  if (group.mclass === "minner") {
11194    node = new mathMLTree.MathNode("mpadded", inner);
11195  } else if (group.mclass === "mord") {
11196    if (group.isCharacterBox) {
11197      node = inner[0];
11198      node.type = "mi";
11199    } else {
11200      node = new mathMLTree.MathNode("mi", inner);
11201    }
11202  } else {
11203    if (group.isCharacterBox) {
11204      node = inner[0];
11205      node.type = "mo";
11206    } else {
11207      node = new mathMLTree.MathNode("mo", inner);
11208    } // Set spacing based on what is the most likely adjacent atom type.
11209    // See TeXbook p170.
11210
11211
11212    if (group.mclass === "mbin") {
11213      node.attributes.lspace = "0.22em"; // medium space
11214
11215      node.attributes.rspace = "0.22em";
11216    } else if (group.mclass === "mpunct") {
11217      node.attributes.lspace = "0em";
11218      node.attributes.rspace = "0.17em"; // thinspace
11219    } else if (group.mclass === "mopen" || group.mclass === "mclose") {
11220      node.attributes.lspace = "0em";
11221      node.attributes.rspace = "0em";
11222    } else if (group.mclass === "minner") {
11223      node.attributes.lspace = "0.0556em"; // 1 mu is the most likely option
11224
11225      node.attributes.width = "+0.1111em";
11226    } // MathML <mo> default space is 5/18 em, so <mrel> needs no action.
11227    // Ref: https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mo
11228
11229  }
11230
11231  return node;
11232} // Math class commands except \mathop
11233
11234
11235defineFunction({
11236  type: "mclass",
11237  names: ["\\mathord", "\\mathbin", "\\mathrel", "\\mathopen", "\\mathclose", "\\mathpunct", "\\mathinner"],
11238  props: {
11239    numArgs: 1,
11240    primitive: true
11241  },
11242
11243  handler(_ref, args) {
11244    var {
11245      parser,
11246      funcName
11247    } = _ref;
11248    var body = args[0];
11249    return {
11250      type: "mclass",
11251      mode: parser.mode,
11252      mclass: "m" + funcName.substr(5),
11253      // TODO(kevinb): don't prefix with 'm'
11254      body: ordargument(body),
11255      isCharacterBox: utils.isCharacterBox(body)
11256    };
11257  },
11258
11259  htmlBuilder: htmlBuilder$6,
11260  mathmlBuilder: mathmlBuilder$5
11261});
11262var binrelClass = arg => {
11263  // \binrel@ spacing varies with (bin|rel|ord) of the atom in the argument.
11264  // (by rendering separately and with {}s before and after, and measuring
11265  // the change in spacing).  We'll do roughly the same by detecting the
11266  // atom type directly.
11267  var atom = arg.type === "ordgroup" && arg.body.length ? arg.body[0] : arg;
11268
11269  if (atom.type === "atom" && (atom.family === "bin" || atom.family === "rel")) {
11270    return "m" + atom.family;
11271  } else {
11272    return "mord";
11273  }
11274}; // \@binrel{x}{y} renders like y but as mbin/mrel/mord if x is mbin/mrel/mord.
11275// This is equivalent to \binrel@{x}\binrel@@{y} in AMSTeX.
11276
11277defineFunction({
11278  type: "mclass",
11279  names: ["\\@binrel"],
11280  props: {
11281    numArgs: 2
11282  },
11283
11284  handler(_ref2, args) {
11285    var {
11286      parser
11287    } = _ref2;
11288    return {
11289      type: "mclass",
11290      mode: parser.mode,
11291      mclass: binrelClass(args[0]),
11292      body: ordargument(args[1]),
11293      isCharacterBox: utils.isCharacterBox(args[1])
11294    };
11295  }
11296
11297}); // Build a relation or stacked op by placing one symbol on top of another
11298
11299defineFunction({
11300  type: "mclass",
11301  names: ["\\stackrel", "\\overset", "\\underset"],
11302  props: {
11303    numArgs: 2
11304  },
11305
11306  handler(_ref3, args) {
11307    var {
11308      parser,
11309      funcName
11310    } = _ref3;
11311    var baseArg = args[1];
11312    var shiftedArg = args[0];
11313    var mclass;
11314
11315    if (funcName !== "\\stackrel") {
11316      // LaTeX applies \binrel spacing to \overset and \underset.
11317      mclass = binrelClass(baseArg);
11318    } else {
11319      mclass = "mrel"; // for \stackrel
11320    }
11321
11322    var baseOp = {
11323      type: "op",
11324      mode: baseArg.mode,
11325      limits: true,
11326      alwaysHandleSupSub: true,
11327      parentIsSupSub: false,
11328      symbol: false,
11329      suppressBaseShift: funcName !== "\\stackrel",
11330      body: ordargument(baseArg)
11331    };
11332    var supsub = {
11333      type: "supsub",
11334      mode: shiftedArg.mode,
11335      base: baseOp,
11336      sup: funcName === "\\underset" ? null : shiftedArg,
11337      sub: funcName === "\\underset" ? shiftedArg : null
11338    };
11339    return {
11340      type: "mclass",
11341      mode: parser.mode,
11342      mclass,
11343      body: [supsub],
11344      isCharacterBox: utils.isCharacterBox(supsub)
11345    };
11346  },
11347
11348  htmlBuilder: htmlBuilder$6,
11349  mathmlBuilder: mathmlBuilder$5
11350});
11351
11352// TODO(kevinb): implement \\sl and \\sc
11353
11354var htmlBuilder$5 = (group, options) => {
11355  var font = group.font;
11356  var newOptions = options.withFont(font);
11357  return buildGroup$1(group.body, newOptions);
11358};
11359
11360var mathmlBuilder$4 = (group, options) => {
11361  var font = group.font;
11362  var newOptions = options.withFont(font);
11363  return buildGroup(group.body, newOptions);
11364};
11365
11366var fontAliases = {
11367  "\\Bbb": "\\mathbb",
11368  "\\bold": "\\mathbf",
11369  "\\frak": "\\mathfrak",
11370  "\\bm": "\\boldsymbol"
11371};
11372defineFunction({
11373  type: "font",
11374  names: [// styles, except \boldsymbol defined below
11375  "\\mathrm", "\\mathit", "\\mathbf", "\\mathnormal", // families
11376  "\\mathbb", "\\mathcal", "\\mathfrak", "\\mathscr", "\\mathsf", "\\mathtt", // aliases, except \bm defined below
11377  "\\Bbb", "\\bold", "\\frak"],
11378  props: {
11379    numArgs: 1,
11380    allowedInArgument: true
11381  },
11382  handler: (_ref, args) => {
11383    var {
11384      parser,
11385      funcName
11386    } = _ref;
11387    var body = normalizeArgument(args[0]);
11388    var func = funcName;
11389
11390    if (func in fontAliases) {
11391      func = fontAliases[func];
11392    }
11393
11394    return {
11395      type: "font",
11396      mode: parser.mode,
11397      font: func.slice(1),
11398      body
11399    };
11400  },
11401  htmlBuilder: htmlBuilder$5,
11402  mathmlBuilder: mathmlBuilder$4
11403});
11404defineFunction({
11405  type: "mclass",
11406  names: ["\\boldsymbol", "\\bm"],
11407  props: {
11408    numArgs: 1
11409  },
11410  handler: (_ref2, args) => {
11411    var {
11412      parser
11413    } = _ref2;
11414    var body = args[0];
11415    var isCharacterBox = utils.isCharacterBox(body); // amsbsy.sty's \boldsymbol uses \binrel spacing to inherit the
11416    // argument's bin|rel|ord status
11417
11418    return {
11419      type: "mclass",
11420      mode: parser.mode,
11421      mclass: binrelClass(body),
11422      body: [{
11423        type: "font",
11424        mode: parser.mode,
11425        font: "boldsymbol",
11426        body
11427      }],
11428      isCharacterBox: isCharacterBox
11429    };
11430  }
11431}); // Old font changing functions
11432
11433defineFunction({
11434  type: "font",
11435  names: ["\\rm", "\\sf", "\\tt", "\\bf", "\\it", "\\cal"],
11436  props: {
11437    numArgs: 0,
11438    allowedInText: true
11439  },
11440  handler: (_ref3, args) => {
11441    var {
11442      parser,
11443      funcName,
11444      breakOnTokenText
11445    } = _ref3;
11446    var {
11447      mode
11448    } = parser;
11449    var body = parser.parseExpression(true, breakOnTokenText);
11450    var style = "math" + funcName.slice(1);
11451    return {
11452      type: "font",
11453      mode: mode,
11454      font: style,
11455      body: {
11456        type: "ordgroup",
11457        mode: parser.mode,
11458        body
11459      }
11460    };
11461  },
11462  htmlBuilder: htmlBuilder$5,
11463  mathmlBuilder: mathmlBuilder$4
11464});
11465
11466var adjustStyle = (size, originalStyle) => {
11467  // Figure out what style this fraction should be in based on the
11468  // function used
11469  var style = originalStyle;
11470
11471  if (size === "display") {
11472    // Get display style as a default.
11473    // If incoming style is sub/sup, use style.text() to get correct size.
11474    style = style.id >= Style$1.SCRIPT.id ? style.text() : Style$1.DISPLAY;
11475  } else if (size === "text" && style.size === Style$1.DISPLAY.size) {
11476    // We're in a \tfrac but incoming style is displaystyle, so:
11477    style = Style$1.TEXT;
11478  } else if (size === "script") {
11479    style = Style$1.SCRIPT;
11480  } else if (size === "scriptscript") {
11481    style = Style$1.SCRIPTSCRIPT;
11482  }
11483
11484  return style;
11485};
11486
11487var htmlBuilder$4 = (group, options) => {
11488  // Fractions are handled in the TeXbook on pages 444-445, rules 15(a-e).
11489  var style = adjustStyle(group.size, options.style);
11490  var nstyle = style.fracNum();
11491  var dstyle = style.fracDen();
11492  var newOptions;
11493  newOptions = options.havingStyle(nstyle);
11494  var numerm = buildGroup$1(group.numer, newOptions, options);
11495
11496  if (group.continued) {
11497    // \cfrac inserts a \strut into the numerator.
11498    // Get \strut dimensions from TeXbook page 353.
11499    var hStrut = 8.5 / options.fontMetrics().ptPerEm;
11500    var dStrut = 3.5 / options.fontMetrics().ptPerEm;
11501    numerm.height = numerm.height < hStrut ? hStrut : numerm.height;
11502    numerm.depth = numerm.depth < dStrut ? dStrut : numerm.depth;
11503  }
11504
11505  newOptions = options.havingStyle(dstyle);
11506  var denomm = buildGroup$1(group.denom, newOptions, options);
11507  var rule;
11508  var ruleWidth;
11509  var ruleSpacing;
11510
11511  if (group.hasBarLine) {
11512    if (group.barSize) {
11513      ruleWidth = calculateSize(group.barSize, options);
11514      rule = buildCommon.makeLineSpan("frac-line", options, ruleWidth);
11515    } else {
11516      rule = buildCommon.makeLineSpan("frac-line", options);
11517    }
11518
11519    ruleWidth = rule.height;
11520    ruleSpacing = rule.height;
11521  } else {
11522    rule = null;
11523    ruleWidth = 0;
11524    ruleSpacing = options.fontMetrics().defaultRuleThickness;
11525  } // Rule 15b
11526
11527
11528  var numShift;
11529  var clearance;
11530  var denomShift;
11531
11532  if (style.size === Style$1.DISPLAY.size || group.size === "display") {
11533    numShift = options.fontMetrics().num1;
11534
11535    if (ruleWidth > 0) {
11536      clearance = 3 * ruleSpacing;
11537    } else {
11538      clearance = 7 * ruleSpacing;
11539    }
11540
11541    denomShift = options.fontMetrics().denom1;
11542  } else {
11543    if (ruleWidth > 0) {
11544      numShift = options.fontMetrics().num2;
11545      clearance = ruleSpacing;
11546    } else {
11547      numShift = options.fontMetrics().num3;
11548      clearance = 3 * ruleSpacing;
11549    }
11550
11551    denomShift = options.fontMetrics().denom2;
11552  }
11553
11554  var frac;
11555
11556  if (!rule) {
11557    // Rule 15c
11558    var candidateClearance = numShift - numerm.depth - (denomm.height - denomShift);
11559
11560    if (candidateClearance < clearance) {
11561      numShift += 0.5 * (clearance - candidateClearance);
11562      denomShift += 0.5 * (clearance - candidateClearance);
11563    }
11564
11565    frac = buildCommon.makeVList({
11566      positionType: "individualShift",
11567      children: [{
11568        type: "elem",
11569        elem: denomm,
11570        shift: denomShift
11571      }, {
11572        type: "elem",
11573        elem: numerm,
11574        shift: -numShift
11575      }]
11576    }, options);
11577  } else {
11578    // Rule 15d
11579    var axisHeight = options.fontMetrics().axisHeight;
11580
11581    if (numShift - numerm.depth - (axisHeight + 0.5 * ruleWidth) < clearance) {
11582      numShift += clearance - (numShift - numerm.depth - (axisHeight + 0.5 * ruleWidth));
11583    }
11584
11585    if (axisHeight - 0.5 * ruleWidth - (denomm.height - denomShift) < clearance) {
11586      denomShift += clearance - (axisHeight - 0.5 * ruleWidth - (denomm.height - denomShift));
11587    }
11588
11589    var midShift = -(axisHeight - 0.5 * ruleWidth);
11590    frac = buildCommon.makeVList({
11591      positionType: "individualShift",
11592      children: [{
11593        type: "elem",
11594        elem: denomm,
11595        shift: denomShift
11596      }, {
11597        type: "elem",
11598        elem: rule,
11599        shift: midShift
11600      }, {
11601        type: "elem",
11602        elem: numerm,
11603        shift: -numShift
11604      }]
11605    }, options);
11606  } // Since we manually change the style sometimes (with \dfrac or \tfrac),
11607  // account for the possible size change here.
11608
11609
11610  newOptions = options.havingStyle(style);
11611  frac.height *= newOptions.sizeMultiplier / options.sizeMultiplier;
11612  frac.depth *= newOptions.sizeMultiplier / options.sizeMultiplier; // Rule 15e
11613
11614  var delimSize;
11615
11616  if (style.size === Style$1.DISPLAY.size) {
11617    delimSize = options.fontMetrics().delim1;
11618  } else if (style.size === Style$1.SCRIPTSCRIPT.size) {
11619    delimSize = options.havingStyle(Style$1.SCRIPT).fontMetrics().delim2;
11620  } else {
11621    delimSize = options.fontMetrics().delim2;
11622  }
11623
11624  var leftDelim;
11625  var rightDelim;
11626
11627  if (group.leftDelim == null) {
11628    leftDelim = makeNullDelimiter(options, ["mopen"]);
11629  } else {
11630    leftDelim = delimiter.customSizedDelim(group.leftDelim, delimSize, true, options.havingStyle(style), group.mode, ["mopen"]);
11631  }
11632
11633  if (group.continued) {
11634    rightDelim = buildCommon.makeSpan([]); // zero width for \cfrac
11635  } else if (group.rightDelim == null) {
11636    rightDelim = makeNullDelimiter(options, ["mclose"]);
11637  } else {
11638    rightDelim = delimiter.customSizedDelim(group.rightDelim, delimSize, true, options.havingStyle(style), group.mode, ["mclose"]);
11639  }
11640
11641  return buildCommon.makeSpan(["mord"].concat(newOptions.sizingClasses(options)), [leftDelim, buildCommon.makeSpan(["mfrac"], [frac]), rightDelim], options);
11642};
11643
11644var mathmlBuilder$3 = (group, options) => {
11645  var node = new mathMLTree.MathNode("mfrac", [buildGroup(group.numer, options), buildGroup(group.denom, options)]);
11646
11647  if (!group.hasBarLine) {
11648    node.setAttribute("linethickness", "0px");
11649  } else if (group.barSize) {
11650    var ruleWidth = calculateSize(group.barSize, options);
11651    node.setAttribute("linethickness", makeEm(ruleWidth));
11652  }
11653
11654  var style = adjustStyle(group.size, options.style);
11655
11656  if (style.size !== options.style.size) {
11657    node = new mathMLTree.MathNode("mstyle", [node]);
11658    var isDisplay = style.size === Style$1.DISPLAY.size ? "true" : "false";
11659    node.setAttribute("displaystyle", isDisplay);
11660    node.setAttribute("scriptlevel", "0");
11661  }
11662
11663  if (group.leftDelim != null || group.rightDelim != null) {
11664    var withDelims = [];
11665
11666    if (group.leftDelim != null) {
11667      var leftOp = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode(group.leftDelim.replace("\\", ""))]);
11668      leftOp.setAttribute("fence", "true");
11669      withDelims.push(leftOp);
11670    }
11671
11672    withDelims.push(node);
11673
11674    if (group.rightDelim != null) {
11675      var rightOp = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode(group.rightDelim.replace("\\", ""))]);
11676      rightOp.setAttribute("fence", "true");
11677      withDelims.push(rightOp);
11678    }
11679
11680    return makeRow(withDelims);
11681  }
11682
11683  return node;
11684};
11685
11686defineFunction({
11687  type: "genfrac",
11688  names: ["\\dfrac", "\\frac", "\\tfrac", "\\dbinom", "\\binom", "\\tbinom", "\\\\atopfrac", // can’t be entered directly
11689  "\\\\bracefrac", "\\\\brackfrac" // ditto
11690  ],
11691  props: {
11692    numArgs: 2,
11693    allowedInArgument: true
11694  },
11695  handler: (_ref, args) => {
11696    var {
11697      parser,
11698      funcName
11699    } = _ref;
11700    var numer = args[0];
11701    var denom = args[1];
11702    var hasBarLine;
11703    var leftDelim = null;
11704    var rightDelim = null;
11705    var size = "auto";
11706
11707    switch (funcName) {
11708      case "\\dfrac":
11709      case "\\frac":
11710      case "\\tfrac":
11711        hasBarLine = true;
11712        break;
11713
11714      case "\\\\atopfrac":
11715        hasBarLine = false;
11716        break;
11717
11718      case "\\dbinom":
11719      case "\\binom":
11720      case "\\tbinom":
11721        hasBarLine = false;
11722        leftDelim = "(";
11723        rightDelim = ")";
11724        break;
11725
11726      case "\\\\bracefrac":
11727        hasBarLine = false;
11728        leftDelim = "\\{";
11729        rightDelim = "\\}";
11730        break;
11731
11732      case "\\\\brackfrac":
11733        hasBarLine = false;
11734        leftDelim = "[";
11735        rightDelim = "]";
11736        break;
11737
11738      default:
11739        throw new Error("Unrecognized genfrac command");
11740    }
11741
11742    switch (funcName) {
11743      case "\\dfrac":
11744      case "\\dbinom":
11745        size = "display";
11746        break;
11747
11748      case "\\tfrac":
11749      case "\\tbinom":
11750        size = "text";
11751        break;
11752    }
11753
11754    return {
11755      type: "genfrac",
11756      mode: parser.mode,
11757      continued: false,
11758      numer,
11759      denom,
11760      hasBarLine,
11761      leftDelim,
11762      rightDelim,
11763      size,
11764      barSize: null
11765    };
11766  },
11767  htmlBuilder: htmlBuilder$4,
11768  mathmlBuilder: mathmlBuilder$3
11769});
11770defineFunction({
11771  type: "genfrac",
11772  names: ["\\cfrac"],
11773  props: {
11774    numArgs: 2
11775  },
11776  handler: (_ref2, args) => {
11777    var {
11778      parser,
11779      funcName
11780    } = _ref2;
11781    var numer = args[0];
11782    var denom = args[1];
11783    return {
11784      type: "genfrac",
11785      mode: parser.mode,
11786      continued: true,
11787      numer,
11788      denom,
11789      hasBarLine: true,
11790      leftDelim: null,
11791      rightDelim: null,
11792      size: "display",
11793      barSize: null
11794    };
11795  }
11796}); // Infix generalized fractions -- these are not rendered directly, but replaced
11797// immediately by one of the variants above.
11798
11799defineFunction({
11800  type: "infix",
11801  names: ["\\over", "\\choose", "\\atop", "\\brace", "\\brack"],
11802  props: {
11803    numArgs: 0,
11804    infix: true
11805  },
11806
11807  handler(_ref3) {
11808    var {
11809      parser,
11810      funcName,
11811      token
11812    } = _ref3;
11813    var replaceWith;
11814
11815    switch (funcName) {
11816      case "\\over":
11817        replaceWith = "\\frac";
11818        break;
11819
11820      case "\\choose":
11821        replaceWith = "\\binom";
11822        break;
11823
11824      case "\\atop":
11825        replaceWith = "\\\\atopfrac";
11826        break;
11827
11828      case "\\brace":
11829        replaceWith = "\\\\bracefrac";
11830        break;
11831
11832      case "\\brack":
11833        replaceWith = "\\\\brackfrac";
11834        break;
11835
11836      default:
11837        throw new Error("Unrecognized infix genfrac command");
11838    }
11839
11840    return {
11841      type: "infix",
11842      mode: parser.mode,
11843      replaceWith,
11844      token
11845    };
11846  }
11847
11848});
11849var stylArray = ["display", "text", "script", "scriptscript"];
11850
11851var delimFromValue = function delimFromValue(delimString) {
11852  var delim = null;
11853
11854  if (delimString.length > 0) {
11855    delim = delimString;
11856    delim = delim === "." ? null : delim;
11857  }
11858
11859  return delim;
11860};
11861
11862defineFunction({
11863  type: "genfrac",
11864  names: ["\\genfrac"],
11865  props: {
11866    numArgs: 6,
11867    allowedInArgument: true,
11868    argTypes: ["math", "math", "size", "text", "math", "math"]
11869  },
11870
11871  handler(_ref4, args) {
11872    var {
11873      parser
11874    } = _ref4;
11875    var numer = args[4];
11876    var denom = args[5]; // Look into the parse nodes to get the desired delimiters.
11877
11878    var leftNode = normalizeArgument(args[0]);
11879    var leftDelim = leftNode.type === "atom" && leftNode.family === "open" ? delimFromValue(leftNode.text) : null;
11880    var rightNode = normalizeArgument(args[1]);
11881    var rightDelim = rightNode.type === "atom" && rightNode.family === "close" ? delimFromValue(rightNode.text) : null;
11882    var barNode = assertNodeType(args[2], "size");
11883    var hasBarLine;
11884    var barSize = null;
11885
11886    if (barNode.isBlank) {
11887      // \genfrac acts differently than \above.
11888      // \genfrac treats an empty size group as a signal to use a
11889      // standard bar size. \above would see size = 0 and omit the bar.
11890      hasBarLine = true;
11891    } else {
11892      barSize = barNode.value;
11893      hasBarLine = barSize.number > 0;
11894    } // Find out if we want displaystyle, textstyle, etc.
11895
11896
11897    var size = "auto";
11898    var styl = args[3];
11899
11900    if (styl.type === "ordgroup") {
11901      if (styl.body.length > 0) {
11902        var textOrd = assertNodeType(styl.body[0], "textord");
11903        size = stylArray[Number(textOrd.text)];
11904      }
11905    } else {
11906      styl = assertNodeType(styl, "textord");
11907      size = stylArray[Number(styl.text)];
11908    }
11909
11910    return {
11911      type: "genfrac",
11912      mode: parser.mode,
11913      numer,
11914      denom,
11915      continued: false,
11916      hasBarLine,
11917      barSize,
11918      leftDelim,
11919      rightDelim,
11920      size
11921    };
11922  },
11923
11924  htmlBuilder: htmlBuilder$4,
11925  mathmlBuilder: mathmlBuilder$3
11926}); // \above is an infix fraction that also defines a fraction bar size.
11927
11928defineFunction({
11929  type: "infix",
11930  names: ["\\above"],
11931  props: {
11932    numArgs: 1,
11933    argTypes: ["size"],
11934    infix: true
11935  },
11936
11937  handler(_ref5, args) {
11938    var {
11939      parser,
11940      funcName,
11941      token
11942    } = _ref5;
11943    return {
11944      type: "infix",
11945      mode: parser.mode,
11946      replaceWith: "\\\\abovefrac",
11947      size: assertNodeType(args[0], "size").value,
11948      token
11949    };
11950  }
11951
11952});
11953defineFunction({
11954  type: "genfrac",
11955  names: ["\\\\abovefrac"],
11956  props: {
11957    numArgs: 3,
11958    argTypes: ["math", "size", "math"]
11959  },
11960  handler: (_ref6, args) => {
11961    var {
11962      parser,
11963      funcName
11964    } = _ref6;
11965    var numer = args[0];
11966    var barSize = assert(assertNodeType(args[1], "infix").size);
11967    var denom = args[2];
11968    var hasBarLine = barSize.number > 0;
11969    return {
11970      type: "genfrac",
11971      mode: parser.mode,
11972      numer,
11973      denom,
11974      continued: false,
11975      hasBarLine,
11976      barSize,
11977      leftDelim: null,
11978      rightDelim: null,
11979      size: "auto"
11980    };
11981  },
11982  htmlBuilder: htmlBuilder$4,
11983  mathmlBuilder: mathmlBuilder$3
11984});
11985
11986// NOTE: Unlike most `htmlBuilder`s, this one handles not only "horizBrace", but
11987// also "supsub" since an over/underbrace can affect super/subscripting.
11988var htmlBuilder$3 = (grp, options) => {
11989  var style = options.style; // Pull out the `ParseNode<"horizBrace">` if `grp` is a "supsub" node.
11990
11991  var supSubGroup;
11992  var group;
11993
11994  if (grp.type === "supsub") {
11995    // Ref: LaTeX source2e: }}}}\limits}
11996    // i.e. LaTeX treats the brace similar to an op and passes it
11997    // with \limits, so we need to assign supsub style.
11998    supSubGroup = grp.sup ? buildGroup$1(grp.sup, options.havingStyle(style.sup()), options) : buildGroup$1(grp.sub, options.havingStyle(style.sub()), options);
11999    group = assertNodeType(grp.base, "horizBrace");
12000  } else {
12001    group = assertNodeType(grp, "horizBrace");
12002  } // Build the base group
12003
12004
12005  var body = buildGroup$1(group.base, options.havingBaseStyle(Style$1.DISPLAY)); // Create the stretchy element
12006
12007  var braceBody = stretchy.svgSpan(group, options); // Generate the vlist, with the appropriate kerns        ┏━━━━━━━━┓
12008  // This first vlist contains the content and the brace:   equation
12009
12010  var vlist;
12011
12012  if (group.isOver) {
12013    vlist = buildCommon.makeVList({
12014      positionType: "firstBaseline",
12015      children: [{
12016        type: "elem",
12017        elem: body
12018      }, {
12019        type: "kern",
12020        size: 0.1
12021      }, {
12022        type: "elem",
12023        elem: braceBody
12024      }]
12025    }, options); // $FlowFixMe: Replace this with passing "svg-align" into makeVList.
12026
12027    vlist.children[0].children[0].children[1].classes.push("svg-align");
12028  } else {
12029    vlist = buildCommon.makeVList({
12030      positionType: "bottom",
12031      positionData: body.depth + 0.1 + braceBody.height,
12032      children: [{
12033        type: "elem",
12034        elem: braceBody
12035      }, {
12036        type: "kern",
12037        size: 0.1
12038      }, {
12039        type: "elem",
12040        elem: body
12041      }]
12042    }, options); // $FlowFixMe: Replace this with passing "svg-align" into makeVList.
12043
12044    vlist.children[0].children[0].children[0].classes.push("svg-align");
12045  }
12046
12047  if (supSubGroup) {
12048    // To write the supsub, wrap the first vlist in another vlist:
12049    // They can't all go in the same vlist, because the note might be
12050    // wider than the equation. We want the equation to control the
12051    // brace width.
12052    //      note          long note           long note
12053    //   ┏━━━━━━━━┓   or    ┏━━━┓     not    ┏━━━━━━━━━┓
12054    //    equation           eqn                 eqn
12055    var vSpan = buildCommon.makeSpan(["mord", group.isOver ? "mover" : "munder"], [vlist], options);
12056
12057    if (group.isOver) {
12058      vlist = buildCommon.makeVList({
12059        positionType: "firstBaseline",
12060        children: [{
12061          type: "elem",
12062          elem: vSpan
12063        }, {
12064          type: "kern",
12065          size: 0.2
12066        }, {
12067          type: "elem",
12068          elem: supSubGroup
12069        }]
12070      }, options);
12071    } else {
12072      vlist = buildCommon.makeVList({
12073        positionType: "bottom",
12074        positionData: vSpan.depth + 0.2 + supSubGroup.height + supSubGroup.depth,
12075        children: [{
12076          type: "elem",
12077          elem: supSubGroup
12078        }, {
12079          type: "kern",
12080          size: 0.2
12081        }, {
12082          type: "elem",
12083          elem: vSpan
12084        }]
12085      }, options);
12086    }
12087  }
12088
12089  return buildCommon.makeSpan(["mord", group.isOver ? "mover" : "munder"], [vlist], options);
12090};
12091
12092var mathmlBuilder$2 = (group, options) => {
12093  var accentNode = stretchy.mathMLnode(group.label);
12094  return new mathMLTree.MathNode(group.isOver ? "mover" : "munder", [buildGroup(group.base, options), accentNode]);
12095}; // Horizontal stretchy braces
12096
12097
12098defineFunction({
12099  type: "horizBrace",
12100  names: ["\\overbrace", "\\underbrace"],
12101  props: {
12102    numArgs: 1
12103  },
12104
12105  handler(_ref, args) {
12106    var {
12107      parser,
12108      funcName
12109    } = _ref;
12110    return {
12111      type: "horizBrace",
12112      mode: parser.mode,
12113      label: funcName,
12114      isOver: /^\\over/.test(funcName),
12115      base: args[0]
12116    };
12117  },
12118
12119  htmlBuilder: htmlBuilder$3,
12120  mathmlBuilder: mathmlBuilder$2
12121});
12122
12123defineFunction({
12124  type: "href",
12125  names: ["\\href"],
12126  props: {
12127    numArgs: 2,
12128    argTypes: ["url", "original"],
12129    allowedInText: true
12130  },
12131  handler: (_ref, args) => {
12132    var {
12133      parser
12134    } = _ref;
12135    var body = args[1];
12136    var href = assertNodeType(args[0], "url").url;
12137
12138    if (!parser.settings.isTrusted({
12139      command: "\\href",
12140      url: href
12141    })) {
12142      return parser.formatUnsupportedCmd("\\href");
12143    }
12144
12145    return {
12146      type: "href",
12147      mode: parser.mode,
12148      href,
12149      body: ordargument(body)
12150    };
12151  },
12152  htmlBuilder: (group, options) => {
12153    var elements = buildExpression$1(group.body, options, false);
12154    return buildCommon.makeAnchor(group.href, [], elements, options);
12155  },
12156  mathmlBuilder: (group, options) => {
12157    var math = buildExpressionRow(group.body, options);
12158
12159    if (!(math instanceof MathNode)) {
12160      math = new MathNode("mrow", [math]);
12161    }
12162
12163    math.setAttribute("href", group.href);
12164    return math;
12165  }
12166});
12167defineFunction({
12168  type: "href",
12169  names: ["\\url"],
12170  props: {
12171    numArgs: 1,
12172    argTypes: ["url"],
12173    allowedInText: true
12174  },
12175  handler: (_ref2, args) => {
12176    var {
12177      parser
12178    } = _ref2;
12179    var href = assertNodeType(args[0], "url").url;
12180
12181    if (!parser.settings.isTrusted({
12182      command: "\\url",
12183      url: href
12184    })) {
12185      return parser.formatUnsupportedCmd("\\url");
12186    }
12187
12188    var chars = [];
12189
12190    for (var i = 0; i < href.length; i++) {
12191      var c = href[i];
12192
12193      if (c === "~") {
12194        c = "\\textasciitilde";
12195      }
12196
12197      chars.push({
12198        type: "textord",
12199        mode: "text",
12200        text: c
12201      });
12202    }
12203
12204    var body = {
12205      type: "text",
12206      mode: parser.mode,
12207      font: "\\texttt",
12208      body: chars
12209    };
12210    return {
12211      type: "href",
12212      mode: parser.mode,
12213      href,
12214      body: ordargument(body)
12215    };
12216  }
12217});
12218
12219// In LaTeX, \vcenter can act only on a box, as in
12220// \vcenter{\hbox{$\frac{a+b}{\dfrac{c}{d}}$}}
12221// This function by itself doesn't do anything but prevent a soft line break.
12222
12223defineFunction({
12224  type: "hbox",
12225  names: ["\\hbox"],
12226  props: {
12227    numArgs: 1,
12228    argTypes: ["text"],
12229    allowedInText: true,
12230    primitive: true
12231  },
12232
12233  handler(_ref, args) {
12234    var {
12235      parser
12236    } = _ref;
12237    return {
12238      type: "hbox",
12239      mode: parser.mode,
12240      body: ordargument(args[0])
12241    };
12242  },
12243
12244  htmlBuilder(group, options) {
12245    var elements = buildExpression$1(group.body, options, false);
12246    return buildCommon.makeFragment(elements);
12247  },
12248
12249  mathmlBuilder(group, options) {
12250    return new mathMLTree.MathNode("mrow", buildExpression(group.body, options));
12251  }
12252
12253});
12254
12255defineFunction({
12256  type: "html",
12257  names: ["\\htmlClass", "\\htmlId", "\\htmlStyle", "\\htmlData"],
12258  props: {
12259    numArgs: 2,
12260    argTypes: ["raw", "original"],
12261    allowedInText: true
12262  },
12263  handler: (_ref, args) => {
12264    var {
12265      parser,
12266      funcName,
12267      token
12268    } = _ref;
12269    var value = assertNodeType(args[0], "raw").string;
12270    var body = args[1];
12271
12272    if (parser.settings.strict) {
12273      parser.settings.reportNonstrict("htmlExtension", "HTML extension is disabled on strict mode");
12274    }
12275
12276    var trustContext;
12277    var attributes = {};
12278
12279    switch (funcName) {
12280      case "\\htmlClass":
12281        attributes.class = value;
12282        trustContext = {
12283          command: "\\htmlClass",
12284          class: value
12285        };
12286        break;
12287
12288      case "\\htmlId":
12289        attributes.id = value;
12290        trustContext = {
12291          command: "\\htmlId",
12292          id: value
12293        };
12294        break;
12295
12296      case "\\htmlStyle":
12297        attributes.style = value;
12298        trustContext = {
12299          command: "\\htmlStyle",
12300          style: value
12301        };
12302        break;
12303
12304      case "\\htmlData":
12305        {
12306          var data = value.split(",");
12307
12308          for (var i = 0; i < data.length; i++) {
12309            var keyVal = data[i].split("=");
12310
12311            if (keyVal.length !== 2) {
12312              throw new ParseError("Error parsing key-value for \\htmlData");
12313            }
12314
12315            attributes["data-" + keyVal[0].trim()] = keyVal[1].trim();
12316          }
12317
12318          trustContext = {
12319            command: "\\htmlData",
12320            attributes
12321          };
12322          break;
12323        }
12324
12325      default:
12326        throw new Error("Unrecognized html command");
12327    }
12328
12329    if (!parser.settings.isTrusted(trustContext)) {
12330      return parser.formatUnsupportedCmd(funcName);
12331    }
12332
12333    return {
12334      type: "html",
12335      mode: parser.mode,
12336      attributes,
12337      body: ordargument(body)
12338    };
12339  },
12340  htmlBuilder: (group, options) => {
12341    var elements = buildExpression$1(group.body, options, false);
12342    var classes = ["enclosing"];
12343
12344    if (group.attributes.class) {
12345      classes.push(...group.attributes.class.trim().split(/\s+/));
12346    }
12347
12348    var span = buildCommon.makeSpan(classes, elements, options);
12349
12350    for (var attr in group.attributes) {
12351      if (attr !== "class" && group.attributes.hasOwnProperty(attr)) {
12352        span.setAttribute(attr, group.attributes[attr]);
12353      }
12354    }
12355
12356    return span;
12357  },
12358  mathmlBuilder: (group, options) => {
12359    return buildExpressionRow(group.body, options);
12360  }
12361});
12362
12363defineFunction({
12364  type: "htmlmathml",
12365  names: ["\\html@mathml"],
12366  props: {
12367    numArgs: 2,
12368    allowedInText: true
12369  },
12370  handler: (_ref, args) => {
12371    var {
12372      parser
12373    } = _ref;
12374    return {
12375      type: "htmlmathml",
12376      mode: parser.mode,
12377      html: ordargument(args[0]),
12378      mathml: ordargument(args[1])
12379    };
12380  },
12381  htmlBuilder: (group, options) => {
12382    var elements = buildExpression$1(group.html, options, false);
12383    return buildCommon.makeFragment(elements);
12384  },
12385  mathmlBuilder: (group, options) => {
12386    return buildExpressionRow(group.mathml, options);
12387  }
12388});
12389
12390var sizeData = function sizeData(str) {
12391  if (/^[-+]? *(\d+(\.\d*)?|\.\d+)$/.test(str)) {
12392    // str is a number with no unit specified.
12393    // default unit is bp, per graphix package.
12394    return {
12395      number: +str,
12396      unit: "bp"
12397    };
12398  } else {
12399    var match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(str);
12400
12401    if (!match) {
12402      throw new ParseError("Invalid size: '" + str + "' in \\includegraphics");
12403    }
12404
12405    var data = {
12406      number: +(match[1] + match[2]),
12407      // sign + magnitude, cast to number
12408      unit: match[3]
12409    };
12410
12411    if (!validUnit(data)) {
12412      throw new ParseError("Invalid unit: '" + data.unit + "' in \\includegraphics.");
12413    }
12414
12415    return data;
12416  }
12417};
12418
12419defineFunction({
12420  type: "includegraphics",
12421  names: ["\\includegraphics"],
12422  props: {
12423    numArgs: 1,
12424    numOptionalArgs: 1,
12425    argTypes: ["raw", "url"],
12426    allowedInText: false
12427  },
12428  handler: (_ref, args, optArgs) => {
12429    var {
12430      parser
12431    } = _ref;
12432    var width = {
12433      number: 0,
12434      unit: "em"
12435    };
12436    var height = {
12437      number: 0.9,
12438      unit: "em"
12439    }; // sorta character sized.
12440
12441    var totalheight = {
12442      number: 0,
12443      unit: "em"
12444    };
12445    var alt = "";
12446
12447    if (optArgs[0]) {
12448      var attributeStr = assertNodeType(optArgs[0], "raw").string; // Parser.js does not parse key/value pairs. We get a string.
12449
12450      var attributes = attributeStr.split(",");
12451
12452      for (var i = 0; i < attributes.length; i++) {
12453        var keyVal = attributes[i].split("=");
12454
12455        if (keyVal.length === 2) {
12456          var str = keyVal[1].trim();
12457
12458          switch (keyVal[0].trim()) {
12459            case "alt":
12460              alt = str;
12461              break;
12462
12463            case "width":
12464              width = sizeData(str);
12465              break;
12466
12467            case "height":
12468              height = sizeData(str);
12469              break;
12470
12471            case "totalheight":
12472              totalheight = sizeData(str);
12473              break;
12474
12475            default:
12476              throw new ParseError("Invalid key: '" + keyVal[0] + "' in \\includegraphics.");
12477          }
12478        }
12479      }
12480    }
12481
12482    var src = assertNodeType(args[0], "url").url;
12483
12484    if (alt === "") {
12485      // No alt given. Use the file name. Strip away the path.
12486      alt = src;
12487      alt = alt.replace(/^.*[\\/]/, '');
12488      alt = alt.substring(0, alt.lastIndexOf('.'));
12489    }
12490
12491    if (!parser.settings.isTrusted({
12492      command: "\\includegraphics",
12493      url: src
12494    })) {
12495      return parser.formatUnsupportedCmd("\\includegraphics");
12496    }
12497
12498    return {
12499      type: "includegraphics",
12500      mode: parser.mode,
12501      alt: alt,
12502      width: width,
12503      height: height,
12504      totalheight: totalheight,
12505      src: src
12506    };
12507  },
12508  htmlBuilder: (group, options) => {
12509    var height = calculateSize(group.height, options);
12510    var depth = 0;
12511
12512    if (group.totalheight.number > 0) {
12513      depth = calculateSize(group.totalheight, options) - height;
12514    }
12515
12516    var width = 0;
12517
12518    if (group.width.number > 0) {
12519      width = calculateSize(group.width, options);
12520    }
12521
12522    var style = {
12523      height: makeEm(height + depth)
12524    };
12525
12526    if (width > 0) {
12527      style.width = makeEm(width);
12528    }
12529
12530    if (depth > 0) {
12531      style.verticalAlign = makeEm(-depth);
12532    }
12533
12534    var node = new Img(group.src, group.alt, style);
12535    node.height = height;
12536    node.depth = depth;
12537    return node;
12538  },
12539  mathmlBuilder: (group, options) => {
12540    var node = new mathMLTree.MathNode("mglyph", []);
12541    node.setAttribute("alt", group.alt);
12542    var height = calculateSize(group.height, options);
12543    var depth = 0;
12544
12545    if (group.totalheight.number > 0) {
12546      depth = calculateSize(group.totalheight, options) - height;
12547      node.setAttribute("valign", makeEm(-depth));
12548    }
12549
12550    node.setAttribute("height", makeEm(height + depth));
12551
12552    if (group.width.number > 0) {
12553      var width = calculateSize(group.width, options);
12554      node.setAttribute("width", makeEm(width));
12555    }
12556
12557    node.setAttribute("src", group.src);
12558    return node;
12559  }
12560});
12561
12562// Horizontal spacing commands
12563
12564defineFunction({
12565  type: "kern",
12566  names: ["\\kern", "\\mkern", "\\hskip", "\\mskip"],
12567  props: {
12568    numArgs: 1,
12569    argTypes: ["size"],
12570    primitive: true,
12571    allowedInText: true
12572  },
12573
12574  handler(_ref, args) {
12575    var {
12576      parser,
12577      funcName
12578    } = _ref;
12579    var size = assertNodeType(args[0], "size");
12580
12581    if (parser.settings.strict) {
12582      var mathFunction = funcName[1] === 'm'; // \mkern, \mskip
12583
12584      var muUnit = size.value.unit === 'mu';
12585
12586      if (mathFunction) {
12587        if (!muUnit) {
12588          parser.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + funcName + " supports only mu units, " + ("not " + size.value.unit + " units"));
12589        }
12590
12591        if (parser.mode !== "math") {
12592          parser.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + funcName + " works only in math mode");
12593        }
12594      } else {
12595        // !mathFunction
12596        if (muUnit) {
12597          parser.settings.reportNonstrict("mathVsTextUnits", "LaTeX's " + funcName + " doesn't support mu units");
12598        }
12599      }
12600    }
12601
12602    return {
12603      type: "kern",
12604      mode: parser.mode,
12605      dimension: size.value
12606    };
12607  },
12608
12609  htmlBuilder(group, options) {
12610    return buildCommon.makeGlue(group.dimension, options);
12611  },
12612
12613  mathmlBuilder(group, options) {
12614    var dimension = calculateSize(group.dimension, options);
12615    return new mathMLTree.SpaceNode(dimension);
12616  }
12617
12618});
12619
12620// Horizontal overlap functions
12621defineFunction({
12622  type: "lap",
12623  names: ["\\mathllap", "\\mathrlap", "\\mathclap"],
12624  props: {
12625    numArgs: 1,
12626    allowedInText: true
12627  },
12628  handler: (_ref, args) => {
12629    var {
12630      parser,
12631      funcName
12632    } = _ref;
12633    var body = args[0];
12634    return {
12635      type: "lap",
12636      mode: parser.mode,
12637      alignment: funcName.slice(5),
12638      body
12639    };
12640  },
12641  htmlBuilder: (group, options) => {
12642    // mathllap, mathrlap, mathclap
12643    var inner;
12644
12645    if (group.alignment === "clap") {
12646      // ref: https://www.math.lsu.edu/~aperlis/publications/mathclap/
12647      inner = buildCommon.makeSpan([], [buildGroup$1(group.body, options)]); // wrap, since CSS will center a .clap > .inner > span
12648
12649      inner = buildCommon.makeSpan(["inner"], [inner], options);
12650    } else {
12651      inner = buildCommon.makeSpan(["inner"], [buildGroup$1(group.body, options)]);
12652    }
12653
12654    var fix = buildCommon.makeSpan(["fix"], []);
12655    var node = buildCommon.makeSpan([group.alignment], [inner, fix], options); // At this point, we have correctly set horizontal alignment of the
12656    // two items involved in the lap.
12657    // Next, use a strut to set the height of the HTML bounding box.
12658    // Otherwise, a tall argument may be misplaced.
12659    // This code resolved issue #1153
12660
12661    var strut = buildCommon.makeSpan(["strut"]);
12662    strut.style.height = makeEm(node.height + node.depth);
12663
12664    if (node.depth) {
12665      strut.style.verticalAlign = makeEm(-node.depth);
12666    }
12667
12668    node.children.unshift(strut); // Next, prevent vertical misplacement when next to something tall.
12669    // This code resolves issue #1234
12670
12671    node = buildCommon.makeSpan(["thinbox"], [node], options);
12672    return buildCommon.makeSpan(["mord", "vbox"], [node], options);
12673  },
12674  mathmlBuilder: (group, options) => {
12675    // mathllap, mathrlap, mathclap
12676    var node = new mathMLTree.MathNode("mpadded", [buildGroup(group.body, options)]);
12677
12678    if (group.alignment !== "rlap") {
12679      var offset = group.alignment === "llap" ? "-1" : "-0.5";
12680      node.setAttribute("lspace", offset + "width");
12681    }
12682
12683    node.setAttribute("width", "0px");
12684    return node;
12685  }
12686});
12687
12688defineFunction({
12689  type: "styling",
12690  names: ["\\(", "$"],
12691  props: {
12692    numArgs: 0,
12693    allowedInText: true,
12694    allowedInMath: false
12695  },
12696
12697  handler(_ref, args) {
12698    var {
12699      funcName,
12700      parser
12701    } = _ref;
12702    var outerMode = parser.mode;
12703    parser.switchMode("math");
12704    var close = funcName === "\\(" ? "\\)" : "$";
12705    var body = parser.parseExpression(false, close);
12706    parser.expect(close);
12707    parser.switchMode(outerMode);
12708    return {
12709      type: "styling",
12710      mode: parser.mode,
12711      style: "text",
12712      body
12713    };
12714  }
12715
12716}); // Check for extra closing math delimiters
12717
12718defineFunction({
12719  type: "text",
12720  // Doesn't matter what this is.
12721  names: ["\\)", "\\]"],
12722  props: {
12723    numArgs: 0,
12724    allowedInText: true,
12725    allowedInMath: false
12726  },
12727
12728  handler(context, args) {
12729    throw new ParseError("Mismatched " + context.funcName);
12730  }
12731
12732});
12733
12734var chooseMathStyle = (group, options) => {
12735  switch (options.style.size) {
12736    case Style$1.DISPLAY.size:
12737      return group.display;
12738
12739    case Style$1.TEXT.size:
12740      return group.text;
12741
12742    case Style$1.SCRIPT.size:
12743      return group.script;
12744
12745    case Style$1.SCRIPTSCRIPT.size:
12746      return group.scriptscript;
12747
12748    default:
12749      return group.text;
12750  }
12751};
12752
12753defineFunction({
12754  type: "mathchoice",
12755  names: ["\\mathchoice"],
12756  props: {
12757    numArgs: 4,
12758    primitive: true
12759  },
12760  handler: (_ref, args) => {
12761    var {
12762      parser
12763    } = _ref;
12764    return {
12765      type: "mathchoice",
12766      mode: parser.mode,
12767      display: ordargument(args[0]),
12768      text: ordargument(args[1]),
12769      script: ordargument(args[2]),
12770      scriptscript: ordargument(args[3])
12771    };
12772  },
12773  htmlBuilder: (group, options) => {
12774    var body = chooseMathStyle(group, options);
12775    var elements = buildExpression$1(body, options, false);
12776    return buildCommon.makeFragment(elements);
12777  },
12778  mathmlBuilder: (group, options) => {
12779    var body = chooseMathStyle(group, options);
12780    return buildExpressionRow(body, options);
12781  }
12782});
12783
12784var assembleSupSub = (base, supGroup, subGroup, options, style, slant, baseShift) => {
12785  base = buildCommon.makeSpan([], [base]);
12786  var subIsSingleCharacter = subGroup && utils.isCharacterBox(subGroup);
12787  var sub;
12788  var sup; // We manually have to handle the superscripts and subscripts. This,
12789  // aside from the kern calculations, is copied from supsub.
12790
12791  if (supGroup) {
12792    var elem = buildGroup$1(supGroup, options.havingStyle(style.sup()), options);
12793    sup = {
12794      elem,
12795      kern: Math.max(options.fontMetrics().bigOpSpacing1, options.fontMetrics().bigOpSpacing3 - elem.depth)
12796    };
12797  }
12798
12799  if (subGroup) {
12800    var _elem = buildGroup$1(subGroup, options.havingStyle(style.sub()), options);
12801
12802    sub = {
12803      elem: _elem,
12804      kern: Math.max(options.fontMetrics().bigOpSpacing2, options.fontMetrics().bigOpSpacing4 - _elem.height)
12805    };
12806  } // Build the final group as a vlist of the possible subscript, base,
12807  // and possible superscript.
12808
12809
12810  var finalGroup;
12811
12812  if (sup && sub) {
12813    var bottom = options.fontMetrics().bigOpSpacing5 + sub.elem.height + sub.elem.depth + sub.kern + base.depth + baseShift;
12814    finalGroup = buildCommon.makeVList({
12815      positionType: "bottom",
12816      positionData: bottom,
12817      children: [{
12818        type: "kern",
12819        size: options.fontMetrics().bigOpSpacing5
12820      }, {
12821        type: "elem",
12822        elem: sub.elem,
12823        marginLeft: makeEm(-slant)
12824      }, {
12825        type: "kern",
12826        size: sub.kern
12827      }, {
12828        type: "elem",
12829        elem: base
12830      }, {
12831        type: "kern",
12832        size: sup.kern
12833      }, {
12834        type: "elem",
12835        elem: sup.elem,
12836        marginLeft: makeEm(slant)
12837      }, {
12838        type: "kern",
12839        size: options.fontMetrics().bigOpSpacing5
12840      }]
12841    }, options);
12842  } else if (sub) {
12843    var top = base.height - baseShift; // Shift the limits by the slant of the symbol. Note
12844    // that we are supposed to shift the limits by 1/2 of the slant,
12845    // but since we are centering the limits adding a full slant of
12846    // margin will shift by 1/2 that.
12847
12848    finalGroup = buildCommon.makeVList({
12849      positionType: "top",
12850      positionData: top,
12851      children: [{
12852        type: "kern",
12853        size: options.fontMetrics().bigOpSpacing5
12854      }, {
12855        type: "elem",
12856        elem: sub.elem,
12857        marginLeft: makeEm(-slant)
12858      }, {
12859        type: "kern",
12860        size: sub.kern
12861      }, {
12862        type: "elem",
12863        elem: base
12864      }]
12865    }, options);
12866  } else if (sup) {
12867    var _bottom = base.depth + baseShift;
12868
12869    finalGroup = buildCommon.makeVList({
12870      positionType: "bottom",
12871      positionData: _bottom,
12872      children: [{
12873        type: "elem",
12874        elem: base
12875      }, {
12876        type: "kern",
12877        size: sup.kern
12878      }, {
12879        type: "elem",
12880        elem: sup.elem,
12881        marginLeft: makeEm(slant)
12882      }, {
12883        type: "kern",
12884        size: options.fontMetrics().bigOpSpacing5
12885      }]
12886    }, options);
12887  } else {
12888    // This case probably shouldn't occur (this would mean the
12889    // supsub was sending us a group with no superscript or
12890    // subscript) but be safe.
12891    return base;
12892  }
12893
12894  var parts = [finalGroup];
12895
12896  if (sub && slant !== 0 && !subIsSingleCharacter) {
12897    // A negative margin-left was applied to the lower limit.
12898    // Avoid an overlap by placing a spacer on the left on the group.
12899    var spacer = buildCommon.makeSpan(["mspace"], [], options);
12900    spacer.style.marginRight = makeEm(slant);
12901    parts.unshift(spacer);
12902  }
12903
12904  return buildCommon.makeSpan(["mop", "op-limits"], parts, options);
12905};
12906
12907// Limits, symbols
12908// Most operators have a large successor symbol, but these don't.
12909var noSuccessor = ["\\smallint"]; // NOTE: Unlike most `htmlBuilder`s, this one handles not only "op", but also
12910// "supsub" since some of them (like \int) can affect super/subscripting.
12911
12912var htmlBuilder$2 = (grp, options) => {
12913  // Operators are handled in the TeXbook pg. 443-444, rule 13(a).
12914  var supGroup;
12915  var subGroup;
12916  var hasLimits = false;
12917  var group;
12918
12919  if (grp.type === "supsub") {
12920    // If we have limits, supsub will pass us its group to handle. Pull
12921    // out the superscript and subscript and set the group to the op in
12922    // its base.
12923    supGroup = grp.sup;
12924    subGroup = grp.sub;
12925    group = assertNodeType(grp.base, "op");
12926    hasLimits = true;
12927  } else {
12928    group = assertNodeType(grp, "op");
12929  }
12930
12931  var style = options.style;
12932  var large = false;
12933
12934  if (style.size === Style$1.DISPLAY.size && group.symbol && !utils.contains(noSuccessor, group.name)) {
12935    // Most symbol operators get larger in displaystyle (rule 13)
12936    large = true;
12937  }
12938
12939  var base;
12940
12941  if (group.symbol) {
12942    // If this is a symbol, create the symbol.
12943    var fontName = large ? "Size2-Regular" : "Size1-Regular";
12944    var stash = "";
12945
12946    if (group.name === "\\oiint" || group.name === "\\oiiint") {
12947      // No font glyphs yet, so use a glyph w/o the oval.
12948      // TODO: When font glyphs are available, delete this code.
12949      stash = group.name.substr(1);
12950      group.name = stash === "oiint" ? "\\iint" : "\\iiint";
12951    }
12952
12953    base = buildCommon.makeSymbol(group.name, fontName, "math", options, ["mop", "op-symbol", large ? "large-op" : "small-op"]);
12954
12955    if (stash.length > 0) {
12956      // We're in \oiint or \oiiint. Overlay the oval.
12957      // TODO: When font glyphs are available, delete this code.
12958      var italic = base.italic;
12959      var oval = buildCommon.staticSvg(stash + "Size" + (large ? "2" : "1"), options);
12960      base = buildCommon.makeVList({
12961        positionType: "individualShift",
12962        children: [{
12963          type: "elem",
12964          elem: base,
12965          shift: 0
12966        }, {
12967          type: "elem",
12968          elem: oval,
12969          shift: large ? 0.08 : 0
12970        }]
12971      }, options);
12972      group.name = "\\" + stash;
12973      base.classes.unshift("mop"); // $FlowFixMe
12974
12975      base.italic = italic;
12976    }
12977  } else if (group.body) {
12978    // If this is a list, compose that list.
12979    var inner = buildExpression$1(group.body, options, true);
12980
12981    if (inner.length === 1 && inner[0] instanceof SymbolNode) {
12982      base = inner[0];
12983      base.classes[0] = "mop"; // replace old mclass
12984    } else {
12985      base = buildCommon.makeSpan(["mop"], inner, options);
12986    }
12987  } else {
12988    // Otherwise, this is a text operator. Build the text from the
12989    // operator's name.
12990    var output = [];
12991
12992    for (var i = 1; i < group.name.length; i++) {
12993      output.push(buildCommon.mathsym(group.name[i], group.mode, options));
12994    }
12995
12996    base = buildCommon.makeSpan(["mop"], output, options);
12997  } // If content of op is a single symbol, shift it vertically.
12998
12999
13000  var baseShift = 0;
13001  var slant = 0;
13002
13003  if ((base instanceof SymbolNode || group.name === "\\oiint" || group.name === "\\oiiint") && !group.suppressBaseShift) {
13004    // We suppress the shift of the base of \overset and \underset. Otherwise,
13005    // shift the symbol so its center lies on the axis (rule 13). It
13006    // appears that our fonts have the centers of the symbols already
13007    // almost on the axis, so these numbers are very small. Note we
13008    // don't actually apply this here, but instead it is used either in
13009    // the vlist creation or separately when there are no limits.
13010    baseShift = (base.height - base.depth) / 2 - options.fontMetrics().axisHeight; // The slant of the symbol is just its italic correction.
13011    // $FlowFixMe
13012
13013    slant = base.italic;
13014  }
13015
13016  if (hasLimits) {
13017    return assembleSupSub(base, supGroup, subGroup, options, style, slant, baseShift);
13018  } else {
13019    if (baseShift) {
13020      base.style.position = "relative";
13021      base.style.top = makeEm(baseShift);
13022    }
13023
13024    return base;
13025  }
13026};
13027
13028var mathmlBuilder$1 = (group, options) => {
13029  var node;
13030
13031  if (group.symbol) {
13032    // This is a symbol. Just add the symbol.
13033    node = new MathNode("mo", [makeText(group.name, group.mode)]);
13034
13035    if (utils.contains(noSuccessor, group.name)) {
13036      node.setAttribute("largeop", "false");
13037    }
13038  } else if (group.body) {
13039    // This is an operator with children. Add them.
13040    node = new MathNode("mo", buildExpression(group.body, options));
13041  } else {
13042    // This is a text operator. Add all of the characters from the
13043    // operator's name.
13044    node = new MathNode("mi", [new TextNode(group.name.slice(1))]); // Append an <mo>&ApplyFunction;</mo>.
13045    // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4
13046
13047    var operator = new MathNode("mo", [makeText("\u2061", "text")]);
13048
13049    if (group.parentIsSupSub) {
13050      node = new MathNode("mrow", [node, operator]);
13051    } else {
13052      node = newDocumentFragment([node, operator]);
13053    }
13054  }
13055
13056  return node;
13057};
13058
13059var singleCharBigOps = {
13060  "\u220F": "\\prod",
13061  "\u2210": "\\coprod",
13062  "\u2211": "\\sum",
13063  "\u22c0": "\\bigwedge",
13064  "\u22c1": "\\bigvee",
13065  "\u22c2": "\\bigcap",
13066  "\u22c3": "\\bigcup",
13067  "\u2a00": "\\bigodot",
13068  "\u2a01": "\\bigoplus",
13069  "\u2a02": "\\bigotimes",
13070  "\u2a04": "\\biguplus",
13071  "\u2a06": "\\bigsqcup"
13072};
13073defineFunction({
13074  type: "op",
13075  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"],
13076  props: {
13077    numArgs: 0
13078  },
13079  handler: (_ref, args) => {
13080    var {
13081      parser,
13082      funcName
13083    } = _ref;
13084    var fName = funcName;
13085
13086    if (fName.length === 1) {
13087      fName = singleCharBigOps[fName];
13088    }
13089
13090    return {
13091      type: "op",
13092      mode: parser.mode,
13093      limits: true,
13094      parentIsSupSub: false,
13095      symbol: true,
13096      name: fName
13097    };
13098  },
13099  htmlBuilder: htmlBuilder$2,
13100  mathmlBuilder: mathmlBuilder$1
13101}); // Note: calling defineFunction with a type that's already been defined only
13102// works because the same htmlBuilder and mathmlBuilder are being used.
13103
13104defineFunction({
13105  type: "op",
13106  names: ["\\mathop"],
13107  props: {
13108    numArgs: 1,
13109    primitive: true
13110  },
13111  handler: (_ref2, args) => {
13112    var {
13113      parser
13114    } = _ref2;
13115    var body = args[0];
13116    return {
13117      type: "op",
13118      mode: parser.mode,
13119      limits: false,
13120      parentIsSupSub: false,
13121      symbol: false,
13122      body: ordargument(body)
13123    };
13124  },
13125  htmlBuilder: htmlBuilder$2,
13126  mathmlBuilder: mathmlBuilder$1
13127}); // There are 2 flags for operators; whether they produce limits in
13128// displaystyle, and whether they are symbols and should grow in
13129// displaystyle. These four groups cover the four possible choices.
13130
13131var singleCharIntegrals = {
13132  "\u222b": "\\int",
13133  "\u222c": "\\iint",
13134  "\u222d": "\\iiint",
13135  "\u222e": "\\oint",
13136  "\u222f": "\\oiint",
13137  "\u2230": "\\oiiint"
13138}; // No limits, not symbols
13139
13140defineFunction({
13141  type: "op",
13142  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"],
13143  props: {
13144    numArgs: 0
13145  },
13146
13147  handler(_ref3) {
13148    var {
13149      parser,
13150      funcName
13151    } = _ref3;
13152    return {
13153      type: "op",
13154      mode: parser.mode,
13155      limits: false,
13156      parentIsSupSub: false,
13157      symbol: false,
13158      name: funcName
13159    };
13160  },
13161
13162  htmlBuilder: htmlBuilder$2,
13163  mathmlBuilder: mathmlBuilder$1
13164}); // Limits, not symbols
13165
13166defineFunction({
13167  type: "op",
13168  names: ["\\det", "\\gcd", "\\inf", "\\lim", "\\max", "\\min", "\\Pr", "\\sup"],
13169  props: {
13170    numArgs: 0
13171  },
13172
13173  handler(_ref4) {
13174    var {
13175      parser,
13176      funcName
13177    } = _ref4;
13178    return {
13179      type: "op",
13180      mode: parser.mode,
13181      limits: true,
13182      parentIsSupSub: false,
13183      symbol: false,
13184      name: funcName
13185    };
13186  },
13187
13188  htmlBuilder: htmlBuilder$2,
13189  mathmlBuilder: mathmlBuilder$1
13190}); // No limits, symbols
13191
13192defineFunction({
13193  type: "op",
13194  names: ["\\int", "\\iint", "\\iiint", "\\oint", "\\oiint", "\\oiiint", "\u222b", "\u222c", "\u222d", "\u222e", "\u222f", "\u2230"],
13195  props: {
13196    numArgs: 0
13197  },
13198
13199  handler(_ref5) {
13200    var {
13201      parser,
13202      funcName
13203    } = _ref5;
13204    var fName = funcName;
13205
13206    if (fName.length === 1) {
13207      fName = singleCharIntegrals[fName];
13208    }
13209
13210    return {
13211      type: "op",
13212      mode: parser.mode,
13213      limits: false,
13214      parentIsSupSub: false,
13215      symbol: true,
13216      name: fName
13217    };
13218  },
13219
13220  htmlBuilder: htmlBuilder$2,
13221  mathmlBuilder: mathmlBuilder$1
13222});
13223
13224// NOTE: Unlike most `htmlBuilder`s, this one handles not only
13225// "operatorname", but also  "supsub" since \operatorname* can
13226// affect super/subscripting.
13227var htmlBuilder$1 = (grp, options) => {
13228  // Operators are handled in the TeXbook pg. 443-444, rule 13(a).
13229  var supGroup;
13230  var subGroup;
13231  var hasLimits = false;
13232  var group;
13233
13234  if (grp.type === "supsub") {
13235    // If we have limits, supsub will pass us its group to handle. Pull
13236    // out the superscript and subscript and set the group to the op in
13237    // its base.
13238    supGroup = grp.sup;
13239    subGroup = grp.sub;
13240    group = assertNodeType(grp.base, "operatorname");
13241    hasLimits = true;
13242  } else {
13243    group = assertNodeType(grp, "operatorname");
13244  }
13245
13246  var base;
13247
13248  if (group.body.length > 0) {
13249    var body = group.body.map(child => {
13250      // $FlowFixMe: Check if the node has a string `text` property.
13251      var childText = child.text;
13252
13253      if (typeof childText === "string") {
13254        return {
13255          type: "textord",
13256          mode: child.mode,
13257          text: childText
13258        };
13259      } else {
13260        return child;
13261      }
13262    }); // Consolidate function names into symbol characters.
13263
13264    var expression = buildExpression$1(body, options.withFont("mathrm"), true);
13265
13266    for (var i = 0; i < expression.length; i++) {
13267      var child = expression[i];
13268
13269      if (child instanceof SymbolNode) {
13270        // Per amsopn package,
13271        // change minus to hyphen and \ast to asterisk
13272        child.text = child.text.replace(/\u2212/, "-").replace(/\u2217/, "*");
13273      }
13274    }
13275
13276    base = buildCommon.makeSpan(["mop"], expression, options);
13277  } else {
13278    base = buildCommon.makeSpan(["mop"], [], options);
13279  }
13280
13281  if (hasLimits) {
13282    return assembleSupSub(base, supGroup, subGroup, options, options.style, 0, 0);
13283  } else {
13284    return base;
13285  }
13286};
13287
13288var mathmlBuilder = (group, options) => {
13289  // The steps taken here are similar to the html version.
13290  var expression = buildExpression(group.body, options.withFont("mathrm")); // Is expression a string or has it something like a fraction?
13291
13292  var isAllString = true; // default
13293
13294  for (var i = 0; i < expression.length; i++) {
13295    var node = expression[i];
13296
13297    if (node instanceof mathMLTree.SpaceNode) ; else if (node instanceof mathMLTree.MathNode) {
13298      switch (node.type) {
13299        case "mi":
13300        case "mn":
13301        case "ms":
13302        case "mspace":
13303        case "mtext":
13304          break;
13305        // Do nothing yet.
13306
13307        case "mo":
13308          {
13309            var child = node.children[0];
13310
13311            if (node.children.length === 1 && child instanceof mathMLTree.TextNode) {
13312              child.text = child.text.replace(/\u2212/, "-").replace(/\u2217/, "*");
13313            } else {
13314              isAllString = false;
13315            }
13316
13317            break;
13318          }
13319
13320        default:
13321          isAllString = false;
13322      }
13323    } else {
13324      isAllString = false;
13325    }
13326  }
13327
13328  if (isAllString) {
13329    // Write a single TextNode instead of multiple nested tags.
13330    var word = expression.map(node => node.toText()).join("");
13331    expression = [new mathMLTree.TextNode(word)];
13332  }
13333
13334  var identifier = new mathMLTree.MathNode("mi", expression);
13335  identifier.setAttribute("mathvariant", "normal"); // \u2061 is the same as &ApplyFunction;
13336  // ref: https://www.w3schools.com/charsets/ref_html_entities_a.asp
13337
13338  var operator = new mathMLTree.MathNode("mo", [makeText("\u2061", "text")]);
13339
13340  if (group.parentIsSupSub) {
13341    return new mathMLTree.MathNode("mrow", [identifier, operator]);
13342  } else {
13343    return mathMLTree.newDocumentFragment([identifier, operator]);
13344  }
13345}; // \operatorname
13346// amsopn.dtx: \mathop{#1\kern\z@\operator@font#3}\newmcodes@
13347
13348
13349defineFunction({
13350  type: "operatorname",
13351  names: ["\\operatorname@", "\\operatornamewithlimits"],
13352  props: {
13353    numArgs: 1
13354  },
13355  handler: (_ref, args) => {
13356    var {
13357      parser,
13358      funcName
13359    } = _ref;
13360    var body = args[0];
13361    return {
13362      type: "operatorname",
13363      mode: parser.mode,
13364      body: ordargument(body),
13365      alwaysHandleSupSub: funcName === "\\operatornamewithlimits",
13366      limits: false,
13367      parentIsSupSub: false
13368    };
13369  },
13370  htmlBuilder: htmlBuilder$1,
13371  mathmlBuilder
13372});
13373defineMacro("\\operatorname", "\\@ifstar\\operatornamewithlimits\\operatorname@");
13374
13375defineFunctionBuilders({
13376  type: "ordgroup",
13377
13378  htmlBuilder(group, options) {
13379    if (group.semisimple) {
13380      return buildCommon.makeFragment(buildExpression$1(group.body, options, false));
13381    }
13382
13383    return buildCommon.makeSpan(["mord"], buildExpression$1(group.body, options, true), options);
13384  },
13385
13386  mathmlBuilder(group, options) {
13387    return buildExpressionRow(group.body, options, true);
13388  }
13389
13390});
13391
13392defineFunction({
13393  type: "overline",
13394  names: ["\\overline"],
13395  props: {
13396    numArgs: 1
13397  },
13398
13399  handler(_ref, args) {
13400    var {
13401      parser
13402    } = _ref;
13403    var body = args[0];
13404    return {
13405      type: "overline",
13406      mode: parser.mode,
13407      body
13408    };
13409  },
13410
13411  htmlBuilder(group, options) {
13412    // Overlines are handled in the TeXbook pg 443, Rule 9.
13413    // Build the inner group in the cramped style.
13414    var innerGroup = buildGroup$1(group.body, options.havingCrampedStyle()); // Create the line above the body
13415
13416    var line = buildCommon.makeLineSpan("overline-line", options); // Generate the vlist, with the appropriate kerns
13417
13418    var defaultRuleThickness = options.fontMetrics().defaultRuleThickness;
13419    var vlist = buildCommon.makeVList({
13420      positionType: "firstBaseline",
13421      children: [{
13422        type: "elem",
13423        elem: innerGroup
13424      }, {
13425        type: "kern",
13426        size: 3 * defaultRuleThickness
13427      }, {
13428        type: "elem",
13429        elem: line
13430      }, {
13431        type: "kern",
13432        size: defaultRuleThickness
13433      }]
13434    }, options);
13435    return buildCommon.makeSpan(["mord", "overline"], [vlist], options);
13436  },
13437
13438  mathmlBuilder(group, options) {
13439    var operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u203e")]);
13440    operator.setAttribute("stretchy", "true");
13441    var node = new mathMLTree.MathNode("mover", [buildGroup(group.body, options), operator]);
13442    node.setAttribute("accent", "true");
13443    return node;
13444  }
13445
13446});
13447
13448defineFunction({
13449  type: "phantom",
13450  names: ["\\phantom"],
13451  props: {
13452    numArgs: 1,
13453    allowedInText: true
13454  },
13455  handler: (_ref, args) => {
13456    var {
13457      parser
13458    } = _ref;
13459    var body = args[0];
13460    return {
13461      type: "phantom",
13462      mode: parser.mode,
13463      body: ordargument(body)
13464    };
13465  },
13466  htmlBuilder: (group, options) => {
13467    var elements = buildExpression$1(group.body, options.withPhantom(), false); // \phantom isn't supposed to affect the elements it contains.
13468    // See "color" for more details.
13469
13470    return buildCommon.makeFragment(elements);
13471  },
13472  mathmlBuilder: (group, options) => {
13473    var inner = buildExpression(group.body, options);
13474    return new mathMLTree.MathNode("mphantom", inner);
13475  }
13476});
13477defineFunction({
13478  type: "hphantom",
13479  names: ["\\hphantom"],
13480  props: {
13481    numArgs: 1,
13482    allowedInText: true
13483  },
13484  handler: (_ref2, args) => {
13485    var {
13486      parser
13487    } = _ref2;
13488    var body = args[0];
13489    return {
13490      type: "hphantom",
13491      mode: parser.mode,
13492      body
13493    };
13494  },
13495  htmlBuilder: (group, options) => {
13496    var node = buildCommon.makeSpan([], [buildGroup$1(group.body, options.withPhantom())]);
13497    node.height = 0;
13498    node.depth = 0;
13499
13500    if (node.children) {
13501      for (var i = 0; i < node.children.length; i++) {
13502        node.children[i].height = 0;
13503        node.children[i].depth = 0;
13504      }
13505    } // See smash for comment re: use of makeVList
13506
13507
13508    node = buildCommon.makeVList({
13509      positionType: "firstBaseline",
13510      children: [{
13511        type: "elem",
13512        elem: node
13513      }]
13514    }, options); // For spacing, TeX treats \smash as a math group (same spacing as ord).
13515
13516    return buildCommon.makeSpan(["mord"], [node], options);
13517  },
13518  mathmlBuilder: (group, options) => {
13519    var inner = buildExpression(ordargument(group.body), options);
13520    var phantom = new mathMLTree.MathNode("mphantom", inner);
13521    var node = new mathMLTree.MathNode("mpadded", [phantom]);
13522    node.setAttribute("height", "0px");
13523    node.setAttribute("depth", "0px");
13524    return node;
13525  }
13526});
13527defineFunction({
13528  type: "vphantom",
13529  names: ["\\vphantom"],
13530  props: {
13531    numArgs: 1,
13532    allowedInText: true
13533  },
13534  handler: (_ref3, args) => {
13535    var {
13536      parser
13537    } = _ref3;
13538    var body = args[0];
13539    return {
13540      type: "vphantom",
13541      mode: parser.mode,
13542      body
13543    };
13544  },
13545  htmlBuilder: (group, options) => {
13546    var inner = buildCommon.makeSpan(["inner"], [buildGroup$1(group.body, options.withPhantom())]);
13547    var fix = buildCommon.makeSpan(["fix"], []);
13548    return buildCommon.makeSpan(["mord", "rlap"], [inner, fix], options);
13549  },
13550  mathmlBuilder: (group, options) => {
13551    var inner = buildExpression(ordargument(group.body), options);
13552    var phantom = new mathMLTree.MathNode("mphantom", inner);
13553    var node = new mathMLTree.MathNode("mpadded", [phantom]);
13554    node.setAttribute("width", "0px");
13555    return node;
13556  }
13557});
13558
13559defineFunction({
13560  type: "raisebox",
13561  names: ["\\raisebox"],
13562  props: {
13563    numArgs: 2,
13564    argTypes: ["size", "hbox"],
13565    allowedInText: true
13566  },
13567
13568  handler(_ref, args) {
13569    var {
13570      parser
13571    } = _ref;
13572    var amount = assertNodeType(args[0], "size").value;
13573    var body = args[1];
13574    return {
13575      type: "raisebox",
13576      mode: parser.mode,
13577      dy: amount,
13578      body
13579    };
13580  },
13581
13582  htmlBuilder(group, options) {
13583    var body = buildGroup$1(group.body, options);
13584    var dy = calculateSize(group.dy, options);
13585    return buildCommon.makeVList({
13586      positionType: "shift",
13587      positionData: -dy,
13588      children: [{
13589        type: "elem",
13590        elem: body
13591      }]
13592    }, options);
13593  },
13594
13595  mathmlBuilder(group, options) {
13596    var node = new mathMLTree.MathNode("mpadded", [buildGroup(group.body, options)]);
13597    var dy = group.dy.number + group.dy.unit;
13598    node.setAttribute("voffset", dy);
13599    return node;
13600  }
13601
13602});
13603
13604defineFunction({
13605  type: "internal",
13606  names: ["\\relax"],
13607  props: {
13608    numArgs: 0,
13609    allowedInText: true
13610  },
13611
13612  handler(_ref) {
13613    var {
13614      parser
13615    } = _ref;
13616    return {
13617      type: "internal",
13618      mode: parser.mode
13619    };
13620  }
13621
13622});
13623
13624defineFunction({
13625  type: "rule",
13626  names: ["\\rule"],
13627  props: {
13628    numArgs: 2,
13629    numOptionalArgs: 1,
13630    argTypes: ["size", "size", "size"]
13631  },
13632
13633  handler(_ref, args, optArgs) {
13634    var {
13635      parser
13636    } = _ref;
13637    var shift = optArgs[0];
13638    var width = assertNodeType(args[0], "size");
13639    var height = assertNodeType(args[1], "size");
13640    return {
13641      type: "rule",
13642      mode: parser.mode,
13643      shift: shift && assertNodeType(shift, "size").value,
13644      width: width.value,
13645      height: height.value
13646    };
13647  },
13648
13649  htmlBuilder(group, options) {
13650    // Make an empty span for the rule
13651    var rule = buildCommon.makeSpan(["mord", "rule"], [], options); // Calculate the shift, width, and height of the rule, and account for units
13652
13653    var width = calculateSize(group.width, options);
13654    var height = calculateSize(group.height, options);
13655    var shift = group.shift ? calculateSize(group.shift, options) : 0; // Style the rule to the right size
13656
13657    rule.style.borderRightWidth = makeEm(width);
13658    rule.style.borderTopWidth = makeEm(height);
13659    rule.style.bottom = makeEm(shift); // Record the height and width
13660
13661    rule.width = width;
13662    rule.height = height + shift;
13663    rule.depth = -shift; // Font size is the number large enough that the browser will
13664    // reserve at least `absHeight` space above the baseline.
13665    // The 1.125 factor was empirically determined
13666
13667    rule.maxFontSize = height * 1.125 * options.sizeMultiplier;
13668    return rule;
13669  },
13670
13671  mathmlBuilder(group, options) {
13672    var width = calculateSize(group.width, options);
13673    var height = calculateSize(group.height, options);
13674    var shift = group.shift ? calculateSize(group.shift, options) : 0;
13675    var color = options.color && options.getColor() || "black";
13676    var rule = new mathMLTree.MathNode("mspace");
13677    rule.setAttribute("mathbackground", color);
13678    rule.setAttribute("width", makeEm(width));
13679    rule.setAttribute("height", makeEm(height));
13680    var wrapper = new mathMLTree.MathNode("mpadded", [rule]);
13681
13682    if (shift >= 0) {
13683      wrapper.setAttribute("height", makeEm(shift));
13684    } else {
13685      wrapper.setAttribute("height", makeEm(shift));
13686      wrapper.setAttribute("depth", makeEm(-shift));
13687    }
13688
13689    wrapper.setAttribute("voffset", makeEm(shift));
13690    return wrapper;
13691  }
13692
13693});
13694
13695function sizingGroup(value, options, baseOptions) {
13696  var inner = buildExpression$1(value, options, false);
13697  var multiplier = options.sizeMultiplier / baseOptions.sizeMultiplier; // Add size-resetting classes to the inner list and set maxFontSize
13698  // manually. Handle nested size changes.
13699
13700  for (var i = 0; i < inner.length; i++) {
13701    var pos = inner[i].classes.indexOf("sizing");
13702
13703    if (pos < 0) {
13704      Array.prototype.push.apply(inner[i].classes, options.sizingClasses(baseOptions));
13705    } else if (inner[i].classes[pos + 1] === "reset-size" + options.size) {
13706      // This is a nested size change: e.g., inner[i] is the "b" in
13707      // `\Huge a \small b`. Override the old size (the `reset-` class)
13708      // but not the new size.
13709      inner[i].classes[pos + 1] = "reset-size" + baseOptions.size;
13710    }
13711
13712    inner[i].height *= multiplier;
13713    inner[i].depth *= multiplier;
13714  }
13715
13716  return buildCommon.makeFragment(inner);
13717}
13718var sizeFuncs = ["\\tiny", "\\sixptsize", "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge"];
13719var htmlBuilder = (group, options) => {
13720  // Handle sizing operators like \Huge. Real TeX doesn't actually allow
13721  // these functions inside of math expressions, so we do some special
13722  // handling.
13723  var newOptions = options.havingSize(group.size);
13724  return sizingGroup(group.body, newOptions, options);
13725};
13726defineFunction({
13727  type: "sizing",
13728  names: sizeFuncs,
13729  props: {
13730    numArgs: 0,
13731    allowedInText: true
13732  },
13733  handler: (_ref, args) => {
13734    var {
13735      breakOnTokenText,
13736      funcName,
13737      parser
13738    } = _ref;
13739    var body = parser.parseExpression(false, breakOnTokenText);
13740    return {
13741      type: "sizing",
13742      mode: parser.mode,
13743      // Figure out what size to use based on the list of functions above
13744      size: sizeFuncs.indexOf(funcName) + 1,
13745      body
13746    };
13747  },
13748  htmlBuilder,
13749  mathmlBuilder: (group, options) => {
13750    var newOptions = options.havingSize(group.size);
13751    var inner = buildExpression(group.body, newOptions);
13752    var node = new mathMLTree.MathNode("mstyle", inner); // TODO(emily): This doesn't produce the correct size for nested size
13753    // changes, because we don't keep state of what style we're currently
13754    // in, so we can't reset the size to normal before changing it.  Now
13755    // that we're passing an options parameter we should be able to fix
13756    // this.
13757
13758    node.setAttribute("mathsize", makeEm(newOptions.sizeMultiplier));
13759    return node;
13760  }
13761});
13762
13763// smash, with optional [tb], as in AMS
13764defineFunction({
13765  type: "smash",
13766  names: ["\\smash"],
13767  props: {
13768    numArgs: 1,
13769    numOptionalArgs: 1,
13770    allowedInText: true
13771  },
13772  handler: (_ref, args, optArgs) => {
13773    var {
13774      parser
13775    } = _ref;
13776    var smashHeight = false;
13777    var smashDepth = false;
13778    var tbArg = optArgs[0] && assertNodeType(optArgs[0], "ordgroup");
13779
13780    if (tbArg) {
13781      // Optional [tb] argument is engaged.
13782      // ref: amsmath: \renewcommand{\smash}[1][tb]{%
13783      //               def\mb@t{\ht}\def\mb@b{\dp}\def\mb@tb{\ht\z@\z@\dp}%
13784      var letter = "";
13785
13786      for (var i = 0; i < tbArg.body.length; ++i) {
13787        var node = tbArg.body[i]; // $FlowFixMe: Not every node type has a `text` property.
13788
13789        letter = node.text;
13790
13791        if (letter === "t") {
13792          smashHeight = true;
13793        } else if (letter === "b") {
13794          smashDepth = true;
13795        } else {
13796          smashHeight = false;
13797          smashDepth = false;
13798          break;
13799        }
13800      }
13801    } else {
13802      smashHeight = true;
13803      smashDepth = true;
13804    }
13805
13806    var body = args[0];
13807    return {
13808      type: "smash",
13809      mode: parser.mode,
13810      body,
13811      smashHeight,
13812      smashDepth
13813    };
13814  },
13815  htmlBuilder: (group, options) => {
13816    var node = buildCommon.makeSpan([], [buildGroup$1(group.body, options)]);
13817
13818    if (!group.smashHeight && !group.smashDepth) {
13819      return node;
13820    }
13821
13822    if (group.smashHeight) {
13823      node.height = 0; // In order to influence makeVList, we have to reset the children.
13824
13825      if (node.children) {
13826        for (var i = 0; i < node.children.length; i++) {
13827          node.children[i].height = 0;
13828        }
13829      }
13830    }
13831
13832    if (group.smashDepth) {
13833      node.depth = 0;
13834
13835      if (node.children) {
13836        for (var _i = 0; _i < node.children.length; _i++) {
13837          node.children[_i].depth = 0;
13838        }
13839      }
13840    } // At this point, we've reset the TeX-like height and depth values.
13841    // But the span still has an HTML line height.
13842    // makeVList applies "display: table-cell", which prevents the browser
13843    // from acting on that line height. So we'll call makeVList now.
13844
13845
13846    var smashedNode = buildCommon.makeVList({
13847      positionType: "firstBaseline",
13848      children: [{
13849        type: "elem",
13850        elem: node
13851      }]
13852    }, options); // For spacing, TeX treats \hphantom as a math group (same spacing as ord).
13853
13854    return buildCommon.makeSpan(["mord"], [smashedNode], options);
13855  },
13856  mathmlBuilder: (group, options) => {
13857    var node = new mathMLTree.MathNode("mpadded", [buildGroup(group.body, options)]);
13858
13859    if (group.smashHeight) {
13860      node.setAttribute("height", "0px");
13861    }
13862
13863    if (group.smashDepth) {
13864      node.setAttribute("depth", "0px");
13865    }
13866
13867    return node;
13868  }
13869});
13870
13871defineFunction({
13872  type: "sqrt",
13873  names: ["\\sqrt"],
13874  props: {
13875    numArgs: 1,
13876    numOptionalArgs: 1
13877  },
13878
13879  handler(_ref, args, optArgs) {
13880    var {
13881      parser
13882    } = _ref;
13883    var index = optArgs[0];
13884    var body = args[0];
13885    return {
13886      type: "sqrt",
13887      mode: parser.mode,
13888      body,
13889      index
13890    };
13891  },
13892
13893  htmlBuilder(group, options) {
13894    // Square roots are handled in the TeXbook pg. 443, Rule 11.
13895    // First, we do the same steps as in overline to build the inner group
13896    // and line
13897    var inner = buildGroup$1(group.body, options.havingCrampedStyle());
13898
13899    if (inner.height === 0) {
13900      // Render a small surd.
13901      inner.height = options.fontMetrics().xHeight;
13902    } // Some groups can return document fragments.  Handle those by wrapping
13903    // them in a span.
13904
13905
13906    inner = buildCommon.wrapFragment(inner, options); // Calculate the minimum size for the \surd delimiter
13907
13908    var metrics = options.fontMetrics();
13909    var theta = metrics.defaultRuleThickness;
13910    var phi = theta;
13911
13912    if (options.style.id < Style$1.TEXT.id) {
13913      phi = options.fontMetrics().xHeight;
13914    } // Calculate the clearance between the body and line
13915
13916
13917    var lineClearance = theta + phi / 4;
13918    var minDelimiterHeight = inner.height + inner.depth + lineClearance + theta; // Create a sqrt SVG of the required minimum size
13919
13920    var {
13921      span: img,
13922      ruleWidth,
13923      advanceWidth
13924    } = delimiter.sqrtImage(minDelimiterHeight, options);
13925    var delimDepth = img.height - ruleWidth; // Adjust the clearance based on the delimiter size
13926
13927    if (delimDepth > inner.height + inner.depth + lineClearance) {
13928      lineClearance = (lineClearance + delimDepth - inner.height - inner.depth) / 2;
13929    } // Shift the sqrt image
13930
13931
13932    var imgShift = img.height - inner.height - lineClearance - ruleWidth;
13933    inner.style.paddingLeft = makeEm(advanceWidth); // Overlay the image and the argument.
13934
13935    var body = buildCommon.makeVList({
13936      positionType: "firstBaseline",
13937      children: [{
13938        type: "elem",
13939        elem: inner,
13940        wrapperClasses: ["svg-align"]
13941      }, {
13942        type: "kern",
13943        size: -(inner.height + imgShift)
13944      }, {
13945        type: "elem",
13946        elem: img
13947      }, {
13948        type: "kern",
13949        size: ruleWidth
13950      }]
13951    }, options);
13952
13953    if (!group.index) {
13954      return buildCommon.makeSpan(["mord", "sqrt"], [body], options);
13955    } else {
13956      // Handle the optional root index
13957      // The index is always in scriptscript style
13958      var newOptions = options.havingStyle(Style$1.SCRIPTSCRIPT);
13959      var rootm = buildGroup$1(group.index, newOptions, options); // The amount the index is shifted by. This is taken from the TeX
13960      // source, in the definition of `\r@@t`.
13961
13962      var toShift = 0.6 * (body.height - body.depth); // Build a VList with the superscript shifted up correctly
13963
13964      var rootVList = buildCommon.makeVList({
13965        positionType: "shift",
13966        positionData: -toShift,
13967        children: [{
13968          type: "elem",
13969          elem: rootm
13970        }]
13971      }, options); // Add a class surrounding it so we can add on the appropriate
13972      // kerning
13973
13974      var rootVListWrap = buildCommon.makeSpan(["root"], [rootVList]);
13975      return buildCommon.makeSpan(["mord", "sqrt"], [rootVListWrap, body], options);
13976    }
13977  },
13978
13979  mathmlBuilder(group, options) {
13980    var {
13981      body,
13982      index
13983    } = group;
13984    return index ? new mathMLTree.MathNode("mroot", [buildGroup(body, options), buildGroup(index, options)]) : new mathMLTree.MathNode("msqrt", [buildGroup(body, options)]);
13985  }
13986
13987});
13988
13989var styleMap = {
13990  "display": Style$1.DISPLAY,
13991  "text": Style$1.TEXT,
13992  "script": Style$1.SCRIPT,
13993  "scriptscript": Style$1.SCRIPTSCRIPT
13994};
13995defineFunction({
13996  type: "styling",
13997  names: ["\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle"],
13998  props: {
13999    numArgs: 0,
14000    allowedInText: true,
14001    primitive: true
14002  },
14003
14004  handler(_ref, args) {
14005    var {
14006      breakOnTokenText,
14007      funcName,
14008      parser
14009    } = _ref;
14010    // parse out the implicit body
14011    var body = parser.parseExpression(true, breakOnTokenText); // TODO: Refactor to avoid duplicating styleMap in multiple places (e.g.
14012    // here and in buildHTML and de-dupe the enumeration of all the styles).
14013    // $FlowFixMe: The names above exactly match the styles.
14014
14015    var style = funcName.slice(1, funcName.length - 5);
14016    return {
14017      type: "styling",
14018      mode: parser.mode,
14019      // Figure out what style to use by pulling out the style from
14020      // the function name
14021      style,
14022      body
14023    };
14024  },
14025
14026  htmlBuilder(group, options) {
14027    // Style changes are handled in the TeXbook on pg. 442, Rule 3.
14028    var newStyle = styleMap[group.style];
14029    var newOptions = options.havingStyle(newStyle).withFont('');
14030    return sizingGroup(group.body, newOptions, options);
14031  },
14032
14033  mathmlBuilder(group, options) {
14034    // Figure out what style we're changing to.
14035    var newStyle = styleMap[group.style];
14036    var newOptions = options.havingStyle(newStyle);
14037    var inner = buildExpression(group.body, newOptions);
14038    var node = new mathMLTree.MathNode("mstyle", inner);
14039    var styleAttributes = {
14040      "display": ["0", "true"],
14041      "text": ["0", "false"],
14042      "script": ["1", "false"],
14043      "scriptscript": ["2", "false"]
14044    };
14045    var attr = styleAttributes[group.style];
14046    node.setAttribute("scriptlevel", attr[0]);
14047    node.setAttribute("displaystyle", attr[1]);
14048    return node;
14049  }
14050
14051});
14052
14053/**
14054 * Sometimes, groups perform special rules when they have superscripts or
14055 * subscripts attached to them. This function lets the `supsub` group know that
14056 * Sometimes, groups perform special rules when they have superscripts or
14057 * its inner element should handle the superscripts and subscripts instead of
14058 * handling them itself.
14059 */
14060var htmlBuilderDelegate = function htmlBuilderDelegate(group, options) {
14061  var base = group.base;
14062
14063  if (!base) {
14064    return null;
14065  } else if (base.type === "op") {
14066    // Operators handle supsubs differently when they have limits
14067    // (e.g. `\displaystyle\sum_2^3`)
14068    var delegate = base.limits && (options.style.size === Style$1.DISPLAY.size || base.alwaysHandleSupSub);
14069    return delegate ? htmlBuilder$2 : null;
14070  } else if (base.type === "operatorname") {
14071    var _delegate = base.alwaysHandleSupSub && (options.style.size === Style$1.DISPLAY.size || base.limits);
14072
14073    return _delegate ? htmlBuilder$1 : null;
14074  } else if (base.type === "accent") {
14075    return utils.isCharacterBox(base.base) ? htmlBuilder$a : null;
14076  } else if (base.type === "horizBrace") {
14077    var isSup = !group.sub;
14078    return isSup === base.isOver ? htmlBuilder$3 : null;
14079  } else {
14080    return null;
14081  }
14082}; // Super scripts and subscripts, whose precise placement can depend on other
14083// functions that precede them.
14084
14085
14086defineFunctionBuilders({
14087  type: "supsub",
14088
14089  htmlBuilder(group, options) {
14090    // Superscript and subscripts are handled in the TeXbook on page
14091    // 445-446, rules 18(a-f).
14092    // Here is where we defer to the inner group if it should handle
14093    // superscripts and subscripts itself.
14094    var builderDelegate = htmlBuilderDelegate(group, options);
14095
14096    if (builderDelegate) {
14097      return builderDelegate(group, options);
14098    }
14099
14100    var {
14101      base: valueBase,
14102      sup: valueSup,
14103      sub: valueSub
14104    } = group;
14105    var base = buildGroup$1(valueBase, options);
14106    var supm;
14107    var subm;
14108    var metrics = options.fontMetrics(); // Rule 18a
14109
14110    var supShift = 0;
14111    var subShift = 0;
14112    var isCharacterBox = valueBase && utils.isCharacterBox(valueBase);
14113
14114    if (valueSup) {
14115      var newOptions = options.havingStyle(options.style.sup());
14116      supm = buildGroup$1(valueSup, newOptions, options);
14117
14118      if (!isCharacterBox) {
14119        supShift = base.height - newOptions.fontMetrics().supDrop * newOptions.sizeMultiplier / options.sizeMultiplier;
14120      }
14121    }
14122
14123    if (valueSub) {
14124      var _newOptions = options.havingStyle(options.style.sub());
14125
14126      subm = buildGroup$1(valueSub, _newOptions, options);
14127
14128      if (!isCharacterBox) {
14129        subShift = base.depth + _newOptions.fontMetrics().subDrop * _newOptions.sizeMultiplier / options.sizeMultiplier;
14130      }
14131    } // Rule 18c
14132
14133
14134    var minSupShift;
14135
14136    if (options.style === Style$1.DISPLAY) {
14137      minSupShift = metrics.sup1;
14138    } else if (options.style.cramped) {
14139      minSupShift = metrics.sup3;
14140    } else {
14141      minSupShift = metrics.sup2;
14142    } // scriptspace is a font-size-independent size, so scale it
14143    // appropriately for use as the marginRight.
14144
14145
14146    var multiplier = options.sizeMultiplier;
14147    var marginRight = makeEm(0.5 / metrics.ptPerEm / multiplier);
14148    var marginLeft = null;
14149
14150    if (subm) {
14151      // Subscripts shouldn't be shifted by the base's italic correction.
14152      // Account for that by shifting the subscript back the appropriate
14153      // amount. Note we only do this when the base is a single symbol.
14154      var isOiint = group.base && group.base.type === "op" && group.base.name && (group.base.name === "\\oiint" || group.base.name === "\\oiiint");
14155
14156      if (base instanceof SymbolNode || isOiint) {
14157        // $FlowFixMe
14158        marginLeft = makeEm(-base.italic);
14159      }
14160    }
14161
14162    var supsub;
14163
14164    if (supm && subm) {
14165      supShift = Math.max(supShift, minSupShift, supm.depth + 0.25 * metrics.xHeight);
14166      subShift = Math.max(subShift, metrics.sub2);
14167      var ruleWidth = metrics.defaultRuleThickness; // Rule 18e
14168
14169      var maxWidth = 4 * ruleWidth;
14170
14171      if (supShift - supm.depth - (subm.height - subShift) < maxWidth) {
14172        subShift = maxWidth - (supShift - supm.depth) + subm.height;
14173        var psi = 0.8 * metrics.xHeight - (supShift - supm.depth);
14174
14175        if (psi > 0) {
14176          supShift += psi;
14177          subShift -= psi;
14178        }
14179      }
14180
14181      var vlistElem = [{
14182        type: "elem",
14183        elem: subm,
14184        shift: subShift,
14185        marginRight,
14186        marginLeft
14187      }, {
14188        type: "elem",
14189        elem: supm,
14190        shift: -supShift,
14191        marginRight
14192      }];
14193      supsub = buildCommon.makeVList({
14194        positionType: "individualShift",
14195        children: vlistElem
14196      }, options);
14197    } else if (subm) {
14198      // Rule 18b
14199      subShift = Math.max(subShift, metrics.sub1, subm.height - 0.8 * metrics.xHeight);
14200      var _vlistElem = [{
14201        type: "elem",
14202        elem: subm,
14203        marginLeft,
14204        marginRight
14205      }];
14206      supsub = buildCommon.makeVList({
14207        positionType: "shift",
14208        positionData: subShift,
14209        children: _vlistElem
14210      }, options);
14211    } else if (supm) {
14212      // Rule 18c, d
14213      supShift = Math.max(supShift, minSupShift, supm.depth + 0.25 * metrics.xHeight);
14214      supsub = buildCommon.makeVList({
14215        positionType: "shift",
14216        positionData: -supShift,
14217        children: [{
14218          type: "elem",
14219          elem: supm,
14220          marginRight
14221        }]
14222      }, options);
14223    } else {
14224      throw new Error("supsub must have either sup or sub.");
14225    } // Wrap the supsub vlist in a span.msupsub to reset text-align.
14226
14227
14228    var mclass = getTypeOfDomTree(base, "right") || "mord";
14229    return buildCommon.makeSpan([mclass], [base, buildCommon.makeSpan(["msupsub"], [supsub])], options);
14230  },
14231
14232  mathmlBuilder(group, options) {
14233    // Is the inner group a relevant horizonal brace?
14234    var isBrace = false;
14235    var isOver;
14236    var isSup;
14237
14238    if (group.base && group.base.type === "horizBrace") {
14239      isSup = !!group.sup;
14240
14241      if (isSup === group.base.isOver) {
14242        isBrace = true;
14243        isOver = group.base.isOver;
14244      }
14245    }
14246
14247    if (group.base && (group.base.type === "op" || group.base.type === "operatorname")) {
14248      group.base.parentIsSupSub = true;
14249    }
14250
14251    var children = [buildGroup(group.base, options)];
14252
14253    if (group.sub) {
14254      children.push(buildGroup(group.sub, options));
14255    }
14256
14257    if (group.sup) {
14258      children.push(buildGroup(group.sup, options));
14259    }
14260
14261    var nodeType;
14262
14263    if (isBrace) {
14264      nodeType = isOver ? "mover" : "munder";
14265    } else if (!group.sub) {
14266      var base = group.base;
14267
14268      if (base && base.type === "op" && base.limits && (options.style === Style$1.DISPLAY || base.alwaysHandleSupSub)) {
14269        nodeType = "mover";
14270      } else if (base && base.type === "operatorname" && base.alwaysHandleSupSub && (base.limits || options.style === Style$1.DISPLAY)) {
14271        nodeType = "mover";
14272      } else {
14273        nodeType = "msup";
14274      }
14275    } else if (!group.sup) {
14276      var _base = group.base;
14277
14278      if (_base && _base.type === "op" && _base.limits && (options.style === Style$1.DISPLAY || _base.alwaysHandleSupSub)) {
14279        nodeType = "munder";
14280      } else if (_base && _base.type === "operatorname" && _base.alwaysHandleSupSub && (_base.limits || options.style === Style$1.DISPLAY)) {
14281        nodeType = "munder";
14282      } else {
14283        nodeType = "msub";
14284      }
14285    } else {
14286      var _base2 = group.base;
14287
14288      if (_base2 && _base2.type === "op" && _base2.limits && options.style === Style$1.DISPLAY) {
14289        nodeType = "munderover";
14290      } else if (_base2 && _base2.type === "operatorname" && _base2.alwaysHandleSupSub && (options.style === Style$1.DISPLAY || _base2.limits)) {
14291        nodeType = "munderover";
14292      } else {
14293        nodeType = "msubsup";
14294      }
14295    }
14296
14297    return new mathMLTree.MathNode(nodeType, children);
14298  }
14299
14300});
14301
14302defineFunctionBuilders({
14303  type: "atom",
14304
14305  htmlBuilder(group, options) {
14306    return buildCommon.mathsym(group.text, group.mode, options, ["m" + group.family]);
14307  },
14308
14309  mathmlBuilder(group, options) {
14310    var node = new mathMLTree.MathNode("mo", [makeText(group.text, group.mode)]);
14311
14312    if (group.family === "bin") {
14313      var variant = getVariant(group, options);
14314
14315      if (variant === "bold-italic") {
14316        node.setAttribute("mathvariant", variant);
14317      }
14318    } else if (group.family === "punct") {
14319      node.setAttribute("separator", "true");
14320    } else if (group.family === "open" || group.family === "close") {
14321      // Delims built here should not stretch vertically.
14322      // See delimsizing.js for stretchy delims.
14323      node.setAttribute("stretchy", "false");
14324    }
14325
14326    return node;
14327  }
14328
14329});
14330
14331// "mathord" and "textord" ParseNodes created in Parser.js from symbol Groups in
14332// src/symbols.js.
14333var defaultVariant = {
14334  "mi": "italic",
14335  "mn": "normal",
14336  "mtext": "normal"
14337};
14338defineFunctionBuilders({
14339  type: "mathord",
14340
14341  htmlBuilder(group, options) {
14342    return buildCommon.makeOrd(group, options, "mathord");
14343  },
14344
14345  mathmlBuilder(group, options) {
14346    var node = new mathMLTree.MathNode("mi", [makeText(group.text, group.mode, options)]);
14347    var variant = getVariant(group, options) || "italic";
14348
14349    if (variant !== defaultVariant[node.type]) {
14350      node.setAttribute("mathvariant", variant);
14351    }
14352
14353    return node;
14354  }
14355
14356});
14357defineFunctionBuilders({
14358  type: "textord",
14359
14360  htmlBuilder(group, options) {
14361    return buildCommon.makeOrd(group, options, "textord");
14362  },
14363
14364  mathmlBuilder(group, options) {
14365    var text = makeText(group.text, group.mode, options);
14366    var variant = getVariant(group, options) || "normal";
14367    var node;
14368
14369    if (group.mode === 'text') {
14370      node = new mathMLTree.MathNode("mtext", [text]);
14371    } else if (/[0-9]/.test(group.text)) {
14372      node = new mathMLTree.MathNode("mn", [text]);
14373    } else if (group.text === "\\prime") {
14374      node = new mathMLTree.MathNode("mo", [text]);
14375    } else {
14376      node = new mathMLTree.MathNode("mi", [text]);
14377    }
14378
14379    if (variant !== defaultVariant[node.type]) {
14380      node.setAttribute("mathvariant", variant);
14381    }
14382
14383    return node;
14384  }
14385
14386});
14387
14388var cssSpace = {
14389  "\\nobreak": "nobreak",
14390  "\\allowbreak": "allowbreak"
14391}; // A lookup table to determine whether a spacing function/symbol should be
14392// treated like a regular space character.  If a symbol or command is a key
14393// in this table, then it should be a regular space character.  Furthermore,
14394// the associated value may have a `className` specifying an extra CSS class
14395// to add to the created `span`.
14396
14397var regularSpace = {
14398  " ": {},
14399  "\\ ": {},
14400  "~": {
14401    className: "nobreak"
14402  },
14403  "\\space": {},
14404  "\\nobreakspace": {
14405    className: "nobreak"
14406  }
14407}; // ParseNode<"spacing"> created in Parser.js from the "spacing" symbol Groups in
14408// src/symbols.js.
14409
14410defineFunctionBuilders({
14411  type: "spacing",
14412
14413  htmlBuilder(group, options) {
14414    if (regularSpace.hasOwnProperty(group.text)) {
14415      var className = regularSpace[group.text].className || ""; // Spaces are generated by adding an actual space. Each of these
14416      // things has an entry in the symbols table, so these will be turned
14417      // into appropriate outputs.
14418
14419      if (group.mode === "text") {
14420        var ord = buildCommon.makeOrd(group, options, "textord");
14421        ord.classes.push(className);
14422        return ord;
14423      } else {
14424        return buildCommon.makeSpan(["mspace", className], [buildCommon.mathsym(group.text, group.mode, options)], options);
14425      }
14426    } else if (cssSpace.hasOwnProperty(group.text)) {
14427      // Spaces based on just a CSS class.
14428      return buildCommon.makeSpan(["mspace", cssSpace[group.text]], [], options);
14429    } else {
14430      throw new ParseError("Unknown type of space \"" + group.text + "\"");
14431    }
14432  },
14433
14434  mathmlBuilder(group, options) {
14435    var node;
14436
14437    if (regularSpace.hasOwnProperty(group.text)) {
14438      node = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode("\u00a0")]);
14439    } else if (cssSpace.hasOwnProperty(group.text)) {
14440      // CSS-based MathML spaces (\nobreak, \allowbreak) are ignored
14441      return new mathMLTree.MathNode("mspace");
14442    } else {
14443      throw new ParseError("Unknown type of space \"" + group.text + "\"");
14444    }
14445
14446    return node;
14447  }
14448
14449});
14450
14451var pad = () => {
14452  var padNode = new mathMLTree.MathNode("mtd", []);
14453  padNode.setAttribute("width", "50%");
14454  return padNode;
14455};
14456
14457defineFunctionBuilders({
14458  type: "tag",
14459
14460  mathmlBuilder(group, options) {
14461    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)])])]);
14462    table.setAttribute("width", "100%");
14463    return table; // TODO: Left-aligned tags.
14464    // Currently, the group and options passed here do not contain
14465    // enough info to set tag alignment. `leqno` is in Settings but it is
14466    // not passed to Options. On the HTML side, leqno is
14467    // set by a CSS class applied in buildTree.js. That would have worked
14468    // in MathML if browsers supported <mlabeledtr>. Since they don't, we
14469    // need to rewrite the way this function is called.
14470  }
14471
14472});
14473
14474var textFontFamilies = {
14475  "\\text": undefined,
14476  "\\textrm": "textrm",
14477  "\\textsf": "textsf",
14478  "\\texttt": "texttt",
14479  "\\textnormal": "textrm"
14480};
14481var textFontWeights = {
14482  "\\textbf": "textbf",
14483  "\\textmd": "textmd"
14484};
14485var textFontShapes = {
14486  "\\textit": "textit",
14487  "\\textup": "textup"
14488};
14489
14490var optionsWithFont = (group, options) => {
14491  var font = group.font; // Checks if the argument is a font family or a font style.
14492
14493  if (!font) {
14494    return options;
14495  } else if (textFontFamilies[font]) {
14496    return options.withTextFontFamily(textFontFamilies[font]);
14497  } else if (textFontWeights[font]) {
14498    return options.withTextFontWeight(textFontWeights[font]);
14499  } else {
14500    return options.withTextFontShape(textFontShapes[font]);
14501  }
14502};
14503
14504defineFunction({
14505  type: "text",
14506  names: [// Font families
14507  "\\text", "\\textrm", "\\textsf", "\\texttt", "\\textnormal", // Font weights
14508  "\\textbf", "\\textmd", // Font Shapes
14509  "\\textit", "\\textup"],
14510  props: {
14511    numArgs: 1,
14512    argTypes: ["text"],
14513    allowedInArgument: true,
14514    allowedInText: true
14515  },
14516
14517  handler(_ref, args) {
14518    var {
14519      parser,
14520      funcName
14521    } = _ref;
14522    var body = args[0];
14523    return {
14524      type: "text",
14525      mode: parser.mode,
14526      body: ordargument(body),
14527      font: funcName
14528    };
14529  },
14530
14531  htmlBuilder(group, options) {
14532    var newOptions = optionsWithFont(group, options);
14533    var inner = buildExpression$1(group.body, newOptions, true);
14534    return buildCommon.makeSpan(["mord", "text"], inner, newOptions);
14535  },
14536
14537  mathmlBuilder(group, options) {
14538    var newOptions = optionsWithFont(group, options);
14539    return buildExpressionRow(group.body, newOptions);
14540  }
14541
14542});
14543
14544defineFunction({
14545  type: "underline",
14546  names: ["\\underline"],
14547  props: {
14548    numArgs: 1,
14549    allowedInText: true
14550  },
14551
14552  handler(_ref, args) {
14553    var {
14554      parser
14555    } = _ref;
14556    return {
14557      type: "underline",
14558      mode: parser.mode,
14559      body: args[0]
14560    };
14561  },
14562
14563  htmlBuilder(group, options) {
14564    // Underlines are handled in the TeXbook pg 443, Rule 10.
14565    // Build the inner group.
14566    var innerGroup = buildGroup$1(group.body, options); // Create the line to go below the body
14567
14568    var line = buildCommon.makeLineSpan("underline-line", options); // Generate the vlist, with the appropriate kerns
14569
14570    var defaultRuleThickness = options.fontMetrics().defaultRuleThickness;
14571    var vlist = buildCommon.makeVList({
14572      positionType: "top",
14573      positionData: innerGroup.height,
14574      children: [{
14575        type: "kern",
14576        size: defaultRuleThickness
14577      }, {
14578        type: "elem",
14579        elem: line
14580      }, {
14581        type: "kern",
14582        size: 3 * defaultRuleThickness
14583      }, {
14584        type: "elem",
14585        elem: innerGroup
14586      }]
14587    }, options);
14588    return buildCommon.makeSpan(["mord", "underline"], [vlist], options);
14589  },
14590
14591  mathmlBuilder(group, options) {
14592    var operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u203e")]);
14593    operator.setAttribute("stretchy", "true");
14594    var node = new mathMLTree.MathNode("munder", [buildGroup(group.body, options), operator]);
14595    node.setAttribute("accentunder", "true");
14596    return node;
14597  }
14598
14599});
14600
14601defineFunction({
14602  type: "vcenter",
14603  names: ["\\vcenter"],
14604  props: {
14605    numArgs: 1,
14606    argTypes: ["original"],
14607    // In LaTeX, \vcenter can act only on a box.
14608    allowedInText: false
14609  },
14610
14611  handler(_ref, args) {
14612    var {
14613      parser
14614    } = _ref;
14615    return {
14616      type: "vcenter",
14617      mode: parser.mode,
14618      body: args[0]
14619    };
14620  },
14621
14622  htmlBuilder(group, options) {
14623    var body = buildGroup$1(group.body, options);
14624    var axisHeight = options.fontMetrics().axisHeight;
14625    var dy = 0.5 * (body.height - axisHeight - (body.depth + axisHeight));
14626    return buildCommon.makeVList({
14627      positionType: "shift",
14628      positionData: dy,
14629      children: [{
14630        type: "elem",
14631        elem: body
14632      }]
14633    }, options);
14634  },
14635
14636  mathmlBuilder(group, options) {
14637    // There is no way to do this in MathML.
14638    // Write a class as a breadcrumb in case some post-processor wants
14639    // to perform a vcenter adjustment.
14640    return new mathMLTree.MathNode("mpadded", [buildGroup(group.body, options)], ["vcenter"]);
14641  }
14642
14643});
14644
14645defineFunction({
14646  type: "verb",
14647  names: ["\\verb"],
14648  props: {
14649    numArgs: 0,
14650    allowedInText: true
14651  },
14652
14653  handler(context, args, optArgs) {
14654    // \verb and \verb* are dealt with directly in Parser.js.
14655    // If we end up here, it's because of a failure to match the two delimiters
14656    // in the regex in Lexer.js.  LaTeX raises the following error when \verb is
14657    // terminated by end of line (or file).
14658    throw new ParseError("\\verb ended by end of line instead of matching delimiter");
14659  },
14660
14661  htmlBuilder(group, options) {
14662    var text = makeVerb(group);
14663    var body = []; // \verb enters text mode and therefore is sized like \textstyle
14664
14665    var newOptions = options.havingStyle(options.style.text());
14666
14667    for (var i = 0; i < text.length; i++) {
14668      var c = text[i];
14669
14670      if (c === '~') {
14671        c = '\\textasciitilde';
14672      }
14673
14674      body.push(buildCommon.makeSymbol(c, "Typewriter-Regular", group.mode, newOptions, ["mord", "texttt"]));
14675    }
14676
14677    return buildCommon.makeSpan(["mord", "text"].concat(newOptions.sizingClasses(options)), buildCommon.tryCombineChars(body), newOptions);
14678  },
14679
14680  mathmlBuilder(group, options) {
14681    var text = new mathMLTree.TextNode(makeVerb(group));
14682    var node = new mathMLTree.MathNode("mtext", [text]);
14683    node.setAttribute("mathvariant", "monospace");
14684    return node;
14685  }
14686
14687});
14688/**
14689 * Converts verb group into body string.
14690 *
14691 * \verb* replaces each space with an open box \u2423
14692 * \verb replaces each space with a no-break space \xA0
14693 */
14694
14695var makeVerb = group => group.body.replace(/ /g, group.star ? '\u2423' : '\xA0');
14696
14697/** Include this to ensure that all functions are defined. */
14698var functions = _functions;
14699
14700/**
14701 * The Lexer class handles tokenizing the input in various ways. Since our
14702 * parser expects us to be able to backtrack, the lexer allows lexing from any
14703 * given starting point.
14704 *
14705 * Its main exposed function is the `lex` function, which takes a position to
14706 * lex from and a type of token to lex. It defers to the appropriate `_innerLex`
14707 * function.
14708 *
14709 * The various `_innerLex` functions perform the actual lexing of different
14710 * kinds.
14711 */
14712
14713/* The following tokenRegex
14714 * - matches typical whitespace (but not NBSP etc.) using its first group
14715 * - does not match any control character \x00-\x1f except whitespace
14716 * - does not match a bare backslash
14717 * - matches any ASCII character except those just mentioned
14718 * - does not match the BMP private use area \uE000-\uF8FF
14719 * - does not match bare surrogate code units
14720 * - matches any BMP character except for those just described
14721 * - matches any valid Unicode surrogate pair
14722 * - matches a backslash followed by one or more whitespace characters
14723 * - matches a backslash followed by one or more letters then whitespace
14724 * - matches a backslash followed by any BMP character
14725 * Capturing groups:
14726 *   [1] regular whitespace
14727 *   [2] backslash followed by whitespace
14728 *   [3] anything else, which may include:
14729 *     [4] left character of \verb*
14730 *     [5] left character of \verb
14731 *     [6] backslash followed by word, excluding any trailing whitespace
14732 * Just because the Lexer matches something doesn't mean it's valid input:
14733 * If there is no matching function or symbol definition, the Parser will
14734 * still reject the input.
14735 */
14736var spaceRegexString = "[ \r\n\t]";
14737var controlWordRegexString = "\\\\[a-zA-Z@]+";
14738var controlSymbolRegexString = "\\\\[^\uD800-\uDFFF]";
14739var controlWordWhitespaceRegexString = "(" + controlWordRegexString + ")" + spaceRegexString + "*";
14740var controlSpaceRegexString = "\\\\(\n|[ \r\t]+\n?)[ \r\t]*";
14741var combiningDiacriticalMarkString = "[\u0300-\u036f]";
14742var combiningDiacriticalMarksEndRegex = new RegExp(combiningDiacriticalMarkString + "+$");
14743var tokenRegexString = "(" + spaceRegexString + "+)|" + ( // whitespace
14744controlSpaceRegexString + "|") + // \whitespace
14745"([!-\\[\\]-\u2027\u202A-\uD7FF\uF900-\uFFFF]" + ( // single codepoint
14746combiningDiacriticalMarkString + "*") + // ...plus accents
14747"|[\uD800-\uDBFF][\uDC00-\uDFFF]" + ( // surrogate pair
14748combiningDiacriticalMarkString + "*") + // ...plus accents
14749"|\\\\verb\\*([^]).*?\\4" + // \verb*
14750"|\\\\verb([^*a-zA-Z]).*?\\5" + ( // \verb unstarred
14751"|" + controlWordWhitespaceRegexString) + ( // \macroName + spaces
14752"|" + controlSymbolRegexString + ")"); // \\, \', etc.
14753
14754/** Main Lexer class */
14755
14756class Lexer {
14757  // Category codes. The lexer only supports comment characters (14) for now.
14758  // MacroExpander additionally distinguishes active (13).
14759  constructor(input, settings) {
14760    this.input = void 0;
14761    this.settings = void 0;
14762    this.tokenRegex = void 0;
14763    this.catcodes = void 0;
14764    // Separate accents from characters
14765    this.input = input;
14766    this.settings = settings;
14767    this.tokenRegex = new RegExp(tokenRegexString, 'g');
14768    this.catcodes = {
14769      "%": 14,
14770      // comment character
14771      "~": 13 // active character
14772
14773    };
14774  }
14775
14776  setCatcode(char, code) {
14777    this.catcodes[char] = code;
14778  }
14779  /**
14780   * This function lexes a single token.
14781   */
14782
14783
14784  lex() {
14785    var input = this.input;
14786    var pos = this.tokenRegex.lastIndex;
14787
14788    if (pos === input.length) {
14789      return new Token("EOF", new SourceLocation(this, pos, pos));
14790    }
14791
14792    var match = this.tokenRegex.exec(input);
14793
14794    if (match === null || match.index !== pos) {
14795      throw new ParseError("Unexpected character: '" + input[pos] + "'", new Token(input[pos], new SourceLocation(this, pos, pos + 1)));
14796    }
14797
14798    var text = match[6] || match[3] || (match[2] ? "\\ " : " ");
14799
14800    if (this.catcodes[text] === 14) {
14801      // comment character
14802      var nlIndex = input.indexOf('\n', this.tokenRegex.lastIndex);
14803
14804      if (nlIndex === -1) {
14805        this.tokenRegex.lastIndex = input.length; // EOF
14806
14807        this.settings.reportNonstrict("commentAtEnd", "% comment has no terminating newline; LaTeX would " + "fail because of commenting the end of math mode (e.g. $)");
14808      } else {
14809        this.tokenRegex.lastIndex = nlIndex + 1;
14810      }
14811
14812      return this.lex();
14813    }
14814
14815    return new Token(text, new SourceLocation(this, pos, this.tokenRegex.lastIndex));
14816  }
14817
14818}
14819
14820/**
14821 * A `Namespace` refers to a space of nameable things like macros or lengths,
14822 * which can be `set` either globally or local to a nested group, using an
14823 * undo stack similar to how TeX implements this functionality.
14824 * Performance-wise, `get` and local `set` take constant time, while global
14825 * `set` takes time proportional to the depth of group nesting.
14826 */
14827class Namespace {
14828  /**
14829   * Both arguments are optional.  The first argument is an object of
14830   * built-in mappings which never change.  The second argument is an object
14831   * of initial (global-level) mappings, which will constantly change
14832   * according to any global/top-level `set`s done.
14833   */
14834  constructor(builtins, globalMacros) {
14835    if (builtins === void 0) {
14836      builtins = {};
14837    }
14838
14839    if (globalMacros === void 0) {
14840      globalMacros = {};
14841    }
14842
14843    this.current = void 0;
14844    this.builtins = void 0;
14845    this.undefStack = void 0;
14846    this.current = globalMacros;
14847    this.builtins = builtins;
14848    this.undefStack = [];
14849  }
14850  /**
14851   * Start a new nested group, affecting future local `set`s.
14852   */
14853
14854
14855  beginGroup() {
14856    this.undefStack.push({});
14857  }
14858  /**
14859   * End current nested group, restoring values before the group began.
14860   */
14861
14862
14863  endGroup() {
14864    if (this.undefStack.length === 0) {
14865      throw new ParseError("Unbalanced namespace destruction: attempt " + "to pop global namespace; please report this as a bug");
14866    }
14867
14868    var undefs = this.undefStack.pop();
14869
14870    for (var undef in undefs) {
14871      if (undefs.hasOwnProperty(undef)) {
14872        if (undefs[undef] == null) {
14873          delete this.current[undef];
14874        } else {
14875          this.current[undef] = undefs[undef];
14876        }
14877      }
14878    }
14879  }
14880  /**
14881   * Ends all currently nested groups (if any), restoring values before the
14882   * groups began.  Useful in case of an error in the middle of parsing.
14883   */
14884
14885
14886  endGroups() {
14887    while (this.undefStack.length > 0) {
14888      this.endGroup();
14889    }
14890  }
14891  /**
14892   * Detect whether `name` has a definition.  Equivalent to
14893   * `get(name) != null`.
14894   */
14895
14896
14897  has(name) {
14898    return this.current.hasOwnProperty(name) || this.builtins.hasOwnProperty(name);
14899  }
14900  /**
14901   * Get the current value of a name, or `undefined` if there is no value.
14902   *
14903   * Note: Do not use `if (namespace.get(...))` to detect whether a macro
14904   * is defined, as the definition may be the empty string which evaluates
14905   * to `false` in JavaScript.  Use `if (namespace.get(...) != null)` or
14906   * `if (namespace.has(...))`.
14907   */
14908
14909
14910  get(name) {
14911    if (this.current.hasOwnProperty(name)) {
14912      return this.current[name];
14913    } else {
14914      return this.builtins[name];
14915    }
14916  }
14917  /**
14918   * Set the current value of a name, and optionally set it globally too.
14919   * Local set() sets the current value and (when appropriate) adds an undo
14920   * operation to the undo stack.  Global set() may change the undo
14921   * operation at every level, so takes time linear in their number.
14922   * A value of undefined means to delete existing definitions.
14923   */
14924
14925
14926  set(name, value, global) {
14927    if (global === void 0) {
14928      global = false;
14929    }
14930
14931    if (global) {
14932      // Global set is equivalent to setting in all groups.  Simulate this
14933      // by destroying any undos currently scheduled for this name,
14934      // and adding an undo with the *new* value (in case it later gets
14935      // locally reset within this environment).
14936      for (var i = 0; i < this.undefStack.length; i++) {
14937        delete this.undefStack[i][name];
14938      }
14939
14940      if (this.undefStack.length > 0) {
14941        this.undefStack[this.undefStack.length - 1][name] = value;
14942      }
14943    } else {
14944      // Undo this set at end of this group (possibly to `undefined`),
14945      // unless an undo is already in place, in which case that older
14946      // value is the correct one.
14947      var top = this.undefStack[this.undefStack.length - 1];
14948
14949      if (top && !top.hasOwnProperty(name)) {
14950        top[name] = this.current[name];
14951      }
14952    }
14953
14954    if (value == null) {
14955      delete this.current[name];
14956    } else {
14957      this.current[name] = value;
14958    }
14959  }
14960
14961}
14962
14963/**
14964 * Predefined macros for KaTeX.
14965 * This can be used to define some commands in terms of others.
14966 */
14967var macros = _macros;
14968// macro tools
14969
14970defineMacro("\\noexpand", function (context) {
14971  // The expansion is the token itself; but that token is interpreted
14972  // as if its meaning were ‘\relax’ if it is a control sequence that
14973  // would ordinarily be expanded by TeX’s expansion rules.
14974  var t = context.popToken();
14975
14976  if (context.isExpandable(t.text)) {
14977    t.noexpand = true;
14978    t.treatAsRelax = true;
14979  }
14980
14981  return {
14982    tokens: [t],
14983    numArgs: 0
14984  };
14985});
14986defineMacro("\\expandafter", function (context) {
14987  // TeX first reads the token that comes immediately after \expandafter,
14988  // without expanding it; let’s call this token t. Then TeX reads the
14989  // token that comes after t (and possibly more tokens, if that token
14990  // has an argument), replacing it by its expansion. Finally TeX puts
14991  // t back in front of that expansion.
14992  var t = context.popToken();
14993  context.expandOnce(true); // expand only an expandable token
14994
14995  return {
14996    tokens: [t],
14997    numArgs: 0
14998  };
14999}); // LaTeX's \@firstoftwo{#1}{#2} expands to #1, skipping #2
15000// TeX source: \long\def\@firstoftwo#1#2{#1}
15001
15002defineMacro("\\@firstoftwo", function (context) {
15003  var args = context.consumeArgs(2);
15004  return {
15005    tokens: args[0],
15006    numArgs: 0
15007  };
15008}); // LaTeX's \@secondoftwo{#1}{#2} expands to #2, skipping #1
15009// TeX source: \long\def\@secondoftwo#1#2{#2}
15010
15011defineMacro("\\@secondoftwo", function (context) {
15012  var args = context.consumeArgs(2);
15013  return {
15014    tokens: args[1],
15015    numArgs: 0
15016  };
15017}); // LaTeX's \@ifnextchar{#1}{#2}{#3} looks ahead to the next (unexpanded)
15018// symbol that isn't a space, consuming any spaces but not consuming the
15019// first nonspace character.  If that nonspace character matches #1, then
15020// the macro expands to #2; otherwise, it expands to #3.
15021
15022defineMacro("\\@ifnextchar", function (context) {
15023  var args = context.consumeArgs(3); // symbol, if, else
15024
15025  context.consumeSpaces();
15026  var nextToken = context.future();
15027
15028  if (args[0].length === 1 && args[0][0].text === nextToken.text) {
15029    return {
15030      tokens: args[1],
15031      numArgs: 0
15032    };
15033  } else {
15034    return {
15035      tokens: args[2],
15036      numArgs: 0
15037    };
15038  }
15039}); // LaTeX's \@ifstar{#1}{#2} looks ahead to the next (unexpanded) symbol.
15040// If it is `*`, then it consumes the symbol, and the macro expands to #1;
15041// otherwise, the macro expands to #2 (without consuming the symbol).
15042// TeX source: \def\@ifstar#1{\@ifnextchar *{\@firstoftwo{#1}}}
15043
15044defineMacro("\\@ifstar", "\\@ifnextchar *{\\@firstoftwo{#1}}"); // LaTeX's \TextOrMath{#1}{#2} expands to #1 in text mode, #2 in math mode
15045
15046defineMacro("\\TextOrMath", function (context) {
15047  var args = context.consumeArgs(2);
15048
15049  if (context.mode === 'text') {
15050    return {
15051      tokens: args[0],
15052      numArgs: 0
15053    };
15054  } else {
15055    return {
15056      tokens: args[1],
15057      numArgs: 0
15058    };
15059  }
15060}); // Lookup table for parsing numbers in base 8 through 16
15061
15062var digitToNumber = {
15063  "0": 0,
15064  "1": 1,
15065  "2": 2,
15066  "3": 3,
15067  "4": 4,
15068  "5": 5,
15069  "6": 6,
15070  "7": 7,
15071  "8": 8,
15072  "9": 9,
15073  "a": 10,
15074  "A": 10,
15075  "b": 11,
15076  "B": 11,
15077  "c": 12,
15078  "C": 12,
15079  "d": 13,
15080  "D": 13,
15081  "e": 14,
15082  "E": 14,
15083  "f": 15,
15084  "F": 15
15085}; // TeX \char makes a literal character (catcode 12) using the following forms:
15086// (see The TeXBook, p. 43)
15087//   \char123  -- decimal
15088//   \char'123 -- octal
15089//   \char"123 -- hex
15090//   \char`x   -- character that can be written (i.e. isn't active)
15091//   \char`\x  -- character that cannot be written (e.g. %)
15092// These all refer to characters from the font, so we turn them into special
15093// calls to a function \@char dealt with in the Parser.
15094
15095defineMacro("\\char", function (context) {
15096  var token = context.popToken();
15097  var base;
15098  var number = '';
15099
15100  if (token.text === "'") {
15101    base = 8;
15102    token = context.popToken();
15103  } else if (token.text === '"') {
15104    base = 16;
15105    token = context.popToken();
15106  } else if (token.text === "`") {
15107    token = context.popToken();
15108
15109    if (token.text[0] === "\\") {
15110      number = token.text.charCodeAt(1);
15111    } else if (token.text === "EOF") {
15112      throw new ParseError("\\char` missing argument");
15113    } else {
15114      number = token.text.charCodeAt(0);
15115    }
15116  } else {
15117    base = 10;
15118  }
15119
15120  if (base) {
15121    // Parse a number in the given base, starting with first `token`.
15122    number = digitToNumber[token.text];
15123
15124    if (number == null || number >= base) {
15125      throw new ParseError("Invalid base-" + base + " digit " + token.text);
15126    }
15127
15128    var digit;
15129
15130    while ((digit = digitToNumber[context.future().text]) != null && digit < base) {
15131      number *= base;
15132      number += digit;
15133      context.popToken();
15134    }
15135  }
15136
15137  return "\\@char{" + number + "}";
15138}); // \newcommand{\macro}[args]{definition}
15139// \renewcommand{\macro}[args]{definition}
15140// TODO: Optional arguments: \newcommand{\macro}[args][default]{definition}
15141
15142var newcommand = (context, existsOK, nonexistsOK) => {
15143  var arg = context.consumeArg().tokens;
15144
15145  if (arg.length !== 1) {
15146    throw new ParseError("\\newcommand's first argument must be a macro name");
15147  }
15148
15149  var name = arg[0].text;
15150  var exists = context.isDefined(name);
15151
15152  if (exists && !existsOK) {
15153    throw new ParseError("\\newcommand{" + name + "} attempting to redefine " + (name + "; use \\renewcommand"));
15154  }
15155
15156  if (!exists && !nonexistsOK) {
15157    throw new ParseError("\\renewcommand{" + name + "} when command " + name + " " + "does not yet exist; use \\newcommand");
15158  }
15159
15160  var numArgs = 0;
15161  arg = context.consumeArg().tokens;
15162
15163  if (arg.length === 1 && arg[0].text === "[") {
15164    var argText = '';
15165    var token = context.expandNextToken();
15166
15167    while (token.text !== "]" && token.text !== "EOF") {
15168      // TODO: Should properly expand arg, e.g., ignore {}s
15169      argText += token.text;
15170      token = context.expandNextToken();
15171    }
15172
15173    if (!argText.match(/^\s*[0-9]+\s*$/)) {
15174      throw new ParseError("Invalid number of arguments: " + argText);
15175    }
15176
15177    numArgs = parseInt(argText);
15178    arg = context.consumeArg().tokens;
15179  } // Final arg is the expansion of the macro
15180
15181
15182  context.macros.set(name, {
15183    tokens: arg,
15184    numArgs
15185  });
15186  return '';
15187};
15188
15189defineMacro("\\newcommand", context => newcommand(context, false, true));
15190defineMacro("\\renewcommand", context => newcommand(context, true, false));
15191defineMacro("\\providecommand", context => newcommand(context, true, true)); // terminal (console) tools
15192
15193defineMacro("\\message", context => {
15194  var arg = context.consumeArgs(1)[0]; // eslint-disable-next-line no-console
15195
15196  console.log(arg.reverse().map(token => token.text).join(""));
15197  return '';
15198});
15199defineMacro("\\errmessage", context => {
15200  var arg = context.consumeArgs(1)[0]; // eslint-disable-next-line no-console
15201
15202  console.error(arg.reverse().map(token => token.text).join(""));
15203  return '';
15204});
15205defineMacro("\\show", context => {
15206  var tok = context.popToken();
15207  var name = tok.text; // eslint-disable-next-line no-console
15208
15209  console.log(tok, context.macros.get(name), functions[name], symbols.math[name], symbols.text[name]);
15210  return '';
15211}); //////////////////////////////////////////////////////////////////////
15212// Grouping
15213// \let\bgroup={ \let\egroup=}
15214
15215defineMacro("\\bgroup", "{");
15216defineMacro("\\egroup", "}"); // Symbols from latex.ltx:
15217// \def~{\nobreakspace{}}
15218// \def\lq{`}
15219// \def\rq{'}
15220// \def \aa {\r a}
15221// \def \AA {\r A}
15222
15223defineMacro("~", "\\nobreakspace");
15224defineMacro("\\lq", "`");
15225defineMacro("\\rq", "'");
15226defineMacro("\\aa", "\\r a");
15227defineMacro("\\AA", "\\r A"); // Copyright (C) and registered (R) symbols. Use raw symbol in MathML.
15228// \DeclareTextCommandDefault{\textcopyright}{\textcircled{c}}
15229// \DeclareTextCommandDefault{\textregistered}{\textcircled{%
15230//      \check@mathfonts\fontsize\sf@size\z@\math@fontsfalse\selectfont R}}
15231// \DeclareRobustCommand{\copyright}{%
15232//    \ifmmode{\nfss@text{\textcopyright}}\else\textcopyright\fi}
15233
15234defineMacro("\\textcopyright", "\\html@mathml{\\textcircled{c}}{\\char`©}");
15235defineMacro("\\copyright", "\\TextOrMath{\\textcopyright}{\\text{\\textcopyright}}");
15236defineMacro("\\textregistered", "\\html@mathml{\\textcircled{\\scriptsize R}}{\\char`®}"); // Characters omitted from Unicode range 1D400–1D7FF
15237
15238defineMacro("\u212C", "\\mathscr{B}"); // script
15239
15240defineMacro("\u2130", "\\mathscr{E}");
15241defineMacro("\u2131", "\\mathscr{F}");
15242defineMacro("\u210B", "\\mathscr{H}");
15243defineMacro("\u2110", "\\mathscr{I}");
15244defineMacro("\u2112", "\\mathscr{L}");
15245defineMacro("\u2133", "\\mathscr{M}");
15246defineMacro("\u211B", "\\mathscr{R}");
15247defineMacro("\u212D", "\\mathfrak{C}"); // Fraktur
15248
15249defineMacro("\u210C", "\\mathfrak{H}");
15250defineMacro("\u2128", "\\mathfrak{Z}"); // Define \Bbbk with a macro that works in both HTML and MathML.
15251
15252defineMacro("\\Bbbk", "\\Bbb{k}"); // Unicode middle dot
15253// The KaTeX fonts do not contain U+00B7. Instead, \cdotp displays
15254// the dot at U+22C5 and gives it punct spacing.
15255
15256defineMacro("\u00b7", "\\cdotp"); // \llap and \rlap render their contents in text mode
15257
15258defineMacro("\\llap", "\\mathllap{\\textrm{#1}}");
15259defineMacro("\\rlap", "\\mathrlap{\\textrm{#1}}");
15260defineMacro("\\clap", "\\mathclap{\\textrm{#1}}"); // \mathstrut from the TeXbook, p 360
15261
15262defineMacro("\\mathstrut", "\\vphantom{(}"); // \underbar from TeXbook p 353
15263
15264defineMacro("\\underbar", "\\underline{\\text{#1}}"); // \not is defined by base/fontmath.ltx via
15265// \DeclareMathSymbol{\not}{\mathrel}{symbols}{"36}
15266// It's thus treated like a \mathrel, but defined by a symbol that has zero
15267// width but extends to the right.  We use \rlap to get that spacing.
15268// For MathML we write U+0338 here. buildMathML.js will then do the overlay.
15269
15270defineMacro("\\not", '\\html@mathml{\\mathrel{\\mathrlap\\@not}}{\\char"338}'); // Negated symbols from base/fontmath.ltx:
15271// \def\neq{\not=} \let\ne=\neq
15272// \DeclareRobustCommand
15273//   \notin{\mathrel{\m@th\mathpalette\c@ncel\in}}
15274// \def\c@ncel#1#2{\m@th\ooalign{$\hfil#1\mkern1mu/\hfil$\crcr$#1#2$}}
15275
15276defineMacro("\\neq", "\\html@mathml{\\mathrel{\\not=}}{\\mathrel{\\char`≠}}");
15277defineMacro("\\ne", "\\neq");
15278defineMacro("\u2260", "\\neq");
15279defineMacro("\\notin", "\\html@mathml{\\mathrel{{\\in}\\mathllap{/\\mskip1mu}}}" + "{\\mathrel{\\char`∉}}");
15280defineMacro("\u2209", "\\notin"); // Unicode stacked relations
15281
15282defineMacro("\u2258", "\\html@mathml{" + "\\mathrel{=\\kern{-1em}\\raisebox{0.4em}{$\\scriptsize\\frown$}}" + "}{\\mathrel{\\char`\u2258}}");
15283defineMacro("\u2259", "\\html@mathml{\\stackrel{\\tiny\\wedge}{=}}{\\mathrel{\\char`\u2258}}");
15284defineMacro("\u225A", "\\html@mathml{\\stackrel{\\tiny\\vee}{=}}{\\mathrel{\\char`\u225A}}");
15285defineMacro("\u225B", "\\html@mathml{\\stackrel{\\scriptsize\\star}{=}}" + "{\\mathrel{\\char`\u225B}}");
15286defineMacro("\u225D", "\\html@mathml{\\stackrel{\\tiny\\mathrm{def}}{=}}" + "{\\mathrel{\\char`\u225D}}");
15287defineMacro("\u225E", "\\html@mathml{\\stackrel{\\tiny\\mathrm{m}}{=}}" + "{\\mathrel{\\char`\u225E}}");
15288defineMacro("\u225F", "\\html@mathml{\\stackrel{\\tiny?}{=}}{\\mathrel{\\char`\u225F}}"); // Misc Unicode
15289
15290defineMacro("\u27C2", "\\perp");
15291defineMacro("\u203C", "\\mathclose{!\\mkern-0.8mu!}");
15292defineMacro("\u220C", "\\notni");
15293defineMacro("\u231C", "\\ulcorner");
15294defineMacro("\u231D", "\\urcorner");
15295defineMacro("\u231E", "\\llcorner");
15296defineMacro("\u231F", "\\lrcorner");
15297defineMacro("\u00A9", "\\copyright");
15298defineMacro("\u00AE", "\\textregistered");
15299defineMacro("\uFE0F", "\\textregistered"); // The KaTeX fonts have corners at codepoints that don't match Unicode.
15300// For MathML purposes, use the Unicode code point.
15301
15302defineMacro("\\ulcorner", "\\html@mathml{\\@ulcorner}{\\mathop{\\char\"231c}}");
15303defineMacro("\\urcorner", "\\html@mathml{\\@urcorner}{\\mathop{\\char\"231d}}");
15304defineMacro("\\llcorner", "\\html@mathml{\\@llcorner}{\\mathop{\\char\"231e}}");
15305defineMacro("\\lrcorner", "\\html@mathml{\\@lrcorner}{\\mathop{\\char\"231f}}"); //////////////////////////////////////////////////////////////////////
15306// LaTeX_2ε
15307// \vdots{\vbox{\baselineskip4\p@  \lineskiplimit\z@
15308// \kern6\p@\hbox{.}\hbox{.}\hbox{.}}}
15309// We'll call \varvdots, which gets a glyph from symbols.js.
15310// The zero-width rule gets us an equivalent to the vertical 6pt kern.
15311
15312defineMacro("\\vdots", "\\mathord{\\varvdots\\rule{0pt}{15pt}}");
15313defineMacro("\u22ee", "\\vdots"); //////////////////////////////////////////////////////////////////////
15314// amsmath.sty
15315// http://mirrors.concertpass.com/tex-archive/macros/latex/required/amsmath/amsmath.pdf
15316// Italic Greek capital letters.  AMS defines these with \DeclareMathSymbol,
15317// but they are equivalent to \mathit{\Letter}.
15318
15319defineMacro("\\varGamma", "\\mathit{\\Gamma}");
15320defineMacro("\\varDelta", "\\mathit{\\Delta}");
15321defineMacro("\\varTheta", "\\mathit{\\Theta}");
15322defineMacro("\\varLambda", "\\mathit{\\Lambda}");
15323defineMacro("\\varXi", "\\mathit{\\Xi}");
15324defineMacro("\\varPi", "\\mathit{\\Pi}");
15325defineMacro("\\varSigma", "\\mathit{\\Sigma}");
15326defineMacro("\\varUpsilon", "\\mathit{\\Upsilon}");
15327defineMacro("\\varPhi", "\\mathit{\\Phi}");
15328defineMacro("\\varPsi", "\\mathit{\\Psi}");
15329defineMacro("\\varOmega", "\\mathit{\\Omega}"); //\newcommand{\substack}[1]{\subarray{c}#1\endsubarray}
15330
15331defineMacro("\\substack", "\\begin{subarray}{c}#1\\end{subarray}"); // \renewcommand{\colon}{\nobreak\mskip2mu\mathpunct{}\nonscript
15332// \mkern-\thinmuskip{:}\mskip6muplus1mu\relax}
15333
15334defineMacro("\\colon", "\\nobreak\\mskip2mu\\mathpunct{}" + "\\mathchoice{\\mkern-3mu}{\\mkern-3mu}{}{}{:}\\mskip6mu\\relax"); // \newcommand{\boxed}[1]{\fbox{\m@th$\displaystyle#1$}}
15335
15336defineMacro("\\boxed", "\\fbox{$\\displaystyle{#1}$}"); // \def\iff{\DOTSB\;\Longleftrightarrow\;}
15337// \def\implies{\DOTSB\;\Longrightarrow\;}
15338// \def\impliedby{\DOTSB\;\Longleftarrow\;}
15339
15340defineMacro("\\iff", "\\DOTSB\\;\\Longleftrightarrow\\;");
15341defineMacro("\\implies", "\\DOTSB\\;\\Longrightarrow\\;");
15342defineMacro("\\impliedby", "\\DOTSB\\;\\Longleftarrow\\;"); // AMSMath's automatic \dots, based on \mdots@@ macro.
15343
15344var dotsByToken = {
15345  ',': '\\dotsc',
15346  '\\not': '\\dotsb',
15347  // \keybin@ checks for the following:
15348  '+': '\\dotsb',
15349  '=': '\\dotsb',
15350  '<': '\\dotsb',
15351  '>': '\\dotsb',
15352  '-': '\\dotsb',
15353  '*': '\\dotsb',
15354  ':': '\\dotsb',
15355  // Symbols whose definition starts with \DOTSB:
15356  '\\DOTSB': '\\dotsb',
15357  '\\coprod': '\\dotsb',
15358  '\\bigvee': '\\dotsb',
15359  '\\bigwedge': '\\dotsb',
15360  '\\biguplus': '\\dotsb',
15361  '\\bigcap': '\\dotsb',
15362  '\\bigcup': '\\dotsb',
15363  '\\prod': '\\dotsb',
15364  '\\sum': '\\dotsb',
15365  '\\bigotimes': '\\dotsb',
15366  '\\bigoplus': '\\dotsb',
15367  '\\bigodot': '\\dotsb',
15368  '\\bigsqcup': '\\dotsb',
15369  '\\And': '\\dotsb',
15370  '\\longrightarrow': '\\dotsb',
15371  '\\Longrightarrow': '\\dotsb',
15372  '\\longleftarrow': '\\dotsb',
15373  '\\Longleftarrow': '\\dotsb',
15374  '\\longleftrightarrow': '\\dotsb',
15375  '\\Longleftrightarrow': '\\dotsb',
15376  '\\mapsto': '\\dotsb',
15377  '\\longmapsto': '\\dotsb',
15378  '\\hookrightarrow': '\\dotsb',
15379  '\\doteq': '\\dotsb',
15380  // Symbols whose definition starts with \mathbin:
15381  '\\mathbin': '\\dotsb',
15382  // Symbols whose definition starts with \mathrel:
15383  '\\mathrel': '\\dotsb',
15384  '\\relbar': '\\dotsb',
15385  '\\Relbar': '\\dotsb',
15386  '\\xrightarrow': '\\dotsb',
15387  '\\xleftarrow': '\\dotsb',
15388  // Symbols whose definition starts with \DOTSI:
15389  '\\DOTSI': '\\dotsi',
15390  '\\int': '\\dotsi',
15391  '\\oint': '\\dotsi',
15392  '\\iint': '\\dotsi',
15393  '\\iiint': '\\dotsi',
15394  '\\iiiint': '\\dotsi',
15395  '\\idotsint': '\\dotsi',
15396  // Symbols whose definition starts with \DOTSX:
15397  '\\DOTSX': '\\dotsx'
15398};
15399defineMacro("\\dots", function (context) {
15400  // TODO: If used in text mode, should expand to \textellipsis.
15401  // However, in KaTeX, \textellipsis and \ldots behave the same
15402  // (in text mode), and it's unlikely we'd see any of the math commands
15403  // that affect the behavior of \dots when in text mode.  So fine for now
15404  // (until we support \ifmmode ... \else ... \fi).
15405  var thedots = '\\dotso';
15406  var next = context.expandAfterFuture().text;
15407
15408  if (next in dotsByToken) {
15409    thedots = dotsByToken[next];
15410  } else if (next.substr(0, 4) === '\\not') {
15411    thedots = '\\dotsb';
15412  } else if (next in symbols.math) {
15413    if (utils.contains(['bin', 'rel'], symbols.math[next].group)) {
15414      thedots = '\\dotsb';
15415    }
15416  }
15417
15418  return thedots;
15419});
15420var spaceAfterDots = {
15421  // \rightdelim@ checks for the following:
15422  ')': true,
15423  ']': true,
15424  '\\rbrack': true,
15425  '\\}': true,
15426  '\\rbrace': true,
15427  '\\rangle': true,
15428  '\\rceil': true,
15429  '\\rfloor': true,
15430  '\\rgroup': true,
15431  '\\rmoustache': true,
15432  '\\right': true,
15433  '\\bigr': true,
15434  '\\biggr': true,
15435  '\\Bigr': true,
15436  '\\Biggr': true,
15437  // \extra@ also tests for the following:
15438  '$': true,
15439  // \extrap@ checks for the following:
15440  ';': true,
15441  '.': true,
15442  ',': true
15443};
15444defineMacro("\\dotso", function (context) {
15445  var next = context.future().text;
15446
15447  if (next in spaceAfterDots) {
15448    return "\\ldots\\,";
15449  } else {
15450    return "\\ldots";
15451  }
15452});
15453defineMacro("\\dotsc", function (context) {
15454  var next = context.future().text; // \dotsc uses \extra@ but not \extrap@, instead specially checking for
15455  // ';' and '.', but doesn't check for ','.
15456
15457  if (next in spaceAfterDots && next !== ',') {
15458    return "\\ldots\\,";
15459  } else {
15460    return "\\ldots";
15461  }
15462});
15463defineMacro("\\cdots", function (context) {
15464  var next = context.future().text;
15465
15466  if (next in spaceAfterDots) {
15467    return "\\@cdots\\,";
15468  } else {
15469    return "\\@cdots";
15470  }
15471});
15472defineMacro("\\dotsb", "\\cdots");
15473defineMacro("\\dotsm", "\\cdots");
15474defineMacro("\\dotsi", "\\!\\cdots"); // amsmath doesn't actually define \dotsx, but \dots followed by a macro
15475// starting with \DOTSX implies \dotso, and then \extra@ detects this case
15476// and forces the added `\,`.
15477
15478defineMacro("\\dotsx", "\\ldots\\,"); // \let\DOTSI\relax
15479// \let\DOTSB\relax
15480// \let\DOTSX\relax
15481
15482defineMacro("\\DOTSI", "\\relax");
15483defineMacro("\\DOTSB", "\\relax");
15484defineMacro("\\DOTSX", "\\relax"); // Spacing, based on amsmath.sty's override of LaTeX defaults
15485// \DeclareRobustCommand{\tmspace}[3]{%
15486//   \ifmmode\mskip#1#2\else\kern#1#3\fi\relax}
15487
15488defineMacro("\\tmspace", "\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"); // \renewcommand{\,}{\tmspace+\thinmuskip{.1667em}}
15489// TODO: math mode should use \thinmuskip
15490
15491defineMacro("\\,", "\\tmspace+{3mu}{.1667em}"); // \let\thinspace\,
15492
15493defineMacro("\\thinspace", "\\,"); // \def\>{\mskip\medmuskip}
15494// \renewcommand{\:}{\tmspace+\medmuskip{.2222em}}
15495// TODO: \> and math mode of \: should use \medmuskip = 4mu plus 2mu minus 4mu
15496
15497defineMacro("\\>", "\\mskip{4mu}");
15498defineMacro("\\:", "\\tmspace+{4mu}{.2222em}"); // \let\medspace\:
15499
15500defineMacro("\\medspace", "\\:"); // \renewcommand{\;}{\tmspace+\thickmuskip{.2777em}}
15501// TODO: math mode should use \thickmuskip = 5mu plus 5mu
15502
15503defineMacro("\\;", "\\tmspace+{5mu}{.2777em}"); // \let\thickspace\;
15504
15505defineMacro("\\thickspace", "\\;"); // \renewcommand{\!}{\tmspace-\thinmuskip{.1667em}}
15506// TODO: math mode should use \thinmuskip
15507
15508defineMacro("\\!", "\\tmspace-{3mu}{.1667em}"); // \let\negthinspace\!
15509
15510defineMacro("\\negthinspace", "\\!"); // \newcommand{\negmedspace}{\tmspace-\medmuskip{.2222em}}
15511// TODO: math mode should use \medmuskip
15512
15513defineMacro("\\negmedspace", "\\tmspace-{4mu}{.2222em}"); // \newcommand{\negthickspace}{\tmspace-\thickmuskip{.2777em}}
15514// TODO: math mode should use \thickmuskip
15515
15516defineMacro("\\negthickspace", "\\tmspace-{5mu}{.277em}"); // \def\enspace{\kern.5em }
15517
15518defineMacro("\\enspace", "\\kern.5em "); // \def\enskip{\hskip.5em\relax}
15519
15520defineMacro("\\enskip", "\\hskip.5em\\relax"); // \def\quad{\hskip1em\relax}
15521
15522defineMacro("\\quad", "\\hskip1em\\relax"); // \def\qquad{\hskip2em\relax}
15523
15524defineMacro("\\qquad", "\\hskip2em\\relax"); // \tag@in@display form of \tag
15525
15526defineMacro("\\tag", "\\@ifstar\\tag@literal\\tag@paren");
15527defineMacro("\\tag@paren", "\\tag@literal{({#1})}");
15528defineMacro("\\tag@literal", context => {
15529  if (context.macros.get("\\df@tag")) {
15530    throw new ParseError("Multiple \\tag");
15531  }
15532
15533  return "\\gdef\\df@tag{\\text{#1}}";
15534}); // \renewcommand{\bmod}{\nonscript\mskip-\medmuskip\mkern5mu\mathbin
15535//   {\operator@font mod}\penalty900
15536//   \mkern5mu\nonscript\mskip-\medmuskip}
15537// \newcommand{\pod}[1]{\allowbreak
15538//   \if@display\mkern18mu\else\mkern8mu\fi(#1)}
15539// \renewcommand{\pmod}[1]{\pod{{\operator@font mod}\mkern6mu#1}}
15540// \newcommand{\mod}[1]{\allowbreak\if@display\mkern18mu
15541//   \else\mkern12mu\fi{\operator@font mod}\,\,#1}
15542// TODO: math mode should use \medmuskip = 4mu plus 2mu minus 4mu
15543
15544defineMacro("\\bmod", "\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}" + "\\mathbin{\\rm mod}" + "\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}");
15545defineMacro("\\pod", "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)");
15546defineMacro("\\pmod", "\\pod{{\\rm mod}\\mkern6mu#1}");
15547defineMacro("\\mod", "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}" + "{\\rm mod}\\,\\,#1"); // \pmb    --   A simulation of bold.
15548// The version in ambsy.sty works by typesetting three copies of the argument
15549// with small offsets. We use two copies. We omit the vertical offset because
15550// of rendering problems that makeVList encounters in Safari.
15551
15552defineMacro("\\pmb", "\\html@mathml{" + "\\@binrel{#1}{\\mathrlap{#1}\\kern0.5px#1}}" + "{\\mathbf{#1}}"); //////////////////////////////////////////////////////////////////////
15553// LaTeX source2e
15554// \expandafter\let\expandafter\@normalcr
15555//     \csname\expandafter\@gobble\string\\ \endcsname
15556// \DeclareRobustCommand\newline{\@normalcr\relax}
15557
15558defineMacro("\\newline", "\\\\\\relax"); // \def\TeX{T\kern-.1667em\lower.5ex\hbox{E}\kern-.125emX\@}
15559// TODO: Doesn't normally work in math mode because \@ fails.  KaTeX doesn't
15560// support \@ yet, so that's omitted, and we add \text so that the result
15561// doesn't look funny in math mode.
15562
15563defineMacro("\\TeX", "\\textrm{\\html@mathml{" + "T\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125emX" + "}{TeX}}"); // \DeclareRobustCommand{\LaTeX}{L\kern-.36em%
15564//         {\sbox\z@ T%
15565//          \vbox to\ht\z@{\hbox{\check@mathfonts
15566//                               \fontsize\sf@size\z@
15567//                               \math@fontsfalse\selectfont
15568//                               A}%
15569//                         \vss}%
15570//         }%
15571//         \kern-.15em%
15572//         \TeX}
15573// This code aligns the top of the A with the T (from the perspective of TeX's
15574// boxes, though visually the A appears to extend above slightly).
15575// We compute the corresponding \raisebox when A is rendered in \normalsize
15576// \scriptstyle, which has a scale factor of 0.7 (see Options.js).
15577
15578var latexRaiseA = makeEm(fontMetricsData['Main-Regular']["T".charCodeAt(0)][1] - 0.7 * fontMetricsData['Main-Regular']["A".charCodeAt(0)][1]);
15579defineMacro("\\LaTeX", "\\textrm{\\html@mathml{" + ("L\\kern-.36em\\raisebox{" + latexRaiseA + "}{\\scriptstyle A}") + "\\kern-.15em\\TeX}{LaTeX}}"); // New KaTeX logo based on tweaking LaTeX logo
15580
15581defineMacro("\\KaTeX", "\\textrm{\\html@mathml{" + ("K\\kern-.17em\\raisebox{" + latexRaiseA + "}{\\scriptstyle A}") + "\\kern-.15em\\TeX}{KaTeX}}"); // \DeclareRobustCommand\hspace{\@ifstar\@hspacer\@hspace}
15582// \def\@hspace#1{\hskip  #1\relax}
15583// \def\@hspacer#1{\vrule \@width\z@\nobreak
15584//                 \hskip #1\hskip \z@skip}
15585
15586defineMacro("\\hspace", "\\@ifstar\\@hspacer\\@hspace");
15587defineMacro("\\@hspace", "\\hskip #1\\relax");
15588defineMacro("\\@hspacer", "\\rule{0pt}{0pt}\\hskip #1\\relax"); //////////////////////////////////////////////////////////////////////
15589// mathtools.sty
15590//\providecommand\ordinarycolon{:}
15591
15592defineMacro("\\ordinarycolon", ":"); //\def\vcentcolon{\mathrel{\mathop\ordinarycolon}}
15593//TODO(edemaine): Not yet centered. Fix via \raisebox or #726
15594
15595defineMacro("\\vcentcolon", "\\mathrel{\\mathop\\ordinarycolon}"); // \providecommand*\dblcolon{\vcentcolon\mathrel{\mkern-.9mu}\vcentcolon}
15596
15597defineMacro("\\dblcolon", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-.9mu}\\vcentcolon}}" + "{\\mathop{\\char\"2237}}"); // \providecommand*\coloneqq{\vcentcolon\mathrel{\mkern-1.2mu}=}
15598
15599defineMacro("\\coloneqq", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}=}}" + "{\\mathop{\\char\"2254}}"); // ≔
15600// \providecommand*\Coloneqq{\dblcolon\mathrel{\mkern-1.2mu}=}
15601
15602defineMacro("\\Coloneqq", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}=}}" + "{\\mathop{\\char\"2237\\char\"3d}}"); // \providecommand*\coloneq{\vcentcolon\mathrel{\mkern-1.2mu}\mathrel{-}}
15603
15604defineMacro("\\coloneq", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}" + "{\\mathop{\\char\"3a\\char\"2212}}"); // \providecommand*\Coloneq{\dblcolon\mathrel{\mkern-1.2mu}\mathrel{-}}
15605
15606defineMacro("\\Coloneq", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}" + "{\\mathop{\\char\"2237\\char\"2212}}"); // \providecommand*\eqqcolon{=\mathrel{\mkern-1.2mu}\vcentcolon}
15607
15608defineMacro("\\eqqcolon", "\\html@mathml{" + "\\mathrel{=\\mathrel{\\mkern-1.2mu}\\vcentcolon}}" + "{\\mathop{\\char\"2255}}"); // ≕
15609// \providecommand*\Eqqcolon{=\mathrel{\mkern-1.2mu}\dblcolon}
15610
15611defineMacro("\\Eqqcolon", "\\html@mathml{" + "\\mathrel{=\\mathrel{\\mkern-1.2mu}\\dblcolon}}" + "{\\mathop{\\char\"3d\\char\"2237}}"); // \providecommand*\eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\vcentcolon}
15612
15613defineMacro("\\eqcolon", "\\html@mathml{" + "\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\vcentcolon}}" + "{\\mathop{\\char\"2239}}"); // \providecommand*\Eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\dblcolon}
15614
15615defineMacro("\\Eqcolon", "\\html@mathml{" + "\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\dblcolon}}" + "{\\mathop{\\char\"2212\\char\"2237}}"); // \providecommand*\colonapprox{\vcentcolon\mathrel{\mkern-1.2mu}\approx}
15616
15617defineMacro("\\colonapprox", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\approx}}" + "{\\mathop{\\char\"3a\\char\"2248}}"); // \providecommand*\Colonapprox{\dblcolon\mathrel{\mkern-1.2mu}\approx}
15618
15619defineMacro("\\Colonapprox", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\approx}}" + "{\\mathop{\\char\"2237\\char\"2248}}"); // \providecommand*\colonsim{\vcentcolon\mathrel{\mkern-1.2mu}\sim}
15620
15621defineMacro("\\colonsim", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\sim}}" + "{\\mathop{\\char\"3a\\char\"223c}}"); // \providecommand*\Colonsim{\dblcolon\mathrel{\mkern-1.2mu}\sim}
15622
15623defineMacro("\\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.
15624
15625defineMacro("\u2237", "\\dblcolon"); // ::
15626
15627defineMacro("\u2239", "\\eqcolon"); // -:
15628
15629defineMacro("\u2254", "\\coloneqq"); // :=
15630
15631defineMacro("\u2255", "\\eqqcolon"); // =:
15632
15633defineMacro("\u2A74", "\\Coloneqq"); // ::=
15634//////////////////////////////////////////////////////////////////////
15635// colonequals.sty
15636// Alternate names for mathtools's macros:
15637
15638defineMacro("\\ratio", "\\vcentcolon");
15639defineMacro("\\coloncolon", "\\dblcolon");
15640defineMacro("\\colonequals", "\\coloneqq");
15641defineMacro("\\coloncolonequals", "\\Coloneqq");
15642defineMacro("\\equalscolon", "\\eqqcolon");
15643defineMacro("\\equalscoloncolon", "\\Eqqcolon");
15644defineMacro("\\colonminus", "\\coloneq");
15645defineMacro("\\coloncolonminus", "\\Coloneq");
15646defineMacro("\\minuscolon", "\\eqcolon");
15647defineMacro("\\minuscoloncolon", "\\Eqcolon"); // \colonapprox name is same in mathtools and colonequals.
15648
15649defineMacro("\\coloncolonapprox", "\\Colonapprox"); // \colonsim name is same in mathtools and colonequals.
15650
15651defineMacro("\\coloncolonsim", "\\Colonsim"); // Additional macros, implemented by analogy with mathtools definitions:
15652
15653defineMacro("\\simcolon", "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\vcentcolon}");
15654defineMacro("\\simcoloncolon", "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\dblcolon}");
15655defineMacro("\\approxcolon", "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\vcentcolon}");
15656defineMacro("\\approxcoloncolon", "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\dblcolon}"); // Present in newtxmath, pxfonts and txfonts
15657
15658defineMacro("\\notni", "\\html@mathml{\\not\\ni}{\\mathrel{\\char`\u220C}}");
15659defineMacro("\\limsup", "\\DOTSB\\operatorname*{lim\\,sup}");
15660defineMacro("\\liminf", "\\DOTSB\\operatorname*{lim\\,inf}"); //////////////////////////////////////////////////////////////////////
15661// From amsopn.sty
15662
15663defineMacro("\\injlim", "\\DOTSB\\operatorname*{inj\\,lim}");
15664defineMacro("\\projlim", "\\DOTSB\\operatorname*{proj\\,lim}");
15665defineMacro("\\varlimsup", "\\DOTSB\\operatorname*{\\overline{lim}}");
15666defineMacro("\\varliminf", "\\DOTSB\\operatorname*{\\underline{lim}}");
15667defineMacro("\\varinjlim", "\\DOTSB\\operatorname*{\\underrightarrow{lim}}");
15668defineMacro("\\varprojlim", "\\DOTSB\\operatorname*{\\underleftarrow{lim}}"); //////////////////////////////////////////////////////////////////////
15669// MathML alternates for KaTeX glyphs in the Unicode private area
15670
15671defineMacro("\\gvertneqq", "\\html@mathml{\\@gvertneqq}{\u2269}");
15672defineMacro("\\lvertneqq", "\\html@mathml{\\@lvertneqq}{\u2268}");
15673defineMacro("\\ngeqq", "\\html@mathml{\\@ngeqq}{\u2271}");
15674defineMacro("\\ngeqslant", "\\html@mathml{\\@ngeqslant}{\u2271}");
15675defineMacro("\\nleqq", "\\html@mathml{\\@nleqq}{\u2270}");
15676defineMacro("\\nleqslant", "\\html@mathml{\\@nleqslant}{\u2270}");
15677defineMacro("\\nshortmid", "\\html@mathml{\\@nshortmid}{∤}");
15678defineMacro("\\nshortparallel", "\\html@mathml{\\@nshortparallel}{∦}");
15679defineMacro("\\nsubseteqq", "\\html@mathml{\\@nsubseteqq}{\u2288}");
15680defineMacro("\\nsupseteqq", "\\html@mathml{\\@nsupseteqq}{\u2289}");
15681defineMacro("\\varsubsetneq", "\\html@mathml{\\@varsubsetneq}{⊊}");
15682defineMacro("\\varsubsetneqq", "\\html@mathml{\\@varsubsetneqq}{⫋}");
15683defineMacro("\\varsupsetneq", "\\html@mathml{\\@varsupsetneq}{⊋}");
15684defineMacro("\\varsupsetneqq", "\\html@mathml{\\@varsupsetneqq}{⫌}");
15685defineMacro("\\imath", "\\html@mathml{\\@imath}{\u0131}");
15686defineMacro("\\jmath", "\\html@mathml{\\@jmath}{\u0237}"); //////////////////////////////////////////////////////////////////////
15687// stmaryrd and semantic
15688// The stmaryrd and semantic packages render the next four items by calling a
15689// glyph. Those glyphs do not exist in the KaTeX fonts. Hence the macros.
15690
15691defineMacro("\\llbracket", "\\html@mathml{" + "\\mathopen{[\\mkern-3.2mu[}}" + "{\\mathopen{\\char`\u27e6}}");
15692defineMacro("\\rrbracket", "\\html@mathml{" + "\\mathclose{]\\mkern-3.2mu]}}" + "{\\mathclose{\\char`\u27e7}}");
15693defineMacro("\u27e6", "\\llbracket"); // blackboard bold [
15694
15695defineMacro("\u27e7", "\\rrbracket"); // blackboard bold ]
15696
15697defineMacro("\\lBrace", "\\html@mathml{" + "\\mathopen{\\{\\mkern-3.2mu[}}" + "{\\mathopen{\\char`\u2983}}");
15698defineMacro("\\rBrace", "\\html@mathml{" + "\\mathclose{]\\mkern-3.2mu\\}}}" + "{\\mathclose{\\char`\u2984}}");
15699defineMacro("\u2983", "\\lBrace"); // blackboard bold {
15700
15701defineMacro("\u2984", "\\rBrace"); // blackboard bold }
15702// TODO: Create variable sized versions of the last two items. I believe that
15703// will require new font glyphs.
15704// The stmaryrd function `\minuso` provides a "Plimsoll" symbol that
15705// superimposes the characters \circ and \mathminus. Used in chemistry.
15706
15707defineMacro("\\minuso", "\\mathbin{\\html@mathml{" + "{\\mathrlap{\\mathchoice{\\kern{0.145em}}{\\kern{0.145em}}" + "{\\kern{0.1015em}}{\\kern{0.0725em}}\\circ}{-}}}" + "{\\char`⦵}}");
15708defineMacro("⦵", "\\minuso"); //////////////////////////////////////////////////////////////////////
15709// texvc.sty
15710// The texvc package contains macros available in mediawiki pages.
15711// We omit the functions deprecated at
15712// https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax
15713// We also omit texvc's \O, which conflicts with \text{\O}
15714
15715defineMacro("\\darr", "\\downarrow");
15716defineMacro("\\dArr", "\\Downarrow");
15717defineMacro("\\Darr", "\\Downarrow");
15718defineMacro("\\lang", "\\langle");
15719defineMacro("\\rang", "\\rangle");
15720defineMacro("\\uarr", "\\uparrow");
15721defineMacro("\\uArr", "\\Uparrow");
15722defineMacro("\\Uarr", "\\Uparrow");
15723defineMacro("\\N", "\\mathbb{N}");
15724defineMacro("\\R", "\\mathbb{R}");
15725defineMacro("\\Z", "\\mathbb{Z}");
15726defineMacro("\\alef", "\\aleph");
15727defineMacro("\\alefsym", "\\aleph");
15728defineMacro("\\Alpha", "\\mathrm{A}");
15729defineMacro("\\Beta", "\\mathrm{B}");
15730defineMacro("\\bull", "\\bullet");
15731defineMacro("\\Chi", "\\mathrm{X}");
15732defineMacro("\\clubs", "\\clubsuit");
15733defineMacro("\\cnums", "\\mathbb{C}");
15734defineMacro("\\Complex", "\\mathbb{C}");
15735defineMacro("\\Dagger", "\\ddagger");
15736defineMacro("\\diamonds", "\\diamondsuit");
15737defineMacro("\\empty", "\\emptyset");
15738defineMacro("\\Epsilon", "\\mathrm{E}");
15739defineMacro("\\Eta", "\\mathrm{H}");
15740defineMacro("\\exist", "\\exists");
15741defineMacro("\\harr", "\\leftrightarrow");
15742defineMacro("\\hArr", "\\Leftrightarrow");
15743defineMacro("\\Harr", "\\Leftrightarrow");
15744defineMacro("\\hearts", "\\heartsuit");
15745defineMacro("\\image", "\\Im");
15746defineMacro("\\infin", "\\infty");
15747defineMacro("\\Iota", "\\mathrm{I}");
15748defineMacro("\\isin", "\\in");
15749defineMacro("\\Kappa", "\\mathrm{K}");
15750defineMacro("\\larr", "\\leftarrow");
15751defineMacro("\\lArr", "\\Leftarrow");
15752defineMacro("\\Larr", "\\Leftarrow");
15753defineMacro("\\lrarr", "\\leftrightarrow");
15754defineMacro("\\lrArr", "\\Leftrightarrow");
15755defineMacro("\\Lrarr", "\\Leftrightarrow");
15756defineMacro("\\Mu", "\\mathrm{M}");
15757defineMacro("\\natnums", "\\mathbb{N}");
15758defineMacro("\\Nu", "\\mathrm{N}");
15759defineMacro("\\Omicron", "\\mathrm{O}");
15760defineMacro("\\plusmn", "\\pm");
15761defineMacro("\\rarr", "\\rightarrow");
15762defineMacro("\\rArr", "\\Rightarrow");
15763defineMacro("\\Rarr", "\\Rightarrow");
15764defineMacro("\\real", "\\Re");
15765defineMacro("\\reals", "\\mathbb{R}");
15766defineMacro("\\Reals", "\\mathbb{R}");
15767defineMacro("\\Rho", "\\mathrm{P}");
15768defineMacro("\\sdot", "\\cdot");
15769defineMacro("\\sect", "\\S");
15770defineMacro("\\spades", "\\spadesuit");
15771defineMacro("\\sub", "\\subset");
15772defineMacro("\\sube", "\\subseteq");
15773defineMacro("\\supe", "\\supseteq");
15774defineMacro("\\Tau", "\\mathrm{T}");
15775defineMacro("\\thetasym", "\\vartheta"); // TODO: defineMacro("\\varcoppa", "\\\mbox{\\coppa}");
15776
15777defineMacro("\\weierp", "\\wp");
15778defineMacro("\\Zeta", "\\mathrm{Z}"); //////////////////////////////////////////////////////////////////////
15779// statmath.sty
15780// https://ctan.math.illinois.edu/macros/latex/contrib/statmath/statmath.pdf
15781
15782defineMacro("\\argmin", "\\DOTSB\\operatorname*{arg\\,min}");
15783defineMacro("\\argmax", "\\DOTSB\\operatorname*{arg\\,max}");
15784defineMacro("\\plim", "\\DOTSB\\mathop{\\operatorname{plim}}\\limits"); //////////////////////////////////////////////////////////////////////
15785// braket.sty
15786// http://ctan.math.washington.edu/tex-archive/macros/latex/contrib/braket/braket.pdf
15787
15788defineMacro("\\bra", "\\mathinner{\\langle{#1}|}");
15789defineMacro("\\ket", "\\mathinner{|{#1}\\rangle}");
15790defineMacro("\\braket", "\\mathinner{\\langle{#1}\\rangle}");
15791defineMacro("\\Bra", "\\left\\langle#1\\right|");
15792defineMacro("\\Ket", "\\left|#1\\right\\rangle"); //////////////////////////////////////////////////////////////////////
15793// actuarialangle.dtx
15794
15795defineMacro("\\angln", "{\\angl n}"); // Custom Khan Academy colors, should be moved to an optional package
15796
15797defineMacro("\\blue", "\\textcolor{##6495ed}{#1}");
15798defineMacro("\\orange", "\\textcolor{##ffa500}{#1}");
15799defineMacro("\\pink", "\\textcolor{##ff00af}{#1}");
15800defineMacro("\\red", "\\textcolor{##df0030}{#1}");
15801defineMacro("\\green", "\\textcolor{##28ae7b}{#1}");
15802defineMacro("\\gray", "\\textcolor{gray}{#1}");
15803defineMacro("\\purple", "\\textcolor{##9d38bd}{#1}");
15804defineMacro("\\blueA", "\\textcolor{##ccfaff}{#1}");
15805defineMacro("\\blueB", "\\textcolor{##80f6ff}{#1}");
15806defineMacro("\\blueC", "\\textcolor{##63d9ea}{#1}");
15807defineMacro("\\blueD", "\\textcolor{##11accd}{#1}");
15808defineMacro("\\blueE", "\\textcolor{##0c7f99}{#1}");
15809defineMacro("\\tealA", "\\textcolor{##94fff5}{#1}");
15810defineMacro("\\tealB", "\\textcolor{##26edd5}{#1}");
15811defineMacro("\\tealC", "\\textcolor{##01d1c1}{#1}");
15812defineMacro("\\tealD", "\\textcolor{##01a995}{#1}");
15813defineMacro("\\tealE", "\\textcolor{##208170}{#1}");
15814defineMacro("\\greenA", "\\textcolor{##b6ffb0}{#1}");
15815defineMacro("\\greenB", "\\textcolor{##8af281}{#1}");
15816defineMacro("\\greenC", "\\textcolor{##74cf70}{#1}");
15817defineMacro("\\greenD", "\\textcolor{##1fab54}{#1}");
15818defineMacro("\\greenE", "\\textcolor{##0d923f}{#1}");
15819defineMacro("\\goldA", "\\textcolor{##ffd0a9}{#1}");
15820defineMacro("\\goldB", "\\textcolor{##ffbb71}{#1}");
15821defineMacro("\\goldC", "\\textcolor{##ff9c39}{#1}");
15822defineMacro("\\goldD", "\\textcolor{##e07d10}{#1}");
15823defineMacro("\\goldE", "\\textcolor{##a75a05}{#1}");
15824defineMacro("\\redA", "\\textcolor{##fca9a9}{#1}");
15825defineMacro("\\redB", "\\textcolor{##ff8482}{#1}");
15826defineMacro("\\redC", "\\textcolor{##f9685d}{#1}");
15827defineMacro("\\redD", "\\textcolor{##e84d39}{#1}");
15828defineMacro("\\redE", "\\textcolor{##bc2612}{#1}");
15829defineMacro("\\maroonA", "\\textcolor{##ffbde0}{#1}");
15830defineMacro("\\maroonB", "\\textcolor{##ff92c6}{#1}");
15831defineMacro("\\maroonC", "\\textcolor{##ed5fa6}{#1}");
15832defineMacro("\\maroonD", "\\textcolor{##ca337c}{#1}");
15833defineMacro("\\maroonE", "\\textcolor{##9e034e}{#1}");
15834defineMacro("\\purpleA", "\\textcolor{##ddd7ff}{#1}");
15835defineMacro("\\purpleB", "\\textcolor{##c6b9fc}{#1}");
15836defineMacro("\\purpleC", "\\textcolor{##aa87ff}{#1}");
15837defineMacro("\\purpleD", "\\textcolor{##7854ab}{#1}");
15838defineMacro("\\purpleE", "\\textcolor{##543b78}{#1}");
15839defineMacro("\\mintA", "\\textcolor{##f5f9e8}{#1}");
15840defineMacro("\\mintB", "\\textcolor{##edf2df}{#1}");
15841defineMacro("\\mintC", "\\textcolor{##e0e5cc}{#1}");
15842defineMacro("\\grayA", "\\textcolor{##f6f7f7}{#1}");
15843defineMacro("\\grayB", "\\textcolor{##f0f1f2}{#1}");
15844defineMacro("\\grayC", "\\textcolor{##e3e5e6}{#1}");
15845defineMacro("\\grayD", "\\textcolor{##d6d8da}{#1}");
15846defineMacro("\\grayE", "\\textcolor{##babec2}{#1}");
15847defineMacro("\\grayF", "\\textcolor{##888d93}{#1}");
15848defineMacro("\\grayG", "\\textcolor{##626569}{#1}");
15849defineMacro("\\grayH", "\\textcolor{##3b3e40}{#1}");
15850defineMacro("\\grayI", "\\textcolor{##21242c}{#1}");
15851defineMacro("\\kaBlue", "\\textcolor{##314453}{#1}");
15852defineMacro("\\kaGreen", "\\textcolor{##71B307}{#1}");
15853
15854/**
15855 * This file contains the “gullet” where macros are expanded
15856 * until only non-macro tokens remain.
15857 */
15858// List of commands that act like macros but aren't defined as a macro,
15859// function, or symbol.  Used in `isDefined`.
15860var implicitCommands = {
15861  "^": true,
15862  // Parser.js
15863  "_": true,
15864  // Parser.js
15865  "\\limits": true,
15866  // Parser.js
15867  "\\nolimits": true // Parser.js
15868
15869};
15870class MacroExpander {
15871  constructor(input, settings, mode) {
15872    this.settings = void 0;
15873    this.expansionCount = void 0;
15874    this.lexer = void 0;
15875    this.macros = void 0;
15876    this.stack = void 0;
15877    this.mode = void 0;
15878    this.settings = settings;
15879    this.expansionCount = 0;
15880    this.feed(input); // Make new global namespace
15881
15882    this.macros = new Namespace(macros, settings.macros);
15883    this.mode = mode;
15884    this.stack = []; // contains tokens in REVERSE order
15885  }
15886  /**
15887   * Feed a new input string to the same MacroExpander
15888   * (with existing macros etc.).
15889   */
15890
15891
15892  feed(input) {
15893    this.lexer = new Lexer(input, this.settings);
15894  }
15895  /**
15896   * Switches between "text" and "math" modes.
15897   */
15898
15899
15900  switchMode(newMode) {
15901    this.mode = newMode;
15902  }
15903  /**
15904   * Start a new group nesting within all namespaces.
15905   */
15906
15907
15908  beginGroup() {
15909    this.macros.beginGroup();
15910  }
15911  /**
15912   * End current group nesting within all namespaces.
15913   */
15914
15915
15916  endGroup() {
15917    this.macros.endGroup();
15918  }
15919  /**
15920   * Ends all currently nested groups (if any), restoring values before the
15921   * groups began.  Useful in case of an error in the middle of parsing.
15922   */
15923
15924
15925  endGroups() {
15926    this.macros.endGroups();
15927  }
15928  /**
15929   * Returns the topmost token on the stack, without expanding it.
15930   * Similar in behavior to TeX's `\futurelet`.
15931   */
15932
15933
15934  future() {
15935    if (this.stack.length === 0) {
15936      this.pushToken(this.lexer.lex());
15937    }
15938
15939    return this.stack[this.stack.length - 1];
15940  }
15941  /**
15942   * Remove and return the next unexpanded token.
15943   */
15944
15945
15946  popToken() {
15947    this.future(); // ensure non-empty stack
15948
15949    return this.stack.pop();
15950  }
15951  /**
15952   * Add a given token to the token stack.  In particular, this get be used
15953   * to put back a token returned from one of the other methods.
15954   */
15955
15956
15957  pushToken(token) {
15958    this.stack.push(token);
15959  }
15960  /**
15961   * Append an array of tokens to the token stack.
15962   */
15963
15964
15965  pushTokens(tokens) {
15966    this.stack.push(...tokens);
15967  }
15968  /**
15969   * Find an macro argument without expanding tokens and append the array of
15970   * tokens to the token stack. Uses Token as a container for the result.
15971   */
15972
15973
15974  scanArgument(isOptional) {
15975    var start;
15976    var end;
15977    var tokens;
15978
15979    if (isOptional) {
15980      this.consumeSpaces(); // \@ifnextchar gobbles any space following it
15981
15982      if (this.future().text !== "[") {
15983        return null;
15984      }
15985
15986      start = this.popToken(); // don't include [ in tokens
15987
15988      ({
15989        tokens,
15990        end
15991      } = this.consumeArg(["]"]));
15992    } else {
15993      ({
15994        tokens,
15995        start,
15996        end
15997      } = this.consumeArg());
15998    } // indicate the end of an argument
15999
16000
16001    this.pushToken(new Token("EOF", end.loc));
16002    this.pushTokens(tokens);
16003    return start.range(end, "");
16004  }
16005  /**
16006   * Consume all following space tokens, without expansion.
16007   */
16008
16009
16010  consumeSpaces() {
16011    for (;;) {
16012      var token = this.future();
16013
16014      if (token.text === " ") {
16015        this.stack.pop();
16016      } else {
16017        break;
16018      }
16019    }
16020  }
16021  /**
16022   * Consume an argument from the token stream, and return the resulting array
16023   * of tokens and start/end token.
16024   */
16025
16026
16027  consumeArg(delims) {
16028    // The argument for a delimited parameter is the shortest (possibly
16029    // empty) sequence of tokens with properly nested {...} groups that is
16030    // followed ... by this particular list of non-parameter tokens.
16031    // The argument for an undelimited parameter is the next nonblank
16032    // token, unless that token is ‘{’, when the argument will be the
16033    // entire {...} group that follows.
16034    var tokens = [];
16035    var isDelimited = delims && delims.length > 0;
16036
16037    if (!isDelimited) {
16038      // Ignore spaces between arguments.  As the TeXbook says:
16039      // "After you have said ‘\def\row#1#2{...}’, you are allowed to
16040      //  put spaces between the arguments (e.g., ‘\row x n’), because
16041      //  TeX doesn’t use single spaces as undelimited arguments."
16042      this.consumeSpaces();
16043    }
16044
16045    var start = this.future();
16046    var tok;
16047    var depth = 0;
16048    var match = 0;
16049
16050    do {
16051      tok = this.popToken();
16052      tokens.push(tok);
16053
16054      if (tok.text === "{") {
16055        ++depth;
16056      } else if (tok.text === "}") {
16057        --depth;
16058
16059        if (depth === -1) {
16060          throw new ParseError("Extra }", tok);
16061        }
16062      } else if (tok.text === "EOF") {
16063        throw new ParseError("Unexpected end of input in a macro argument" + ", expected '" + (delims && isDelimited ? delims[match] : "}") + "'", tok);
16064      }
16065
16066      if (delims && isDelimited) {
16067        if ((depth === 0 || depth === 1 && delims[match] === "{") && tok.text === delims[match]) {
16068          ++match;
16069
16070          if (match === delims.length) {
16071            // don't include delims in tokens
16072            tokens.splice(-match, match);
16073            break;
16074          }
16075        } else {
16076          match = 0;
16077        }
16078      }
16079    } while (depth !== 0 || isDelimited); // If the argument found ... has the form ‘{<nested tokens>}’,
16080    // ... the outermost braces enclosing the argument are removed
16081
16082
16083    if (start.text === "{" && tokens[tokens.length - 1].text === "}") {
16084      tokens.pop();
16085      tokens.shift();
16086    }
16087
16088    tokens.reverse(); // to fit in with stack order
16089
16090    return {
16091      tokens,
16092      start,
16093      end: tok
16094    };
16095  }
16096  /**
16097   * Consume the specified number of (delimited) arguments from the token
16098   * stream and return the resulting array of arguments.
16099   */
16100
16101
16102  consumeArgs(numArgs, delimiters) {
16103    if (delimiters) {
16104      if (delimiters.length !== numArgs + 1) {
16105        throw new ParseError("The length of delimiters doesn't match the number of args!");
16106      }
16107
16108      var delims = delimiters[0];
16109
16110      for (var i = 0; i < delims.length; i++) {
16111        var tok = this.popToken();
16112
16113        if (delims[i] !== tok.text) {
16114          throw new ParseError("Use of the macro doesn't match its definition", tok);
16115        }
16116      }
16117    }
16118
16119    var args = [];
16120
16121    for (var _i = 0; _i < numArgs; _i++) {
16122      args.push(this.consumeArg(delimiters && delimiters[_i + 1]).tokens);
16123    }
16124
16125    return args;
16126  }
16127  /**
16128   * Expand the next token only once if possible.
16129   *
16130   * If the token is expanded, the resulting tokens will be pushed onto
16131   * the stack in reverse order and will be returned as an array,
16132   * also in reverse order.
16133   *
16134   * If not, the next token will be returned without removing it
16135   * from the stack.  This case can be detected by a `Token` return value
16136   * instead of an `Array` return value.
16137   *
16138   * In either case, the next token will be on the top of the stack,
16139   * or the stack will be empty.
16140   *
16141   * Used to implement `expandAfterFuture` and `expandNextToken`.
16142   *
16143   * If expandableOnly, only expandable tokens are expanded and
16144   * an undefined control sequence results in an error.
16145   */
16146
16147
16148  expandOnce(expandableOnly) {
16149    var topToken = this.popToken();
16150    var name = topToken.text;
16151    var expansion = !topToken.noexpand ? this._getExpansion(name) : null;
16152
16153    if (expansion == null || expandableOnly && expansion.unexpandable) {
16154      if (expandableOnly && expansion == null && name[0] === "\\" && !this.isDefined(name)) {
16155        throw new ParseError("Undefined control sequence: " + name);
16156      }
16157
16158      this.pushToken(topToken);
16159      return topToken;
16160    }
16161
16162    this.expansionCount++;
16163
16164    if (this.expansionCount > this.settings.maxExpand) {
16165      throw new ParseError("Too many expansions: infinite loop or " + "need to increase maxExpand setting");
16166    }
16167
16168    var tokens = expansion.tokens;
16169    var args = this.consumeArgs(expansion.numArgs, expansion.delimiters);
16170
16171    if (expansion.numArgs) {
16172      // paste arguments in place of the placeholders
16173      tokens = tokens.slice(); // make a shallow copy
16174
16175      for (var i = tokens.length - 1; i >= 0; --i) {
16176        var tok = tokens[i];
16177
16178        if (tok.text === "#") {
16179          if (i === 0) {
16180            throw new ParseError("Incomplete placeholder at end of macro body", tok);
16181          }
16182
16183          tok = tokens[--i]; // next token on stack
16184
16185          if (tok.text === "#") {
16186            // ## → #
16187            tokens.splice(i + 1, 1); // drop first #
16188          } else if (/^[1-9]$/.test(tok.text)) {
16189            // replace the placeholder with the indicated argument
16190            tokens.splice(i, 2, ...args[+tok.text - 1]);
16191          } else {
16192            throw new ParseError("Not a valid argument number", tok);
16193          }
16194        }
16195      }
16196    } // Concatenate expansion onto top of stack.
16197
16198
16199    this.pushTokens(tokens);
16200    return tokens;
16201  }
16202  /**
16203   * Expand the next token only once (if possible), and return the resulting
16204   * top token on the stack (without removing anything from the stack).
16205   * Similar in behavior to TeX's `\expandafter\futurelet`.
16206   * Equivalent to expandOnce() followed by future().
16207   */
16208
16209
16210  expandAfterFuture() {
16211    this.expandOnce();
16212    return this.future();
16213  }
16214  /**
16215   * Recursively expand first token, then return first non-expandable token.
16216   */
16217
16218
16219  expandNextToken() {
16220    for (;;) {
16221      var expanded = this.expandOnce(); // expandOnce returns Token if and only if it's fully expanded.
16222
16223      if (expanded instanceof Token) {
16224        // the token after \noexpand is interpreted as if its meaning
16225        // were ‘\relax’
16226        if (expanded.treatAsRelax) {
16227          expanded.text = "\\relax";
16228        }
16229
16230        return this.stack.pop(); // === expanded
16231      }
16232    } // Flow unable to figure out that this pathway is impossible.
16233    // https://github.com/facebook/flow/issues/4808
16234
16235
16236    throw new Error(); // eslint-disable-line no-unreachable
16237  }
16238  /**
16239   * Fully expand the given macro name and return the resulting list of
16240   * tokens, or return `undefined` if no such macro is defined.
16241   */
16242
16243
16244  expandMacro(name) {
16245    return this.macros.has(name) ? this.expandTokens([new Token(name)]) : undefined;
16246  }
16247  /**
16248   * Fully expand the given token stream and return the resulting list of tokens
16249   */
16250
16251
16252  expandTokens(tokens) {
16253    var output = [];
16254    var oldStackLength = this.stack.length;
16255    this.pushTokens(tokens);
16256
16257    while (this.stack.length > oldStackLength) {
16258      var expanded = this.expandOnce(true); // expand only expandable tokens
16259      // expandOnce returns Token if and only if it's fully expanded.
16260
16261      if (expanded instanceof Token) {
16262        if (expanded.treatAsRelax) {
16263          // the expansion of \noexpand is the token itself
16264          expanded.noexpand = false;
16265          expanded.treatAsRelax = false;
16266        }
16267
16268        output.push(this.stack.pop());
16269      }
16270    }
16271
16272    return output;
16273  }
16274  /**
16275   * Fully expand the given macro name and return the result as a string,
16276   * or return `undefined` if no such macro is defined.
16277   */
16278
16279
16280  expandMacroAsText(name) {
16281    var tokens = this.expandMacro(name);
16282
16283    if (tokens) {
16284      return tokens.map(token => token.text).join("");
16285    } else {
16286      return tokens;
16287    }
16288  }
16289  /**
16290   * Returns the expanded macro as a reversed array of tokens and a macro
16291   * argument count.  Or returns `null` if no such macro.
16292   */
16293
16294
16295  _getExpansion(name) {
16296    var definition = this.macros.get(name);
16297
16298    if (definition == null) {
16299      // mainly checking for undefined here
16300      return definition;
16301    } // If a single character has an associated catcode other than 13
16302    // (active character), then don't expand it.
16303
16304
16305    if (name.length === 1) {
16306      var catcode = this.lexer.catcodes[name];
16307
16308      if (catcode != null && catcode !== 13) {
16309        return;
16310      }
16311    }
16312
16313    var expansion = typeof definition === "function" ? definition(this) : definition;
16314
16315    if (typeof expansion === "string") {
16316      var numArgs = 0;
16317
16318      if (expansion.indexOf("#") !== -1) {
16319        var stripped = expansion.replace(/##/g, "");
16320
16321        while (stripped.indexOf("#" + (numArgs + 1)) !== -1) {
16322          ++numArgs;
16323        }
16324      }
16325
16326      var bodyLexer = new Lexer(expansion, this.settings);
16327      var tokens = [];
16328      var tok = bodyLexer.lex();
16329
16330      while (tok.text !== "EOF") {
16331        tokens.push(tok);
16332        tok = bodyLexer.lex();
16333      }
16334
16335      tokens.reverse(); // to fit in with stack using push and pop
16336
16337      var expanded = {
16338        tokens,
16339        numArgs
16340      };
16341      return expanded;
16342    }
16343
16344    return expansion;
16345  }
16346  /**
16347   * Determine whether a command is currently "defined" (has some
16348   * functionality), meaning that it's a macro (in the current group),
16349   * a function, a symbol, or one of the special commands listed in
16350   * `implicitCommands`.
16351   */
16352
16353
16354  isDefined(name) {
16355    return this.macros.has(name) || functions.hasOwnProperty(name) || symbols.math.hasOwnProperty(name) || symbols.text.hasOwnProperty(name) || implicitCommands.hasOwnProperty(name);
16356  }
16357  /**
16358   * Determine whether a command is expandable.
16359   */
16360
16361
16362  isExpandable(name) {
16363    var macro = this.macros.get(name);
16364    return macro != null ? typeof macro === "string" || typeof macro === "function" || !macro.unexpandable : functions.hasOwnProperty(name) && !functions[name].primitive;
16365  }
16366
16367}
16368
16369/* eslint no-constant-condition:0 */
16370
16371var unicodeAccents = {
16372  "́": {
16373    "text": "\\'",
16374    "math": "\\acute"
16375  },
16376  "̀": {
16377    "text": "\\`",
16378    "math": "\\grave"
16379  },
16380  "̈": {
16381    "text": "\\\"",
16382    "math": "\\ddot"
16383  },
16384  "̃": {
16385    "text": "\\~",
16386    "math": "\\tilde"
16387  },
16388  "̄": {
16389    "text": "\\=",
16390    "math": "\\bar"
16391  },
16392  "̆": {
16393    "text": "\\u",
16394    "math": "\\breve"
16395  },
16396  "̌": {
16397    "text": "\\v",
16398    "math": "\\check"
16399  },
16400  "̂": {
16401    "text": "\\^",
16402    "math": "\\hat"
16403  },
16404  "̇": {
16405    "text": "\\.",
16406    "math": "\\dot"
16407  },
16408  "̊": {
16409    "text": "\\r",
16410    "math": "\\mathring"
16411  },
16412  "̋": {
16413    "text": "\\H"
16414  },
16415  "̧": {
16416    "text": "\\c"
16417  }
16418};
16419var unicodeSymbols = {
16420  "á": "á",
16421  "à": "à",
16422  "ä": "ä",
16423  "ǟ": "ǟ",
16424  "ã": "ã",
16425  "ā": "ā",
16426  "ă": "ă",
16427  "ắ": "ắ",
16428  "ằ": "ằ",
16429  "ẵ": "ẵ",
16430  "ǎ": "ǎ",
16431  "â": "â",
16432  "ấ": "ấ",
16433  "ầ": "ầ",
16434  "ẫ": "ẫ",
16435  "ȧ": "ȧ",
16436  "ǡ": "ǡ",
16437  "å": "å",
16438  "ǻ": "ǻ",
16439  "ḃ": "ḃ",
16440  "ć": "ć",
16441  "ḉ": "ḉ",
16442  "č": "č",
16443  "ĉ": "ĉ",
16444  "ċ": "ċ",
16445  "ç": "ç",
16446  "ď": "ď",
16447  "ḋ": "ḋ",
16448  "ḑ": "ḑ",
16449  "é": "é",
16450  "è": "è",
16451  "ë": "ë",
16452  "ẽ": "ẽ",
16453  "ē": "ē",
16454  "ḗ": "ḗ",
16455  "ḕ": "ḕ",
16456  "ĕ": "ĕ",
16457  "ḝ": "ḝ",
16458  "ě": "ě",
16459  "ê": "ê",
16460  "ế": "ế",
16461  "ề": "ề",
16462  "ễ": "ễ",
16463  "ė": "ė",
16464  "ȩ": "ȩ",
16465  "ḟ": "ḟ",
16466  "ǵ": "ǵ",
16467  "ḡ": "ḡ",
16468  "ğ": "ğ",
16469  "ǧ": "ǧ",
16470  "ĝ": "ĝ",
16471  "ġ": "ġ",
16472  "ģ": "ģ",
16473  "ḧ": "ḧ",
16474  "ȟ": "ȟ",
16475  "ĥ": "ĥ",
16476  "ḣ": "ḣ",
16477  "ḩ": "ḩ",
16478  "í": "í",
16479  "ì": "ì",
16480  "ï": "ï",
16481  "ḯ": "ḯ",
16482  "ĩ": "ĩ",
16483  "ī": "ī",
16484  "ĭ": "ĭ",
16485  "ǐ": "ǐ",
16486  "î": "î",
16487  "ǰ": "ǰ",
16488  "ĵ": "ĵ",
16489  "ḱ": "ḱ",
16490  "ǩ": "ǩ",
16491  "ķ": "ķ",
16492  "ĺ": "ĺ",
16493  "ľ": "ľ",
16494  "ļ": "ļ",
16495  "ḿ": "ḿ",
16496  "ṁ": "ṁ",
16497  "ń": "ń",
16498  "ǹ": "ǹ",
16499  "ñ": "ñ",
16500  "ň": "ň",
16501  "ṅ": "ṅ",
16502  "ņ": "ņ",
16503  "ó": "ó",
16504  "ò": "ò",
16505  "ö": "ö",
16506  "ȫ": "ȫ",
16507  "õ": "õ",
16508  "ṍ": "ṍ",
16509  "ṏ": "ṏ",
16510  "ȭ": "ȭ",
16511  "ō": "ō",
16512  "ṓ": "ṓ",
16513  "ṑ": "ṑ",
16514  "ŏ": "ŏ",
16515  "ǒ": "ǒ",
16516  "ô": "ô",
16517  "ố": "ố",
16518  "ồ": "ồ",
16519  "ỗ": "ỗ",
16520  "ȯ": "ȯ",
16521  "ȱ": "ȱ",
16522  "ő": "ő",
16523  "ṕ": "ṕ",
16524  "ṗ": "ṗ",
16525  "ŕ": "ŕ",
16526  "ř": "ř",
16527  "ṙ": "ṙ",
16528  "ŗ": "ŗ",
16529  "ś": "ś",
16530  "ṥ": "ṥ",
16531  "š": "š",
16532  "ṧ": "ṧ",
16533  "ŝ": "ŝ",
16534  "ṡ": "ṡ",
16535  "ş": "ş",
16536  "ẗ": "ẗ",
16537  "ť": "ť",
16538  "ṫ": "ṫ",
16539  "ţ": "ţ",
16540  "ú": "ú",
16541  "ù": "ù",
16542  "ü": "ü",
16543  "ǘ": "ǘ",
16544  "ǜ": "ǜ",
16545  "ǖ": "ǖ",
16546  "ǚ": "ǚ",
16547  "ũ": "ũ",
16548  "ṹ": "ṹ",
16549  "ū": "ū",
16550  "ṻ": "ṻ",
16551  "ŭ": "ŭ",
16552  "ǔ": "ǔ",
16553  "û": "û",
16554  "ů": "ů",
16555  "ű": "ű",
16556  "ṽ": "ṽ",
16557  "ẃ": "ẃ",
16558  "ẁ": "ẁ",
16559  "ẅ": "ẅ",
16560  "ŵ": "ŵ",
16561  "ẇ": "ẇ",
16562  "ẘ": "ẘ",
16563  "ẍ": "ẍ",
16564  "ẋ": "ẋ",
16565  "ý": "ý",
16566  "ỳ": "ỳ",
16567  "ÿ": "ÿ",
16568  "ỹ": "ỹ",
16569  "ȳ": "ȳ",
16570  "ŷ": "ŷ",
16571  "ẏ": "ẏ",
16572  "ẙ": "ẙ",
16573  "ź": "ź",
16574  "ž": "ž",
16575  "ẑ": "ẑ",
16576  "ż": "ż",
16577  "Á": "Á",
16578  "À": "À",
16579  "Ä": "Ä",
16580  "Ǟ": "Ǟ",
16581  "Ã": "Ã",
16582  "Ā": "Ā",
16583  "Ă": "Ă",
16584  "Ắ": "Ắ",
16585  "Ằ": "Ằ",
16586  "Ẵ": "Ẵ",
16587  "Ǎ": "Ǎ",
16588  "Â": "Â",
16589  "Ấ": "Ấ",
16590  "Ầ": "Ầ",
16591  "Ẫ": "Ẫ",
16592  "Ȧ": "Ȧ",
16593  "Ǡ": "Ǡ",
16594  "Å": "Å",
16595  "Ǻ": "Ǻ",
16596  "Ḃ": "Ḃ",
16597  "Ć": "Ć",
16598  "Ḉ": "Ḉ",
16599  "Č": "Č",
16600  "Ĉ": "Ĉ",
16601  "Ċ": "Ċ",
16602  "Ç": "Ç",
16603  "Ď": "Ď",
16604  "Ḋ": "Ḋ",
16605  "Ḑ": "Ḑ",
16606  "É": "É",
16607  "È": "È",
16608  "Ë": "Ë",
16609  "Ẽ": "Ẽ",
16610  "Ē": "Ē",
16611  "Ḗ": "Ḗ",
16612  "Ḕ": "Ḕ",
16613  "Ĕ": "Ĕ",
16614  "Ḝ": "Ḝ",
16615  "Ě": "Ě",
16616  "Ê": "Ê",
16617  "Ế": "Ế",
16618  "Ề": "Ề",
16619  "Ễ": "Ễ",
16620  "Ė": "Ė",
16621  "Ȩ": "Ȩ",
16622  "Ḟ": "Ḟ",
16623  "Ǵ": "Ǵ",
16624  "Ḡ": "Ḡ",
16625  "Ğ": "Ğ",
16626  "Ǧ": "Ǧ",
16627  "Ĝ": "Ĝ",
16628  "Ġ": "Ġ",
16629  "Ģ": "Ģ",
16630  "Ḧ": "Ḧ",
16631  "Ȟ": "Ȟ",
16632  "Ĥ": "Ĥ",
16633  "Ḣ": "Ḣ",
16634  "Ḩ": "Ḩ",
16635  "Í": "Í",
16636  "Ì": "Ì",
16637  "Ï": "Ï",
16638  "Ḯ": "Ḯ",
16639  "Ĩ": "Ĩ",
16640  "Ī": "Ī",
16641  "Ĭ": "Ĭ",
16642  "Ǐ": "Ǐ",
16643  "Î": "Î",
16644  "İ": "İ",
16645  "Ĵ": "Ĵ",
16646  "Ḱ": "Ḱ",
16647  "Ǩ": "Ǩ",
16648  "Ķ": "Ķ",
16649  "Ĺ": "Ĺ",
16650  "Ľ": "Ľ",
16651  "Ļ": "Ļ",
16652  "Ḿ": "Ḿ",
16653  "Ṁ": "Ṁ",
16654  "Ń": "Ń",
16655  "Ǹ": "Ǹ",
16656  "Ñ": "Ñ",
16657  "Ň": "Ň",
16658  "Ṅ": "Ṅ",
16659  "Ņ": "Ņ",
16660  "Ó": "Ó",
16661  "Ò": "Ò",
16662  "Ö": "Ö",
16663  "Ȫ": "Ȫ",
16664  "Õ": "Õ",
16665  "Ṍ": "Ṍ",
16666  "Ṏ": "Ṏ",
16667  "Ȭ": "Ȭ",
16668  "Ō": "Ō",
16669  "Ṓ": "Ṓ",
16670  "Ṑ": "Ṑ",
16671  "Ŏ": "Ŏ",
16672  "Ǒ": "Ǒ",
16673  "Ô": "Ô",
16674  "Ố": "Ố",
16675  "Ồ": "Ồ",
16676  "Ỗ": "Ỗ",
16677  "Ȯ": "Ȯ",
16678  "Ȱ": "Ȱ",
16679  "Ő": "Ő",
16680  "Ṕ": "Ṕ",
16681  "Ṗ": "Ṗ",
16682  "Ŕ": "Ŕ",
16683  "Ř": "Ř",
16684  "Ṙ": "Ṙ",
16685  "Ŗ": "Ŗ",
16686  "Ś": "Ś",
16687  "Ṥ": "Ṥ",
16688  "Š": "Š",
16689  "Ṧ": "Ṧ",
16690  "Ŝ": "Ŝ",
16691  "Ṡ": "Ṡ",
16692  "Ş": "Ş",
16693  "Ť": "Ť",
16694  "Ṫ": "Ṫ",
16695  "Ţ": "Ţ",
16696  "Ú": "Ú",
16697  "Ù": "Ù",
16698  "Ü": "Ü",
16699  "Ǘ": "Ǘ",
16700  "Ǜ": "Ǜ",
16701  "Ǖ": "Ǖ",
16702  "Ǚ": "Ǚ",
16703  "Ũ": "Ũ",
16704  "Ṹ": "Ṹ",
16705  "Ū": "Ū",
16706  "Ṻ": "Ṻ",
16707  "Ŭ": "Ŭ",
16708  "Ǔ": "Ǔ",
16709  "Û": "Û",
16710  "Ů": "Ů",
16711  "Ű": "Ű",
16712  "Ṽ": "Ṽ",
16713  "Ẃ": "Ẃ",
16714  "Ẁ": "Ẁ",
16715  "Ẅ": "Ẅ",
16716  "Ŵ": "Ŵ",
16717  "Ẇ": "Ẇ",
16718  "Ẍ": "Ẍ",
16719  "Ẋ": "Ẋ",
16720  "Ý": "Ý",
16721  "Ỳ": "Ỳ",
16722  "Ÿ": "Ÿ",
16723  "Ỹ": "Ỹ",
16724  "Ȳ": "Ȳ",
16725  "Ŷ": "Ŷ",
16726  "Ẏ": "Ẏ",
16727  "Ź": "Ź",
16728  "Ž": "Ž",
16729  "Ẑ": "Ẑ",
16730  "Ż": "Ż",
16731  "ά": "ά",
16732  "ὰ": "ὰ",
16733  "ᾱ": "ᾱ",
16734  "ᾰ": "ᾰ",
16735  "έ": "έ",
16736  "ὲ": "ὲ",
16737  "ή": "ή",
16738  "ὴ": "ὴ",
16739  "ί": "ί",
16740  "ὶ": "ὶ",
16741  "ϊ": "ϊ",
16742  "ΐ": "ΐ",
16743  "ῒ": "ῒ",
16744  "ῑ": "ῑ",
16745  "ῐ": "ῐ",
16746  "ό": "ό",
16747  "ὸ": "ὸ",
16748  "ύ": "ύ",
16749  "ὺ": "ὺ",
16750  "ϋ": "ϋ",
16751  "ΰ": "ΰ",
16752  "ῢ": "ῢ",
16753  "ῡ": "ῡ",
16754  "ῠ": "ῠ",
16755  "ώ": "ώ",
16756  "ὼ": "ὼ",
16757  "Ύ": "Ύ",
16758  "Ὺ": "Ὺ",
16759  "Ϋ": "Ϋ",
16760  "Ῡ": "Ῡ",
16761  "Ῠ": "Ῠ",
16762  "Ώ": "Ώ",
16763  "Ὼ": "Ὼ"
16764};
16765
16766/**
16767 * This file contains the parser used to parse out a TeX expression from the
16768 * input. Since TeX isn't context-free, standard parsers don't work particularly
16769 * well.
16770 *
16771 * The strategy of this parser is as such:
16772 *
16773 * The main functions (the `.parse...` ones) take a position in the current
16774 * parse string to parse tokens from. The lexer (found in Lexer.js, stored at
16775 * this.gullet.lexer) also supports pulling out tokens at arbitrary places. When
16776 * individual tokens are needed at a position, the lexer is called to pull out a
16777 * token, which is then used.
16778 *
16779 * The parser has a property called "mode" indicating the mode that
16780 * the parser is currently in. Currently it has to be one of "math" or
16781 * "text", which denotes whether the current environment is a math-y
16782 * one or a text-y one (e.g. inside \text). Currently, this serves to
16783 * limit the functions which can be used in text mode.
16784 *
16785 * The main functions then return an object which contains the useful data that
16786 * was parsed at its given point, and a new position at the end of the parsed
16787 * data. The main functions can call each other and continue the parsing by
16788 * using the returned position as a new starting point.
16789 *
16790 * There are also extra `.handle...` functions, which pull out some reused
16791 * functionality into self-contained functions.
16792 *
16793 * The functions return ParseNodes.
16794 */
16795class Parser {
16796  constructor(input, settings) {
16797    this.mode = void 0;
16798    this.gullet = void 0;
16799    this.settings = void 0;
16800    this.leftrightDepth = void 0;
16801    this.nextToken = void 0;
16802    // Start in math mode
16803    this.mode = "math"; // Create a new macro expander (gullet) and (indirectly via that) also a
16804    // new lexer (mouth) for this parser (stomach, in the language of TeX)
16805
16806    this.gullet = new MacroExpander(input, settings, this.mode); // Store the settings for use in parsing
16807
16808    this.settings = settings; // Count leftright depth (for \middle errors)
16809
16810    this.leftrightDepth = 0;
16811  }
16812  /**
16813   * Checks a result to make sure it has the right type, and throws an
16814   * appropriate error otherwise.
16815   */
16816
16817
16818  expect(text, consume) {
16819    if (consume === void 0) {
16820      consume = true;
16821    }
16822
16823    if (this.fetch().text !== text) {
16824      throw new ParseError("Expected '" + text + "', got '" + this.fetch().text + "'", this.fetch());
16825    }
16826
16827    if (consume) {
16828      this.consume();
16829    }
16830  }
16831  /**
16832   * Discards the current lookahead token, considering it consumed.
16833   */
16834
16835
16836  consume() {
16837    this.nextToken = null;
16838  }
16839  /**
16840   * Return the current lookahead token, or if there isn't one (at the
16841   * beginning, or if the previous lookahead token was consume()d),
16842   * fetch the next token as the new lookahead token and return it.
16843   */
16844
16845
16846  fetch() {
16847    if (this.nextToken == null) {
16848      this.nextToken = this.gullet.expandNextToken();
16849    }
16850
16851    return this.nextToken;
16852  }
16853  /**
16854   * Switches between "text" and "math" modes.
16855   */
16856
16857
16858  switchMode(newMode) {
16859    this.mode = newMode;
16860    this.gullet.switchMode(newMode);
16861  }
16862  /**
16863   * Main parsing function, which parses an entire input.
16864   */
16865
16866
16867  parse() {
16868    if (!this.settings.globalGroup) {
16869      // Create a group namespace for the math expression.
16870      // (LaTeX creates a new group for every $...$, $$...$$, \[...\].)
16871      this.gullet.beginGroup();
16872    } // Use old \color behavior (same as LaTeX's \textcolor) if requested.
16873    // We do this within the group for the math expression, so it doesn't
16874    // pollute settings.macros.
16875
16876
16877    if (this.settings.colorIsTextColor) {
16878      this.gullet.macros.set("\\color", "\\textcolor");
16879    }
16880
16881    try {
16882      // Try to parse the input
16883      var parse = this.parseExpression(false); // If we succeeded, make sure there's an EOF at the end
16884
16885      this.expect("EOF"); // End the group namespace for the expression
16886
16887      if (!this.settings.globalGroup) {
16888        this.gullet.endGroup();
16889      }
16890
16891      return parse; // Close any leftover groups in case of a parse error.
16892    } finally {
16893      this.gullet.endGroups();
16894    }
16895  }
16896  /**
16897   * Fully parse a separate sequence of tokens as a separate job.
16898   * Tokens should be specified in reverse order, as in a MacroDefinition.
16899   */
16900
16901
16902  subparse(tokens) {
16903    // Save the next token from the current job.
16904    var oldToken = this.nextToken;
16905    this.consume(); // Run the new job, terminating it with an excess '}'
16906
16907    this.gullet.pushToken(new Token("}"));
16908    this.gullet.pushTokens(tokens);
16909    var parse = this.parseExpression(false);
16910    this.expect("}"); // Restore the next token from the current job.
16911
16912    this.nextToken = oldToken;
16913    return parse;
16914  }
16915
16916  /**
16917   * Parses an "expression", which is a list of atoms.
16918   *
16919   * `breakOnInfix`: Should the parsing stop when we hit infix nodes? This
16920   *                 happens when functions have higher precendence han infix
16921   *                 nodes in implicit parses.
16922   *
16923   * `breakOnTokenText`: The text of the token that the expression should end
16924   *                     with, or `null` if something else should end the
16925   *                     expression.
16926   */
16927  parseExpression(breakOnInfix, breakOnTokenText) {
16928    var body = []; // Keep adding atoms to the body until we can't parse any more atoms (either
16929    // we reached the end, a }, or a \right)
16930
16931    while (true) {
16932      // Ignore spaces in math mode
16933      if (this.mode === "math") {
16934        this.consumeSpaces();
16935      }
16936
16937      var lex = this.fetch();
16938
16939      if (Parser.endOfExpression.indexOf(lex.text) !== -1) {
16940        break;
16941      }
16942
16943      if (breakOnTokenText && lex.text === breakOnTokenText) {
16944        break;
16945      }
16946
16947      if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) {
16948        break;
16949      }
16950
16951      var atom = this.parseAtom(breakOnTokenText);
16952
16953      if (!atom) {
16954        break;
16955      } else if (atom.type === "internal") {
16956        continue;
16957      }
16958
16959      body.push(atom);
16960    }
16961
16962    if (this.mode === "text") {
16963      this.formLigatures(body);
16964    }
16965
16966    return this.handleInfixNodes(body);
16967  }
16968  /**
16969   * Rewrites infix operators such as \over with corresponding commands such
16970   * as \frac.
16971   *
16972   * There can only be one infix operator per group.  If there's more than one
16973   * then the expression is ambiguous.  This can be resolved by adding {}.
16974   */
16975
16976
16977  handleInfixNodes(body) {
16978    var overIndex = -1;
16979    var funcName;
16980
16981    for (var i = 0; i < body.length; i++) {
16982      if (body[i].type === "infix") {
16983        if (overIndex !== -1) {
16984          throw new ParseError("only one infix operator per group", body[i].token);
16985        }
16986
16987        overIndex = i;
16988        funcName = body[i].replaceWith;
16989      }
16990    }
16991
16992    if (overIndex !== -1 && funcName) {
16993      var numerNode;
16994      var denomNode;
16995      var numerBody = body.slice(0, overIndex);
16996      var denomBody = body.slice(overIndex + 1);
16997
16998      if (numerBody.length === 1 && numerBody[0].type === "ordgroup") {
16999        numerNode = numerBody[0];
17000      } else {
17001        numerNode = {
17002          type: "ordgroup",
17003          mode: this.mode,
17004          body: numerBody
17005        };
17006      }
17007
17008      if (denomBody.length === 1 && denomBody[0].type === "ordgroup") {
17009        denomNode = denomBody[0];
17010      } else {
17011        denomNode = {
17012          type: "ordgroup",
17013          mode: this.mode,
17014          body: denomBody
17015        };
17016      }
17017
17018      var node;
17019
17020      if (funcName === "\\\\abovefrac") {
17021        node = this.callFunction(funcName, [numerNode, body[overIndex], denomNode], []);
17022      } else {
17023        node = this.callFunction(funcName, [numerNode, denomNode], []);
17024      }
17025
17026      return [node];
17027    } else {
17028      return body;
17029    }
17030  }
17031  /**
17032   * Handle a subscript or superscript with nice errors.
17033   */
17034
17035
17036  handleSupSubscript(name // For error reporting.
17037  ) {
17038    var symbolToken = this.fetch();
17039    var symbol = symbolToken.text;
17040    this.consume();
17041    this.consumeSpaces(); // ignore spaces before sup/subscript argument
17042
17043    var group = this.parseGroup(name);
17044
17045    if (!group) {
17046      throw new ParseError("Expected group after '" + symbol + "'", symbolToken);
17047    }
17048
17049    return group;
17050  }
17051  /**
17052   * Converts the textual input of an unsupported command into a text node
17053   * contained within a color node whose color is determined by errorColor
17054   */
17055
17056
17057  formatUnsupportedCmd(text) {
17058    var textordArray = [];
17059
17060    for (var i = 0; i < text.length; i++) {
17061      textordArray.push({
17062        type: "textord",
17063        mode: "text",
17064        text: text[i]
17065      });
17066    }
17067
17068    var textNode = {
17069      type: "text",
17070      mode: this.mode,
17071      body: textordArray
17072    };
17073    var colorNode = {
17074      type: "color",
17075      mode: this.mode,
17076      color: this.settings.errorColor,
17077      body: [textNode]
17078    };
17079    return colorNode;
17080  }
17081  /**
17082   * Parses a group with optional super/subscripts.
17083   */
17084
17085
17086  parseAtom(breakOnTokenText) {
17087    // The body of an atom is an implicit group, so that things like
17088    // \left(x\right)^2 work correctly.
17089    var base = this.parseGroup("atom", breakOnTokenText); // In text mode, we don't have superscripts or subscripts
17090
17091    if (this.mode === "text") {
17092      return base;
17093    } // Note that base may be empty (i.e. null) at this point.
17094
17095
17096    var superscript;
17097    var subscript;
17098
17099    while (true) {
17100      // Guaranteed in math mode, so eat any spaces first.
17101      this.consumeSpaces(); // Lex the first token
17102
17103      var lex = this.fetch();
17104
17105      if (lex.text === "\\limits" || lex.text === "\\nolimits") {
17106        // We got a limit control
17107        if (base && base.type === "op") {
17108          var limits = lex.text === "\\limits";
17109          base.limits = limits;
17110          base.alwaysHandleSupSub = true;
17111        } else if (base && base.type === "operatorname") {
17112          if (base.alwaysHandleSupSub) {
17113            base.limits = lex.text === "\\limits";
17114          }
17115        } else {
17116          throw new ParseError("Limit controls must follow a math operator", lex);
17117        }
17118
17119        this.consume();
17120      } else if (lex.text === "^") {
17121        // We got a superscript start
17122        if (superscript) {
17123          throw new ParseError("Double superscript", lex);
17124        }
17125
17126        superscript = this.handleSupSubscript("superscript");
17127      } else if (lex.text === "_") {
17128        // We got a subscript start
17129        if (subscript) {
17130          throw new ParseError("Double subscript", lex);
17131        }
17132
17133        subscript = this.handleSupSubscript("subscript");
17134      } else if (lex.text === "'") {
17135        // We got a prime
17136        if (superscript) {
17137          throw new ParseError("Double superscript", lex);
17138        }
17139
17140        var prime = {
17141          type: "textord",
17142          mode: this.mode,
17143          text: "\\prime"
17144        }; // Many primes can be grouped together, so we handle this here
17145
17146        var primes = [prime];
17147        this.consume(); // Keep lexing tokens until we get something that's not a prime
17148
17149        while (this.fetch().text === "'") {
17150          // For each one, add another prime to the list
17151          primes.push(prime);
17152          this.consume();
17153        } // If there's a superscript following the primes, combine that
17154        // superscript in with the primes.
17155
17156
17157        if (this.fetch().text === "^") {
17158          primes.push(this.handleSupSubscript("superscript"));
17159        } // Put everything into an ordgroup as the superscript
17160
17161
17162        superscript = {
17163          type: "ordgroup",
17164          mode: this.mode,
17165          body: primes
17166        };
17167      } else {
17168        // If it wasn't ^, _, or ', stop parsing super/subscripts
17169        break;
17170      }
17171    } // Base must be set if superscript or subscript are set per logic above,
17172    // but need to check here for type check to pass.
17173
17174
17175    if (superscript || subscript) {
17176      // If we got either a superscript or subscript, create a supsub
17177      return {
17178        type: "supsub",
17179        mode: this.mode,
17180        base: base,
17181        sup: superscript,
17182        sub: subscript
17183      };
17184    } else {
17185      // Otherwise return the original body
17186      return base;
17187    }
17188  }
17189  /**
17190   * Parses an entire function, including its base and all of its arguments.
17191   */
17192
17193
17194  parseFunction(breakOnTokenText, name // For determining its context
17195  ) {
17196    var token = this.fetch();
17197    var func = token.text;
17198    var funcData = functions[func];
17199
17200    if (!funcData) {
17201      return null;
17202    }
17203
17204    this.consume(); // consume command token
17205
17206    if (name && name !== "atom" && !funcData.allowedInArgument) {
17207      throw new ParseError("Got function '" + func + "' with no arguments" + (name ? " as " + name : ""), token);
17208    } else if (this.mode === "text" && !funcData.allowedInText) {
17209      throw new ParseError("Can't use function '" + func + "' in text mode", token);
17210    } else if (this.mode === "math" && funcData.allowedInMath === false) {
17211      throw new ParseError("Can't use function '" + func + "' in math mode", token);
17212    }
17213
17214    var {
17215      args,
17216      optArgs
17217    } = this.parseArguments(func, funcData);
17218    return this.callFunction(func, args, optArgs, token, breakOnTokenText);
17219  }
17220  /**
17221   * Call a function handler with a suitable context and arguments.
17222   */
17223
17224
17225  callFunction(name, args, optArgs, token, breakOnTokenText) {
17226    var context = {
17227      funcName: name,
17228      parser: this,
17229      token,
17230      breakOnTokenText
17231    };
17232    var func = functions[name];
17233
17234    if (func && func.handler) {
17235      return func.handler(context, args, optArgs);
17236    } else {
17237      throw new ParseError("No function handler for " + name);
17238    }
17239  }
17240  /**
17241   * Parses the arguments of a function or environment
17242   */
17243
17244
17245  parseArguments(func, // Should look like "\name" or "\begin{name}".
17246  funcData) {
17247    var totalArgs = funcData.numArgs + funcData.numOptionalArgs;
17248
17249    if (totalArgs === 0) {
17250      return {
17251        args: [],
17252        optArgs: []
17253      };
17254    }
17255
17256    var args = [];
17257    var optArgs = [];
17258
17259    for (var i = 0; i < totalArgs; i++) {
17260      var argType = funcData.argTypes && funcData.argTypes[i];
17261      var isOptional = i < funcData.numOptionalArgs;
17262
17263      if (funcData.primitive && argType == null || // \sqrt expands into primitive if optional argument doesn't exist
17264      funcData.type === "sqrt" && i === 1 && optArgs[0] == null) {
17265        argType = "primitive";
17266      }
17267
17268      var arg = this.parseGroupOfType("argument to '" + func + "'", argType, isOptional);
17269
17270      if (isOptional) {
17271        optArgs.push(arg);
17272      } else if (arg != null) {
17273        args.push(arg);
17274      } else {
17275        // should be unreachable
17276        throw new ParseError("Null argument, please report this as a bug");
17277      }
17278    }
17279
17280    return {
17281      args,
17282      optArgs
17283    };
17284  }
17285  /**
17286   * Parses a group when the mode is changing.
17287   */
17288
17289
17290  parseGroupOfType(name, type, optional) {
17291    switch (type) {
17292      case "color":
17293        return this.parseColorGroup(optional);
17294
17295      case "size":
17296        return this.parseSizeGroup(optional);
17297
17298      case "url":
17299        return this.parseUrlGroup(optional);
17300
17301      case "math":
17302      case "text":
17303        return this.parseArgumentGroup(optional, type);
17304
17305      case "hbox":
17306        {
17307          // hbox argument type wraps the argument in the equivalent of
17308          // \hbox, which is like \text but switching to \textstyle size.
17309          var group = this.parseArgumentGroup(optional, "text");
17310          return group != null ? {
17311            type: "styling",
17312            mode: group.mode,
17313            body: [group],
17314            style: "text" // simulate \textstyle
17315
17316          } : null;
17317        }
17318
17319      case "raw":
17320        {
17321          var token = this.parseStringGroup("raw", optional);
17322          return token != null ? {
17323            type: "raw",
17324            mode: "text",
17325            string: token.text
17326          } : null;
17327        }
17328
17329      case "primitive":
17330        {
17331          if (optional) {
17332            throw new ParseError("A primitive argument cannot be optional");
17333          }
17334
17335          var _group = this.parseGroup(name);
17336
17337          if (_group == null) {
17338            throw new ParseError("Expected group as " + name, this.fetch());
17339          }
17340
17341          return _group;
17342        }
17343
17344      case "original":
17345      case null:
17346      case undefined:
17347        return this.parseArgumentGroup(optional);
17348
17349      default:
17350        throw new ParseError("Unknown group type as " + name, this.fetch());
17351    }
17352  }
17353  /**
17354   * Discard any space tokens, fetching the next non-space token.
17355   */
17356
17357
17358  consumeSpaces() {
17359    while (this.fetch().text === " ") {
17360      this.consume();
17361    }
17362  }
17363  /**
17364   * Parses a group, essentially returning the string formed by the
17365   * brace-enclosed tokens plus some position information.
17366   */
17367
17368
17369  parseStringGroup(modeName, // Used to describe the mode in error messages.
17370  optional) {
17371    var argToken = this.gullet.scanArgument(optional);
17372
17373    if (argToken == null) {
17374      return null;
17375    }
17376
17377    var str = "";
17378    var nextToken;
17379
17380    while ((nextToken = this.fetch()).text !== "EOF") {
17381      str += nextToken.text;
17382      this.consume();
17383    }
17384
17385    this.consume(); // consume the end of the argument
17386
17387    argToken.text = str;
17388    return argToken;
17389  }
17390  /**
17391   * Parses a regex-delimited group: the largest sequence of tokens
17392   * whose concatenated strings match `regex`. Returns the string
17393   * formed by the tokens plus some position information.
17394   */
17395
17396
17397  parseRegexGroup(regex, modeName // Used to describe the mode in error messages.
17398  ) {
17399    var firstToken = this.fetch();
17400    var lastToken = firstToken;
17401    var str = "";
17402    var nextToken;
17403
17404    while ((nextToken = this.fetch()).text !== "EOF" && regex.test(str + nextToken.text)) {
17405      lastToken = nextToken;
17406      str += lastToken.text;
17407      this.consume();
17408    }
17409
17410    if (str === "") {
17411      throw new ParseError("Invalid " + modeName + ": '" + firstToken.text + "'", firstToken);
17412    }
17413
17414    return firstToken.range(lastToken, str);
17415  }
17416  /**
17417   * Parses a color description.
17418   */
17419
17420
17421  parseColorGroup(optional) {
17422    var res = this.parseStringGroup("color", optional);
17423
17424    if (res == null) {
17425      return null;
17426    }
17427
17428    var match = /^(#[a-f0-9]{3}|#?[a-f0-9]{6}|[a-z]+)$/i.exec(res.text);
17429
17430    if (!match) {
17431      throw new ParseError("Invalid color: '" + res.text + "'", res);
17432    }
17433
17434    var color = match[0];
17435
17436    if (/^[0-9a-f]{6}$/i.test(color)) {
17437      // We allow a 6-digit HTML color spec without a leading "#".
17438      // This follows the xcolor package's HTML color model.
17439      // Predefined color names are all missed by this RegEx pattern.
17440      color = "#" + color;
17441    }
17442
17443    return {
17444      type: "color-token",
17445      mode: this.mode,
17446      color
17447    };
17448  }
17449  /**
17450   * Parses a size specification, consisting of magnitude and unit.
17451   */
17452
17453
17454  parseSizeGroup(optional) {
17455    var res;
17456    var isBlank = false; // don't expand before parseStringGroup
17457
17458    this.gullet.consumeSpaces();
17459
17460    if (!optional && this.gullet.future().text !== "{") {
17461      res = this.parseRegexGroup(/^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2} *$/, "size");
17462    } else {
17463      res = this.parseStringGroup("size", optional);
17464    }
17465
17466    if (!res) {
17467      return null;
17468    }
17469
17470    if (!optional && res.text.length === 0) {
17471      // Because we've tested for what is !optional, this block won't
17472      // affect \kern, \hspace, etc. It will capture the mandatory arguments
17473      // to \genfrac and \above.
17474      res.text = "0pt"; // Enable \above{}
17475
17476      isBlank = true; // This is here specifically for \genfrac
17477    }
17478
17479    var match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(res.text);
17480
17481    if (!match) {
17482      throw new ParseError("Invalid size: '" + res.text + "'", res);
17483    }
17484
17485    var data = {
17486      number: +(match[1] + match[2]),
17487      // sign + magnitude, cast to number
17488      unit: match[3]
17489    };
17490
17491    if (!validUnit(data)) {
17492      throw new ParseError("Invalid unit: '" + data.unit + "'", res);
17493    }
17494
17495    return {
17496      type: "size",
17497      mode: this.mode,
17498      value: data,
17499      isBlank
17500    };
17501  }
17502  /**
17503   * Parses an URL, checking escaped letters and allowed protocols,
17504   * and setting the catcode of % as an active character (as in \hyperref).
17505   */
17506
17507
17508  parseUrlGroup(optional) {
17509    this.gullet.lexer.setCatcode("%", 13); // active character
17510
17511    this.gullet.lexer.setCatcode("~", 12); // other character
17512
17513    var res = this.parseStringGroup("url", optional);
17514    this.gullet.lexer.setCatcode("%", 14); // comment character
17515
17516    this.gullet.lexer.setCatcode("~", 13); // active character
17517
17518    if (res == null) {
17519      return null;
17520    } // hyperref package allows backslashes alone in href, but doesn't
17521    // generate valid links in such cases; we interpret this as
17522    // "undefined" behaviour, and keep them as-is. Some browser will
17523    // replace backslashes with forward slashes.
17524
17525
17526    var url = res.text.replace(/\\([#$%&~_^{}])/g, '$1');
17527    return {
17528      type: "url",
17529      mode: this.mode,
17530      url
17531    };
17532  }
17533  /**
17534   * Parses an argument with the mode specified.
17535   */
17536
17537
17538  parseArgumentGroup(optional, mode) {
17539    var argToken = this.gullet.scanArgument(optional);
17540
17541    if (argToken == null) {
17542      return null;
17543    }
17544
17545    var outerMode = this.mode;
17546
17547    if (mode) {
17548      // Switch to specified mode
17549      this.switchMode(mode);
17550    }
17551
17552    this.gullet.beginGroup();
17553    var expression = this.parseExpression(false, "EOF"); // TODO: find an alternative way to denote the end
17554
17555    this.expect("EOF"); // expect the end of the argument
17556
17557    this.gullet.endGroup();
17558    var result = {
17559      type: "ordgroup",
17560      mode: this.mode,
17561      loc: argToken.loc,
17562      body: expression
17563    };
17564
17565    if (mode) {
17566      // Switch mode back
17567      this.switchMode(outerMode);
17568    }
17569
17570    return result;
17571  }
17572  /**
17573   * Parses an ordinary group, which is either a single nucleus (like "x")
17574   * or an expression in braces (like "{x+y}") or an implicit group, a group
17575   * that starts at the current position, and ends right before a higher explicit
17576   * group ends, or at EOF.
17577   */
17578
17579
17580  parseGroup(name, // For error reporting.
17581  breakOnTokenText) {
17582    var firstToken = this.fetch();
17583    var text = firstToken.text;
17584    var result; // Try to parse an open brace or \begingroup
17585
17586    if (text === "{" || text === "\\begingroup") {
17587      this.consume();
17588      var groupEnd = text === "{" ? "}" : "\\endgroup";
17589      this.gullet.beginGroup(); // If we get a brace, parse an expression
17590
17591      var expression = this.parseExpression(false, groupEnd);
17592      var lastToken = this.fetch();
17593      this.expect(groupEnd); // Check that we got a matching closing brace
17594
17595      this.gullet.endGroup();
17596      result = {
17597        type: "ordgroup",
17598        mode: this.mode,
17599        loc: SourceLocation.range(firstToken, lastToken),
17600        body: expression,
17601        // A group formed by \begingroup...\endgroup is a semi-simple group
17602        // which doesn't affect spacing in math mode, i.e., is transparent.
17603        // https://tex.stackexchange.com/questions/1930/when-should-one-
17604        // use-begingroup-instead-of-bgroup
17605        semisimple: text === "\\begingroup" || undefined
17606      };
17607    } else {
17608      // If there exists a function with this name, parse the function.
17609      // Otherwise, just return a nucleus
17610      result = this.parseFunction(breakOnTokenText, name) || this.parseSymbol();
17611
17612      if (result == null && text[0] === "\\" && !implicitCommands.hasOwnProperty(text)) {
17613        if (this.settings.throwOnError) {
17614          throw new ParseError("Undefined control sequence: " + text, firstToken);
17615        }
17616
17617        result = this.formatUnsupportedCmd(text);
17618        this.consume();
17619      }
17620    }
17621
17622    return result;
17623  }
17624  /**
17625   * Form ligature-like combinations of characters for text mode.
17626   * This includes inputs like "--", "---", "``" and "''".
17627   * The result will simply replace multiple textord nodes with a single
17628   * character in each value by a single textord node having multiple
17629   * characters in its value.  The representation is still ASCII source.
17630   * The group will be modified in place.
17631   */
17632
17633
17634  formLigatures(group) {
17635    var n = group.length - 1;
17636
17637    for (var i = 0; i < n; ++i) {
17638      var a = group[i]; // $FlowFixMe: Not every node type has a `text` property.
17639
17640      var v = a.text;
17641
17642      if (v === "-" && group[i + 1].text === "-") {
17643        if (i + 1 < n && group[i + 2].text === "-") {
17644          group.splice(i, 3, {
17645            type: "textord",
17646            mode: "text",
17647            loc: SourceLocation.range(a, group[i + 2]),
17648            text: "---"
17649          });
17650          n -= 2;
17651        } else {
17652          group.splice(i, 2, {
17653            type: "textord",
17654            mode: "text",
17655            loc: SourceLocation.range(a, group[i + 1]),
17656            text: "--"
17657          });
17658          n -= 1;
17659        }
17660      }
17661
17662      if ((v === "'" || v === "`") && group[i + 1].text === v) {
17663        group.splice(i, 2, {
17664          type: "textord",
17665          mode: "text",
17666          loc: SourceLocation.range(a, group[i + 1]),
17667          text: v + v
17668        });
17669        n -= 1;
17670      }
17671    }
17672  }
17673  /**
17674   * Parse a single symbol out of the string. Here, we handle single character
17675   * symbols and special functions like \verb.
17676   */
17677
17678
17679  parseSymbol() {
17680    var nucleus = this.fetch();
17681    var text = nucleus.text;
17682
17683    if (/^\\verb[^a-zA-Z]/.test(text)) {
17684      this.consume();
17685      var arg = text.slice(5);
17686      var star = arg.charAt(0) === "*";
17687
17688      if (star) {
17689        arg = arg.slice(1);
17690      } // Lexer's tokenRegex is constructed to always have matching
17691      // first/last characters.
17692
17693
17694      if (arg.length < 2 || arg.charAt(0) !== arg.slice(-1)) {
17695        throw new ParseError("\\verb assertion failed --\n                    please report what input caused this bug");
17696      }
17697
17698      arg = arg.slice(1, -1); // remove first and last char
17699
17700      return {
17701        type: "verb",
17702        mode: "text",
17703        body: arg,
17704        star
17705      };
17706    } // At this point, we should have a symbol, possibly with accents.
17707    // First expand any accented base symbol according to unicodeSymbols.
17708
17709
17710    if (unicodeSymbols.hasOwnProperty(text[0]) && !symbols[this.mode][text[0]]) {
17711      // This behavior is not strict (XeTeX-compatible) in math mode.
17712      if (this.settings.strict && this.mode === "math") {
17713        this.settings.reportNonstrict("unicodeTextInMathMode", "Accented Unicode text character \"" + text[0] + "\" used in " + "math mode", nucleus);
17714      }
17715
17716      text = unicodeSymbols[text[0]] + text.substr(1);
17717    } // Strip off any combining characters
17718
17719
17720    var match = combiningDiacriticalMarksEndRegex.exec(text);
17721
17722    if (match) {
17723      text = text.substring(0, match.index);
17724
17725      if (text === 'i') {
17726        text = '\u0131'; // dotless i, in math and text mode
17727      } else if (text === 'j') {
17728        text = '\u0237'; // dotless j, in math and text mode
17729      }
17730    } // Recognize base symbol
17731
17732
17733    var symbol;
17734
17735    if (symbols[this.mode][text]) {
17736      if (this.settings.strict && this.mode === 'math' && extraLatin.indexOf(text) >= 0) {
17737        this.settings.reportNonstrict("unicodeTextInMathMode", "Latin-1/Unicode text character \"" + text[0] + "\" used in " + "math mode", nucleus);
17738      }
17739
17740      var group = symbols[this.mode][text].group;
17741      var loc = SourceLocation.range(nucleus);
17742      var s;
17743
17744      if (ATOMS.hasOwnProperty(group)) {
17745        // $FlowFixMe
17746        var family = group;
17747        s = {
17748          type: "atom",
17749          mode: this.mode,
17750          family,
17751          loc,
17752          text
17753        };
17754      } else {
17755        // $FlowFixMe
17756        s = {
17757          type: group,
17758          mode: this.mode,
17759          loc,
17760          text
17761        };
17762      } // $FlowFixMe
17763
17764
17765      symbol = s;
17766    } else if (text.charCodeAt(0) >= 0x80) {
17767      // no symbol for e.g. ^
17768      if (this.settings.strict) {
17769        if (!supportedCodepoint(text.charCodeAt(0))) {
17770          this.settings.reportNonstrict("unknownSymbol", "Unrecognized Unicode character \"" + text[0] + "\"" + (" (" + text.charCodeAt(0) + ")"), nucleus);
17771        } else if (this.mode === "math") {
17772          this.settings.reportNonstrict("unicodeTextInMathMode", "Unicode text character \"" + text[0] + "\" used in math mode", nucleus);
17773        }
17774      } // All nonmathematical Unicode characters are rendered as if they
17775      // are in text mode (wrapped in \text) because that's what it
17776      // takes to render them in LaTeX.  Setting `mode: this.mode` is
17777      // another natural choice (the user requested math mode), but
17778      // this makes it more difficult for getCharacterMetrics() to
17779      // distinguish Unicode characters without metrics and those for
17780      // which we want to simulate the letter M.
17781
17782
17783      symbol = {
17784        type: "textord",
17785        mode: "text",
17786        loc: SourceLocation.range(nucleus),
17787        text
17788      };
17789    } else {
17790      return null; // EOF, ^, _, {, }, etc.
17791    }
17792
17793    this.consume(); // Transform combining characters into accents
17794
17795    if (match) {
17796      for (var i = 0; i < match[0].length; i++) {
17797        var accent = match[0][i];
17798
17799        if (!unicodeAccents[accent]) {
17800          throw new ParseError("Unknown accent ' " + accent + "'", nucleus);
17801        }
17802
17803        var command = unicodeAccents[accent][this.mode] || unicodeAccents[accent].text;
17804
17805        if (!command) {
17806          throw new ParseError("Accent " + accent + " unsupported in " + this.mode + " mode", nucleus);
17807        }
17808
17809        symbol = {
17810          type: "accent",
17811          mode: this.mode,
17812          loc: SourceLocation.range(nucleus),
17813          label: command,
17814          isStretchy: false,
17815          isShifty: true,
17816          // $FlowFixMe
17817          base: symbol
17818        };
17819      }
17820    } // $FlowFixMe
17821
17822
17823    return symbol;
17824  }
17825
17826}
17827Parser.endOfExpression = ["}", "\\endgroup", "\\end", "\\right", "&"];
17828
17829/**
17830 * Provides a single function for parsing an expression using a Parser
17831 * TODO(emily): Remove this
17832 */
17833
17834/**
17835 * Parses an expression using a Parser, then returns the parsed result.
17836 */
17837var parseTree = function parseTree(toParse, settings) {
17838  if (!(typeof toParse === 'string' || toParse instanceof String)) {
17839    throw new TypeError('KaTeX can only parse string typed expression');
17840  }
17841
17842  var parser = new Parser(toParse, settings); // Blank out any \df@tag to avoid spurious "Duplicate \tag" errors
17843
17844  delete parser.gullet.macros.current["\\df@tag"];
17845  var tree = parser.parse(); // Prevent a color definition from persisting between calls to katex.render().
17846
17847  delete parser.gullet.macros.current["\\current@color"];
17848  delete parser.gullet.macros.current["\\color"]; // If the input used \tag, it will set the \df@tag macro to the tag.
17849  // In this case, we separately parse the tag and wrap the tree.
17850
17851  if (parser.gullet.macros.get("\\df@tag")) {
17852    if (!settings.displayMode) {
17853      throw new ParseError("\\tag works only in display equations");
17854    }
17855
17856    tree = [{
17857      type: "tag",
17858      mode: "text",
17859      body: tree,
17860      tag: parser.subparse([new Token("\\df@tag")])
17861    }];
17862  }
17863
17864  return tree;
17865};
17866
17867/* eslint no-console:0 */
17868
17869/**
17870 * Parse and build an expression, and place that expression in the DOM node
17871 * given.
17872 */
17873var render = function render(expression, baseNode, options) {
17874  baseNode.textContent = "";
17875  var node = renderToDomTree(expression, options).toNode();
17876  baseNode.appendChild(node);
17877}; // KaTeX's styles don't work properly in quirks mode. Print out an error, and
17878// disable rendering.
17879
17880
17881if (typeof document !== "undefined") {
17882  if (document.compatMode !== "CSS1Compat") {
17883    typeof console !== "undefined" && console.warn("Warning: KaTeX doesn't work in quirks mode. Make sure your " + "website has a suitable doctype.");
17884
17885    render = function render() {
17886      throw new ParseError("KaTeX doesn't work in quirks mode.");
17887    };
17888  }
17889}
17890/**
17891 * Parse and build an expression, and return the markup for that.
17892 */
17893
17894
17895var renderToString = function renderToString(expression, options) {
17896  var markup = renderToDomTree(expression, options).toMarkup();
17897  return markup;
17898};
17899/**
17900 * Parse an expression and return the parse tree.
17901 */
17902
17903
17904var generateParseTree = function generateParseTree(expression, options) {
17905  var settings = new Settings(options);
17906  return parseTree(expression, settings);
17907};
17908/**
17909 * If the given error is a KaTeX ParseError and options.throwOnError is false,
17910 * renders the invalid LaTeX as a span with hover title giving the KaTeX
17911 * error message.  Otherwise, simply throws the error.
17912 */
17913
17914
17915var renderError = function renderError(error, expression, options) {
17916  if (options.throwOnError || !(error instanceof ParseError)) {
17917    throw error;
17918  }
17919
17920  var node = buildCommon.makeSpan(["katex-error"], [new SymbolNode(expression)]);
17921  node.setAttribute("title", error.toString());
17922  node.setAttribute("style", "color:" + options.errorColor);
17923  return node;
17924};
17925/**
17926 * Generates and returns the katex build tree. This is used for advanced
17927 * use cases (like rendering to custom output).
17928 */
17929
17930
17931var renderToDomTree = function renderToDomTree(expression, options) {
17932  var settings = new Settings(options);
17933
17934  try {
17935    var tree = parseTree(expression, settings);
17936    return buildTree(tree, expression, settings);
17937  } catch (error) {
17938    return renderError(error, expression, settings);
17939  }
17940};
17941/**
17942 * Generates and returns the katex build tree, with just HTML (no MathML).
17943 * This is used for advanced use cases (like rendering to custom output).
17944 */
17945
17946
17947var renderToHTMLTree = function renderToHTMLTree(expression, options) {
17948  var settings = new Settings(options);
17949
17950  try {
17951    var tree = parseTree(expression, settings);
17952    return buildHTMLTree(tree, expression, settings);
17953  } catch (error) {
17954    return renderError(error, expression, settings);
17955  }
17956};
17957
17958var katex = {
17959  /**
17960   * Current KaTeX version
17961   */
17962  version: "0.15.3",
17963
17964  /**
17965   * Renders the given LaTeX into an HTML+MathML combination, and adds
17966   * it as a child to the specified DOM node.
17967   */
17968  render,
17969
17970  /**
17971   * Renders the given LaTeX into an HTML+MathML combination string,
17972   * for sending to the client.
17973   */
17974  renderToString,
17975
17976  /**
17977   * KaTeX error, usually during parsing.
17978   */
17979  ParseError,
17980
17981  /**
17982   * The shema of Settings
17983   */
17984  SETTINGS_SCHEMA,
17985
17986  /**
17987   * Parses the given LaTeX into KaTeX's internal parse tree structure,
17988   * without rendering to HTML or MathML.
17989   *
17990   * NOTE: This method is not currently recommended for public use.
17991   * The internal tree representation is unstable and is very likely
17992   * to change. Use at your own risk.
17993   */
17994  __parse: generateParseTree,
17995
17996  /**
17997   * Renders the given LaTeX into an HTML+MathML internal DOM tree
17998   * representation, without flattening that representation to a string.
17999   *
18000   * NOTE: This method is not currently recommended for public use.
18001   * The internal tree representation is unstable and is very likely
18002   * to change. Use at your own risk.
18003   */
18004  __renderToDomTree: renderToDomTree,
18005
18006  /**
18007   * Renders the given LaTeX into an HTML internal DOM tree representation,
18008   * without MathML and without flattening that representation to a string.
18009   *
18010   * NOTE: This method is not currently recommended for public use.
18011   * The internal tree representation is unstable and is very likely
18012   * to change. Use at your own risk.
18013   */
18014  __renderToHTMLTree: renderToHTMLTree,
18015
18016  /**
18017   * extends internal font metrics object with a new object
18018   * each key in the new object represents a font name
18019  */
18020  __setFontMetrics: setFontMetrics,
18021
18022  /**
18023   * adds a new symbol to builtin symbols table
18024   */
18025  __defineSymbol: defineSymbol,
18026
18027  /**
18028   * adds a new macro to builtin macro list
18029   */
18030  __defineMacro: defineMacro,
18031
18032  /**
18033   * Expose the dom tree node types, which can be useful for type checking nodes.
18034   *
18035   * NOTE: This method is not currently recommended for public use.
18036   * The internal tree representation is unstable and is very likely
18037   * to change. Use at your own risk.
18038   */
18039  __domTree: {
18040    Span,
18041    Anchor,
18042    SymbolNode,
18043    SvgNode,
18044    PathNode,
18045    LineNode
18046  }
18047};
18048
18049export { katex as default };