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  constructor(text, // the text of this token
60  loc) {
61    this.text = void 0;
62    this.loc = void 0;
63    this.text = text;
64    this.loc = loc;
65  }
66  /**
67   * Given a pair of tokens (this and endToken), compute a `Token` encompassing
68   * the whole input range enclosed by these two.
69   */
70
71
72  range(endToken, // last token of the range, inclusive
73  text) // the text of the newly constructed token
74  {
75    return new Token(text, SourceLocation.range(this, endToken));
76  }
77
78}
79
80/**
81 * This is the ParseError class, which is the main error thrown by KaTeX
82 * functions when something has gone wrong. This is used to distinguish internal
83 * errors from errors in the expression that the user provided.
84 *
85 * If possible, a caller should provide a Token or ParseNode with information
86 * about where in the source string the problem occurred.
87 */
88class ParseError {
89  // Error position based on passed-in Token or ParseNode.
90  constructor(message, // The error message
91  token) // An object providing position information
92  {
93    this.position = void 0;
94    let error = "KaTeX parse error: " + message;
95    let start;
96    const loc = token && token.loc;
97
98    if (loc && loc.start <= loc.end) {
99      // If we have the input and a position, make the error a bit fancier
100      // Get the input
101      const input = loc.lexer.input; // Prepend some information
102
103      start = loc.start;
104      const end = loc.end;
105
106      if (start === input.length) {
107        error += " at end of input: ";
108      } else {
109        error += " at position " + (start + 1) + ": ";
110      } // Underline token in question using combining underscores
111
112
113      const underlined = input.slice(start, end).replace(/[^]/g, "$&\u0332"); // Extract some context from the input and add it to the error
114
115      let left;
116
117      if (start > 15) {
118        left = "…" + input.slice(start - 15, start);
119      } else {
120        left = input.slice(0, start);
121      }
122
123      let right;
124
125      if (end + 15 < input.length) {
126        right = input.slice(end, end + 15) + "…";
127      } else {
128        right = input.slice(end);
129      }
130
131      error += left + underlined + right;
132    } // Some hackery to make ParseError a prototype of Error
133    // See http://stackoverflow.com/a/8460753
134
135
136    const self = new Error(error);
137    self.name = "ParseError"; // $FlowFixMe
138
139    self.__proto__ = ParseError.prototype; // $FlowFixMe
140
141    self.position = start;
142    return self;
143  }
144
145} // $FlowFixMe More hackery
146
147
148ParseError.prototype.__proto__ = Error.prototype;
149
150/**
151 * This file contains a list of utility functions which are useful in other
152 * files.
153 */
154
155/**
156 * Return whether an element is contained in a list
157 */
158const contains = function contains(list, elem) {
159  return list.indexOf(elem) !== -1;
160};
161/**
162 * Provide a default value if a setting is undefined
163 * NOTE: Couldn't use `T` as the output type due to facebook/flow#5022.
164 */
165
166
167const deflt = function deflt(setting, defaultIfUndefined) {
168  return setting === undefined ? defaultIfUndefined : setting;
169}; // hyphenate and escape adapted from Facebook's React under Apache 2 license
170
171
172const uppercase = /([A-Z])/g;
173
174const hyphenate = function hyphenate(str) {
175  return str.replace(uppercase, "-$1").toLowerCase();
176};
177
178const ESCAPE_LOOKUP = {
179  "&": "&amp;",
180  ">": "&gt;",
181  "<": "&lt;",
182  "\"": "&quot;",
183  "'": "&#x27;"
184};
185const ESCAPE_REGEX = /[&><"']/g;
186/**
187 * Escapes text to prevent scripting attacks.
188 */
189
190function escape(text) {
191  return String(text).replace(ESCAPE_REGEX, match => ESCAPE_LOOKUP[match]);
192}
193/**
194 * Sometimes we want to pull out the innermost element of a group. In most
195 * cases, this will just be the group itself, but when ordgroups and colors have
196 * a single element, we want to pull that out.
197 */
198
199
200const getBaseElem = function getBaseElem(group) {
201  if (group.type === "ordgroup") {
202    if (group.body.length === 1) {
203      return getBaseElem(group.body[0]);
204    } else {
205      return group;
206    }
207  } else if (group.type === "color") {
208    if (group.body.length === 1) {
209      return getBaseElem(group.body[0]);
210    } else {
211      return group;
212    }
213  } else if (group.type === "font") {
214    return getBaseElem(group.body);
215  } else {
216    return group;
217  }
218};
219/**
220 * TeXbook algorithms often reference "character boxes", which are simply groups
221 * with a single character in them. To decide if something is a character box,
222 * we find its innermost group, and see if it is a single character.
223 */
224
225
226const isCharacterBox = function isCharacterBox(group) {
227  const baseElem = getBaseElem(group); // These are all they types of groups which hold single characters
228
229  return baseElem.type === "mathord" || baseElem.type === "textord" || baseElem.type === "atom";
230};
231
232const assert = function assert(value) {
233  if (!value) {
234    throw new Error('Expected non-null, but got ' + String(value));
235  }
236
237  return value;
238};
239/**
240 * Return the protocol of a URL, or "_relative" if the URL does not specify a
241 * protocol (and thus is relative).
242 */
243
244const protocolFromUrl = function protocolFromUrl(url) {
245  const protocol = /^\s*([^\\/#]*?)(?::|&#0*58|&#x0*3a)/i.exec(url);
246  return protocol != null ? protocol[1] : "_relative";
247};
248var utils = {
249  contains,
250  deflt,
251  escape,
252  hyphenate,
253  getBaseElem,
254  isCharacterBox,
255  protocolFromUrl
256};
257
258/* eslint no-console:0 */
259
260/**
261 * The main Settings object
262 *
263 * The current options stored are:
264 *  - displayMode: Whether the expression should be typeset as inline math
265 *                 (false, the default), meaning that the math starts in
266 *                 \textstyle and is placed in an inline-block); or as display
267 *                 math (true), meaning that the math starts in \displaystyle
268 *                 and is placed in a block with vertical margin.
269 */
270class Settings {
271  constructor(options) {
272    this.displayMode = void 0;
273    this.output = void 0;
274    this.leqno = void 0;
275    this.fleqn = void 0;
276    this.throwOnError = void 0;
277    this.errorColor = void 0;
278    this.macros = void 0;
279    this.minRuleThickness = void 0;
280    this.colorIsTextColor = void 0;
281    this.strict = void 0;
282    this.trust = void 0;
283    this.maxSize = void 0;
284    this.maxExpand = void 0;
285    // allow null options
286    options = options || {};
287    this.displayMode = utils.deflt(options.displayMode, false);
288    this.output = utils.deflt(options.output, "htmlAndMathml");
289    this.leqno = utils.deflt(options.leqno, false);
290    this.fleqn = utils.deflt(options.fleqn, false);
291    this.throwOnError = utils.deflt(options.throwOnError, true);
292    this.errorColor = utils.deflt(options.errorColor, "#cc0000");
293    this.macros = options.macros || {};
294    this.minRuleThickness = Math.max(0, utils.deflt(options.minRuleThickness, 0));
295    this.colorIsTextColor = utils.deflt(options.colorIsTextColor, false);
296    this.strict = utils.deflt(options.strict, "warn");
297    this.trust = utils.deflt(options.trust, false);
298    this.maxSize = Math.max(0, utils.deflt(options.maxSize, Infinity));
299    this.maxExpand = Math.max(0, utils.deflt(options.maxExpand, 1000));
300  }
301  /**
302   * Report nonstrict (non-LaTeX-compatible) input.
303   * Can safely not be called if `this.strict` is false in JavaScript.
304   */
305
306
307  reportNonstrict(errorCode, errorMsg, token) {
308    let strict = this.strict;
309
310    if (typeof strict === "function") {
311      // Allow return value of strict function to be boolean or string
312      // (or null/undefined, meaning no further processing).
313      strict = strict(errorCode, errorMsg, token);
314    }
315
316    if (!strict || strict === "ignore") {
317      return;
318    } else if (strict === true || strict === "error") {
319      throw new ParseError("LaTeX-incompatible input and strict mode is set to 'error': " + `${errorMsg} [${errorCode}]`, token);
320    } else if (strict === "warn") {
321      typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to 'warn': " + `${errorMsg} [${errorCode}]`);
322    } else {
323      // won't happen in type-safe code
324      typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to " + `unrecognized '${strict}': ${errorMsg} [${errorCode}]`);
325    }
326  }
327  /**
328   * Check whether to apply strict (LaTeX-adhering) behavior for unusual
329   * input (like `\\`).  Unlike `nonstrict`, will not throw an error;
330   * instead, "error" translates to a return value of `true`, while "ignore"
331   * translates to a return value of `false`.  May still print a warning:
332   * "warn" prints a warning and returns `false`.
333   * This is for the second category of `errorCode`s listed in the README.
334   */
335
336
337  useStrictBehavior(errorCode, errorMsg, token) {
338    let strict = this.strict;
339
340    if (typeof strict === "function") {
341      // Allow return value of strict function to be boolean or string
342      // (or null/undefined, meaning no further processing).
343      // But catch any exceptions thrown by function, treating them
344      // like "error".
345      try {
346        strict = strict(errorCode, errorMsg, token);
347      } catch (error) {
348        strict = "error";
349      }
350    }
351
352    if (!strict || strict === "ignore") {
353      return false;
354    } else if (strict === true || strict === "error") {
355      return true;
356    } else if (strict === "warn") {
357      typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to 'warn': " + `${errorMsg} [${errorCode}]`);
358      return false;
359    } else {
360      // won't happen in type-safe code
361      typeof console !== "undefined" && console.warn("LaTeX-incompatible input and strict mode is set to " + `unrecognized '${strict}': ${errorMsg} [${errorCode}]`);
362      return false;
363    }
364  }
365  /**
366   * Check whether to test potentially dangerous input, and return
367   * `true` (trusted) or `false` (untrusted).  The sole argument `context`
368   * should be an object with `command` field specifying the relevant LaTeX
369   * command (as a string starting with `\`), and any other arguments, etc.
370   * If `context` has a `url` field, a `protocol` field will automatically
371   * get added by this function (changing the specified object).
372   */
373
374
375  isTrusted(context) {
376    if (context.url && !context.protocol) {
377      context.protocol = utils.protocolFromUrl(context.url);
378    }
379
380    const trust = typeof this.trust === "function" ? this.trust(context) : this.trust;
381    return Boolean(trust);
382  }
383
384}
385
386/**
387 * This file contains information and classes for the various kinds of styles
388 * used in TeX. It provides a generic `Style` class, which holds information
389 * about a specific style. It then provides instances of all the different kinds
390 * of styles possible, and provides functions to move between them and get
391 * information about them.
392 */
393
394/**
395 * The main style class. Contains a unique id for the style, a size (which is
396 * the same for cramped and uncramped version of a style), and a cramped flag.
397 */
398class Style {
399  constructor(id, size, cramped) {
400    this.id = void 0;
401    this.size = void 0;
402    this.cramped = void 0;
403    this.id = id;
404    this.size = size;
405    this.cramped = cramped;
406  }
407  /**
408   * Get the style of a superscript given a base in the current style.
409   */
410
411
412  sup() {
413    return styles[sup[this.id]];
414  }
415  /**
416   * Get the style of a subscript given a base in the current style.
417   */
418
419
420  sub() {
421    return styles[sub[this.id]];
422  }
423  /**
424   * Get the style of a fraction numerator given the fraction in the current
425   * style.
426   */
427
428
429  fracNum() {
430    return styles[fracNum[this.id]];
431  }
432  /**
433   * Get the style of a fraction denominator given the fraction in the current
434   * style.
435   */
436
437
438  fracDen() {
439    return styles[fracDen[this.id]];
440  }
441  /**
442   * Get the cramped version of a style (in particular, cramping a cramped style
443   * doesn't change the style).
444   */
445
446
447  cramp() {
448    return styles[cramp[this.id]];
449  }
450  /**
451   * Get a text or display version of this style.
452   */
453
454
455  text() {
456    return styles[text[this.id]];
457  }
458  /**
459   * Return true if this style is tightly spaced (scriptstyle/scriptscriptstyle)
460   */
461
462
463  isTight() {
464    return this.size >= 2;
465  }
466
467} // Export an interface for type checking, but don't expose the implementation.
468// This way, no more styles can be generated.
469
470
471// IDs of the different styles
472const D = 0;
473const Dc = 1;
474const T = 2;
475const Tc = 3;
476const S = 4;
477const Sc = 5;
478const SS = 6;
479const SSc = 7; // Instances of the different styles
480
481const 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
482
483const sup = [S, Sc, S, Sc, SS, SSc, SS, SSc];
484const sub = [Sc, Sc, Sc, Sc, SSc, SSc, SSc, SSc];
485const fracNum = [T, Tc, S, Sc, SS, SSc, SS, SSc];
486const fracDen = [Tc, Tc, Sc, Sc, SSc, SSc, SSc, SSc];
487const cramp = [Dc, Dc, Tc, Tc, Sc, Sc, SSc, SSc];
488const text = [D, Dc, T, Tc, T, Tc, T, Tc]; // We only export some of the styles.
489
490var Style$1 = {
491  DISPLAY: styles[D],
492  TEXT: styles[T],
493  SCRIPT: styles[S],
494  SCRIPTSCRIPT: styles[SS]
495};
496
497/*
498 * This file defines the Unicode scripts and script families that we
499 * support. To add new scripts or families, just add a new entry to the
500 * scriptData array below. Adding scripts to the scriptData array allows
501 * characters from that script to appear in \text{} environments.
502 */
503
504/**
505 * Each script or script family has a name and an array of blocks.
506 * Each block is an array of two numbers which specify the start and
507 * end points (inclusive) of a block of Unicode codepoints.
508 */
509
510/**
511 * Unicode block data for the families of scripts we support in \text{}.
512 * Scripts only need to appear here if they do not have font metrics.
513 */
514const scriptData = [{
515  // Latin characters beyond the Latin-1 characters we have metrics for.
516  // Needed for Czech, Hungarian and Turkish text, for example.
517  name: 'latin',
518  blocks: [[0x0100, 0x024f], // Latin Extended-A and Latin Extended-B
519  [0x0300, 0x036f]]
520}, {
521  // The Cyrillic script used by Russian and related languages.
522  // A Cyrillic subset used to be supported as explicitly defined
523  // symbols in symbols.js
524  name: 'cyrillic',
525  blocks: [[0x0400, 0x04ff]]
526}, {
527  // The Brahmic scripts of South and Southeast Asia
528  // Devanagari (0900–097F)
529  // Bengali (0980–09FF)
530  // Gurmukhi (0A00–0A7F)
531  // Gujarati (0A80–0AFF)
532  // Oriya (0B00–0B7F)
533  // Tamil (0B80–0BFF)
534  // Telugu (0C00–0C7F)
535  // Kannada (0C80–0CFF)
536  // Malayalam (0D00–0D7F)
537  // Sinhala (0D80–0DFF)
538  // Thai (0E00–0E7F)
539  // Lao (0E80–0EFF)
540  // Tibetan (0F00–0FFF)
541  // Myanmar (1000–109F)
542  name: 'brahmic',
543  blocks: [[0x0900, 0x109F]]
544}, {
545  name: 'georgian',
546  blocks: [[0x10A0, 0x10ff]]
547}, {
548  // Chinese and Japanese.
549  // The "k" in cjk is for Korean, but we've separated Korean out
550  name: "cjk",
551  blocks: [[0x3000, 0x30FF], // CJK symbols and punctuation, Hiragana, Katakana
552  [0x4E00, 0x9FAF], // CJK ideograms
553  [0xFF00, 0xFF60]]
554}, {
555  // Korean
556  name: 'hangul',
557  blocks: [[0xAC00, 0xD7AF]]
558}];
559/**
560 * Given a codepoint, return the name of the script or script family
561 * it is from, or null if it is not part of a known block
562 */
563
564function scriptFromCodepoint(codepoint) {
565  for (let i = 0; i < scriptData.length; i++) {
566    const script = scriptData[i];
567
568    for (let i = 0; i < script.blocks.length; i++) {
569      const block = script.blocks[i];
570
571      if (codepoint >= block[0] && codepoint <= block[1]) {
572        return script.name;
573      }
574    }
575  }
576
577  return null;
578}
579/**
580 * A flattened version of all the supported blocks in a single array.
581 * This is an optimization to make supportedCodepoint() fast.
582 */
583
584const allBlocks = [];
585scriptData.forEach(s => s.blocks.forEach(b => allBlocks.push(...b)));
586/**
587 * Given a codepoint, return true if it falls within one of the
588 * scripts or script families defined above and false otherwise.
589 *
590 * Micro benchmarks shows that this is faster than
591 * /[\u3000-\u30FF\u4E00-\u9FAF\uFF00-\uFF60\uAC00-\uD7AF\u0900-\u109F]/.test()
592 * in Firefox, Chrome and Node.
593 */
594
595function supportedCodepoint(codepoint) {
596  for (let i = 0; i < allBlocks.length; i += 2) {
597    if (codepoint >= allBlocks[i] && codepoint <= allBlocks[i + 1]) {
598      return true;
599    }
600  }
601
602  return false;
603}
604
605/**
606 * This file provides support to domTree.js and delimiter.js.
607 * It's a storehouse of path geometry for SVG images.
608 */
609// In all paths below, the viewBox-to-em scale is 1000:1.
610const hLinePad = 80; // padding above a sqrt viniculum. Prevents image cropping.
611// The viniculum of a \sqrt can be made thicker by a KaTeX rendering option.
612// Think of variable extraViniculum as two detours in the SVG path.
613// The detour begins at the lower left of the area labeled extraViniculum below.
614// The detour proceeds one extraViniculum distance up and slightly to the right,
615// displacing the radiused corner between surd and viniculum. The radius is
616// traversed as usual, then the detour resumes. It goes right, to the end of
617// the very long viniculumn, then down one extraViniculum distance,
618// after which it resumes regular path geometry for the radical.
619
620/*                                                  viniculum
621                                                   /
622         /▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒←extraViniculum
623        / █████████████████████←0.04em (40 unit) std viniculum thickness
624       / /
625      / /
626     / /\
627    / / surd
628*/
629
630const sqrtMain = function sqrtMain(extraViniculum, hLinePad) {
631  // sqrtMain path geometry is from glyph U221A in the font KaTeX Main
632  return `M95,${622 + extraViniculum + hLinePad}
633c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14
634c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54
635c44.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
636s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429
637c69,-144,104.5,-217.7,106.5,-221
638l${extraViniculum / 2.075} -${extraViniculum}
639c5.3,-9.3,12,-14,20,-14
640H400000v${40 + extraViniculum}H845.2724
641s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7
642c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47z
643M${834 + extraViniculum} ${hLinePad}h400000v${40 + extraViniculum}h-400000z`;
644};
645
646const sqrtSize1 = function sqrtSize1(extraViniculum, hLinePad) {
647  // size1 is from glyph U221A in the font KaTeX_Size1-Regular
648  return `M263,${601 + extraViniculum + hLinePad}c0.7,0,18,39.7,52,119
649c34,79.3,68.167,158.7,102.5,238c34.3,79.3,51.8,119.3,52.5,120
650c340,-704.7,510.7,-1060.3,512,-1067
651l${extraViniculum / 2.084} -${extraViniculum}
652c4.7,-7.3,11,-11,19,-11
653H40000v${40 + extraViniculum}H1012.3
654s-271.3,567,-271.3,567c-38.7,80.7,-84,175,-136,283c-52,108,-89.167,185.3,-111.5,232
655c-22.3,46.7,-33.8,70.3,-34.5,71c-4.7,4.7,-12.3,7,-23,7s-12,-1,-12,-1
656s-109,-253,-109,-253c-72.7,-168,-109.3,-252,-110,-252c-10.7,8,-22,16.7,-34,26
657c-22,17.3,-33.3,26,-34,26s-26,-26,-26,-26s76,-59,76,-59s76,-60,76,-60z
658M${1001 + extraViniculum} ${hLinePad}h400000v${40 + extraViniculum}h-400000z`;
659};
660
661const sqrtSize2 = function sqrtSize2(extraViniculum, hLinePad) {
662  // size2 is from glyph U221A in the font KaTeX_Size2-Regular
663  return `M983 ${10 + extraViniculum + hLinePad}
664l${extraViniculum / 3.13} -${extraViniculum}
665c4,-6.7,10,-10,18,-10 H400000v${40 + extraViniculum}
666H1013.1s-83.4,268,-264.1,840c-180.7,572,-277,876.3,-289,913c-4.7,4.7,-12.7,7,-24,7
667s-12,0,-12,0c-1.3,-3.3,-3.7,-11.7,-7,-25c-35.3,-125.3,-106.7,-373.3,-214,-744
668c-10,12,-21,25,-33,39s-32,39,-32,39c-6,-5.3,-15,-14,-27,-26s25,-30,25,-30
669c26.7,-32.7,52,-63,76,-91s52,-60,52,-60s208,722,208,722
670c56,-175.3,126.3,-397.3,211,-666c84.7,-268.7,153.8,-488.2,207.5,-658.5
671c53.7,-170.3,84.5,-266.8,92.5,-289.5z
672M${1001 + extraViniculum} ${hLinePad}h400000v${40 + extraViniculum}h-400000z`;
673};
674
675const sqrtSize3 = function sqrtSize3(extraViniculum, hLinePad) {
676  // size3 is from glyph U221A in the font KaTeX_Size3-Regular
677  return `M424,${2398 + extraViniculum + hLinePad}
678c-1.3,-0.7,-38.5,-172,-111.5,-514c-73,-342,-109.8,-513.3,-110.5,-514
679c0,-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
680s-5,7,-5,7c-4,-3.3,-8.3,-7.7,-13,-13s-13,-13,-13,-13s76,-122,76,-122s77,-121,77,-121
681s209,968,209,968c0,-2,84.7,-361.7,254,-1079c169.3,-717.3,254.7,-1077.7,256,-1081
682l${extraViniculum / 4.223} -${extraViniculum}c4,-6.7,10,-10,18,-10 H400000
683v${40 + extraViniculum}H1014.6
684s-87.3,378.7,-272.6,1166c-185.3,787.3,-279.3,1182.3,-282,1185
685c-2,6,-10,9,-24,9
686c-8,0,-12,-0.7,-12,-2z M${1001 + extraViniculum} ${hLinePad}
687h400000v${40 + extraViniculum}h-400000z`;
688};
689
690const sqrtSize4 = function sqrtSize4(extraViniculum, hLinePad) {
691  // size4 is from glyph U221A in the font KaTeX_Size4-Regular
692  return `M473,${2713 + extraViniculum + hLinePad}
693c339.3,-1799.3,509.3,-2700,510,-2702 l${extraViniculum / 5.298} -${extraViniculum}
694c3.3,-7.3,9.3,-11,18,-11 H400000v${40 + extraViniculum}H1017.7
695s-90.5,478,-276.2,1466c-185.7,988,-279.5,1483,-281.5,1485c-2,6,-10,9,-24,9
696c-8,0,-12,-0.7,-12,-2c0,-1.3,-5.3,-32,-16,-92c-50.7,-293.3,-119.7,-693.3,-207,-1200
697c0,-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
698s76,-153,76,-153s77,-151,77,-151c0.7,0.7,35.7,202,105,604c67.3,400.7,102,602.7,104,
699606zM${1001 + extraViniculum} ${hLinePad}h400000v${40 + extraViniculum}H1017.7z`;
700};
701
702const sqrtTall = function sqrtTall(extraViniculum, hLinePad, viewBoxHeight) {
703  // sqrtTall is from glyph U23B7 in the font KaTeX_Size4-Regular
704  // One path edge has a variable length. It runs vertically from the viniculumn
705  // to a point near (14 units) the bottom of the surd. The viniculum
706  // is normally 40 units thick. So the length of the line in question is:
707  const vertSegment = viewBoxHeight - 54 - hLinePad - extraViniculum;
708  return `M702 ${extraViniculum + hLinePad}H400000${40 + extraViniculum}
709H742v${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
710h-12l-28-84c-16.667-52-96.667 -294.333-240-727l-212 -643 -85 170
711c-4-3.333-8.333-7.667-13 -13l-13-13l77-155 77-156c66 199.333 139 419.667
712219 661 l218 661zM702 ${hLinePad}H400000v${40 + extraViniculum}H742z`;
713};
714
715const sqrtPath = function sqrtPath(size, extraViniculum, viewBoxHeight) {
716  extraViniculum = 1000 * extraViniculum; // Convert from document ems to viewBox.
717
718  let path = "";
719
720  switch (size) {
721    case "sqrtMain":
722      path = sqrtMain(extraViniculum, hLinePad);
723      break;
724
725    case "sqrtSize1":
726      path = sqrtSize1(extraViniculum, hLinePad);
727      break;
728
729    case "sqrtSize2":
730      path = sqrtSize2(extraViniculum, hLinePad);
731      break;
732
733    case "sqrtSize3":
734      path = sqrtSize3(extraViniculum, hLinePad);
735      break;
736
737    case "sqrtSize4":
738      path = sqrtSize4(extraViniculum, hLinePad);
739      break;
740
741    case "sqrtTall":
742      path = sqrtTall(extraViniculum, hLinePad, viewBoxHeight);
743  }
744
745  return path;
746};
747const path = {
748  // The doubleleftarrow geometry is from glyph U+21D0 in the font KaTeX Main
749  doubleleftarrow: `M262 157
750l10-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
751 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
752 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
753c2 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
754 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
755-86-123l-10-10h399738v-40H218c328 0 0 0 0 0l-10-8c-26.7-20-65.7-43-117-69 2.7
756-2 6-3.7 10-5 36.7-16 72.3-37.3 107-64l10-8h399782v-40z
757m8 0v40h399730v-40zm0 194v40h399730v-40z`,
758  // doublerightarrow is from glyph U+21D2 in font KaTeX Main
759  doublerightarrow: `M399738 392l
760-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
761 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
762-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
763-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
764-13h-6c-12 .7-18 4-18 10 0 2 1.7 7 5 15 23.3 46 52 87 86 123l10 10H0v40h399782
765c-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
766-107 64l-10 8H0v40zM0 157v40h399730v-40zm0 194v40h399730v-40z`,
767  // leftarrow is from glyph U+2190 in font KaTeX Main
768  leftarrow: `M400000 241H110l3-3c68.7-52.7 113.7-120
769 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
770-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
771c-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
772 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
773 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
774 l-3-3h399890zM100 241v40h399900v-40z`,
775  // overbrace is from glyphs U+23A9/23A8/23A7 in font KaTeX_Size4-Regular
776  leftbrace: `M6 548l-6-6v-35l6-11c56-104 135.3-181.3 238-232 57.3-28.7 117
777-45 179-50h399577v120H403c-43.3 7-81 15-113 26-100.7 33-179.7 91-237 174-2.7
778 5-6 9-10 13-.7 1-7.3 1-20 1H6z`,
779  leftbraceunder: `M0 6l6-6h17c12.688 0 19.313.3 20 1 4 4 7.313 8.3 10 13
780 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
781 0 2 .3 4 1 18.688 2.7 76 4.3 172 5h399450v120H429l-6-1c-124.688-8-235-61.7
782-331-161C60.687 138.7 32.312 99.3 7 54L0 41V6z`,
783  // overgroup is from the MnSymbol package (public domain)
784  leftgroup: `M400000 80
785H435C64 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
786 435 0h399565z`,
787  leftgroupunder: `M400000 262
788H435C64 262 168.3 112.6 21 82c-5.9-1.2-18 0-18 0-2 0-3 1-3 3v38c76 158 257 219
789 435 219h399565z`,
790  // Harpoons are from glyph U+21BD in font KaTeX Main
791  leftharpoon: `M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3
792-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
793-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
794-196 228-6.7 4.7-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40z`,
795  leftharpoonplus: `M0 267c.7 5.3 3 10 7 14h399993v-40H93c3.3-3.3 10.2-9.5
796 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
797-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
798-10.7 8-12 10-1.3 2-2 5.7-2 11zm100-26v40h399900v-40zM0 435v40h400000v-40z
799m0 0v40h400000v-40z`,
800  leftharpoondown: `M7 241c-4 4-6.333 8.667-7 14 0 5.333.667 9 2 11s5.333
801 5.333 12 10c90.667 54 156 130 196 228 3.333 10.667 6.333 16.333 9 17 2 .667 5
802 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
803-152-211l-3-3h399907v-40zM93 281 H400000 v-40L7 241z`,
804  leftharpoondownplus: `M7 435c-4 4-6.3 8.7-7 14 0 5.3.7 9 2 11s5.3 5.3 12
805 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
806-2 18-6 2-2.7 1-9.7-3-21-32-87.3-82.7-157.7-152-211l-3-3h399907v-40H7zm93 0
807v40h399900v-40zM0 241v40h399900v-40zm0 0v40h399900v-40z`,
808  // hook is from glyph U+21A9 in font KaTeX Main
809  lefthook: `M400000 281 H103s-33-11.2-61-33.5S0 197.3 0 164s14.2-61.2 42.5
810-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
811-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
812 71.5 23h399859zM103 281v-40h399897v40z`,
813  leftlinesegment: `M40 281 V428 H0 V94 H40 V241 H400000 v40z
814M40 281 V428 H0 V94 H40 V241 H400000 v40z`,
815  leftmapsto: `M40 281 V448H0V74H40V241H400000v40z
816M40 281 V448H0V74H40V241H400000v40z`,
817  // tofrom is from glyph U+21C4 in font KaTeX AMS Regular
818  leftToFrom: `M0 147h400000v40H0zm0 214c68 40 115.7 95.7 143 167h22c15.3 0 23
819-.3 23-1 0-1.3-5.3-13.7-16-37-18-35.3-41.3-69-70-101l-7-8h399905v-40H95l7-8
820c28.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
821 68 321 0 361zm0-174v-40h399900v40zm100 154v40h399900v-40z`,
822  longequal: `M0 50 h400000 v40H0z m0 194h40000v40H0z
823M0 50 h400000 v40H0z m0 194h40000v40H0z`,
824  midbrace: `M200428 334
825c-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
826-53.3 86.7-123.7 153-211 199-66.7 36-137.3 56.3-212 62H0V214h199568c178.3-11.7
827 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
828 12 44.7 59.3 101.3 106.3 170 141s145.3 54.3 229 60h199572v120z`,
829  midbraceunder: `M199572 214
830c100.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
831 53.3-86.7 123.7-153 211-199 66.7-36 137.3-56.3 212-62h199568v120H200432c-178.3
832 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
833-5-4-11-12-44.7-59.3-101.3-106.3-170-141s-145.3-54.3-229-60H0V214z`,
834  oiintSize1: `M512.6 71.6c272.6 0 320.3 106.8 320.3 178.2 0 70.8-47.7 177.6
835-320.3 177.6S193.1 320.6 193.1 249.8c0-71.4 46.9-178.2 319.5-178.2z
836m368.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
83760.9 214.8 367.3 214.8 307.2 0 368.1-129 368.1-214.8z`,
838  oiintSize2: `M757.8 100.1c384.7 0 451.1 137.6 451.1 230 0 91.3-66.4 228.8
839-451.1 228.8-386.3 0-452.7-137.5-452.7-228.8 0-92.4 66.4-230 452.7-230z
840m502.4 230c0-111.2-82.4-277.2-502.4-277.2s-504 166-504 277.2
841c0 110 84 276 504 276s502.4-166 502.4-276z`,
842  oiiintSize1: `M681.4 71.6c408.9 0 480.5 106.8 480.5 178.2 0 70.8-71.6 177.6
843-480.5 177.6S202.1 320.6 202.1 249.8c0-71.4 70.5-178.2 479.3-178.2z
844m525.8 178.2c0-86.4-86.8-215.4-525.7-215.4-437.9 0-524.7 129-524.7 215.4 0
84585.8 86.8 214.8 524.7 214.8 438.9 0 525.7-129 525.7-214.8z`,
846  oiiintSize2: `M1021.2 53c603.6 0 707.8 165.8 707.8 277.2 0 110-104.2 275.8
847-707.8 275.8-606 0-710.2-165.8-710.2-275.8C311 218.8 415.2 53 1021.2 53z
848m770.4 277.1c0-131.2-126.4-327.6-770.5-327.6S248.4 198.9 248.4 330.1
849c0 130 128.8 326.4 772.7 326.4s770.5-196.4 770.5-326.4z`,
850  rightarrow: `M0 241v40h399891c-47.3 35.3-84 78-110 128
851-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
852 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
853 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
854-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
855-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
856 151.7 139 205zm0 0v40h399900v-40z`,
857  rightbrace: `M400000 542l
858-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
859s-117.2-55.8-184.5-66.5c-.7 0-2-.3-4-1-18.7-2.7-76-4.3-172-5H0V214h399571l6 1
860c124.7 8 235 61.7 331 161 31.3 33.3 59.7 72.7 85 118l7 13v35z`,
861  rightbraceunder: `M399994 0l6 6v35l-6 11c-56 104-135.3 181.3-238 232-57.3
862 28.7-117 45-179 50H-300V214h399897c43.3-7 81-15 113-26 100.7-33 179.7-91 237
863-174 2.7-5 6-9 10-13 .7-1 7.3-1 20-1h17z`,
864  rightgroup: `M0 80h399565c371 0 266.7 149.4 414 180 5.9 1.2 18 0 18 0 2 0
865 3-1 3-3v-38c-76-158-257-219-435-219H0z`,
866  rightgroupunder: `M0 262h399565c371 0 266.7-149.4 414-180 5.9-1.2 18 0 18
867 0 2 0 3 1 3 3v38c-76 158-257 219-435 219H0z`,
868  rightharpoon: `M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3
869-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
870-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
871 69.2 92 94.5zm0 0v40h399900v-40z`,
872  rightharpoonplus: `M0 241v40h399993c4.7-4.7 7-9.3 7-14 0-9.3-3.7-15.3-11
873-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
874 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
875m0 0v40h399900v-40z m100 194v40h399900v-40zm0 0v40h399900v-40z`,
876  rightharpoondown: `M399747 511c0 7.3 6.7 11 20 11 8 0 13-.8 15-2.5s4.7-6.8
877 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
878-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
879-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 241v40h399900v-40z`,
880  rightharpoondownplus: `M399747 705c0 7.3 6.7 11 20 11 8 0 13-.8
881 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
882 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
883-64.7 57-92 95-27.3 38-48.7 77.7-64 119-3.3 8.7-5 14-5 16zM0 435v40h399900v-40z
884m0-194v40h400000v-40zm0 0v40h400000v-40z`,
885  righthook: `M399859 241c-764 0 0 0 0 0 40-3.3 68.7-15.7 86-37 10-12 15-25.3
886 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
887-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
888 66.8s-14 61.2-42 83.5c-28 22.3-61 33.5-99 33.5L0 241z M0 281v-40h399859v40z`,
889  rightlinesegment: `M399960 241 V94 h40 V428 h-40 V281 H0 v-40z
890M399960 241 V94 h40 V428 h-40 V281 H0 v-40z`,
891  rightToFrom: `M400000 167c-70.7-42-118-97.7-142-167h-23c-15.3 0-23 .3-23
892 1 0 1.3 5.3 13.7 16 37 18 35.3 41.3 69 70 101l7 8H0v40h399905l-7 8c-28.7 32
893-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
894-167z M100 147v40h399900v-40zM0 341v40h399900v-40z`,
895  // twoheadleftarrow is from glyph U+219E in font KaTeX AMS Regular
896  twoheadleftarrow: `M0 167c68 40
897 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
898-70-101l-7-8h125l9 7c50.7 39.3 85 86 103 140h46c0-4.7-6.3-18.7-19-42-18-35.3
899-40-67.3-66-96l-9-9h399716v-40H284l9-9c26-28.7 48-60.7 66-96 12.7-23.333 19
900-37.333 19-42h-46c-18 54-52.3 100.7-103 140l-9 7H95l7-8c28.7-32 52-65.7 70-101
901 10.7-23.333 16-35.7 16-37 0-.7-7.7-1-23-1h-22C115.7 71.3 68 127 0 167z`,
902  twoheadrightarrow: `M400000 167
903c-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
904 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
905 18 35.3 40 67.3 66 96l9 9H0v40h399716l-9 9c-26 28.7-48 60.7-66 96-12.7 23.333
906-19 37.333-19 42h46c18-54 52.3-100.7 103-140l9-7h125l-7 8c-28.7 32-52 65.7-70
907 101-10.7 23.333-16 35.7-16 37 0 .7 7.7 1 23 1h22c27.3-71.3 75-127 143-167z`,
908  // tilde1 is a modified version of a glyph from the MnSymbol package
909  tilde1: `M200 55.538c-77 0-168 73.953-177 73.953-3 0-7
910-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
911 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
912 4.35-2 7.613-5 9.788l-19 13.05c-92 63.077-116.937 75.308-183 76.128
913-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
916-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
917 31.9 283 0 358 0c148 0 188 122 331 122s314-97 326-97c4 0 8 2 10 7l7 21.114
918c1 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
919 181.476 676 181.476c-149 0-189-126.21-332-126.21z`,
920  tilde3: `M786 59C457 59 32 175.242 13 175.242c-6 0-10-3.457
921-11-10.37L.15 138c-1-7 3-12 10-13l19.2-6.4C378.4 40.7 634.3 0 804.3 0c337 0
922 411.8 157 746.8 157 328 0 754-112 773-112 5 0 10 3 11 9l1 14.075c1 8.066-.697
923 16.595-6.697 17.492l-21.052 7.31c-367.9 98.146-609.15 122.696-778.15 122.696
924 -338 0-409-156.573-744-156.573z`,
925  tilde4: `M786 58C457 58 32 177.487 13 177.487c-6 0-10-3.345
926-11-10.035L.15 143c-1-7 3-12 10-13l22-6.7C381.2 35 637.15 0 807.15 0c337 0 409
927 177 744 177 328 0 754-127 773-127 5 0 10 3 11 9l1 14.794c1 7.805-3 13.38-9
928 14.495l-20.7 5.574c-366.85 99.79-607.3 139.372-776.3 139.372-338 0-409
929 -175.236-744-175.236z`,
930  // vec is from glyph U+20D7 in font KaTeX Main
931  vec: `M377 20c0-5.333 1.833-10 5.5-14S391 0 397 0c4.667 0 8.667 1.667 12 5
9323.333 2.667 6.667 9 10 19 6.667 24.667 20.333 43.667 41 57 7.333 4.667 11
93310.667 11 18 0 6-1 10-3 12s-6.667 5-14 9c-28.667 14.667-53.667 35.667-75 63
934-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
935-7 1c-4.667 0-9.167-1.833-13.5-5.5S337 184 337 178c0-12.667 15.667-32.333 47-59
936H213l-171-1c-8.667-6-13-12.333-13-19 0-4.667 4.333-11.333 13-20h359
937c-16-25.333-24-45-24-59z`,
938  // widehat1 is a modified version of a glyph from the MnSymbol package
939  widehat1: `M529 0h5l519 115c5 1 9 5 9 10 0 1-1 2-1 3l-4 22
940c-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`,
941  // ditto widehat2, widehat3, & widehat4
942  widehat2: `M1181 0h2l1171 176c6 0 10 5 10 11l-2 23c-1 6-5 10
943-11 10h-1L1182 67 15 220h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z`,
944  widehat3: `M1181 0h2l1171 236c6 0 10 5 10 11l-2 23c-1 6-5 10
945-11 10h-1L1182 67 15 280h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z`,
946  widehat4: `M1181 0h2l1171 296c6 0 10 5 10 11l-2 23c-1 6-5 10
947-11 10h-1L1182 67 15 340h-1c-6 0-10-4-11-10l-2-23c-1-6 4-11 10-11z`,
948  // widecheck paths are all inverted versions of widehat
949  widecheck1: `M529,159h5l519,-115c5,-1,9,-5,9,-10c0,-1,-1,-2,-1,-3l-4,-22c-1,
950-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`,
951  widecheck2: `M1181,220h2l1171,-176c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,
952-11,-10h-1l-1168,153l-1167,-153h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z`,
953  widecheck3: `M1181,280h2l1171,-236c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,
954-11,-10h-1l-1168,213l-1167,-213h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z`,
955  widecheck4: `M1181,340h2l1171,-296c6,0,10,-5,10,-11l-2,-23c-1,-6,-5,-10,
956-11,-10h-1l-1168,273l-1167,-273h-1c-6,0,-10,4,-11,10l-2,23c-1,6,4,11,10,11z`,
957  // The next ten paths support reaction arrows from the mhchem package.
958  // Arrows for \ce{<-->} are offset from xAxis by 0.22ex, per mhchem in LaTeX
959  // baraboveleftarrow is mostly from from glyph U+2190 in font KaTeX Main
960  baraboveleftarrow: `M400000 620h-399890l3 -3c68.7 -52.7 113.7 -120 135 -202
961c4 -14.7 6 -23 6 -25c0 -7.3 -7 -11 -21 -11c-8 0 -13.2 0.8 -15.5 2.5
962c-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
963s-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
964121.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
965s2.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
966c0 -2 -2 -10.3 -6 -25c-20 -79.3 -65 -146.7 -135 -202l-3 -3h399890z
967M100 620v40h399900v-40z M0 241v40h399900v-40zM0 241v40h399900v-40z`,
968  // rightarrowabovebar is mostly from glyph U+2192, KaTeX Main
969  rightarrowabovebar: `M0 241v40h399891c-47.3 35.3-84 78-110 128-16.7 32
970-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
97113.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
972-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
973-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
974-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
975151.7 139 205zm96 379h399894v40H0zm0 0h399904v40H0z`,
976  // The short left harpoon has 0.5em (i.e. 500 units) kern on the left end.
977  // Ref from mhchem.sty: \rlap{\raisebox{-.22ex}{$\kern0.5em
978  baraboveshortleftharpoon: `M507,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11
979c1.3,2,5.3,5.3,12,10c90.7,54,156,130,196,228c3.3,10.7,6.3,16.3,9,17
980c2,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
981c-32,-87.3,-82.7,-157.7,-152,-211c0,0,-3,-3,-3,-3l399351,0l0,-40
982c-398570,0,-399437,0,-399437,0z M593 435 v40 H399500 v-40z
983M0 281 v-40 H399908 v40z M0 281 v-40 H399908 v40z`,
984  rightharpoonaboveshortbar: `M0,241 l0,40c399126,0,399993,0,399993,0
985c4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,
986-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
987c-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
988M0 241 v40 H399908 v-40z M0 475 v-40 H399500 v40z M0 475 v-40 H399500 v40z`,
989  shortbaraboveleftharpoon: `M7,435c-4,4,-6.3,8.7,-7,14c0,5.3,0.7,9,2,11
990c1.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,
9911c0,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,
992-152,-211c0,0,-3,-3,-3,-3l399907,0l0,-40c-399126,0,-399993,0,-399993,0z
993M93 435 v40 H400000 v-40z M500 241 v40 H400000 v-40z M500 241 v40 H400000 v-40z`,
994  shortrightharpoonabovebar: `M53,241l0,40c398570,0,399437,0,399437,0
995c4.7,-4.7,7,-9.3,7,-14c0,-9.3,-3.7,-15.3,-11,-18c-92.7,-56.7,-159,-133.7,-199,
996-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
997c-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
998M500 241 v40 H399408 v-40z M500 435 v40 H400000 v-40z`
999};
1000
1001/**
1002 * This node represents a document fragment, which contains elements, but when
1003 * placed into the DOM doesn't have any representation itself. It only contains
1004 * children and doesn't have any DOM node properties.
1005 */
1006class DocumentFragment {
1007  // HtmlDomNode
1008  // Never used; needed for satisfying interface.
1009  constructor(children) {
1010    this.children = void 0;
1011    this.classes = void 0;
1012    this.height = void 0;
1013    this.depth = void 0;
1014    this.maxFontSize = void 0;
1015    this.style = void 0;
1016    this.children = children;
1017    this.classes = [];
1018    this.height = 0;
1019    this.depth = 0;
1020    this.maxFontSize = 0;
1021    this.style = {};
1022  }
1023
1024  hasClass(className) {
1025    return utils.contains(this.classes, className);
1026  }
1027  /** Convert the fragment into a node. */
1028
1029
1030  toNode() {
1031    const frag = document.createDocumentFragment();
1032
1033    for (let i = 0; i < this.children.length; i++) {
1034      frag.appendChild(this.children[i].toNode());
1035    }
1036
1037    return frag;
1038  }
1039  /** Convert the fragment into HTML markup. */
1040
1041
1042  toMarkup() {
1043    let markup = ""; // Simply concatenate the markup for the children together.
1044
1045    for (let i = 0; i < this.children.length; i++) {
1046      markup += this.children[i].toMarkup();
1047    }
1048
1049    return markup;
1050  }
1051  /**
1052   * Converts the math node into a string, similar to innerText. Applies to
1053   * MathDomNode's only.
1054   */
1055
1056
1057  toText() {
1058    // To avoid this, we would subclass documentFragment separately for
1059    // MathML, but polyfills for subclassing is expensive per PR 1469.
1060    // $FlowFixMe: Only works for ChildType = MathDomNode.
1061    const toText = child => child.toText();
1062
1063    return this.children.map(toText).join("");
1064  }
1065
1066}
1067
1068/**
1069 * These objects store the data about the DOM nodes we create, as well as some
1070 * extra data. They can then be transformed into real DOM nodes with the
1071 * `toNode` function or HTML markup using `toMarkup`. They are useful for both
1072 * storing extra properties on the nodes, as well as providing a way to easily
1073 * work with the DOM.
1074 *
1075 * Similar functions for working with MathML nodes exist in mathMLTree.js.
1076 *
1077 * TODO: refactor `span` and `anchor` into common superclass when
1078 * target environments support class inheritance
1079 */
1080
1081/**
1082 * Create an HTML className based on a list of classes. In addition to joining
1083 * with spaces, we also remove empty classes.
1084 */
1085const createClass = function createClass(classes) {
1086  return classes.filter(cls => cls).join(" ");
1087};
1088
1089const initNode = function initNode(classes, options, style) {
1090  this.classes = classes || [];
1091  this.attributes = {};
1092  this.height = 0;
1093  this.depth = 0;
1094  this.maxFontSize = 0;
1095  this.style = style || {};
1096
1097  if (options) {
1098    if (options.style.isTight()) {
1099      this.classes.push("mtight");
1100    }
1101
1102    const color = options.getColor();
1103
1104    if (color) {
1105      this.style.color = color;
1106    }
1107  }
1108};
1109/**
1110 * Convert into an HTML node
1111 */
1112
1113
1114const toNode = function toNode(tagName) {
1115  const node = document.createElement(tagName); // Apply the class
1116
1117  node.className = createClass(this.classes); // Apply inline styles
1118
1119  for (const style in this.style) {
1120    if (this.style.hasOwnProperty(style)) {
1121      // $FlowFixMe Flow doesn't seem to understand span.style's type.
1122      node.style[style] = this.style[style];
1123    }
1124  } // Apply attributes
1125
1126
1127  for (const attr in this.attributes) {
1128    if (this.attributes.hasOwnProperty(attr)) {
1129      node.setAttribute(attr, this.attributes[attr]);
1130    }
1131  } // Append the children, also as HTML nodes
1132
1133
1134  for (let i = 0; i < this.children.length; i++) {
1135    node.appendChild(this.children[i].toNode());
1136  }
1137
1138  return node;
1139};
1140/**
1141 * Convert into an HTML markup string
1142 */
1143
1144
1145const toMarkup = function toMarkup(tagName) {
1146  let markup = `<${tagName}`; // Add the class
1147
1148  if (this.classes.length) {
1149    markup += ` class="${utils.escape(createClass(this.classes))}"`;
1150  }
1151
1152  let styles = ""; // Add the styles, after hyphenation
1153
1154  for (const style in this.style) {
1155    if (this.style.hasOwnProperty(style)) {
1156      styles += `${utils.hyphenate(style)}:${this.style[style]};`;
1157    }
1158  }
1159
1160  if (styles) {
1161    markup += ` style="${utils.escape(styles)}"`;
1162  } // Add the attributes
1163
1164
1165  for (const attr in this.attributes) {
1166    if (this.attributes.hasOwnProperty(attr)) {
1167      markup += ` ${attr}="${utils.escape(this.attributes[attr])}"`;
1168    }
1169  }
1170
1171  markup += ">"; // Add the markup of the children, also as markup
1172
1173  for (let i = 0; i < this.children.length; i++) {
1174    markup += this.children[i].toMarkup();
1175  }
1176
1177  markup += `</${tagName}>`;
1178  return markup;
1179}; // Making the type below exact with all optional fields doesn't work due to
1180// - https://github.com/facebook/flow/issues/4582
1181// - https://github.com/facebook/flow/issues/5688
1182// However, since *all* fields are optional, $Shape<> works as suggested in 5688
1183// above.
1184// This type does not include all CSS properties. Additional properties should
1185// be added as needed.
1186
1187
1188/**
1189 * This node represents a span node, with a className, a list of children, and
1190 * an inline style. It also contains information about its height, depth, and
1191 * maxFontSize.
1192 *
1193 * Represents two types with different uses: SvgSpan to wrap an SVG and DomSpan
1194 * otherwise. This typesafety is important when HTML builders access a span's
1195 * children.
1196 */
1197class Span {
1198  constructor(classes, children, options, style) {
1199    this.children = void 0;
1200    this.attributes = void 0;
1201    this.classes = void 0;
1202    this.height = void 0;
1203    this.depth = void 0;
1204    this.width = void 0;
1205    this.maxFontSize = void 0;
1206    this.style = void 0;
1207    initNode.call(this, classes, options, style);
1208    this.children = children || [];
1209  }
1210  /**
1211   * Sets an arbitrary attribute on the span. Warning: use this wisely. Not
1212   * all browsers support attributes the same, and having too many custom
1213   * attributes is probably bad.
1214   */
1215
1216
1217  setAttribute(attribute, value) {
1218    this.attributes[attribute] = value;
1219  }
1220
1221  hasClass(className) {
1222    return utils.contains(this.classes, className);
1223  }
1224
1225  toNode() {
1226    return toNode.call(this, "span");
1227  }
1228
1229  toMarkup() {
1230    return toMarkup.call(this, "span");
1231  }
1232
1233}
1234/**
1235 * This node represents an anchor (<a>) element with a hyperlink.  See `span`
1236 * for further details.
1237 */
1238
1239class Anchor {
1240  constructor(href, classes, children, options) {
1241    this.children = void 0;
1242    this.attributes = void 0;
1243    this.classes = void 0;
1244    this.height = void 0;
1245    this.depth = void 0;
1246    this.maxFontSize = void 0;
1247    this.style = void 0;
1248    initNode.call(this, classes, options);
1249    this.children = children || [];
1250    this.setAttribute('href', href);
1251  }
1252
1253  setAttribute(attribute, value) {
1254    this.attributes[attribute] = value;
1255  }
1256
1257  hasClass(className) {
1258    return utils.contains(this.classes, className);
1259  }
1260
1261  toNode() {
1262    return toNode.call(this, "a");
1263  }
1264
1265  toMarkup() {
1266    return toMarkup.call(this, "a");
1267  }
1268
1269}
1270/**
1271 * This node represents an image embed (<img>) element.
1272 */
1273
1274class Img {
1275  constructor(src, alt, style) {
1276    this.src = void 0;
1277    this.alt = void 0;
1278    this.classes = void 0;
1279    this.height = void 0;
1280    this.depth = void 0;
1281    this.maxFontSize = void 0;
1282    this.style = void 0;
1283    this.alt = alt;
1284    this.src = src;
1285    this.classes = ["mord"];
1286    this.style = style;
1287  }
1288
1289  hasClass(className) {
1290    return utils.contains(this.classes, className);
1291  }
1292
1293  toNode() {
1294    const node = document.createElement("img");
1295    node.src = this.src;
1296    node.alt = this.alt;
1297    node.className = "mord"; // Apply inline styles
1298
1299    for (const style in this.style) {
1300      if (this.style.hasOwnProperty(style)) {
1301        // $FlowFixMe
1302        node.style[style] = this.style[style];
1303      }
1304    }
1305
1306    return node;
1307  }
1308
1309  toMarkup() {
1310    let markup = `<img  src='${this.src} 'alt='${this.alt}' `; // Add the styles, after hyphenation
1311
1312    let styles = "";
1313
1314    for (const style in this.style) {
1315      if (this.style.hasOwnProperty(style)) {
1316        styles += `${utils.hyphenate(style)}:${this.style[style]};`;
1317      }
1318    }
1319
1320    if (styles) {
1321      markup += ` style="${utils.escape(styles)}"`;
1322    }
1323
1324    markup += "'/>";
1325    return markup;
1326  }
1327
1328}
1329const iCombinations = {
1330  'î': '\u0131\u0302',
1331  'ï': '\u0131\u0308',
1332  'í': '\u0131\u0301',
1333  // 'ī': '\u0131\u0304', // enable when we add Extended Latin
1334  'ì': '\u0131\u0300'
1335};
1336/**
1337 * A symbol node contains information about a single symbol. It either renders
1338 * to a single text node, or a span with a single text node in it, depending on
1339 * whether it has CSS classes, styles, or needs italic correction.
1340 */
1341
1342class SymbolNode {
1343  constructor(text, height, depth, italic, skew, width, classes, style) {
1344    this.text = void 0;
1345    this.height = void 0;
1346    this.depth = void 0;
1347    this.italic = void 0;
1348    this.skew = void 0;
1349    this.width = void 0;
1350    this.maxFontSize = void 0;
1351    this.classes = void 0;
1352    this.style = void 0;
1353    this.text = text;
1354    this.height = height || 0;
1355    this.depth = depth || 0;
1356    this.italic = italic || 0;
1357    this.skew = skew || 0;
1358    this.width = width || 0;
1359    this.classes = classes || [];
1360    this.style = style || {};
1361    this.maxFontSize = 0; // Mark text from non-Latin scripts with specific classes so that we
1362    // can specify which fonts to use.  This allows us to render these
1363    // characters with a serif font in situations where the browser would
1364    // either default to a sans serif or render a placeholder character.
1365    // We use CSS class names like cjk_fallback, hangul_fallback and
1366    // brahmic_fallback. See ./unicodeScripts.js for the set of possible
1367    // script names
1368
1369    const script = scriptFromCodepoint(this.text.charCodeAt(0));
1370
1371    if (script) {
1372      this.classes.push(script + "_fallback");
1373    }
1374
1375    if (/[îïíì]/.test(this.text)) {
1376      // add ī when we add Extended Latin
1377      this.text = iCombinations[this.text];
1378    }
1379  }
1380
1381  hasClass(className) {
1382    return utils.contains(this.classes, className);
1383  }
1384  /**
1385   * Creates a text node or span from a symbol node. Note that a span is only
1386   * created if it is needed.
1387   */
1388
1389
1390  toNode() {
1391    const node = document.createTextNode(this.text);
1392    let span = null;
1393
1394    if (this.italic > 0) {
1395      span = document.createElement("span");
1396      span.style.marginRight = this.italic + "em";
1397    }
1398
1399    if (this.classes.length > 0) {
1400      span = span || document.createElement("span");
1401      span.className = createClass(this.classes);
1402    }
1403
1404    for (const style in this.style) {
1405      if (this.style.hasOwnProperty(style)) {
1406        span = span || document.createElement("span"); // $FlowFixMe Flow doesn't seem to understand span.style's type.
1407
1408        span.style[style] = this.style[style];
1409      }
1410    }
1411
1412    if (span) {
1413      span.appendChild(node);
1414      return span;
1415    } else {
1416      return node;
1417    }
1418  }
1419  /**
1420   * Creates markup for a symbol node.
1421   */
1422
1423
1424  toMarkup() {
1425    // TODO(alpert): More duplication than I'd like from
1426    // span.prototype.toMarkup and symbolNode.prototype.toNode...
1427    let needsSpan = false;
1428    let markup = "<span";
1429
1430    if (this.classes.length) {
1431      needsSpan = true;
1432      markup += " class=\"";
1433      markup += utils.escape(createClass(this.classes));
1434      markup += "\"";
1435    }
1436
1437    let styles = "";
1438
1439    if (this.italic > 0) {
1440      styles += "margin-right:" + this.italic + "em;";
1441    }
1442
1443    for (const style in this.style) {
1444      if (this.style.hasOwnProperty(style)) {
1445        styles += utils.hyphenate(style) + ":" + this.style[style] + ";";
1446      }
1447    }
1448
1449    if (styles) {
1450      needsSpan = true;
1451      markup += " style=\"" + utils.escape(styles) + "\"";
1452    }
1453
1454    const escaped = utils.escape(this.text);
1455
1456    if (needsSpan) {
1457      markup += ">";
1458      markup += escaped;
1459      markup += "</span>";
1460      return markup;
1461    } else {
1462      return escaped;
1463    }
1464  }
1465
1466}
1467/**
1468 * SVG nodes are used to render stretchy wide elements.
1469 */
1470
1471class SvgNode {
1472  constructor(children, attributes) {
1473    this.children = void 0;
1474    this.attributes = void 0;
1475    this.children = children || [];
1476    this.attributes = attributes || {};
1477  }
1478
1479  toNode() {
1480    const svgNS = "http://www.w3.org/2000/svg";
1481    const node = document.createElementNS(svgNS, "svg"); // Apply attributes
1482
1483    for (const attr in this.attributes) {
1484      if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
1485        node.setAttribute(attr, this.attributes[attr]);
1486      }
1487    }
1488
1489    for (let i = 0; i < this.children.length; i++) {
1490      node.appendChild(this.children[i].toNode());
1491    }
1492
1493    return node;
1494  }
1495
1496  toMarkup() {
1497    let markup = "<svg"; // Apply attributes
1498
1499    for (const attr in this.attributes) {
1500      if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
1501        markup += ` ${attr}='${this.attributes[attr]}'`;
1502      }
1503    }
1504
1505    markup += ">";
1506
1507    for (let i = 0; i < this.children.length; i++) {
1508      markup += this.children[i].toMarkup();
1509    }
1510
1511    markup += "</svg>";
1512    return markup;
1513  }
1514
1515}
1516class PathNode {
1517  constructor(pathName, alternate) {
1518    this.pathName = void 0;
1519    this.alternate = void 0;
1520    this.pathName = pathName;
1521    this.alternate = alternate; // Used only for \sqrt
1522  }
1523
1524  toNode() {
1525    const svgNS = "http://www.w3.org/2000/svg";
1526    const node = document.createElementNS(svgNS, "path");
1527
1528    if (this.alternate) {
1529      node.setAttribute("d", this.alternate);
1530    } else {
1531      node.setAttribute("d", path[this.pathName]);
1532    }
1533
1534    return node;
1535  }
1536
1537  toMarkup() {
1538    if (this.alternate) {
1539      return `<path d='${this.alternate}'/>`;
1540    } else {
1541      return `<path d='${path[this.pathName]}'/>`;
1542    }
1543  }
1544
1545}
1546class LineNode {
1547  constructor(attributes) {
1548    this.attributes = void 0;
1549    this.attributes = attributes || {};
1550  }
1551
1552  toNode() {
1553    const svgNS = "http://www.w3.org/2000/svg";
1554    const node = document.createElementNS(svgNS, "line"); // Apply attributes
1555
1556    for (const attr in this.attributes) {
1557      if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
1558        node.setAttribute(attr, this.attributes[attr]);
1559      }
1560    }
1561
1562    return node;
1563  }
1564
1565  toMarkup() {
1566    let markup = "<line";
1567
1568    for (const attr in this.attributes) {
1569      if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
1570        markup += ` ${attr}='${this.attributes[attr]}'`;
1571      }
1572    }
1573
1574    markup += "/>";
1575    return markup;
1576  }
1577
1578}
1579function assertSymbolDomNode(group) {
1580  if (group instanceof SymbolNode) {
1581    return group;
1582  } else {
1583    throw new Error(`Expected symbolNode but got ${String(group)}.`);
1584  }
1585}
1586function assertSpan(group) {
1587  if (group instanceof Span) {
1588    return group;
1589  } else {
1590    throw new Error(`Expected span<HtmlDomNode> but got ${String(group)}.`);
1591  }
1592}
1593
1594// This file is GENERATED by buildMetrics.sh. DO NOT MODIFY.
1595var metricMap = {
1596  "AMS-Regular": {
1597    "65": [0, 0.68889, 0, 0, 0.72222],
1598    "66": [0, 0.68889, 0, 0, 0.66667],
1599    "67": [0, 0.68889, 0, 0, 0.72222],
1600    "68": [0, 0.68889, 0, 0, 0.72222],
1601    "69": [0, 0.68889, 0, 0, 0.66667],
1602    "70": [0, 0.68889, 0, 0, 0.61111],
1603    "71": [0, 0.68889, 0, 0, 0.77778],
1604    "72": [0, 0.68889, 0, 0, 0.77778],
1605    "73": [0, 0.68889, 0, 0, 0.38889],
1606    "74": [0.16667, 0.68889, 0, 0, 0.5],
1607    "75": [0, 0.68889, 0, 0, 0.77778],
1608    "76": [0, 0.68889, 0, 0, 0.66667],
1609    "77": [0, 0.68889, 0, 0, 0.94445],
1610    "78": [0, 0.68889, 0, 0, 0.72222],
1611    "79": [0.16667, 0.68889, 0, 0, 0.77778],
1612    "80": [0, 0.68889, 0, 0, 0.61111],
1613    "81": [0.16667, 0.68889, 0, 0, 0.77778],
1614    "82": [0, 0.68889, 0, 0, 0.72222],
1615    "83": [0, 0.68889, 0, 0, 0.55556],
1616    "84": [0, 0.68889, 0, 0, 0.66667],
1617    "85": [0, 0.68889, 0, 0, 0.72222],
1618    "86": [0, 0.68889, 0, 0, 0.72222],
1619    "87": [0, 0.68889, 0, 0, 1.0],
1620    "88": [0, 0.68889, 0, 0, 0.72222],
1621    "89": [0, 0.68889, 0, 0, 0.72222],
1622    "90": [0, 0.68889, 0, 0, 0.66667],
1623    "107": [0, 0.68889, 0, 0, 0.55556],
1624    "165": [0, 0.675, 0.025, 0, 0.75],
1625    "174": [0.15559, 0.69224, 0, 0, 0.94666],
1626    "240": [0, 0.68889, 0, 0, 0.55556],
1627    "295": [0, 0.68889, 0, 0, 0.54028],
1628    "710": [0, 0.825, 0, 0, 2.33334],
1629    "732": [0, 0.9, 0, 0, 2.33334],
1630    "770": [0, 0.825, 0, 0, 2.33334],
1631    "771": [0, 0.9, 0, 0, 2.33334],
1632    "989": [0.08167, 0.58167, 0, 0, 0.77778],
1633    "1008": [0, 0.43056, 0.04028, 0, 0.66667],
1634    "8245": [0, 0.54986, 0, 0, 0.275],
1635    "8463": [0, 0.68889, 0, 0, 0.54028],
1636    "8487": [0, 0.68889, 0, 0, 0.72222],
1637    "8498": [0, 0.68889, 0, 0, 0.55556],
1638    "8502": [0, 0.68889, 0, 0, 0.66667],
1639    "8503": [0, 0.68889, 0, 0, 0.44445],
1640    "8504": [0, 0.68889, 0, 0, 0.66667],
1641    "8513": [0, 0.68889, 0, 0, 0.63889],
1642    "8592": [-0.03598, 0.46402, 0, 0, 0.5],
1643    "8594": [-0.03598, 0.46402, 0, 0, 0.5],
1644    "8602": [-0.13313, 0.36687, 0, 0, 1.0],
1645    "8603": [-0.13313, 0.36687, 0, 0, 1.0],
1646    "8606": [0.01354, 0.52239, 0, 0, 1.0],
1647    "8608": [0.01354, 0.52239, 0, 0, 1.0],
1648    "8610": [0.01354, 0.52239, 0, 0, 1.11111],
1649    "8611": [0.01354, 0.52239, 0, 0, 1.11111],
1650    "8619": [0, 0.54986, 0, 0, 1.0],
1651    "8620": [0, 0.54986, 0, 0, 1.0],
1652    "8621": [-0.13313, 0.37788, 0, 0, 1.38889],
1653    "8622": [-0.13313, 0.36687, 0, 0, 1.0],
1654    "8624": [0, 0.69224, 0, 0, 0.5],
1655    "8625": [0, 0.69224, 0, 0, 0.5],
1656    "8630": [0, 0.43056, 0, 0, 1.0],
1657    "8631": [0, 0.43056, 0, 0, 1.0],
1658    "8634": [0.08198, 0.58198, 0, 0, 0.77778],
1659    "8635": [0.08198, 0.58198, 0, 0, 0.77778],
1660    "8638": [0.19444, 0.69224, 0, 0, 0.41667],
1661    "8639": [0.19444, 0.69224, 0, 0, 0.41667],
1662    "8642": [0.19444, 0.69224, 0, 0, 0.41667],
1663    "8643": [0.19444, 0.69224, 0, 0, 0.41667],
1664    "8644": [0.1808, 0.675, 0, 0, 1.0],
1665    "8646": [0.1808, 0.675, 0, 0, 1.0],
1666    "8647": [0.1808, 0.675, 0, 0, 1.0],
1667    "8648": [0.19444, 0.69224, 0, 0, 0.83334],
1668    "8649": [0.1808, 0.675, 0, 0, 1.0],
1669    "8650": [0.19444, 0.69224, 0, 0, 0.83334],
1670    "8651": [0.01354, 0.52239, 0, 0, 1.0],
1671    "8652": [0.01354, 0.52239, 0, 0, 1.0],
1672    "8653": [-0.13313, 0.36687, 0, 0, 1.0],
1673    "8654": [-0.13313, 0.36687, 0, 0, 1.0],
1674    "8655": [-0.13313, 0.36687, 0, 0, 1.0],
1675    "8666": [0.13667, 0.63667, 0, 0, 1.0],
1676    "8667": [0.13667, 0.63667, 0, 0, 1.0],
1677    "8669": [-0.13313, 0.37788, 0, 0, 1.0],
1678    "8672": [-0.064, 0.437, 0, 0, 1.334],
1679    "8674": [-0.064, 0.437, 0, 0, 1.334],
1680    "8705": [0, 0.825, 0, 0, 0.5],
1681    "8708": [0, 0.68889, 0, 0, 0.55556],
1682    "8709": [0.08167, 0.58167, 0, 0, 0.77778],
1683    "8717": [0, 0.43056, 0, 0, 0.42917],
1684    "8722": [-0.03598, 0.46402, 0, 0, 0.5],
1685    "8724": [0.08198, 0.69224, 0, 0, 0.77778],
1686    "8726": [0.08167, 0.58167, 0, 0, 0.77778],
1687    "8733": [0, 0.69224, 0, 0, 0.77778],
1688    "8736": [0, 0.69224, 0, 0, 0.72222],
1689    "8737": [0, 0.69224, 0, 0, 0.72222],
1690    "8738": [0.03517, 0.52239, 0, 0, 0.72222],
1691    "8739": [0.08167, 0.58167, 0, 0, 0.22222],
1692    "8740": [0.25142, 0.74111, 0, 0, 0.27778],
1693    "8741": [0.08167, 0.58167, 0, 0, 0.38889],
1694    "8742": [0.25142, 0.74111, 0, 0, 0.5],
1695    "8756": [0, 0.69224, 0, 0, 0.66667],
1696    "8757": [0, 0.69224, 0, 0, 0.66667],
1697    "8764": [-0.13313, 0.36687, 0, 0, 0.77778],
1698    "8765": [-0.13313, 0.37788, 0, 0, 0.77778],
1699    "8769": [-0.13313, 0.36687, 0, 0, 0.77778],
1700    "8770": [-0.03625, 0.46375, 0, 0, 0.77778],
1701    "8774": [0.30274, 0.79383, 0, 0, 0.77778],
1702    "8776": [-0.01688, 0.48312, 0, 0, 0.77778],
1703    "8778": [0.08167, 0.58167, 0, 0, 0.77778],
1704    "8782": [0.06062, 0.54986, 0, 0, 0.77778],
1705    "8783": [0.06062, 0.54986, 0, 0, 0.77778],
1706    "8785": [0.08198, 0.58198, 0, 0, 0.77778],
1707    "8786": [0.08198, 0.58198, 0, 0, 0.77778],
1708    "8787": [0.08198, 0.58198, 0, 0, 0.77778],
1709    "8790": [0, 0.69224, 0, 0, 0.77778],
1710    "8791": [0.22958, 0.72958, 0, 0, 0.77778],
1711    "8796": [0.08198, 0.91667, 0, 0, 0.77778],
1712    "8806": [0.25583, 0.75583, 0, 0, 0.77778],
1713    "8807": [0.25583, 0.75583, 0, 0, 0.77778],
1714    "8808": [0.25142, 0.75726, 0, 0, 0.77778],
1715    "8809": [0.25142, 0.75726, 0, 0, 0.77778],
1716    "8812": [0.25583, 0.75583, 0, 0, 0.5],
1717    "8814": [0.20576, 0.70576, 0, 0, 0.77778],
1718    "8815": [0.20576, 0.70576, 0, 0, 0.77778],
1719    "8816": [0.30274, 0.79383, 0, 0, 0.77778],
1720    "8817": [0.30274, 0.79383, 0, 0, 0.77778],
1721    "8818": [0.22958, 0.72958, 0, 0, 0.77778],
1722    "8819": [0.22958, 0.72958, 0, 0, 0.77778],
1723    "8822": [0.1808, 0.675, 0, 0, 0.77778],
1724    "8823": [0.1808, 0.675, 0, 0, 0.77778],
1725    "8828": [0.13667, 0.63667, 0, 0, 0.77778],
1726    "8829": [0.13667, 0.63667, 0, 0, 0.77778],
1727    "8830": [0.22958, 0.72958, 0, 0, 0.77778],
1728    "8831": [0.22958, 0.72958, 0, 0, 0.77778],
1729    "8832": [0.20576, 0.70576, 0, 0, 0.77778],
1730    "8833": [0.20576, 0.70576, 0, 0, 0.77778],
1731    "8840": [0.30274, 0.79383, 0, 0, 0.77778],
1732    "8841": [0.30274, 0.79383, 0, 0, 0.77778],
1733    "8842": [0.13597, 0.63597, 0, 0, 0.77778],
1734    "8843": [0.13597, 0.63597, 0, 0, 0.77778],
1735    "8847": [0.03517, 0.54986, 0, 0, 0.77778],
1736    "8848": [0.03517, 0.54986, 0, 0, 0.77778],
1737    "8858": [0.08198, 0.58198, 0, 0, 0.77778],
1738    "8859": [0.08198, 0.58198, 0, 0, 0.77778],
1739    "8861": [0.08198, 0.58198, 0, 0, 0.77778],
1740    "8862": [0, 0.675, 0, 0, 0.77778],
1741    "8863": [0, 0.675, 0, 0, 0.77778],
1742    "8864": [0, 0.675, 0, 0, 0.77778],
1743    "8865": [0, 0.675, 0, 0, 0.77778],
1744    "8872": [0, 0.69224, 0, 0, 0.61111],
1745    "8873": [0, 0.69224, 0, 0, 0.72222],
1746    "8874": [0, 0.69224, 0, 0, 0.88889],
1747    "8876": [0, 0.68889, 0, 0, 0.61111],
1748    "8877": [0, 0.68889, 0, 0, 0.61111],
1749    "8878": [0, 0.68889, 0, 0, 0.72222],
1750    "8879": [0, 0.68889, 0, 0, 0.72222],
1751    "8882": [0.03517, 0.54986, 0, 0, 0.77778],
1752    "8883": [0.03517, 0.54986, 0, 0, 0.77778],
1753    "8884": [0.13667, 0.63667, 0, 0, 0.77778],
1754    "8885": [0.13667, 0.63667, 0, 0, 0.77778],
1755    "8888": [0, 0.54986, 0, 0, 1.11111],
1756    "8890": [0.19444, 0.43056, 0, 0, 0.55556],
1757    "8891": [0.19444, 0.69224, 0, 0, 0.61111],
1758    "8892": [0.19444, 0.69224, 0, 0, 0.61111],
1759    "8901": [0, 0.54986, 0, 0, 0.27778],
1760    "8903": [0.08167, 0.58167, 0, 0, 0.77778],
1761    "8905": [0.08167, 0.58167, 0, 0, 0.77778],
1762    "8906": [0.08167, 0.58167, 0, 0, 0.77778],
1763    "8907": [0, 0.69224, 0, 0, 0.77778],
1764    "8908": [0, 0.69224, 0, 0, 0.77778],
1765    "8909": [-0.03598, 0.46402, 0, 0, 0.77778],
1766    "8910": [0, 0.54986, 0, 0, 0.76042],
1767    "8911": [0, 0.54986, 0, 0, 0.76042],
1768    "8912": [0.03517, 0.54986, 0, 0, 0.77778],
1769    "8913": [0.03517, 0.54986, 0, 0, 0.77778],
1770    "8914": [0, 0.54986, 0, 0, 0.66667],
1771    "8915": [0, 0.54986, 0, 0, 0.66667],
1772    "8916": [0, 0.69224, 0, 0, 0.66667],
1773    "8918": [0.0391, 0.5391, 0, 0, 0.77778],
1774    "8919": [0.0391, 0.5391, 0, 0, 0.77778],
1775    "8920": [0.03517, 0.54986, 0, 0, 1.33334],
1776    "8921": [0.03517, 0.54986, 0, 0, 1.33334],
1777    "8922": [0.38569, 0.88569, 0, 0, 0.77778],
1778    "8923": [0.38569, 0.88569, 0, 0, 0.77778],
1779    "8926": [0.13667, 0.63667, 0, 0, 0.77778],
1780    "8927": [0.13667, 0.63667, 0, 0, 0.77778],
1781    "8928": [0.30274, 0.79383, 0, 0, 0.77778],
1782    "8929": [0.30274, 0.79383, 0, 0, 0.77778],
1783    "8934": [0.23222, 0.74111, 0, 0, 0.77778],
1784    "8935": [0.23222, 0.74111, 0, 0, 0.77778],
1785    "8936": [0.23222, 0.74111, 0, 0, 0.77778],
1786    "8937": [0.23222, 0.74111, 0, 0, 0.77778],
1787    "8938": [0.20576, 0.70576, 0, 0, 0.77778],
1788    "8939": [0.20576, 0.70576, 0, 0, 0.77778],
1789    "8940": [0.30274, 0.79383, 0, 0, 0.77778],
1790    "8941": [0.30274, 0.79383, 0, 0, 0.77778],
1791    "8994": [0.19444, 0.69224, 0, 0, 0.77778],
1792    "8995": [0.19444, 0.69224, 0, 0, 0.77778],
1793    "9416": [0.15559, 0.69224, 0, 0, 0.90222],
1794    "9484": [0, 0.69224, 0, 0, 0.5],
1795    "9488": [0, 0.69224, 0, 0, 0.5],
1796    "9492": [0, 0.37788, 0, 0, 0.5],
1797    "9496": [0, 0.37788, 0, 0, 0.5],
1798    "9585": [0.19444, 0.68889, 0, 0, 0.88889],
1799    "9586": [0.19444, 0.74111, 0, 0, 0.88889],
1800    "9632": [0, 0.675, 0, 0, 0.77778],
1801    "9633": [0, 0.675, 0, 0, 0.77778],
1802    "9650": [0, 0.54986, 0, 0, 0.72222],
1803    "9651": [0, 0.54986, 0, 0, 0.72222],
1804    "9654": [0.03517, 0.54986, 0, 0, 0.77778],
1805    "9660": [0, 0.54986, 0, 0, 0.72222],
1806    "9661": [0, 0.54986, 0, 0, 0.72222],
1807    "9664": [0.03517, 0.54986, 0, 0, 0.77778],
1808    "9674": [0.11111, 0.69224, 0, 0, 0.66667],
1809    "9733": [0.19444, 0.69224, 0, 0, 0.94445],
1810    "10003": [0, 0.69224, 0, 0, 0.83334],
1811    "10016": [0, 0.69224, 0, 0, 0.83334],
1812    "10731": [0.11111, 0.69224, 0, 0, 0.66667],
1813    "10846": [0.19444, 0.75583, 0, 0, 0.61111],
1814    "10877": [0.13667, 0.63667, 0, 0, 0.77778],
1815    "10878": [0.13667, 0.63667, 0, 0, 0.77778],
1816    "10885": [0.25583, 0.75583, 0, 0, 0.77778],
1817    "10886": [0.25583, 0.75583, 0, 0, 0.77778],
1818    "10887": [0.13597, 0.63597, 0, 0, 0.77778],
1819    "10888": [0.13597, 0.63597, 0, 0, 0.77778],
1820    "10889": [0.26167, 0.75726, 0, 0, 0.77778],
1821    "10890": [0.26167, 0.75726, 0, 0, 0.77778],
1822    "10891": [0.48256, 0.98256, 0, 0, 0.77778],
1823    "10892": [0.48256, 0.98256, 0, 0, 0.77778],
1824    "10901": [0.13667, 0.63667, 0, 0, 0.77778],
1825    "10902": [0.13667, 0.63667, 0, 0, 0.77778],
1826    "10933": [0.25142, 0.75726, 0, 0, 0.77778],
1827    "10934": [0.25142, 0.75726, 0, 0, 0.77778],
1828    "10935": [0.26167, 0.75726, 0, 0, 0.77778],
1829    "10936": [0.26167, 0.75726, 0, 0, 0.77778],
1830    "10937": [0.26167, 0.75726, 0, 0, 0.77778],
1831    "10938": [0.26167, 0.75726, 0, 0, 0.77778],
1832    "10949": [0.25583, 0.75583, 0, 0, 0.77778],
1833    "10950": [0.25583, 0.75583, 0, 0, 0.77778],
1834    "10955": [0.28481, 0.79383, 0, 0, 0.77778],
1835    "10956": [0.28481, 0.79383, 0, 0, 0.77778],
1836    "57350": [0.08167, 0.58167, 0, 0, 0.22222],
1837    "57351": [0.08167, 0.58167, 0, 0, 0.38889],
1838    "57352": [0.08167, 0.58167, 0, 0, 0.77778],
1839    "57353": [0, 0.43056, 0.04028, 0, 0.66667],
1840    "57356": [0.25142, 0.75726, 0, 0, 0.77778],
1841    "57357": [0.25142, 0.75726, 0, 0, 0.77778],
1842    "57358": [0.41951, 0.91951, 0, 0, 0.77778],
1843    "57359": [0.30274, 0.79383, 0, 0, 0.77778],
1844    "57360": [0.30274, 0.79383, 0, 0, 0.77778],
1845    "57361": [0.41951, 0.91951, 0, 0, 0.77778],
1846    "57366": [0.25142, 0.75726, 0, 0, 0.77778],
1847    "57367": [0.25142, 0.75726, 0, 0, 0.77778],
1848    "57368": [0.25142, 0.75726, 0, 0, 0.77778],
1849    "57369": [0.25142, 0.75726, 0, 0, 0.77778],
1850    "57370": [0.13597, 0.63597, 0, 0, 0.77778],
1851    "57371": [0.13597, 0.63597, 0, 0, 0.77778]
1852  },
1853  "Caligraphic-Regular": {
1854    "48": [0, 0.43056, 0, 0, 0.5],
1855    "49": [0, 0.43056, 0, 0, 0.5],
1856    "50": [0, 0.43056, 0, 0, 0.5],
1857    "51": [0.19444, 0.43056, 0, 0, 0.5],
1858    "52": [0.19444, 0.43056, 0, 0, 0.5],
1859    "53": [0.19444, 0.43056, 0, 0, 0.5],
1860    "54": [0, 0.64444, 0, 0, 0.5],
1861    "55": [0.19444, 0.43056, 0, 0, 0.5],
1862    "56": [0, 0.64444, 0, 0, 0.5],
1863    "57": [0.19444, 0.43056, 0, 0, 0.5],
1864    "65": [0, 0.68333, 0, 0.19445, 0.79847],
1865    "66": [0, 0.68333, 0.03041, 0.13889, 0.65681],
1866    "67": [0, 0.68333, 0.05834, 0.13889, 0.52653],
1867    "68": [0, 0.68333, 0.02778, 0.08334, 0.77139],
1868    "69": [0, 0.68333, 0.08944, 0.11111, 0.52778],
1869    "70": [0, 0.68333, 0.09931, 0.11111, 0.71875],
1870    "71": [0.09722, 0.68333, 0.0593, 0.11111, 0.59487],
1871    "72": [0, 0.68333, 0.00965, 0.11111, 0.84452],
1872    "73": [0, 0.68333, 0.07382, 0, 0.54452],
1873    "74": [0.09722, 0.68333, 0.18472, 0.16667, 0.67778],
1874    "75": [0, 0.68333, 0.01445, 0.05556, 0.76195],
1875    "76": [0, 0.68333, 0, 0.13889, 0.68972],
1876    "77": [0, 0.68333, 0, 0.13889, 1.2009],
1877    "78": [0, 0.68333, 0.14736, 0.08334, 0.82049],
1878    "79": [0, 0.68333, 0.02778, 0.11111, 0.79611],
1879    "80": [0, 0.68333, 0.08222, 0.08334, 0.69556],
1880    "81": [0.09722, 0.68333, 0, 0.11111, 0.81667],
1881    "82": [0, 0.68333, 0, 0.08334, 0.8475],
1882    "83": [0, 0.68333, 0.075, 0.13889, 0.60556],
1883    "84": [0, 0.68333, 0.25417, 0, 0.54464],
1884    "85": [0, 0.68333, 0.09931, 0.08334, 0.62583],
1885    "86": [0, 0.68333, 0.08222, 0, 0.61278],
1886    "87": [0, 0.68333, 0.08222, 0.08334, 0.98778],
1887    "88": [0, 0.68333, 0.14643, 0.13889, 0.7133],
1888    "89": [0.09722, 0.68333, 0.08222, 0.08334, 0.66834],
1889    "90": [0, 0.68333, 0.07944, 0.13889, 0.72473]
1890  },
1891  "Fraktur-Regular": {
1892    "33": [0, 0.69141, 0, 0, 0.29574],
1893    "34": [0, 0.69141, 0, 0, 0.21471],
1894    "38": [0, 0.69141, 0, 0, 0.73786],
1895    "39": [0, 0.69141, 0, 0, 0.21201],
1896    "40": [0.24982, 0.74947, 0, 0, 0.38865],
1897    "41": [0.24982, 0.74947, 0, 0, 0.38865],
1898    "42": [0, 0.62119, 0, 0, 0.27764],
1899    "43": [0.08319, 0.58283, 0, 0, 0.75623],
1900    "44": [0, 0.10803, 0, 0, 0.27764],
1901    "45": [0.08319, 0.58283, 0, 0, 0.75623],
1902    "46": [0, 0.10803, 0, 0, 0.27764],
1903    "47": [0.24982, 0.74947, 0, 0, 0.50181],
1904    "48": [0, 0.47534, 0, 0, 0.50181],
1905    "49": [0, 0.47534, 0, 0, 0.50181],
1906    "50": [0, 0.47534, 0, 0, 0.50181],
1907    "51": [0.18906, 0.47534, 0, 0, 0.50181],
1908    "52": [0.18906, 0.47534, 0, 0, 0.50181],
1909    "53": [0.18906, 0.47534, 0, 0, 0.50181],
1910    "54": [0, 0.69141, 0, 0, 0.50181],
1911    "55": [0.18906, 0.47534, 0, 0, 0.50181],
1912    "56": [0, 0.69141, 0, 0, 0.50181],
1913    "57": [0.18906, 0.47534, 0, 0, 0.50181],
1914    "58": [0, 0.47534, 0, 0, 0.21606],
1915    "59": [0.12604, 0.47534, 0, 0, 0.21606],
1916    "61": [-0.13099, 0.36866, 0, 0, 0.75623],
1917    "63": [0, 0.69141, 0, 0, 0.36245],
1918    "65": [0, 0.69141, 0, 0, 0.7176],
1919    "66": [0, 0.69141, 0, 0, 0.88397],
1920    "67": [0, 0.69141, 0, 0, 0.61254],
1921    "68": [0, 0.69141, 0, 0, 0.83158],
1922    "69": [0, 0.69141, 0, 0, 0.66278],
1923    "70": [0.12604, 0.69141, 0, 0, 0.61119],
1924    "71": [0, 0.69141, 0, 0, 0.78539],
1925    "72": [0.06302, 0.69141, 0, 0, 0.7203],
1926    "73": [0, 0.69141, 0, 0, 0.55448],
1927    "74": [0.12604, 0.69141, 0, 0, 0.55231],
1928    "75": [0, 0.69141, 0, 0, 0.66845],
1929    "76": [0, 0.69141, 0, 0, 0.66602],
1930    "77": [0, 0.69141, 0, 0, 1.04953],
1931    "78": [0, 0.69141, 0, 0, 0.83212],
1932    "79": [0, 0.69141, 0, 0, 0.82699],
1933    "80": [0.18906, 0.69141, 0, 0, 0.82753],
1934    "81": [0.03781, 0.69141, 0, 0, 0.82699],
1935    "82": [0, 0.69141, 0, 0, 0.82807],
1936    "83": [0, 0.69141, 0, 0, 0.82861],
1937    "84": [0, 0.69141, 0, 0, 0.66899],
1938    "85": [0, 0.69141, 0, 0, 0.64576],
1939    "86": [0, 0.69141, 0, 0, 0.83131],
1940    "87": [0, 0.69141, 0, 0, 1.04602],
1941    "88": [0, 0.69141, 0, 0, 0.71922],
1942    "89": [0.18906, 0.69141, 0, 0, 0.83293],
1943    "90": [0.12604, 0.69141, 0, 0, 0.60201],
1944    "91": [0.24982, 0.74947, 0, 0, 0.27764],
1945    "93": [0.24982, 0.74947, 0, 0, 0.27764],
1946    "94": [0, 0.69141, 0, 0, 0.49965],
1947    "97": [0, 0.47534, 0, 0, 0.50046],
1948    "98": [0, 0.69141, 0, 0, 0.51315],
1949    "99": [0, 0.47534, 0, 0, 0.38946],
1950    "100": [0, 0.62119, 0, 0, 0.49857],
1951    "101": [0, 0.47534, 0, 0, 0.40053],
1952    "102": [0.18906, 0.69141, 0, 0, 0.32626],
1953    "103": [0.18906, 0.47534, 0, 0, 0.5037],
1954    "104": [0.18906, 0.69141, 0, 0, 0.52126],
1955    "105": [0, 0.69141, 0, 0, 0.27899],
1956    "106": [0, 0.69141, 0, 0, 0.28088],
1957    "107": [0, 0.69141, 0, 0, 0.38946],
1958    "108": [0, 0.69141, 0, 0, 0.27953],
1959    "109": [0, 0.47534, 0, 0, 0.76676],
1960    "110": [0, 0.47534, 0, 0, 0.52666],
1961    "111": [0, 0.47534, 0, 0, 0.48885],
1962    "112": [0.18906, 0.52396, 0, 0, 0.50046],
1963    "113": [0.18906, 0.47534, 0, 0, 0.48912],
1964    "114": [0, 0.47534, 0, 0, 0.38919],
1965    "115": [0, 0.47534, 0, 0, 0.44266],
1966    "116": [0, 0.62119, 0, 0, 0.33301],
1967    "117": [0, 0.47534, 0, 0, 0.5172],
1968    "118": [0, 0.52396, 0, 0, 0.5118],
1969    "119": [0, 0.52396, 0, 0, 0.77351],
1970    "120": [0.18906, 0.47534, 0, 0, 0.38865],
1971    "121": [0.18906, 0.47534, 0, 0, 0.49884],
1972    "122": [0.18906, 0.47534, 0, 0, 0.39054],
1973    "8216": [0, 0.69141, 0, 0, 0.21471],
1974    "8217": [0, 0.69141, 0, 0, 0.21471],
1975    "58112": [0, 0.62119, 0, 0, 0.49749],
1976    "58113": [0, 0.62119, 0, 0, 0.4983],
1977    "58114": [0.18906, 0.69141, 0, 0, 0.33328],
1978    "58115": [0.18906, 0.69141, 0, 0, 0.32923],
1979    "58116": [0.18906, 0.47534, 0, 0, 0.50343],
1980    "58117": [0, 0.69141, 0, 0, 0.33301],
1981    "58118": [0, 0.62119, 0, 0, 0.33409],
1982    "58119": [0, 0.47534, 0, 0, 0.50073]
1983  },
1984  "Main-Bold": {
1985    "33": [0, 0.69444, 0, 0, 0.35],
1986    "34": [0, 0.69444, 0, 0, 0.60278],
1987    "35": [0.19444, 0.69444, 0, 0, 0.95833],
1988    "36": [0.05556, 0.75, 0, 0, 0.575],
1989    "37": [0.05556, 0.75, 0, 0, 0.95833],
1990    "38": [0, 0.69444, 0, 0, 0.89444],
1991    "39": [0, 0.69444, 0, 0, 0.31944],
1992    "40": [0.25, 0.75, 0, 0, 0.44722],
1993    "41": [0.25, 0.75, 0, 0, 0.44722],
1994    "42": [0, 0.75, 0, 0, 0.575],
1995    "43": [0.13333, 0.63333, 0, 0, 0.89444],
1996    "44": [0.19444, 0.15556, 0, 0, 0.31944],
1997    "45": [0, 0.44444, 0, 0, 0.38333],
1998    "46": [0, 0.15556, 0, 0, 0.31944],
1999    "47": [0.25, 0.75, 0, 0, 0.575],
2000    "48": [0, 0.64444, 0, 0, 0.575],
2001    "49": [0, 0.64444, 0, 0, 0.575],
2002    "50": [0, 0.64444, 0, 0, 0.575],
2003    "51": [0, 0.64444, 0, 0, 0.575],
2004    "52": [0, 0.64444, 0, 0, 0.575],
2005    "53": [0, 0.64444, 0, 0, 0.575],
2006    "54": [0, 0.64444, 0, 0, 0.575],
2007    "55": [0, 0.64444, 0, 0, 0.575],
2008    "56": [0, 0.64444, 0, 0, 0.575],
2009    "57": [0, 0.64444, 0, 0, 0.575],
2010    "58": [0, 0.44444, 0, 0, 0.31944],
2011    "59": [0.19444, 0.44444, 0, 0, 0.31944],
2012    "60": [0.08556, 0.58556, 0, 0, 0.89444],
2013    "61": [-0.10889, 0.39111, 0, 0, 0.89444],
2014    "62": [0.08556, 0.58556, 0, 0, 0.89444],
2015    "63": [0, 0.69444, 0, 0, 0.54305],
2016    "64": [0, 0.69444, 0, 0, 0.89444],
2017    "65": [0, 0.68611, 0, 0, 0.86944],
2018    "66": [0, 0.68611, 0, 0, 0.81805],
2019    "67": [0, 0.68611, 0, 0, 0.83055],
2020    "68": [0, 0.68611, 0, 0, 0.88194],
2021    "69": [0, 0.68611, 0, 0, 0.75555],
2022    "70": [0, 0.68611, 0, 0, 0.72361],
2023    "71": [0, 0.68611, 0, 0, 0.90416],
2024    "72": [0, 0.68611, 0, 0, 0.9],
2025    "73": [0, 0.68611, 0, 0, 0.43611],
2026    "74": [0, 0.68611, 0, 0, 0.59444],
2027    "75": [0, 0.68611, 0, 0, 0.90138],
2028    "76": [0, 0.68611, 0, 0, 0.69166],
2029    "77": [0, 0.68611, 0, 0, 1.09166],
2030    "78": [0, 0.68611, 0, 0, 0.9],
2031    "79": [0, 0.68611, 0, 0, 0.86388],
2032    "80": [0, 0.68611, 0, 0, 0.78611],
2033    "81": [0.19444, 0.68611, 0, 0, 0.86388],
2034    "82": [0, 0.68611, 0, 0, 0.8625],
2035    "83": [0, 0.68611, 0, 0, 0.63889],
2036    "84": [0, 0.68611, 0, 0, 0.8],
2037    "85": [0, 0.68611, 0, 0, 0.88472],
2038    "86": [0, 0.68611, 0.01597, 0, 0.86944],
2039    "87": [0, 0.68611, 0.01597, 0, 1.18888],
2040    "88": [0, 0.68611, 0, 0, 0.86944],
2041    "89": [0, 0.68611, 0.02875, 0, 0.86944],
2042    "90": [0, 0.68611, 0, 0, 0.70277],
2043    "91": [0.25, 0.75, 0, 0, 0.31944],
2044    "92": [0.25, 0.75, 0, 0, 0.575],
2045    "93": [0.25, 0.75, 0, 0, 0.31944],
2046    "94": [0, 0.69444, 0, 0, 0.575],
2047    "95": [0.31, 0.13444, 0.03194, 0, 0.575],
2048    "97": [0, 0.44444, 0, 0, 0.55902],
2049    "98": [0, 0.69444, 0, 0, 0.63889],
2050    "99": [0, 0.44444, 0, 0, 0.51111],
2051    "100": [0, 0.69444, 0, 0, 0.63889],
2052    "101": [0, 0.44444, 0, 0, 0.52708],
2053    "102": [0, 0.69444, 0.10903, 0, 0.35139],
2054    "103": [0.19444, 0.44444, 0.01597, 0, 0.575],
2055    "104": [0, 0.69444, 0, 0, 0.63889],
2056    "105": [0, 0.69444, 0, 0, 0.31944],
2057    "106": [0.19444, 0.69444, 0, 0, 0.35139],
2058    "107": [0, 0.69444, 0, 0, 0.60694],
2059    "108": [0, 0.69444, 0, 0, 0.31944],
2060    "109": [0, 0.44444, 0, 0, 0.95833],
2061    "110": [0, 0.44444, 0, 0, 0.63889],
2062    "111": [0, 0.44444, 0, 0, 0.575],
2063    "112": [0.19444, 0.44444, 0, 0, 0.63889],
2064    "113": [0.19444, 0.44444, 0, 0, 0.60694],
2065    "114": [0, 0.44444, 0, 0, 0.47361],
2066    "115": [0, 0.44444, 0, 0, 0.45361],
2067    "116": [0, 0.63492, 0, 0, 0.44722],
2068    "117": [0, 0.44444, 0, 0, 0.63889],
2069    "118": [0, 0.44444, 0.01597, 0, 0.60694],
2070    "119": [0, 0.44444, 0.01597, 0, 0.83055],
2071    "120": [0, 0.44444, 0, 0, 0.60694],
2072    "121": [0.19444, 0.44444, 0.01597, 0, 0.60694],
2073    "122": [0, 0.44444, 0, 0, 0.51111],
2074    "123": [0.25, 0.75, 0, 0, 0.575],
2075    "124": [0.25, 0.75, 0, 0, 0.31944],
2076    "125": [0.25, 0.75, 0, 0, 0.575],
2077    "126": [0.35, 0.34444, 0, 0, 0.575],
2078    "168": [0, 0.69444, 0, 0, 0.575],
2079    "172": [0, 0.44444, 0, 0, 0.76666],
2080    "176": [0, 0.69444, 0, 0, 0.86944],
2081    "177": [0.13333, 0.63333, 0, 0, 0.89444],
2082    "184": [0.17014, 0, 0, 0, 0.51111],
2083    "198": [0, 0.68611, 0, 0, 1.04166],
2084    "215": [0.13333, 0.63333, 0, 0, 0.89444],
2085    "216": [0.04861, 0.73472, 0, 0, 0.89444],
2086    "223": [0, 0.69444, 0, 0, 0.59722],
2087    "230": [0, 0.44444, 0, 0, 0.83055],
2088    "247": [0.13333, 0.63333, 0, 0, 0.89444],
2089    "248": [0.09722, 0.54167, 0, 0, 0.575],
2090    "305": [0, 0.44444, 0, 0, 0.31944],
2091    "338": [0, 0.68611, 0, 0, 1.16944],
2092    "339": [0, 0.44444, 0, 0, 0.89444],
2093    "567": [0.19444, 0.44444, 0, 0, 0.35139],
2094    "710": [0, 0.69444, 0, 0, 0.575],
2095    "711": [0, 0.63194, 0, 0, 0.575],
2096    "713": [0, 0.59611, 0, 0, 0.575],
2097    "714": [0, 0.69444, 0, 0, 0.575],
2098    "715": [0, 0.69444, 0, 0, 0.575],
2099    "728": [0, 0.69444, 0, 0, 0.575],
2100    "729": [0, 0.69444, 0, 0, 0.31944],
2101    "730": [0, 0.69444, 0, 0, 0.86944],
2102    "732": [0, 0.69444, 0, 0, 0.575],
2103    "733": [0, 0.69444, 0, 0, 0.575],
2104    "915": [0, 0.68611, 0, 0, 0.69166],
2105    "916": [0, 0.68611, 0, 0, 0.95833],
2106    "920": [0, 0.68611, 0, 0, 0.89444],
2107    "923": [0, 0.68611, 0, 0, 0.80555],
2108    "926": [0, 0.68611, 0, 0, 0.76666],
2109    "928": [0, 0.68611, 0, 0, 0.9],
2110    "931": [0, 0.68611, 0, 0, 0.83055],
2111    "933": [0, 0.68611, 0, 0, 0.89444],
2112    "934": [0, 0.68611, 0, 0, 0.83055],
2113    "936": [0, 0.68611, 0, 0, 0.89444],
2114    "937": [0, 0.68611, 0, 0, 0.83055],
2115    "8211": [0, 0.44444, 0.03194, 0, 0.575],
2116    "8212": [0, 0.44444, 0.03194, 0, 1.14999],
2117    "8216": [0, 0.69444, 0, 0, 0.31944],
2118    "8217": [0, 0.69444, 0, 0, 0.31944],
2119    "8220": [0, 0.69444, 0, 0, 0.60278],
2120    "8221": [0, 0.69444, 0, 0, 0.60278],
2121    "8224": [0.19444, 0.69444, 0, 0, 0.51111],
2122    "8225": [0.19444, 0.69444, 0, 0, 0.51111],
2123    "8242": [0, 0.55556, 0, 0, 0.34444],
2124    "8407": [0, 0.72444, 0.15486, 0, 0.575],
2125    "8463": [0, 0.69444, 0, 0, 0.66759],
2126    "8465": [0, 0.69444, 0, 0, 0.83055],
2127    "8467": [0, 0.69444, 0, 0, 0.47361],
2128    "8472": [0.19444, 0.44444, 0, 0, 0.74027],
2129    "8476": [0, 0.69444, 0, 0, 0.83055],
2130    "8501": [0, 0.69444, 0, 0, 0.70277],
2131    "8592": [-0.10889, 0.39111, 0, 0, 1.14999],
2132    "8593": [0.19444, 0.69444, 0, 0, 0.575],
2133    "8594": [-0.10889, 0.39111, 0, 0, 1.14999],
2134    "8595": [0.19444, 0.69444, 0, 0, 0.575],
2135    "8596": [-0.10889, 0.39111, 0, 0, 1.14999],
2136    "8597": [0.25, 0.75, 0, 0, 0.575],
2137    "8598": [0.19444, 0.69444, 0, 0, 1.14999],
2138    "8599": [0.19444, 0.69444, 0, 0, 1.14999],
2139    "8600": [0.19444, 0.69444, 0, 0, 1.14999],
2140    "8601": [0.19444, 0.69444, 0, 0, 1.14999],
2141    "8636": [-0.10889, 0.39111, 0, 0, 1.14999],
2142    "8637": [-0.10889, 0.39111, 0, 0, 1.14999],
2143    "8640": [-0.10889, 0.39111, 0, 0, 1.14999],
2144    "8641": [-0.10889, 0.39111, 0, 0, 1.14999],
2145    "8656": [-0.10889, 0.39111, 0, 0, 1.14999],
2146    "8657": [0.19444, 0.69444, 0, 0, 0.70277],
2147    "8658": [-0.10889, 0.39111, 0, 0, 1.14999],
2148    "8659": [0.19444, 0.69444, 0, 0, 0.70277],
2149    "8660": [-0.10889, 0.39111, 0, 0, 1.14999],
2150    "8661": [0.25, 0.75, 0, 0, 0.70277],
2151    "8704": [0, 0.69444, 0, 0, 0.63889],
2152    "8706": [0, 0.69444, 0.06389, 0, 0.62847],
2153    "8707": [0, 0.69444, 0, 0, 0.63889],
2154    "8709": [0.05556, 0.75, 0, 0, 0.575],
2155    "8711": [0, 0.68611, 0, 0, 0.95833],
2156    "8712": [0.08556, 0.58556, 0, 0, 0.76666],
2157    "8715": [0.08556, 0.58556, 0, 0, 0.76666],
2158    "8722": [0.13333, 0.63333, 0, 0, 0.89444],
2159    "8723": [0.13333, 0.63333, 0, 0, 0.89444],
2160    "8725": [0.25, 0.75, 0, 0, 0.575],
2161    "8726": [0.25, 0.75, 0, 0, 0.575],
2162    "8727": [-0.02778, 0.47222, 0, 0, 0.575],
2163    "8728": [-0.02639, 0.47361, 0, 0, 0.575],
2164    "8729": [-0.02639, 0.47361, 0, 0, 0.575],
2165    "8730": [0.18, 0.82, 0, 0, 0.95833],
2166    "8733": [0, 0.44444, 0, 0, 0.89444],
2167    "8734": [0, 0.44444, 0, 0, 1.14999],
2168    "8736": [0, 0.69224, 0, 0, 0.72222],
2169    "8739": [0.25, 0.75, 0, 0, 0.31944],
2170    "8741": [0.25, 0.75, 0, 0, 0.575],
2171    "8743": [0, 0.55556, 0, 0, 0.76666],
2172    "8744": [0, 0.55556, 0, 0, 0.76666],
2173    "8745": [0, 0.55556, 0, 0, 0.76666],
2174    "8746": [0, 0.55556, 0, 0, 0.76666],
2175    "8747": [0.19444, 0.69444, 0.12778, 0, 0.56875],
2176    "8764": [-0.10889, 0.39111, 0, 0, 0.89444],
2177    "8768": [0.19444, 0.69444, 0, 0, 0.31944],
2178    "8771": [0.00222, 0.50222, 0, 0, 0.89444],
2179    "8776": [0.02444, 0.52444, 0, 0, 0.89444],
2180    "8781": [0.00222, 0.50222, 0, 0, 0.89444],
2181    "8801": [0.00222, 0.50222, 0, 0, 0.89444],
2182    "8804": [0.19667, 0.69667, 0, 0, 0.89444],
2183    "8805": [0.19667, 0.69667, 0, 0, 0.89444],
2184    "8810": [0.08556, 0.58556, 0, 0, 1.14999],
2185    "8811": [0.08556, 0.58556, 0, 0, 1.14999],
2186    "8826": [0.08556, 0.58556, 0, 0, 0.89444],
2187    "8827": [0.08556, 0.58556, 0, 0, 0.89444],
2188    "8834": [0.08556, 0.58556, 0, 0, 0.89444],
2189    "8835": [0.08556, 0.58556, 0, 0, 0.89444],
2190    "8838": [0.19667, 0.69667, 0, 0, 0.89444],
2191    "8839": [0.19667, 0.69667, 0, 0, 0.89444],
2192    "8846": [0, 0.55556, 0, 0, 0.76666],
2193    "8849": [0.19667, 0.69667, 0, 0, 0.89444],
2194    "8850": [0.19667, 0.69667, 0, 0, 0.89444],
2195    "8851": [0, 0.55556, 0, 0, 0.76666],
2196    "8852": [0, 0.55556, 0, 0, 0.76666],
2197    "8853": [0.13333, 0.63333, 0, 0, 0.89444],
2198    "8854": [0.13333, 0.63333, 0, 0, 0.89444],
2199    "8855": [0.13333, 0.63333, 0, 0, 0.89444],
2200    "8856": [0.13333, 0.63333, 0, 0, 0.89444],
2201    "8857": [0.13333, 0.63333, 0, 0, 0.89444],
2202    "8866": [0, 0.69444, 0, 0, 0.70277],
2203    "8867": [0, 0.69444, 0, 0, 0.70277],
2204    "8868": [0, 0.69444, 0, 0, 0.89444],
2205    "8869": [0, 0.69444, 0, 0, 0.89444],
2206    "8900": [-0.02639, 0.47361, 0, 0, 0.575],
2207    "8901": [-0.02639, 0.47361, 0, 0, 0.31944],
2208    "8902": [-0.02778, 0.47222, 0, 0, 0.575],
2209    "8968": [0.25, 0.75, 0, 0, 0.51111],
2210    "8969": [0.25, 0.75, 0, 0, 0.51111],
2211    "8970": [0.25, 0.75, 0, 0, 0.51111],
2212    "8971": [0.25, 0.75, 0, 0, 0.51111],
2213    "8994": [-0.13889, 0.36111, 0, 0, 1.14999],
2214    "8995": [-0.13889, 0.36111, 0, 0, 1.14999],
2215    "9651": [0.19444, 0.69444, 0, 0, 1.02222],
2216    "9657": [-0.02778, 0.47222, 0, 0, 0.575],
2217    "9661": [0.19444, 0.69444, 0, 0, 1.02222],
2218    "9667": [-0.02778, 0.47222, 0, 0, 0.575],
2219    "9711": [0.19444, 0.69444, 0, 0, 1.14999],
2220    "9824": [0.12963, 0.69444, 0, 0, 0.89444],
2221    "9825": [0.12963, 0.69444, 0, 0, 0.89444],
2222    "9826": [0.12963, 0.69444, 0, 0, 0.89444],
2223    "9827": [0.12963, 0.69444, 0, 0, 0.89444],
2224    "9837": [0, 0.75, 0, 0, 0.44722],
2225    "9838": [0.19444, 0.69444, 0, 0, 0.44722],
2226    "9839": [0.19444, 0.69444, 0, 0, 0.44722],
2227    "10216": [0.25, 0.75, 0, 0, 0.44722],
2228    "10217": [0.25, 0.75, 0, 0, 0.44722],
2229    "10815": [0, 0.68611, 0, 0, 0.9],
2230    "10927": [0.19667, 0.69667, 0, 0, 0.89444],
2231    "10928": [0.19667, 0.69667, 0, 0, 0.89444],
2232    "57376": [0.19444, 0.69444, 0, 0, 0]
2233  },
2234  "Main-BoldItalic": {
2235    "33": [0, 0.69444, 0.11417, 0, 0.38611],
2236    "34": [0, 0.69444, 0.07939, 0, 0.62055],
2237    "35": [0.19444, 0.69444, 0.06833, 0, 0.94444],
2238    "37": [0.05556, 0.75, 0.12861, 0, 0.94444],
2239    "38": [0, 0.69444, 0.08528, 0, 0.88555],
2240    "39": [0, 0.69444, 0.12945, 0, 0.35555],
2241    "40": [0.25, 0.75, 0.15806, 0, 0.47333],
2242    "41": [0.25, 0.75, 0.03306, 0, 0.47333],
2243    "42": [0, 0.75, 0.14333, 0, 0.59111],
2244    "43": [0.10333, 0.60333, 0.03306, 0, 0.88555],
2245    "44": [0.19444, 0.14722, 0, 0, 0.35555],
2246    "45": [0, 0.44444, 0.02611, 0, 0.41444],
2247    "46": [0, 0.14722, 0, 0, 0.35555],
2248    "47": [0.25, 0.75, 0.15806, 0, 0.59111],
2249    "48": [0, 0.64444, 0.13167, 0, 0.59111],
2250    "49": [0, 0.64444, 0.13167, 0, 0.59111],
2251    "50": [0, 0.64444, 0.13167, 0, 0.59111],
2252    "51": [0, 0.64444, 0.13167, 0, 0.59111],
2253    "52": [0.19444, 0.64444, 0.13167, 0, 0.59111],
2254    "53": [0, 0.64444, 0.13167, 0, 0.59111],
2255    "54": [0, 0.64444, 0.13167, 0, 0.59111],
2256    "55": [0.19444, 0.64444, 0.13167, 0, 0.59111],
2257    "56": [0, 0.64444, 0.13167, 0, 0.59111],
2258    "57": [0, 0.64444, 0.13167, 0, 0.59111],
2259    "58": [0, 0.44444, 0.06695, 0, 0.35555],
2260    "59": [0.19444, 0.44444, 0.06695, 0, 0.35555],
2261    "61": [-0.10889, 0.39111, 0.06833, 0, 0.88555],
2262    "63": [0, 0.69444, 0.11472, 0, 0.59111],
2263    "64": [0, 0.69444, 0.09208, 0, 0.88555],
2264    "65": [0, 0.68611, 0, 0, 0.86555],
2265    "66": [0, 0.68611, 0.0992, 0, 0.81666],
2266    "67": [0, 0.68611, 0.14208, 0, 0.82666],
2267    "68": [0, 0.68611, 0.09062, 0, 0.87555],
2268    "69": [0, 0.68611, 0.11431, 0, 0.75666],
2269    "70": [0, 0.68611, 0.12903, 0, 0.72722],
2270    "71": [0, 0.68611, 0.07347, 0, 0.89527],
2271    "72": [0, 0.68611, 0.17208, 0, 0.8961],
2272    "73": [0, 0.68611, 0.15681, 0, 0.47166],
2273    "74": [0, 0.68611, 0.145, 0, 0.61055],
2274    "75": [0, 0.68611, 0.14208, 0, 0.89499],
2275    "76": [0, 0.68611, 0, 0, 0.69777],
2276    "77": [0, 0.68611, 0.17208, 0, 1.07277],
2277    "78": [0, 0.68611, 0.17208, 0, 0.8961],
2278    "79": [0, 0.68611, 0.09062, 0, 0.85499],
2279    "80": [0, 0.68611, 0.0992, 0, 0.78721],
2280    "81": [0.19444, 0.68611, 0.09062, 0, 0.85499],
2281    "82": [0, 0.68611, 0.02559, 0, 0.85944],
2282    "83": [0, 0.68611, 0.11264, 0, 0.64999],
2283    "84": [0, 0.68611, 0.12903, 0, 0.7961],
2284    "85": [0, 0.68611, 0.17208, 0, 0.88083],
2285    "86": [0, 0.68611, 0.18625, 0, 0.86555],
2286    "87": [0, 0.68611, 0.18625, 0, 1.15999],
2287    "88": [0, 0.68611, 0.15681, 0, 0.86555],
2288    "89": [0, 0.68611, 0.19803, 0, 0.86555],
2289    "90": [0, 0.68611, 0.14208, 0, 0.70888],
2290    "91": [0.25, 0.75, 0.1875, 0, 0.35611],
2291    "93": [0.25, 0.75, 0.09972, 0, 0.35611],
2292    "94": [0, 0.69444, 0.06709, 0, 0.59111],
2293    "95": [0.31, 0.13444, 0.09811, 0, 0.59111],
2294    "97": [0, 0.44444, 0.09426, 0, 0.59111],
2295    "98": [0, 0.69444, 0.07861, 0, 0.53222],
2296    "99": [0, 0.44444, 0.05222, 0, 0.53222],
2297    "100": [0, 0.69444, 0.10861, 0, 0.59111],
2298    "101": [0, 0.44444, 0.085, 0, 0.53222],
2299    "102": [0.19444, 0.69444, 0.21778, 0, 0.4],
2300    "103": [0.19444, 0.44444, 0.105, 0, 0.53222],
2301    "104": [0, 0.69444, 0.09426, 0, 0.59111],
2302    "105": [0, 0.69326, 0.11387, 0, 0.35555],
2303    "106": [0.19444, 0.69326, 0.1672, 0, 0.35555],
2304    "107": [0, 0.69444, 0.11111, 0, 0.53222],
2305    "108": [0, 0.69444, 0.10861, 0, 0.29666],
2306    "109": [0, 0.44444, 0.09426, 0, 0.94444],
2307    "110": [0, 0.44444, 0.09426, 0, 0.64999],
2308    "111": [0, 0.44444, 0.07861, 0, 0.59111],
2309    "112": [0.19444, 0.44444, 0.07861, 0, 0.59111],
2310    "113": [0.19444, 0.44444, 0.105, 0, 0.53222],
2311    "114": [0, 0.44444, 0.11111, 0, 0.50167],
2312    "115": [0, 0.44444, 0.08167, 0, 0.48694],
2313    "116": [0, 0.63492, 0.09639, 0, 0.385],
2314    "117": [0, 0.44444, 0.09426, 0, 0.62055],
2315    "118": [0, 0.44444, 0.11111, 0, 0.53222],
2316    "119": [0, 0.44444, 0.11111, 0, 0.76777],
2317    "120": [0, 0.44444, 0.12583, 0, 0.56055],
2318    "121": [0.19444, 0.44444, 0.105, 0, 0.56166],
2319    "122": [0, 0.44444, 0.13889, 0, 0.49055],
2320    "126": [0.35, 0.34444, 0.11472, 0, 0.59111],
2321    "163": [0, 0.69444, 0, 0, 0.86853],
2322    "168": [0, 0.69444, 0.11473, 0, 0.59111],
2323    "176": [0, 0.69444, 0, 0, 0.94888],
2324    "184": [0.17014, 0, 0, 0, 0.53222],
2325    "198": [0, 0.68611, 0.11431, 0, 1.02277],
2326    "216": [0.04861, 0.73472, 0.09062, 0, 0.88555],
2327    "223": [0.19444, 0.69444, 0.09736, 0, 0.665],
2328    "230": [0, 0.44444, 0.085, 0, 0.82666],
2329    "248": [0.09722, 0.54167, 0.09458, 0, 0.59111],
2330    "305": [0, 0.44444, 0.09426, 0, 0.35555],
2331    "338": [0, 0.68611, 0.11431, 0, 1.14054],
2332    "339": [0, 0.44444, 0.085, 0, 0.82666],
2333    "567": [0.19444, 0.44444, 0.04611, 0, 0.385],
2334    "710": [0, 0.69444, 0.06709, 0, 0.59111],
2335    "711": [0, 0.63194, 0.08271, 0, 0.59111],
2336    "713": [0, 0.59444, 0.10444, 0, 0.59111],
2337    "714": [0, 0.69444, 0.08528, 0, 0.59111],
2338    "715": [0, 0.69444, 0, 0, 0.59111],
2339    "728": [0, 0.69444, 0.10333, 0, 0.59111],
2340    "729": [0, 0.69444, 0.12945, 0, 0.35555],
2341    "730": [0, 0.69444, 0, 0, 0.94888],
2342    "732": [0, 0.69444, 0.11472, 0, 0.59111],
2343    "733": [0, 0.69444, 0.11472, 0, 0.59111],
2344    "915": [0, 0.68611, 0.12903, 0, 0.69777],
2345    "916": [0, 0.68611, 0, 0, 0.94444],
2346    "920": [0, 0.68611, 0.09062, 0, 0.88555],
2347    "923": [0, 0.68611, 0, 0, 0.80666],
2348    "926": [0, 0.68611, 0.15092, 0, 0.76777],
2349    "928": [0, 0.68611, 0.17208, 0, 0.8961],
2350    "931": [0, 0.68611, 0.11431, 0, 0.82666],
2351    "933": [0, 0.68611, 0.10778, 0, 0.88555],
2352    "934": [0, 0.68611, 0.05632, 0, 0.82666],
2353    "936": [0, 0.68611, 0.10778, 0, 0.88555],
2354    "937": [0, 0.68611, 0.0992, 0, 0.82666],
2355    "8211": [0, 0.44444, 0.09811, 0, 0.59111],
2356    "8212": [0, 0.44444, 0.09811, 0, 1.18221],
2357    "8216": [0, 0.69444, 0.12945, 0, 0.35555],
2358    "8217": [0, 0.69444, 0.12945, 0, 0.35555],
2359    "8220": [0, 0.69444, 0.16772, 0, 0.62055],
2360    "8221": [0, 0.69444, 0.07939, 0, 0.62055]
2361  },
2362  "Main-Italic": {
2363    "33": [0, 0.69444, 0.12417, 0, 0.30667],
2364    "34": [0, 0.69444, 0.06961, 0, 0.51444],
2365    "35": [0.19444, 0.69444, 0.06616, 0, 0.81777],
2366    "37": [0.05556, 0.75, 0.13639, 0, 0.81777],
2367    "38": [0, 0.69444, 0.09694, 0, 0.76666],
2368    "39": [0, 0.69444, 0.12417, 0, 0.30667],
2369    "40": [0.25, 0.75, 0.16194, 0, 0.40889],
2370    "41": [0.25, 0.75, 0.03694, 0, 0.40889],
2371    "42": [0, 0.75, 0.14917, 0, 0.51111],
2372    "43": [0.05667, 0.56167, 0.03694, 0, 0.76666],
2373    "44": [0.19444, 0.10556, 0, 0, 0.30667],
2374    "45": [0, 0.43056, 0.02826, 0, 0.35778],
2375    "46": [0, 0.10556, 0, 0, 0.30667],
2376    "47": [0.25, 0.75, 0.16194, 0, 0.51111],
2377    "48": [0, 0.64444, 0.13556, 0, 0.51111],
2378    "49": [0, 0.64444, 0.13556, 0, 0.51111],
2379    "50": [0, 0.64444, 0.13556, 0, 0.51111],
2380    "51": [0, 0.64444, 0.13556, 0, 0.51111],
2381    "52": [0.19444, 0.64444, 0.13556, 0, 0.51111],
2382    "53": [0, 0.64444, 0.13556, 0, 0.51111],
2383    "54": [0, 0.64444, 0.13556, 0, 0.51111],
2384    "55": [0.19444, 0.64444, 0.13556, 0, 0.51111],
2385    "56": [0, 0.64444, 0.13556, 0, 0.51111],
2386    "57": [0, 0.64444, 0.13556, 0, 0.51111],
2387    "58": [0, 0.43056, 0.0582, 0, 0.30667],
2388    "59": [0.19444, 0.43056, 0.0582, 0, 0.30667],
2389    "61": [-0.13313, 0.36687, 0.06616, 0, 0.76666],
2390    "63": [0, 0.69444, 0.1225, 0, 0.51111],
2391    "64": [0, 0.69444, 0.09597, 0, 0.76666],
2392    "65": [0, 0.68333, 0, 0, 0.74333],
2393    "66": [0, 0.68333, 0.10257, 0, 0.70389],
2394    "67": [0, 0.68333, 0.14528, 0, 0.71555],
2395    "68": [0, 0.68333, 0.09403, 0, 0.755],
2396    "69": [0, 0.68333, 0.12028, 0, 0.67833],
2397    "70": [0, 0.68333, 0.13305, 0, 0.65277],
2398    "71": [0, 0.68333, 0.08722, 0, 0.77361],
2399    "72": [0, 0.68333, 0.16389, 0, 0.74333],
2400    "73": [0, 0.68333, 0.15806, 0, 0.38555],
2401    "74": [0, 0.68333, 0.14028, 0, 0.525],
2402    "75": [0, 0.68333, 0.14528, 0, 0.76888],
2403    "76": [0, 0.68333, 0, 0, 0.62722],
2404    "77": [0, 0.68333, 0.16389, 0, 0.89666],
2405    "78": [0, 0.68333, 0.16389, 0, 0.74333],
2406    "79": [0, 0.68333, 0.09403, 0, 0.76666],
2407    "80": [0, 0.68333, 0.10257, 0, 0.67833],
2408    "81": [0.19444, 0.68333, 0.09403, 0, 0.76666],
2409    "82": [0, 0.68333, 0.03868, 0, 0.72944],
2410    "83": [0, 0.68333, 0.11972, 0, 0.56222],
2411    "84": [0, 0.68333, 0.13305, 0, 0.71555],
2412    "85": [0, 0.68333, 0.16389, 0, 0.74333],
2413    "86": [0, 0.68333, 0.18361, 0, 0.74333],
2414    "87": [0, 0.68333, 0.18361, 0, 0.99888],
2415    "88": [0, 0.68333, 0.15806, 0, 0.74333],
2416    "89": [0, 0.68333, 0.19383, 0, 0.74333],
2417    "90": [0, 0.68333, 0.14528, 0, 0.61333],
2418    "91": [0.25, 0.75, 0.1875, 0, 0.30667],
2419    "93": [0.25, 0.75, 0.10528, 0, 0.30667],
2420    "94": [0, 0.69444, 0.06646, 0, 0.51111],
2421    "95": [0.31, 0.12056, 0.09208, 0, 0.51111],
2422    "97": [0, 0.43056, 0.07671, 0, 0.51111],
2423    "98": [0, 0.69444, 0.06312, 0, 0.46],
2424    "99": [0, 0.43056, 0.05653, 0, 0.46],
2425    "100": [0, 0.69444, 0.10333, 0, 0.51111],
2426    "101": [0, 0.43056, 0.07514, 0, 0.46],
2427    "102": [0.19444, 0.69444, 0.21194, 0, 0.30667],
2428    "103": [0.19444, 0.43056, 0.08847, 0, 0.46],
2429    "104": [0, 0.69444, 0.07671, 0, 0.51111],
2430    "105": [0, 0.65536, 0.1019, 0, 0.30667],
2431    "106": [0.19444, 0.65536, 0.14467, 0, 0.30667],
2432    "107": [0, 0.69444, 0.10764, 0, 0.46],
2433    "108": [0, 0.69444, 0.10333, 0, 0.25555],
2434    "109": [0, 0.43056, 0.07671, 0, 0.81777],
2435    "110": [0, 0.43056, 0.07671, 0, 0.56222],
2436    "111": [0, 0.43056, 0.06312, 0, 0.51111],
2437    "112": [0.19444, 0.43056, 0.06312, 0, 0.51111],
2438    "113": [0.19444, 0.43056, 0.08847, 0, 0.46],
2439    "114": [0, 0.43056, 0.10764, 0, 0.42166],
2440    "115": [0, 0.43056, 0.08208, 0, 0.40889],
2441    "116": [0, 0.61508, 0.09486, 0, 0.33222],
2442    "117": [0, 0.43056, 0.07671, 0, 0.53666],
2443    "118": [0, 0.43056, 0.10764, 0, 0.46],
2444    "119": [0, 0.43056, 0.10764, 0, 0.66444],
2445    "120": [0, 0.43056, 0.12042, 0, 0.46389],
2446    "121": [0.19444, 0.43056, 0.08847, 0, 0.48555],
2447    "122": [0, 0.43056, 0.12292, 0, 0.40889],
2448    "126": [0.35, 0.31786, 0.11585, 0, 0.51111],
2449    "163": [0, 0.69444, 0, 0, 0.76909],
2450    "168": [0, 0.66786, 0.10474, 0, 0.51111],
2451    "176": [0, 0.69444, 0, 0, 0.83129],
2452    "184": [0.17014, 0, 0, 0, 0.46],
2453    "198": [0, 0.68333, 0.12028, 0, 0.88277],
2454    "216": [0.04861, 0.73194, 0.09403, 0, 0.76666],
2455    "223": [0.19444, 0.69444, 0.10514, 0, 0.53666],
2456    "230": [0, 0.43056, 0.07514, 0, 0.71555],
2457    "248": [0.09722, 0.52778, 0.09194, 0, 0.51111],
2458    "305": [0, 0.43056, 0, 0.02778, 0.32246],
2459    "338": [0, 0.68333, 0.12028, 0, 0.98499],
2460    "339": [0, 0.43056, 0.07514, 0, 0.71555],
2461    "567": [0.19444, 0.43056, 0, 0.08334, 0.38403],
2462    "710": [0, 0.69444, 0.06646, 0, 0.51111],
2463    "711": [0, 0.62847, 0.08295, 0, 0.51111],
2464    "713": [0, 0.56167, 0.10333, 0, 0.51111],
2465    "714": [0, 0.69444, 0.09694, 0, 0.51111],
2466    "715": [0, 0.69444, 0, 0, 0.51111],
2467    "728": [0, 0.69444, 0.10806, 0, 0.51111],
2468    "729": [0, 0.66786, 0.11752, 0, 0.30667],
2469    "730": [0, 0.69444, 0, 0, 0.83129],
2470    "732": [0, 0.66786, 0.11585, 0, 0.51111],
2471    "733": [0, 0.69444, 0.1225, 0, 0.51111],
2472    "915": [0, 0.68333, 0.13305, 0, 0.62722],
2473    "916": [0, 0.68333, 0, 0, 0.81777],
2474    "920": [0, 0.68333, 0.09403, 0, 0.76666],
2475    "923": [0, 0.68333, 0, 0, 0.69222],
2476    "926": [0, 0.68333, 0.15294, 0, 0.66444],
2477    "928": [0, 0.68333, 0.16389, 0, 0.74333],
2478    "931": [0, 0.68333, 0.12028, 0, 0.71555],
2479    "933": [0, 0.68333, 0.11111, 0, 0.76666],
2480    "934": [0, 0.68333, 0.05986, 0, 0.71555],
2481    "936": [0, 0.68333, 0.11111, 0, 0.76666],
2482    "937": [0, 0.68333, 0.10257, 0, 0.71555],
2483    "8211": [0, 0.43056, 0.09208, 0, 0.51111],
2484    "8212": [0, 0.43056, 0.09208, 0, 1.02222],
2485    "8216": [0, 0.69444, 0.12417, 0, 0.30667],
2486    "8217": [0, 0.69444, 0.12417, 0, 0.30667],
2487    "8220": [0, 0.69444, 0.1685, 0, 0.51444],
2488    "8221": [0, 0.69444, 0.06961, 0, 0.51444],
2489    "8463": [0, 0.68889, 0, 0, 0.54028]
2490  },
2491  "Main-Regular": {
2492    "32": [0, 0, 0, 0, 0.25],
2493    "33": [0, 0.69444, 0, 0, 0.27778],
2494    "34": [0, 0.69444, 0, 0, 0.5],
2495    "35": [0.19444, 0.69444, 0, 0, 0.83334],
2496    "36": [0.05556, 0.75, 0, 0, 0.5],
2497    "37": [0.05556, 0.75, 0, 0, 0.83334],
2498    "38": [0, 0.69444, 0, 0, 0.77778],
2499    "39": [0, 0.69444, 0, 0, 0.27778],
2500    "40": [0.25, 0.75, 0, 0, 0.38889],
2501    "41": [0.25, 0.75, 0, 0, 0.38889],
2502    "42": [0, 0.75, 0, 0, 0.5],
2503    "43": [0.08333, 0.58333, 0, 0, 0.77778],
2504    "44": [0.19444, 0.10556, 0, 0, 0.27778],
2505    "45": [0, 0.43056, 0, 0, 0.33333],
2506    "46": [0, 0.10556, 0, 0, 0.27778],
2507    "47": [0.25, 0.75, 0, 0, 0.5],
2508    "48": [0, 0.64444, 0, 0, 0.5],
2509    "49": [0, 0.64444, 0, 0, 0.5],
2510    "50": [0, 0.64444, 0, 0, 0.5],
2511    "51": [0, 0.64444, 0, 0, 0.5],
2512    "52": [0, 0.64444, 0, 0, 0.5],
2513    "53": [0, 0.64444, 0, 0, 0.5],
2514    "54": [0, 0.64444, 0, 0, 0.5],
2515    "55": [0, 0.64444, 0, 0, 0.5],
2516    "56": [0, 0.64444, 0, 0, 0.5],
2517    "57": [0, 0.64444, 0, 0, 0.5],
2518    "58": [0, 0.43056, 0, 0, 0.27778],
2519    "59": [0.19444, 0.43056, 0, 0, 0.27778],
2520    "60": [0.0391, 0.5391, 0, 0, 0.77778],
2521    "61": [-0.13313, 0.36687, 0, 0, 0.77778],
2522    "62": [0.0391, 0.5391, 0, 0, 0.77778],
2523    "63": [0, 0.69444, 0, 0, 0.47222],
2524    "64": [0, 0.69444, 0, 0, 0.77778],
2525    "65": [0, 0.68333, 0, 0, 0.75],
2526    "66": [0, 0.68333, 0, 0, 0.70834],
2527    "67": [0, 0.68333, 0, 0, 0.72222],
2528    "68": [0, 0.68333, 0, 0, 0.76389],
2529    "69": [0, 0.68333, 0, 0, 0.68056],
2530    "70": [0, 0.68333, 0, 0, 0.65278],
2531    "71": [0, 0.68333, 0, 0, 0.78472],
2532    "72": [0, 0.68333, 0, 0, 0.75],
2533    "73": [0, 0.68333, 0, 0, 0.36111],
2534    "74": [0, 0.68333, 0, 0, 0.51389],
2535    "75": [0, 0.68333, 0, 0, 0.77778],
2536    "76": [0, 0.68333, 0, 0, 0.625],
2537    "77": [0, 0.68333, 0, 0, 0.91667],
2538    "78": [0, 0.68333, 0, 0, 0.75],
2539    "79": [0, 0.68333, 0, 0, 0.77778],
2540    "80": [0, 0.68333, 0, 0, 0.68056],
2541    "81": [0.19444, 0.68333, 0, 0, 0.77778],
2542    "82": [0, 0.68333, 0, 0, 0.73611],
2543    "83": [0, 0.68333, 0, 0, 0.55556],
2544    "84": [0, 0.68333, 0, 0, 0.72222],
2545    "85": [0, 0.68333, 0, 0, 0.75],
2546    "86": [0, 0.68333, 0.01389, 0, 0.75],
2547    "87": [0, 0.68333, 0.01389, 0, 1.02778],
2548    "88": [0, 0.68333, 0, 0, 0.75],
2549    "89": [0, 0.68333, 0.025, 0, 0.75],
2550    "90": [0, 0.68333, 0, 0, 0.61111],
2551    "91": [0.25, 0.75, 0, 0, 0.27778],
2552    "92": [0.25, 0.75, 0, 0, 0.5],
2553    "93": [0.25, 0.75, 0, 0, 0.27778],
2554    "94": [0, 0.69444, 0, 0, 0.5],
2555    "95": [0.31, 0.12056, 0.02778, 0, 0.5],
2556    "97": [0, 0.43056, 0, 0, 0.5],
2557    "98": [0, 0.69444, 0, 0, 0.55556],
2558    "99": [0, 0.43056, 0, 0, 0.44445],
2559    "100": [0, 0.69444, 0, 0, 0.55556],
2560    "101": [0, 0.43056, 0, 0, 0.44445],
2561    "102": [0, 0.69444, 0.07778, 0, 0.30556],
2562    "103": [0.19444, 0.43056, 0.01389, 0, 0.5],
2563    "104": [0, 0.69444, 0, 0, 0.55556],
2564    "105": [0, 0.66786, 0, 0, 0.27778],
2565    "106": [0.19444, 0.66786, 0, 0, 0.30556],
2566    "107": [0, 0.69444, 0, 0, 0.52778],
2567    "108": [0, 0.69444, 0, 0, 0.27778],
2568    "109": [0, 0.43056, 0, 0, 0.83334],
2569    "110": [0, 0.43056, 0, 0, 0.55556],
2570    "111": [0, 0.43056, 0, 0, 0.5],
2571    "112": [0.19444, 0.43056, 0, 0, 0.55556],
2572    "113": [0.19444, 0.43056, 0, 0, 0.52778],
2573    "114": [0, 0.43056, 0, 0, 0.39167],
2574    "115": [0, 0.43056, 0, 0, 0.39445],
2575    "116": [0, 0.61508, 0, 0, 0.38889],
2576    "117": [0, 0.43056, 0, 0, 0.55556],
2577    "118": [0, 0.43056, 0.01389, 0, 0.52778],
2578    "119": [0, 0.43056, 0.01389, 0, 0.72222],
2579    "120": [0, 0.43056, 0, 0, 0.52778],
2580    "121": [0.19444, 0.43056, 0.01389, 0, 0.52778],
2581    "122": [0, 0.43056, 0, 0, 0.44445],
2582    "123": [0.25, 0.75, 0, 0, 0.5],
2583    "124": [0.25, 0.75, 0, 0, 0.27778],
2584    "125": [0.25, 0.75, 0, 0, 0.5],
2585    "126": [0.35, 0.31786, 0, 0, 0.5],
2586    "160": [0, 0, 0, 0, 0.25],
2587    "167": [0.19444, 0.69444, 0, 0, 0.44445],
2588    "168": [0, 0.66786, 0, 0, 0.5],
2589    "172": [0, 0.43056, 0, 0, 0.66667],
2590    "176": [0, 0.69444, 0, 0, 0.75],
2591    "177": [0.08333, 0.58333, 0, 0, 0.77778],
2592    "182": [0.19444, 0.69444, 0, 0, 0.61111],
2593    "184": [0.17014, 0, 0, 0, 0.44445],
2594    "198": [0, 0.68333, 0, 0, 0.90278],
2595    "215": [0.08333, 0.58333, 0, 0, 0.77778],
2596    "216": [0.04861, 0.73194, 0, 0, 0.77778],
2597    "223": [0, 0.69444, 0, 0, 0.5],
2598    "230": [0, 0.43056, 0, 0, 0.72222],
2599    "247": [0.08333, 0.58333, 0, 0, 0.77778],
2600    "248": [0.09722, 0.52778, 0, 0, 0.5],
2601    "305": [0, 0.43056, 0, 0, 0.27778],
2602    "338": [0, 0.68333, 0, 0, 1.01389],
2603    "339": [0, 0.43056, 0, 0, 0.77778],
2604    "567": [0.19444, 0.43056, 0, 0, 0.30556],
2605    "710": [0, 0.69444, 0, 0, 0.5],
2606    "711": [0, 0.62847, 0, 0, 0.5],
2607    "713": [0, 0.56778, 0, 0, 0.5],
2608    "714": [0, 0.69444, 0, 0, 0.5],
2609    "715": [0, 0.69444, 0, 0, 0.5],
2610    "728": [0, 0.69444, 0, 0, 0.5],
2611    "729": [0, 0.66786, 0, 0, 0.27778],
2612    "730": [0, 0.69444, 0, 0, 0.75],
2613    "732": [0, 0.66786, 0, 0, 0.5],
2614    "733": [0, 0.69444, 0, 0, 0.5],
2615    "915": [0, 0.68333, 0, 0, 0.625],
2616    "916": [0, 0.68333, 0, 0, 0.83334],
2617    "920": [0, 0.68333, 0, 0, 0.77778],
2618    "923": [0, 0.68333, 0, 0, 0.69445],
2619    "926": [0, 0.68333, 0, 0, 0.66667],
2620    "928": [0, 0.68333, 0, 0, 0.75],
2621    "931": [0, 0.68333, 0, 0, 0.72222],
2622    "933": [0, 0.68333, 0, 0, 0.77778],
2623    "934": [0, 0.68333, 0, 0, 0.72222],
2624    "936": [0, 0.68333, 0, 0, 0.77778],
2625    "937": [0, 0.68333, 0, 0, 0.72222],
2626    "8211": [0, 0.43056, 0.02778, 0, 0.5],
2627    "8212": [0, 0.43056, 0.02778, 0, 1.0],
2628    "8216": [0, 0.69444, 0, 0, 0.27778],
2629    "8217": [0, 0.69444, 0, 0, 0.27778],
2630    "8220": [0, 0.69444, 0, 0, 0.5],
2631    "8221": [0, 0.69444, 0, 0, 0.5],
2632    "8224": [0.19444, 0.69444, 0, 0, 0.44445],
2633    "8225": [0.19444, 0.69444, 0, 0, 0.44445],
2634    "8230": [0, 0.12, 0, 0, 1.172],
2635    "8242": [0, 0.55556, 0, 0, 0.275],
2636    "8407": [0, 0.71444, 0.15382, 0, 0.5],
2637    "8463": [0, 0.68889, 0, 0, 0.54028],
2638    "8465": [0, 0.69444, 0, 0, 0.72222],
2639    "8467": [0, 0.69444, 0, 0.11111, 0.41667],
2640    "8472": [0.19444, 0.43056, 0, 0.11111, 0.63646],
2641    "8476": [0, 0.69444, 0, 0, 0.72222],
2642    "8501": [0, 0.69444, 0, 0, 0.61111],
2643    "8592": [-0.13313, 0.36687, 0, 0, 1.0],
2644    "8593": [0.19444, 0.69444, 0, 0, 0.5],
2645    "8594": [-0.13313, 0.36687, 0, 0, 1.0],
2646    "8595": [0.19444, 0.69444, 0, 0, 0.5],
2647    "8596": [-0.13313, 0.36687, 0, 0, 1.0],
2648    "8597": [0.25, 0.75, 0, 0, 0.5],
2649    "8598": [0.19444, 0.69444, 0, 0, 1.0],
2650    "8599": [0.19444, 0.69444, 0, 0, 1.0],
2651    "8600": [0.19444, 0.69444, 0, 0, 1.0],
2652    "8601": [0.19444, 0.69444, 0, 0, 1.0],
2653    "8614": [0.011, 0.511, 0, 0, 1.0],
2654    "8617": [0.011, 0.511, 0, 0, 1.126],
2655    "8618": [0.011, 0.511, 0, 0, 1.126],
2656    "8636": [-0.13313, 0.36687, 0, 0, 1.0],
2657    "8637": [-0.13313, 0.36687, 0, 0, 1.0],
2658    "8640": [-0.13313, 0.36687, 0, 0, 1.0],
2659    "8641": [-0.13313, 0.36687, 0, 0, 1.0],
2660    "8652": [0.011, 0.671, 0, 0, 1.0],
2661    "8656": [-0.13313, 0.36687, 0, 0, 1.0],
2662    "8657": [0.19444, 0.69444, 0, 0, 0.61111],
2663    "8658": [-0.13313, 0.36687, 0, 0, 1.0],
2664    "8659": [0.19444, 0.69444, 0, 0, 0.61111],
2665    "8660": [-0.13313, 0.36687, 0, 0, 1.0],
2666    "8661": [0.25, 0.75, 0, 0, 0.61111],
2667    "8704": [0, 0.69444, 0, 0, 0.55556],
2668    "8706": [0, 0.69444, 0.05556, 0.08334, 0.5309],
2669    "8707": [0, 0.69444, 0, 0, 0.55556],
2670    "8709": [0.05556, 0.75, 0, 0, 0.5],
2671    "8711": [0, 0.68333, 0, 0, 0.83334],
2672    "8712": [0.0391, 0.5391, 0, 0, 0.66667],
2673    "8715": [0.0391, 0.5391, 0, 0, 0.66667],
2674    "8722": [0.08333, 0.58333, 0, 0, 0.77778],
2675    "8723": [0.08333, 0.58333, 0, 0, 0.77778],
2676    "8725": [0.25, 0.75, 0, 0, 0.5],
2677    "8726": [0.25, 0.75, 0, 0, 0.5],
2678    "8727": [-0.03472, 0.46528, 0, 0, 0.5],
2679    "8728": [-0.05555, 0.44445, 0, 0, 0.5],
2680    "8729": [-0.05555, 0.44445, 0, 0, 0.5],
2681    "8730": [0.2, 0.8, 0, 0, 0.83334],
2682    "8733": [0, 0.43056, 0, 0, 0.77778],
2683    "8734": [0, 0.43056, 0, 0, 1.0],
2684    "8736": [0, 0.69224, 0, 0, 0.72222],
2685    "8739": [0.25, 0.75, 0, 0, 0.27778],
2686    "8741": [0.25, 0.75, 0, 0, 0.5],
2687    "8743": [0, 0.55556, 0, 0, 0.66667],
2688    "8744": [0, 0.55556, 0, 0, 0.66667],
2689    "8745": [0, 0.55556, 0, 0, 0.66667],
2690    "8746": [0, 0.55556, 0, 0, 0.66667],
2691    "8747": [0.19444, 0.69444, 0.11111, 0, 0.41667],
2692    "8764": [-0.13313, 0.36687, 0, 0, 0.77778],
2693    "8768": [0.19444, 0.69444, 0, 0, 0.27778],
2694    "8771": [-0.03625, 0.46375, 0, 0, 0.77778],
2695    "8773": [-0.022, 0.589, 0, 0, 1.0],
2696    "8776": [-0.01688, 0.48312, 0, 0, 0.77778],
2697    "8781": [-0.03625, 0.46375, 0, 0, 0.77778],
2698    "8784": [-0.133, 0.67, 0, 0, 0.778],
2699    "8801": [-0.03625, 0.46375, 0, 0, 0.77778],
2700    "8804": [0.13597, 0.63597, 0, 0, 0.77778],
2701    "8805": [0.13597, 0.63597, 0, 0, 0.77778],
2702    "8810": [0.0391, 0.5391, 0, 0, 1.0],
2703    "8811": [0.0391, 0.5391, 0, 0, 1.0],
2704    "8826": [0.0391, 0.5391, 0, 0, 0.77778],
2705    "8827": [0.0391, 0.5391, 0, 0, 0.77778],
2706    "8834": [0.0391, 0.5391, 0, 0, 0.77778],
2707    "8835": [0.0391, 0.5391, 0, 0, 0.77778],
2708    "8838": [0.13597, 0.63597, 0, 0, 0.77778],
2709    "8839": [0.13597, 0.63597, 0, 0, 0.77778],
2710    "8846": [0, 0.55556, 0, 0, 0.66667],
2711    "8849": [0.13597, 0.63597, 0, 0, 0.77778],
2712    "8850": [0.13597, 0.63597, 0, 0, 0.77778],
2713    "8851": [0, 0.55556, 0, 0, 0.66667],
2714    "8852": [0, 0.55556, 0, 0, 0.66667],
2715    "8853": [0.08333, 0.58333, 0, 0, 0.77778],
2716    "8854": [0.08333, 0.58333, 0, 0, 0.77778],
2717    "8855": [0.08333, 0.58333, 0, 0, 0.77778],
2718    "8856": [0.08333, 0.58333, 0, 0, 0.77778],
2719    "8857": [0.08333, 0.58333, 0, 0, 0.77778],
2720    "8866": [0, 0.69444, 0, 0, 0.61111],
2721    "8867": [0, 0.69444, 0, 0, 0.61111],
2722    "8868": [0, 0.69444, 0, 0, 0.77778],
2723    "8869": [0, 0.69444, 0, 0, 0.77778],
2724    "8872": [0.249, 0.75, 0, 0, 0.867],
2725    "8900": [-0.05555, 0.44445, 0, 0, 0.5],
2726    "8901": [-0.05555, 0.44445, 0, 0, 0.27778],
2727    "8902": [-0.03472, 0.46528, 0, 0, 0.5],
2728    "8904": [0.005, 0.505, 0, 0, 0.9],
2729    "8942": [0.03, 0.9, 0, 0, 0.278],
2730    "8943": [-0.19, 0.31, 0, 0, 1.172],
2731    "8945": [-0.1, 0.82, 0, 0, 1.282],
2732    "8968": [0.25, 0.75, 0, 0, 0.44445],
2733    "8969": [0.25, 0.75, 0, 0, 0.44445],
2734    "8970": [0.25, 0.75, 0, 0, 0.44445],
2735    "8971": [0.25, 0.75, 0, 0, 0.44445],
2736    "8994": [-0.14236, 0.35764, 0, 0, 1.0],
2737    "8995": [-0.14236, 0.35764, 0, 0, 1.0],
2738    "9136": [0.244, 0.744, 0, 0, 0.412],
2739    "9137": [0.244, 0.744, 0, 0, 0.412],
2740    "9651": [0.19444, 0.69444, 0, 0, 0.88889],
2741    "9657": [-0.03472, 0.46528, 0, 0, 0.5],
2742    "9661": [0.19444, 0.69444, 0, 0, 0.88889],
2743    "9667": [-0.03472, 0.46528, 0, 0, 0.5],
2744    "9711": [0.19444, 0.69444, 0, 0, 1.0],
2745    "9824": [0.12963, 0.69444, 0, 0, 0.77778],
2746    "9825": [0.12963, 0.69444, 0, 0, 0.77778],
2747    "9826": [0.12963, 0.69444, 0, 0, 0.77778],
2748    "9827": [0.12963, 0.69444, 0, 0, 0.77778],
2749    "9837": [0, 0.75, 0, 0, 0.38889],
2750    "9838": [0.19444, 0.69444, 0, 0, 0.38889],
2751    "9839": [0.19444, 0.69444, 0, 0, 0.38889],
2752    "10216": [0.25, 0.75, 0, 0, 0.38889],
2753    "10217": [0.25, 0.75, 0, 0, 0.38889],
2754    "10222": [0.244, 0.744, 0, 0, 0.412],
2755    "10223": [0.244, 0.744, 0, 0, 0.412],
2756    "10229": [0.011, 0.511, 0, 0, 1.609],
2757    "10230": [0.011, 0.511, 0, 0, 1.638],
2758    "10231": [0.011, 0.511, 0, 0, 1.859],
2759    "10232": [0.024, 0.525, 0, 0, 1.609],
2760    "10233": [0.024, 0.525, 0, 0, 1.638],
2761    "10234": [0.024, 0.525, 0, 0, 1.858],
2762    "10236": [0.011, 0.511, 0, 0, 1.638],
2763    "10815": [0, 0.68333, 0, 0, 0.75],
2764    "10927": [0.13597, 0.63597, 0, 0, 0.77778],
2765    "10928": [0.13597, 0.63597, 0, 0, 0.77778],
2766    "57376": [0.19444, 0.69444, 0, 0, 0]
2767  },
2768  "Math-BoldItalic": {
2769    "65": [0, 0.68611, 0, 0, 0.86944],
2770    "66": [0, 0.68611, 0.04835, 0, 0.8664],
2771    "67": [0, 0.68611, 0.06979, 0, 0.81694],
2772    "68": [0, 0.68611, 0.03194, 0, 0.93812],
2773    "69": [0, 0.68611, 0.05451, 0, 0.81007],
2774    "70": [0, 0.68611, 0.15972, 0, 0.68889],
2775    "71": [0, 0.68611, 0, 0, 0.88673],
2776    "72": [0, 0.68611, 0.08229, 0, 0.98229],
2777    "73": [0, 0.68611, 0.07778, 0, 0.51111],
2778    "74": [0, 0.68611, 0.10069, 0, 0.63125],
2779    "75": [0, 0.68611, 0.06979, 0, 0.97118],
2780    "76": [0, 0.68611, 0, 0, 0.75555],
2781    "77": [0, 0.68611, 0.11424, 0, 1.14201],
2782    "78": [0, 0.68611, 0.11424, 0, 0.95034],
2783    "79": [0, 0.68611, 0.03194, 0, 0.83666],
2784    "80": [0, 0.68611, 0.15972, 0, 0.72309],
2785    "81": [0.19444, 0.68611, 0, 0, 0.86861],
2786    "82": [0, 0.68611, 0.00421, 0, 0.87235],
2787    "83": [0, 0.68611, 0.05382, 0, 0.69271],
2788    "84": [0, 0.68611, 0.15972, 0, 0.63663],
2789    "85": [0, 0.68611, 0.11424, 0, 0.80027],
2790    "86": [0, 0.68611, 0.25555, 0, 0.67778],
2791    "87": [0, 0.68611, 0.15972, 0, 1.09305],
2792    "88": [0, 0.68611, 0.07778, 0, 0.94722],
2793    "89": [0, 0.68611, 0.25555, 0, 0.67458],
2794    "90": [0, 0.68611, 0.06979, 0, 0.77257],
2795    "97": [0, 0.44444, 0, 0, 0.63287],
2796    "98": [0, 0.69444, 0, 0, 0.52083],
2797    "99": [0, 0.44444, 0, 0, 0.51342],
2798    "100": [0, 0.69444, 0, 0, 0.60972],
2799    "101": [0, 0.44444, 0, 0, 0.55361],
2800    "102": [0.19444, 0.69444, 0.11042, 0, 0.56806],
2801    "103": [0.19444, 0.44444, 0.03704, 0, 0.5449],
2802    "104": [0, 0.69444, 0, 0, 0.66759],
2803    "105": [0, 0.69326, 0, 0, 0.4048],
2804    "106": [0.19444, 0.69326, 0.0622, 0, 0.47083],
2805    "107": [0, 0.69444, 0.01852, 0, 0.6037],
2806    "108": [0, 0.69444, 0.0088, 0, 0.34815],
2807    "109": [0, 0.44444, 0, 0, 1.0324],
2808    "110": [0, 0.44444, 0, 0, 0.71296],
2809    "111": [0, 0.44444, 0, 0, 0.58472],
2810    "112": [0.19444, 0.44444, 0, 0, 0.60092],
2811    "113": [0.19444, 0.44444, 0.03704, 0, 0.54213],
2812    "114": [0, 0.44444, 0.03194, 0, 0.5287],
2813    "115": [0, 0.44444, 0, 0, 0.53125],
2814    "116": [0, 0.63492, 0, 0, 0.41528],
2815    "117": [0, 0.44444, 0, 0, 0.68102],
2816    "118": [0, 0.44444, 0.03704, 0, 0.56666],
2817    "119": [0, 0.44444, 0.02778, 0, 0.83148],
2818    "120": [0, 0.44444, 0, 0, 0.65903],
2819    "121": [0.19444, 0.44444, 0.03704, 0, 0.59028],
2820    "122": [0, 0.44444, 0.04213, 0, 0.55509],
2821    "915": [0, 0.68611, 0.15972, 0, 0.65694],
2822    "916": [0, 0.68611, 0, 0, 0.95833],
2823    "920": [0, 0.68611, 0.03194, 0, 0.86722],
2824    "923": [0, 0.68611, 0, 0, 0.80555],
2825    "926": [0, 0.68611, 0.07458, 0, 0.84125],
2826    "928": [0, 0.68611, 0.08229, 0, 0.98229],
2827    "931": [0, 0.68611, 0.05451, 0, 0.88507],
2828    "933": [0, 0.68611, 0.15972, 0, 0.67083],
2829    "934": [0, 0.68611, 0, 0, 0.76666],
2830    "936": [0, 0.68611, 0.11653, 0, 0.71402],
2831    "937": [0, 0.68611, 0.04835, 0, 0.8789],
2832    "945": [0, 0.44444, 0, 0, 0.76064],
2833    "946": [0.19444, 0.69444, 0.03403, 0, 0.65972],
2834    "947": [0.19444, 0.44444, 0.06389, 0, 0.59003],
2835    "948": [0, 0.69444, 0.03819, 0, 0.52222],
2836    "949": [0, 0.44444, 0, 0, 0.52882],
2837    "950": [0.19444, 0.69444, 0.06215, 0, 0.50833],
2838    "951": [0.19444, 0.44444, 0.03704, 0, 0.6],
2839    "952": [0, 0.69444, 0.03194, 0, 0.5618],
2840    "953": [0, 0.44444, 0, 0, 0.41204],
2841    "954": [0, 0.44444, 0, 0, 0.66759],
2842    "955": [0, 0.69444, 0, 0, 0.67083],
2843    "956": [0.19444, 0.44444, 0, 0, 0.70787],
2844    "957": [0, 0.44444, 0.06898, 0, 0.57685],
2845    "958": [0.19444, 0.69444, 0.03021, 0, 0.50833],
2846    "959": [0, 0.44444, 0, 0, 0.58472],
2847    "960": [0, 0.44444, 0.03704, 0, 0.68241],
2848    "961": [0.19444, 0.44444, 0, 0, 0.6118],
2849    "962": [0.09722, 0.44444, 0.07917, 0, 0.42361],
2850    "963": [0, 0.44444, 0.03704, 0, 0.68588],
2851    "964": [0, 0.44444, 0.13472, 0, 0.52083],
2852    "965": [0, 0.44444, 0.03704, 0, 0.63055],
2853    "966": [0.19444, 0.44444, 0, 0, 0.74722],
2854    "967": [0.19444, 0.44444, 0, 0, 0.71805],
2855    "968": [0.19444, 0.69444, 0.03704, 0, 0.75833],
2856    "969": [0, 0.44444, 0.03704, 0, 0.71782],
2857    "977": [0, 0.69444, 0, 0, 0.69155],
2858    "981": [0.19444, 0.69444, 0, 0, 0.7125],
2859    "982": [0, 0.44444, 0.03194, 0, 0.975],
2860    "1009": [0.19444, 0.44444, 0, 0, 0.6118],
2861    "1013": [0, 0.44444, 0, 0, 0.48333]
2862  },
2863  "Math-Italic": {
2864    "65": [0, 0.68333, 0, 0.13889, 0.75],
2865    "66": [0, 0.68333, 0.05017, 0.08334, 0.75851],
2866    "67": [0, 0.68333, 0.07153, 0.08334, 0.71472],
2867    "68": [0, 0.68333, 0.02778, 0.05556, 0.82792],
2868    "69": [0, 0.68333, 0.05764, 0.08334, 0.7382],
2869    "70": [0, 0.68333, 0.13889, 0.08334, 0.64306],
2870    "71": [0, 0.68333, 0, 0.08334, 0.78625],
2871    "72": [0, 0.68333, 0.08125, 0.05556, 0.83125],
2872    "73": [0, 0.68333, 0.07847, 0.11111, 0.43958],
2873    "74": [0, 0.68333, 0.09618, 0.16667, 0.55451],
2874    "75": [0, 0.68333, 0.07153, 0.05556, 0.84931],
2875    "76": [0, 0.68333, 0, 0.02778, 0.68056],
2876    "77": [0, 0.68333, 0.10903, 0.08334, 0.97014],
2877    "78": [0, 0.68333, 0.10903, 0.08334, 0.80347],
2878    "79": [0, 0.68333, 0.02778, 0.08334, 0.76278],
2879    "80": [0, 0.68333, 0.13889, 0.08334, 0.64201],
2880    "81": [0.19444, 0.68333, 0, 0.08334, 0.79056],
2881    "82": [0, 0.68333, 0.00773, 0.08334, 0.75929],
2882    "83": [0, 0.68333, 0.05764, 0.08334, 0.6132],
2883    "84": [0, 0.68333, 0.13889, 0.08334, 0.58438],
2884    "85": [0, 0.68333, 0.10903, 0.02778, 0.68278],
2885    "86": [0, 0.68333, 0.22222, 0, 0.58333],
2886    "87": [0, 0.68333, 0.13889, 0, 0.94445],
2887    "88": [0, 0.68333, 0.07847, 0.08334, 0.82847],
2888    "89": [0, 0.68333, 0.22222, 0, 0.58056],
2889    "90": [0, 0.68333, 0.07153, 0.08334, 0.68264],
2890    "97": [0, 0.43056, 0, 0, 0.52859],
2891    "98": [0, 0.69444, 0, 0, 0.42917],
2892    "99": [0, 0.43056, 0, 0.05556, 0.43276],
2893    "100": [0, 0.69444, 0, 0.16667, 0.52049],
2894    "101": [0, 0.43056, 0, 0.05556, 0.46563],
2895    "102": [0.19444, 0.69444, 0.10764, 0.16667, 0.48959],
2896    "103": [0.19444, 0.43056, 0.03588, 0.02778, 0.47697],
2897    "104": [0, 0.69444, 0, 0, 0.57616],
2898    "105": [0, 0.65952, 0, 0, 0.34451],
2899    "106": [0.19444, 0.65952, 0.05724, 0, 0.41181],
2900    "107": [0, 0.69444, 0.03148, 0, 0.5206],
2901    "108": [0, 0.69444, 0.01968, 0.08334, 0.29838],
2902    "109": [0, 0.43056, 0, 0, 0.87801],
2903    "110": [0, 0.43056, 0, 0, 0.60023],
2904    "111": [0, 0.43056, 0, 0.05556, 0.48472],
2905    "112": [0.19444, 0.43056, 0, 0.08334, 0.50313],
2906    "113": [0.19444, 0.43056, 0.03588, 0.08334, 0.44641],
2907    "114": [0, 0.43056, 0.02778, 0.05556, 0.45116],
2908    "115": [0, 0.43056, 0, 0.05556, 0.46875],
2909    "116": [0, 0.61508, 0, 0.08334, 0.36111],
2910    "117": [0, 0.43056, 0, 0.02778, 0.57246],
2911    "118": [0, 0.43056, 0.03588, 0.02778, 0.48472],
2912    "119": [0, 0.43056, 0.02691, 0.08334, 0.71592],
2913    "120": [0, 0.43056, 0, 0.02778, 0.57153],
2914    "121": [0.19444, 0.43056, 0.03588, 0.05556, 0.49028],
2915    "122": [0, 0.43056, 0.04398, 0.05556, 0.46505],
2916    "915": [0, 0.68333, 0.13889, 0.08334, 0.61528],
2917    "916": [0, 0.68333, 0, 0.16667, 0.83334],
2918    "920": [0, 0.68333, 0.02778, 0.08334, 0.76278],
2919    "923": [0, 0.68333, 0, 0.16667, 0.69445],
2920    "926": [0, 0.68333, 0.07569, 0.08334, 0.74236],
2921    "928": [0, 0.68333, 0.08125, 0.05556, 0.83125],
2922    "931": [0, 0.68333, 0.05764, 0.08334, 0.77986],
2923    "933": [0, 0.68333, 0.13889, 0.05556, 0.58333],
2924    "934": [0, 0.68333, 0, 0.08334, 0.66667],
2925    "936": [0, 0.68333, 0.11, 0.05556, 0.61222],
2926    "937": [0, 0.68333, 0.05017, 0.08334, 0.7724],
2927    "945": [0, 0.43056, 0.0037, 0.02778, 0.6397],
2928    "946": [0.19444, 0.69444, 0.05278, 0.08334, 0.56563],
2929    "947": [0.19444, 0.43056, 0.05556, 0, 0.51773],
2930    "948": [0, 0.69444, 0.03785, 0.05556, 0.44444],
2931    "949": [0, 0.43056, 0, 0.08334, 0.46632],
2932    "950": [0.19444, 0.69444, 0.07378, 0.08334, 0.4375],
2933    "951": [0.19444, 0.43056, 0.03588, 0.05556, 0.49653],
2934    "952": [0, 0.69444, 0.02778, 0.08334, 0.46944],
2935    "953": [0, 0.43056, 0, 0.05556, 0.35394],
2936    "954": [0, 0.43056, 0, 0, 0.57616],
2937    "955": [0, 0.69444, 0, 0, 0.58334],
2938    "956": [0.19444, 0.43056, 0, 0.02778, 0.60255],
2939    "957": [0, 0.43056, 0.06366, 0.02778, 0.49398],
2940    "958": [0.19444, 0.69444, 0.04601, 0.11111, 0.4375],
2941    "959": [0, 0.43056, 0, 0.05556, 0.48472],
2942    "960": [0, 0.43056, 0.03588, 0, 0.57003],
2943    "961": [0.19444, 0.43056, 0, 0.08334, 0.51702],
2944    "962": [0.09722, 0.43056, 0.07986, 0.08334, 0.36285],
2945    "963": [0, 0.43056, 0.03588, 0, 0.57141],
2946    "964": [0, 0.43056, 0.1132, 0.02778, 0.43715],
2947    "965": [0, 0.43056, 0.03588, 0.02778, 0.54028],
2948    "966": [0.19444, 0.43056, 0, 0.08334, 0.65417],
2949    "967": [0.19444, 0.43056, 0, 0.05556, 0.62569],
2950    "968": [0.19444, 0.69444, 0.03588, 0.11111, 0.65139],
2951    "969": [0, 0.43056, 0.03588, 0, 0.62245],
2952    "977": [0, 0.69444, 0, 0.08334, 0.59144],
2953    "981": [0.19444, 0.69444, 0, 0.08334, 0.59583],
2954    "982": [0, 0.43056, 0.02778, 0, 0.82813],
2955    "1009": [0.19444, 0.43056, 0, 0.08334, 0.51702],
2956    "1013": [0, 0.43056, 0, 0.05556, 0.4059]
2957  },
2958  "Math-Regular": {
2959    "65": [0, 0.68333, 0, 0.13889, 0.75],
2960    "66": [0, 0.68333, 0.05017, 0.08334, 0.75851],
2961    "67": [0, 0.68333, 0.07153, 0.08334, 0.71472],
2962    "68": [0, 0.68333, 0.02778, 0.05556, 0.82792],
2963    "69": [0, 0.68333, 0.05764, 0.08334, 0.7382],
2964    "70": [0, 0.68333, 0.13889, 0.08334, 0.64306],
2965    "71": [0, 0.68333, 0, 0.08334, 0.78625],
2966    "72": [0, 0.68333, 0.08125, 0.05556, 0.83125],
2967    "73": [0, 0.68333, 0.07847, 0.11111, 0.43958],
2968    "74": [0, 0.68333, 0.09618, 0.16667, 0.55451],
2969    "75": [0, 0.68333, 0.07153, 0.05556, 0.84931],
2970    "76": [0, 0.68333, 0, 0.02778, 0.68056],
2971    "77": [0, 0.68333, 0.10903, 0.08334, 0.97014],
2972    "78": [0, 0.68333, 0.10903, 0.08334, 0.80347],
2973    "79": [0, 0.68333, 0.02778, 0.08334, 0.76278],
2974    "80": [0, 0.68333, 0.13889, 0.08334, 0.64201],
2975    "81": [0.19444, 0.68333, 0, 0.08334, 0.79056],
2976    "82": [0, 0.68333, 0.00773, 0.08334, 0.75929],
2977    "83": [0, 0.68333, 0.05764, 0.08334, 0.6132],
2978    "84": [0, 0.68333, 0.13889, 0.08334, 0.58438],
2979    "85": [0, 0.68333, 0.10903, 0.02778, 0.68278],
2980    "86": [0, 0.68333, 0.22222, 0, 0.58333],
2981    "87": [0, 0.68333, 0.13889, 0, 0.94445],
2982    "88": [0, 0.68333, 0.07847, 0.08334, 0.82847],
2983    "89": [0, 0.68333, 0.22222, 0, 0.58056],
2984    "90": [0, 0.68333, 0.07153, 0.08334, 0.68264],
2985    "97": [0, 0.43056, 0, 0, 0.52859],
2986    "98": [0, 0.69444, 0, 0, 0.42917],
2987    "99": [0, 0.43056, 0, 0.05556, 0.43276],
2988    "100": [0, 0.69444, 0, 0.16667, 0.52049],
2989    "101": [0, 0.43056, 0, 0.05556, 0.46563],
2990    "102": [0.19444, 0.69444, 0.10764, 0.16667, 0.48959],
2991    "103": [0.19444, 0.43056, 0.03588, 0.02778, 0.47697],
2992    "104": [0, 0.69444, 0, 0, 0.57616],
2993    "105": [0, 0.65952, 0, 0, 0.34451],
2994    "106": [0.19444, 0.65952, 0.05724, 0, 0.41181],
2995    "107": [0, 0.69444, 0.03148, 0, 0.5206],
2996    "108": [0, 0.69444, 0.01968, 0.08334, 0.29838],
2997    "109": [0, 0.43056, 0, 0, 0.87801],
2998    "110": [0, 0.43056, 0, 0, 0.60023],
2999    "111": [0, 0.43056, 0, 0.05556, 0.48472],
3000    "112": [0.19444, 0.43056, 0, 0.08334, 0.50313],
3001    "113": [0.19444, 0.43056, 0.03588, 0.08334, 0.44641],
3002    "114": [0, 0.43056, 0.02778, 0.05556, 0.45116],
3003    "115": [0, 0.43056, 0, 0.05556, 0.46875],
3004    "116": [0, 0.61508, 0, 0.08334, 0.36111],
3005    "117": [0, 0.43056, 0, 0.02778, 0.57246],
3006    "118": [0, 0.43056, 0.03588, 0.02778, 0.48472],
3007    "119": [0, 0.43056, 0.02691, 0.08334, 0.71592],
3008    "120": [0, 0.43056, 0, 0.02778, 0.57153],
3009    "121": [0.19444, 0.43056, 0.03588, 0.05556, 0.49028],
3010    "122": [0, 0.43056, 0.04398, 0.05556, 0.46505],
3011    "915": [0, 0.68333, 0.13889, 0.08334, 0.61528],
3012    "916": [0, 0.68333, 0, 0.16667, 0.83334],
3013    "920": [0, 0.68333, 0.02778, 0.08334, 0.76278],
3014    "923": [0, 0.68333, 0, 0.16667, 0.69445],
3015    "926": [0, 0.68333, 0.07569, 0.08334, 0.74236],
3016    "928": [0, 0.68333, 0.08125, 0.05556, 0.83125],
3017    "931": [0, 0.68333, 0.05764, 0.08334, 0.77986],
3018    "933": [0, 0.68333, 0.13889, 0.05556, 0.58333],
3019    "934": [0, 0.68333, 0, 0.08334, 0.66667],
3020    "936": [0, 0.68333, 0.11, 0.05556, 0.61222],
3021    "937": [0, 0.68333, 0.05017, 0.08334, 0.7724],
3022    "945": [0, 0.43056, 0.0037, 0.02778, 0.6397],
3023    "946": [0.19444, 0.69444, 0.05278, 0.08334, 0.56563],
3024    "947": [0.19444, 0.43056, 0.05556, 0, 0.51773],
3025    "948": [0, 0.69444, 0.03785, 0.05556, 0.44444],
3026    "949": [0, 0.43056, 0, 0.08334, 0.46632],
3027    "950": [0.19444, 0.69444, 0.07378, 0.08334, 0.4375],
3028    "951": [0.19444, 0.43056, 0.03588, 0.05556, 0.49653],
3029    "952": [0, 0.69444, 0.02778, 0.08334, 0.46944],
3030    "953": [0, 0.43056, 0, 0.05556, 0.35394],
3031    "954": [0, 0.43056, 0, 0, 0.57616],
3032    "955": [0, 0.69444, 0, 0, 0.58334],
3033    "956": [0.19444, 0.43056, 0, 0.02778, 0.60255],
3034    "957": [0, 0.43056, 0.06366, 0.02778, 0.49398],
3035    "958": [0.19444, 0.69444, 0.04601, 0.11111, 0.4375],
3036    "959": [0, 0.43056, 0, 0.05556, 0.48472],
3037    "960": [0, 0.43056, 0.03588, 0, 0.57003],
3038    "961": [0.19444, 0.43056, 0, 0.08334, 0.51702],
3039    "962": [0.09722, 0.43056, 0.07986, 0.08334, 0.36285],
3040    "963": [0, 0.43056, 0.03588, 0, 0.57141],
3041    "964": [0, 0.43056, 0.1132, 0.02778, 0.43715],
3042    "965": [0, 0.43056, 0.03588, 0.02778, 0.54028],
3043    "966": [0.19444, 0.43056, 0, 0.08334, 0.65417],
3044    "967": [0.19444, 0.43056, 0, 0.05556, 0.62569],
3045    "968": [0.19444, 0.69444, 0.03588, 0.11111, 0.65139],
3046    "969": [0, 0.43056, 0.03588, 0, 0.62245],
3047    "977": [0, 0.69444, 0, 0.08334, 0.59144],
3048    "981": [0.19444, 0.69444, 0, 0.08334, 0.59583],
3049    "982": [0, 0.43056, 0.02778, 0, 0.82813],
3050    "1009": [0.19444, 0.43056, 0, 0.08334, 0.51702],
3051    "1013": [0, 0.43056, 0, 0.05556, 0.4059]
3052  },
3053  "SansSerif-Bold": {
3054    "33": [0, 0.69444, 0, 0, 0.36667],
3055    "34": [0, 0.69444, 0, 0, 0.55834],
3056    "35": [0.19444, 0.69444, 0, 0, 0.91667],
3057    "36": [0.05556, 0.75, 0, 0, 0.55],
3058    "37": [0.05556, 0.75, 0, 0, 1.02912],
3059    "38": [0, 0.69444, 0, 0, 0.83056],
3060    "39": [0, 0.69444, 0, 0, 0.30556],
3061    "40": [0.25, 0.75, 0, 0, 0.42778],
3062    "41": [0.25, 0.75, 0, 0, 0.42778],
3063    "42": [0, 0.75, 0, 0, 0.55],
3064    "43": [0.11667, 0.61667, 0, 0, 0.85556],
3065    "44": [0.10556, 0.13056, 0, 0, 0.30556],
3066    "45": [0, 0.45833, 0, 0, 0.36667],
3067    "46": [0, 0.13056, 0, 0, 0.30556],
3068    "47": [0.25, 0.75, 0, 0, 0.55],
3069    "48": [0, 0.69444, 0, 0, 0.55],
3070    "49": [0, 0.69444, 0, 0, 0.55],
3071    "50": [0, 0.69444, 0, 0, 0.55],
3072    "51": [0, 0.69444, 0, 0, 0.55],
3073    "52": [0, 0.69444, 0, 0, 0.55],
3074    "53": [0, 0.69444, 0, 0, 0.55],
3075    "54": [0, 0.69444, 0, 0, 0.55],
3076    "55": [0, 0.69444, 0, 0, 0.55],
3077    "56": [0, 0.69444, 0, 0, 0.55],
3078    "57": [0, 0.69444, 0, 0, 0.55],
3079    "58": [0, 0.45833, 0, 0, 0.30556],
3080    "59": [0.10556, 0.45833, 0, 0, 0.30556],
3081    "61": [-0.09375, 0.40625, 0, 0, 0.85556],
3082    "63": [0, 0.69444, 0, 0, 0.51945],
3083    "64": [0, 0.69444, 0, 0, 0.73334],
3084    "65": [0, 0.69444, 0, 0, 0.73334],
3085    "66": [0, 0.69444, 0, 0, 0.73334],
3086    "67": [0, 0.69444, 0, 0, 0.70278],
3087    "68": [0, 0.69444, 0, 0, 0.79445],
3088    "69": [0, 0.69444, 0, 0, 0.64167],
3089    "70": [0, 0.69444, 0, 0, 0.61111],
3090    "71": [0, 0.69444, 0, 0, 0.73334],
3091    "72": [0, 0.69444, 0, 0, 0.79445],
3092    "73": [0, 0.69444, 0, 0, 0.33056],
3093    "74": [0, 0.69444, 0, 0, 0.51945],
3094    "75": [0, 0.69444, 0, 0, 0.76389],
3095    "76": [0, 0.69444, 0, 0, 0.58056],
3096    "77": [0, 0.69444, 0, 0, 0.97778],
3097    "78": [0, 0.69444, 0, 0, 0.79445],
3098    "79": [0, 0.69444, 0, 0, 0.79445],
3099    "80": [0, 0.69444, 0, 0, 0.70278],
3100    "81": [0.10556, 0.69444, 0, 0, 0.79445],
3101    "82": [0, 0.69444, 0, 0, 0.70278],
3102    "83": [0, 0.69444, 0, 0, 0.61111],
3103    "84": [0, 0.69444, 0, 0, 0.73334],
3104    "85": [0, 0.69444, 0, 0, 0.76389],
3105    "86": [0, 0.69444, 0.01528, 0, 0.73334],
3106    "87": [0, 0.69444, 0.01528, 0, 1.03889],
3107    "88": [0, 0.69444, 0, 0, 0.73334],
3108    "89": [0, 0.69444, 0.0275, 0, 0.73334],
3109    "90": [0, 0.69444, 0, 0, 0.67223],
3110    "91": [0.25, 0.75, 0, 0, 0.34306],
3111    "93": [0.25, 0.75, 0, 0, 0.34306],
3112    "94": [0, 0.69444, 0, 0, 0.55],
3113    "95": [0.35, 0.10833, 0.03056, 0, 0.55],
3114    "97": [0, 0.45833, 0, 0, 0.525],
3115    "98": [0, 0.69444, 0, 0, 0.56111],
3116    "99": [0, 0.45833, 0, 0, 0.48889],
3117    "100": [0, 0.69444, 0, 0, 0.56111],
3118    "101": [0, 0.45833, 0, 0, 0.51111],
3119    "102": [0, 0.69444, 0.07639, 0, 0.33611],
3120    "103": [0.19444, 0.45833, 0.01528, 0, 0.55],
3121    "104": [0, 0.69444, 0, 0, 0.56111],
3122    "105": [0, 0.69444, 0, 0, 0.25556],
3123    "106": [0.19444, 0.69444, 0, 0, 0.28611],
3124    "107": [0, 0.69444, 0, 0, 0.53056],
3125    "108": [0, 0.69444, 0, 0, 0.25556],
3126    "109": [0, 0.45833, 0, 0, 0.86667],
3127    "110": [0, 0.45833, 0, 0, 0.56111],
3128    "111": [0, 0.45833, 0, 0, 0.55],
3129    "112": [0.19444, 0.45833, 0, 0, 0.56111],
3130    "113": [0.19444, 0.45833, 0, 0, 0.56111],
3131    "114": [0, 0.45833, 0.01528, 0, 0.37222],
3132    "115": [0, 0.45833, 0, 0, 0.42167],
3133    "116": [0, 0.58929, 0, 0, 0.40417],
3134    "117": [0, 0.45833, 0, 0, 0.56111],
3135    "118": [0, 0.45833, 0.01528, 0, 0.5],
3136    "119": [0, 0.45833, 0.01528, 0, 0.74445],
3137    "120": [0, 0.45833, 0, 0, 0.5],
3138    "121": [0.19444, 0.45833, 0.01528, 0, 0.5],
3139    "122": [0, 0.45833, 0, 0, 0.47639],
3140    "126": [0.35, 0.34444, 0, 0, 0.55],
3141    "168": [0, 0.69444, 0, 0, 0.55],
3142    "176": [0, 0.69444, 0, 0, 0.73334],
3143    "180": [0, 0.69444, 0, 0, 0.55],
3144    "184": [0.17014, 0, 0, 0, 0.48889],
3145    "305": [0, 0.45833, 0, 0, 0.25556],
3146    "567": [0.19444, 0.45833, 0, 0, 0.28611],
3147    "710": [0, 0.69444, 0, 0, 0.55],
3148    "711": [0, 0.63542, 0, 0, 0.55],
3149    "713": [0, 0.63778, 0, 0, 0.55],
3150    "728": [0, 0.69444, 0, 0, 0.55],
3151    "729": [0, 0.69444, 0, 0, 0.30556],
3152    "730": [0, 0.69444, 0, 0, 0.73334],
3153    "732": [0, 0.69444, 0, 0, 0.55],
3154    "733": [0, 0.69444, 0, 0, 0.55],
3155    "915": [0, 0.69444, 0, 0, 0.58056],
3156    "916": [0, 0.69444, 0, 0, 0.91667],
3157    "920": [0, 0.69444, 0, 0, 0.85556],
3158    "923": [0, 0.69444, 0, 0, 0.67223],
3159    "926": [0, 0.69444, 0, 0, 0.73334],
3160    "928": [0, 0.69444, 0, 0, 0.79445],
3161    "931": [0, 0.69444, 0, 0, 0.79445],
3162    "933": [0, 0.69444, 0, 0, 0.85556],
3163    "934": [0, 0.69444, 0, 0, 0.79445],
3164    "936": [0, 0.69444, 0, 0, 0.85556],
3165    "937": [0, 0.69444, 0, 0, 0.79445],
3166    "8211": [0, 0.45833, 0.03056, 0, 0.55],
3167    "8212": [0, 0.45833, 0.03056, 0, 1.10001],
3168    "8216": [0, 0.69444, 0, 0, 0.30556],
3169    "8217": [0, 0.69444, 0, 0, 0.30556],
3170    "8220": [0, 0.69444, 0, 0, 0.55834],
3171    "8221": [0, 0.69444, 0, 0, 0.55834]
3172  },
3173  "SansSerif-Italic": {
3174    "33": [0, 0.69444, 0.05733, 0, 0.31945],
3175    "34": [0, 0.69444, 0.00316, 0, 0.5],
3176    "35": [0.19444, 0.69444, 0.05087, 0, 0.83334],
3177    "36": [0.05556, 0.75, 0.11156, 0, 0.5],
3178    "37": [0.05556, 0.75, 0.03126, 0, 0.83334],
3179    "38": [0, 0.69444, 0.03058, 0, 0.75834],
3180    "39": [0, 0.69444, 0.07816, 0, 0.27778],
3181    "40": [0.25, 0.75, 0.13164, 0, 0.38889],
3182    "41": [0.25, 0.75, 0.02536, 0, 0.38889],
3183    "42": [0, 0.75, 0.11775, 0, 0.5],
3184    "43": [0.08333, 0.58333, 0.02536, 0, 0.77778],
3185    "44": [0.125, 0.08333, 0, 0, 0.27778],
3186    "45": [0, 0.44444, 0.01946, 0, 0.33333],
3187    "46": [0, 0.08333, 0, 0, 0.27778],
3188    "47": [0.25, 0.75, 0.13164, 0, 0.5],
3189    "48": [0, 0.65556, 0.11156, 0, 0.5],
3190    "49": [0, 0.65556, 0.11156, 0, 0.5],
3191    "50": [0, 0.65556, 0.11156, 0, 0.5],
3192    "51": [0, 0.65556, 0.11156, 0, 0.5],
3193    "52": [0, 0.65556, 0.11156, 0, 0.5],
3194    "53": [0, 0.65556, 0.11156, 0, 0.5],
3195    "54": [0, 0.65556, 0.11156, 0, 0.5],
3196    "55": [0, 0.65556, 0.11156, 0, 0.5],
3197    "56": [0, 0.65556, 0.11156, 0, 0.5],
3198    "57": [0, 0.65556, 0.11156, 0, 0.5],
3199    "58": [0, 0.44444, 0.02502, 0, 0.27778],
3200    "59": [0.125, 0.44444, 0.02502, 0, 0.27778],
3201    "61": [-0.13, 0.37, 0.05087, 0, 0.77778],
3202    "63": [0, 0.69444, 0.11809, 0, 0.47222],
3203    "64": [0, 0.69444, 0.07555, 0, 0.66667],
3204    "65": [0, 0.69444, 0, 0, 0.66667],
3205    "66": [0, 0.69444, 0.08293, 0, 0.66667],
3206    "67": [0, 0.69444, 0.11983, 0, 0.63889],
3207    "68": [0, 0.69444, 0.07555, 0, 0.72223],
3208    "69": [0, 0.69444, 0.11983, 0, 0.59722],
3209    "70": [0, 0.69444, 0.13372, 0, 0.56945],
3210    "71": [0, 0.69444, 0.11983, 0, 0.66667],
3211    "72": [0, 0.69444, 0.08094, 0, 0.70834],
3212    "73": [0, 0.69444, 0.13372, 0, 0.27778],
3213    "74": [0, 0.69444, 0.08094, 0, 0.47222],
3214    "75": [0, 0.69444, 0.11983, 0, 0.69445],
3215    "76": [0, 0.69444, 0, 0, 0.54167],
3216    "77": [0, 0.69444, 0.08094, 0, 0.875],
3217    "78": [0, 0.69444, 0.08094, 0, 0.70834],
3218    "79": [0, 0.69444, 0.07555, 0, 0.73611],
3219    "80": [0, 0.69444, 0.08293, 0, 0.63889],
3220    "81": [0.125, 0.69444, 0.07555, 0, 0.73611],
3221    "82": [0, 0.69444, 0.08293, 0, 0.64584],
3222    "83": [0, 0.69444, 0.09205, 0, 0.55556],
3223    "84": [0, 0.69444, 0.13372, 0, 0.68056],
3224    "85": [0, 0.69444, 0.08094, 0, 0.6875],
3225    "86": [0, 0.69444, 0.1615, 0, 0.66667],
3226    "87": [0, 0.69444, 0.1615, 0, 0.94445],
3227    "88": [0, 0.69444, 0.13372, 0, 0.66667],
3228    "89": [0, 0.69444, 0.17261, 0, 0.66667],
3229    "90": [0, 0.69444, 0.11983, 0, 0.61111],
3230    "91": [0.25, 0.75, 0.15942, 0, 0.28889],
3231    "93": [0.25, 0.75, 0.08719, 0, 0.28889],
3232    "94": [0, 0.69444, 0.0799, 0, 0.5],
3233    "95": [0.35, 0.09444, 0.08616, 0, 0.5],
3234    "97": [0, 0.44444, 0.00981, 0, 0.48056],
3235    "98": [0, 0.69444, 0.03057, 0, 0.51667],
3236    "99": [0, 0.44444, 0.08336, 0, 0.44445],
3237    "100": [0, 0.69444, 0.09483, 0, 0.51667],
3238    "101": [0, 0.44444, 0.06778, 0, 0.44445],
3239    "102": [0, 0.69444, 0.21705, 0, 0.30556],
3240    "103": [0.19444, 0.44444, 0.10836, 0, 0.5],
3241    "104": [0, 0.69444, 0.01778, 0, 0.51667],
3242    "105": [0, 0.67937, 0.09718, 0, 0.23889],
3243    "106": [0.19444, 0.67937, 0.09162, 0, 0.26667],
3244    "107": [0, 0.69444, 0.08336, 0, 0.48889],
3245    "108": [0, 0.69444, 0.09483, 0, 0.23889],
3246    "109": [0, 0.44444, 0.01778, 0, 0.79445],
3247    "110": [0, 0.44444, 0.01778, 0, 0.51667],
3248    "111": [0, 0.44444, 0.06613, 0, 0.5],
3249    "112": [0.19444, 0.44444, 0.0389, 0, 0.51667],
3250    "113": [0.19444, 0.44444, 0.04169, 0, 0.51667],
3251    "114": [0, 0.44444, 0.10836, 0, 0.34167],
3252    "115": [0, 0.44444, 0.0778, 0, 0.38333],
3253    "116": [0, 0.57143, 0.07225, 0, 0.36111],
3254    "117": [0, 0.44444, 0.04169, 0, 0.51667],
3255    "118": [0, 0.44444, 0.10836, 0, 0.46111],
3256    "119": [0, 0.44444, 0.10836, 0, 0.68334],
3257    "120": [0, 0.44444, 0.09169, 0, 0.46111],
3258    "121": [0.19444, 0.44444, 0.10836, 0, 0.46111],
3259    "122": [0, 0.44444, 0.08752, 0, 0.43472],
3260    "126": [0.35, 0.32659, 0.08826, 0, 0.5],
3261    "168": [0, 0.67937, 0.06385, 0, 0.5],
3262    "176": [0, 0.69444, 0, 0, 0.73752],
3263    "184": [0.17014, 0, 0, 0, 0.44445],
3264    "305": [0, 0.44444, 0.04169, 0, 0.23889],
3265    "567": [0.19444, 0.44444, 0.04169, 0, 0.26667],
3266    "710": [0, 0.69444, 0.0799, 0, 0.5],
3267    "711": [0, 0.63194, 0.08432, 0, 0.5],
3268    "713": [0, 0.60889, 0.08776, 0, 0.5],
3269    "714": [0, 0.69444, 0.09205, 0, 0.5],
3270    "715": [0, 0.69444, 0, 0, 0.5],
3271    "728": [0, 0.69444, 0.09483, 0, 0.5],
3272    "729": [0, 0.67937, 0.07774, 0, 0.27778],
3273    "730": [0, 0.69444, 0, 0, 0.73752],
3274    "732": [0, 0.67659, 0.08826, 0, 0.5],
3275    "733": [0, 0.69444, 0.09205, 0, 0.5],
3276    "915": [0, 0.69444, 0.13372, 0, 0.54167],
3277    "916": [0, 0.69444, 0, 0, 0.83334],
3278    "920": [0, 0.69444, 0.07555, 0, 0.77778],
3279    "923": [0, 0.69444, 0, 0, 0.61111],
3280    "926": [0, 0.69444, 0.12816, 0, 0.66667],
3281    "928": [0, 0.69444, 0.08094, 0, 0.70834],
3282    "931": [0, 0.69444, 0.11983, 0, 0.72222],
3283    "933": [0, 0.69444, 0.09031, 0, 0.77778],
3284    "934": [0, 0.69444, 0.04603, 0, 0.72222],
3285    "936": [0, 0.69444, 0.09031, 0, 0.77778],
3286    "937": [0, 0.69444, 0.08293, 0, 0.72222],
3287    "8211": [0, 0.44444, 0.08616, 0, 0.5],
3288    "8212": [0, 0.44444, 0.08616, 0, 1.0],
3289    "8216": [0, 0.69444, 0.07816, 0, 0.27778],
3290    "8217": [0, 0.69444, 0.07816, 0, 0.27778],
3291    "8220": [0, 0.69444, 0.14205, 0, 0.5],
3292    "8221": [0, 0.69444, 0.00316, 0, 0.5]
3293  },
3294  "SansSerif-Regular": {
3295    "33": [0, 0.69444, 0, 0, 0.31945],
3296    "34": [0, 0.69444, 0, 0, 0.5],
3297    "35": [0.19444, 0.69444, 0, 0, 0.83334],
3298    "36": [0.05556, 0.75, 0, 0, 0.5],
3299    "37": [0.05556, 0.75, 0, 0, 0.83334],
3300    "38": [0, 0.69444, 0, 0, 0.75834],
3301    "39": [0, 0.69444, 0, 0, 0.27778],
3302    "40": [0.25, 0.75, 0, 0, 0.38889],
3303    "41": [0.25, 0.75, 0, 0, 0.38889],
3304    "42": [0, 0.75, 0, 0, 0.5],
3305    "43": [0.08333, 0.58333, 0, 0, 0.77778],
3306    "44": [0.125, 0.08333, 0, 0, 0.27778],
3307    "45": [0, 0.44444, 0, 0, 0.33333],
3308    "46": [0, 0.08333, 0, 0, 0.27778],
3309    "47": [0.25, 0.75, 0, 0, 0.5],
3310    "48": [0, 0.65556, 0, 0, 0.5],
3311    "49": [0, 0.65556, 0, 0, 0.5],
3312    "50": [0, 0.65556, 0, 0, 0.5],
3313    "51": [0, 0.65556, 0, 0, 0.5],
3314    "52": [0, 0.65556, 0, 0, 0.5],
3315    "53": [0, 0.65556, 0, 0, 0.5],
3316    "54": [0, 0.65556, 0, 0, 0.5],
3317    "55": [0, 0.65556, 0, 0, 0.5],
3318    "56": [0, 0.65556, 0, 0, 0.5],
3319    "57": [0, 0.65556, 0, 0, 0.5],
3320    "58": [0, 0.44444, 0, 0, 0.27778],
3321    "59": [0.125, 0.44444, 0, 0, 0.27778],
3322    "61": [-0.13, 0.37, 0, 0, 0.77778],
3323    "63": [0, 0.69444, 0, 0, 0.47222],
3324    "64": [0, 0.69444, 0, 0, 0.66667],
3325    "65": [0, 0.69444, 0, 0, 0.66667],
3326    "66": [0, 0.69444, 0, 0, 0.66667],
3327    "67": [0, 0.69444, 0, 0, 0.63889],
3328    "68": [0, 0.69444, 0, 0, 0.72223],
3329    "69": [0, 0.69444, 0, 0, 0.59722],
3330    "70": [0, 0.69444, 0, 0, 0.56945],
3331    "71": [0, 0.69444, 0, 0, 0.66667],
3332    "72": [0, 0.69444, 0, 0, 0.70834],
3333    "73": [0, 0.69444, 0, 0, 0.27778],
3334    "74": [0, 0.69444, 0, 0, 0.47222],
3335    "75": [0, 0.69444, 0, 0, 0.69445],
3336    "76": [0, 0.69444, 0, 0, 0.54167],
3337    "77": [0, 0.69444, 0, 0, 0.875],
3338    "78": [0, 0.69444, 0, 0, 0.70834],
3339    "79": [0, 0.69444, 0, 0, 0.73611],
3340    "80": [0, 0.69444, 0, 0, 0.63889],
3341    "81": [0.125, 0.69444, 0, 0, 0.73611],
3342    "82": [0, 0.69444, 0, 0, 0.64584],
3343    "83": [0, 0.69444, 0, 0, 0.55556],
3344    "84": [0, 0.69444, 0, 0, 0.68056],
3345    "85": [0, 0.69444, 0, 0, 0.6875],
3346    "86": [0, 0.69444, 0.01389, 0, 0.66667],
3347    "87": [0, 0.69444, 0.01389, 0, 0.94445],
3348    "88": [0, 0.69444, 0, 0, 0.66667],
3349    "89": [0, 0.69444, 0.025, 0, 0.66667],
3350    "90": [0, 0.69444, 0, 0, 0.61111],
3351    "91": [0.25, 0.75, 0, 0, 0.28889],
3352    "93": [0.25, 0.75, 0, 0, 0.28889],
3353    "94": [0, 0.69444, 0, 0, 0.5],
3354    "95": [0.35, 0.09444, 0.02778, 0, 0.5],
3355    "97": [0, 0.44444, 0, 0, 0.48056],
3356    "98": [0, 0.69444, 0, 0, 0.51667],
3357    "99": [0, 0.44444, 0, 0, 0.44445],
3358    "100": [0, 0.69444, 0, 0, 0.51667],
3359    "101": [0, 0.44444, 0, 0, 0.44445],
3360    "102": [0, 0.69444, 0.06944, 0, 0.30556],
3361    "103": [0.19444, 0.44444, 0.01389, 0, 0.5],
3362    "104": [0, 0.69444, 0, 0, 0.51667],
3363    "105": [0, 0.67937, 0, 0, 0.23889],
3364    "106": [0.19444, 0.67937, 0, 0, 0.26667],
3365    "107": [0, 0.69444, 0, 0, 0.48889],
3366    "108": [0, 0.69444, 0, 0, 0.23889],
3367    "109": [0, 0.44444, 0, 0, 0.79445],
3368    "110": [0, 0.44444, 0, 0, 0.51667],
3369    "111": [0, 0.44444, 0, 0, 0.5],
3370    "112": [0.19444, 0.44444, 0, 0, 0.51667],
3371    "113": [0.19444, 0.44444, 0, 0, 0.51667],
3372    "114": [0, 0.44444, 0.01389, 0, 0.34167],
3373    "115": [0, 0.44444, 0, 0, 0.38333],
3374    "116": [0, 0.57143, 0, 0, 0.36111],
3375    "117": [0, 0.44444, 0, 0, 0.51667],
3376    "118": [0, 0.44444, 0.01389, 0, 0.46111],
3377    "119": [0, 0.44444, 0.01389, 0, 0.68334],
3378    "120": [0, 0.44444, 0, 0, 0.46111],
3379    "121": [0.19444, 0.44444, 0.01389, 0, 0.46111],
3380    "122": [0, 0.44444, 0, 0, 0.43472],
3381    "126": [0.35, 0.32659, 0, 0, 0.5],
3382    "168": [0, 0.67937, 0, 0, 0.5],
3383    "176": [0, 0.69444, 0, 0, 0.66667],
3384    "184": [0.17014, 0, 0, 0, 0.44445],
3385    "305": [0, 0.44444, 0, 0, 0.23889],
3386    "567": [0.19444, 0.44444, 0, 0, 0.26667],
3387    "710": [0, 0.69444, 0, 0, 0.5],
3388    "711": [0, 0.63194, 0, 0, 0.5],
3389    "713": [0, 0.60889, 0, 0, 0.5],
3390    "714": [0, 0.69444, 0, 0, 0.5],
3391    "715": [0, 0.69444, 0, 0, 0.5],
3392    "728": [0, 0.69444, 0, 0, 0.5],
3393    "729": [0, 0.67937, 0, 0, 0.27778],
3394    "730": [0, 0.69444, 0, 0, 0.66667],
3395    "732": [0, 0.67659, 0, 0, 0.5],
3396    "733": [0, 0.69444, 0, 0, 0.5],
3397    "915": [0, 0.69444, 0, 0, 0.54167],
3398    "916": [0, 0.69444, 0, 0, 0.83334],
3399    "920": [0, 0.69444, 0, 0, 0.77778],
3400    "923": [0, 0.69444, 0, 0, 0.61111],
3401    "926": [0, 0.69444, 0, 0, 0.66667],
3402    "928": [0, 0.69444, 0, 0, 0.70834],
3403    "931": [0, 0.69444, 0, 0, 0.72222],
3404    "933": [0, 0.69444, 0, 0, 0.77778],
3405    "934": [0, 0.69444, 0, 0, 0.72222],
3406    "936": [0, 0.69444, 0, 0, 0.77778],
3407    "937": [0, 0.69444, 0, 0, 0.72222],
3408    "8211": [0, 0.44444, 0.02778, 0, 0.5],
3409    "8212": [0, 0.44444, 0.02778, 0, 1.0],
3410    "8216": [0, 0.69444, 0, 0, 0.27778],
3411    "8217": [0, 0.69444, 0, 0, 0.27778],
3412    "8220": [0, 0.69444, 0, 0, 0.5],
3413    "8221": [0, 0.69444, 0, 0, 0.5]
3414  },
3415  "Script-Regular": {
3416    "65": [0, 0.7, 0.22925, 0, 0.80253],
3417    "66": [0, 0.7, 0.04087, 0, 0.90757],
3418    "67": [0, 0.7, 0.1689, 0, 0.66619],
3419    "68": [0, 0.7, 0.09371, 0, 0.77443],
3420    "69": [0, 0.7, 0.18583, 0, 0.56162],
3421    "70": [0, 0.7, 0.13634, 0, 0.89544],
3422    "71": [0, 0.7, 0.17322, 0, 0.60961],
3423    "72": [0, 0.7, 0.29694, 0, 0.96919],
3424    "73": [0, 0.7, 0.19189, 0, 0.80907],
3425    "74": [0.27778, 0.7, 0.19189, 0, 1.05159],
3426    "75": [0, 0.7, 0.31259, 0, 0.91364],
3427    "76": [0, 0.7, 0.19189, 0, 0.87373],
3428    "77": [0, 0.7, 0.15981, 0, 1.08031],
3429    "78": [0, 0.7, 0.3525, 0, 0.9015],
3430    "79": [0, 0.7, 0.08078, 0, 0.73787],
3431    "80": [0, 0.7, 0.08078, 0, 1.01262],
3432    "81": [0, 0.7, 0.03305, 0, 0.88282],
3433    "82": [0, 0.7, 0.06259, 0, 0.85],
3434    "83": [0, 0.7, 0.19189, 0, 0.86767],
3435    "84": [0, 0.7, 0.29087, 0, 0.74697],
3436    "85": [0, 0.7, 0.25815, 0, 0.79996],
3437    "86": [0, 0.7, 0.27523, 0, 0.62204],
3438    "87": [0, 0.7, 0.27523, 0, 0.80532],
3439    "88": [0, 0.7, 0.26006, 0, 0.94445],
3440    "89": [0, 0.7, 0.2939, 0, 0.70961],
3441    "90": [0, 0.7, 0.24037, 0, 0.8212]
3442  },
3443  "Size1-Regular": {
3444    "40": [0.35001, 0.85, 0, 0, 0.45834],
3445    "41": [0.35001, 0.85, 0, 0, 0.45834],
3446    "47": [0.35001, 0.85, 0, 0, 0.57778],
3447    "91": [0.35001, 0.85, 0, 0, 0.41667],
3448    "92": [0.35001, 0.85, 0, 0, 0.57778],
3449    "93": [0.35001, 0.85, 0, 0, 0.41667],
3450    "123": [0.35001, 0.85, 0, 0, 0.58334],
3451    "125": [0.35001, 0.85, 0, 0, 0.58334],
3452    "710": [0, 0.72222, 0, 0, 0.55556],
3453    "732": [0, 0.72222, 0, 0, 0.55556],
3454    "770": [0, 0.72222, 0, 0, 0.55556],
3455    "771": [0, 0.72222, 0, 0, 0.55556],
3456    "8214": [-0.00099, 0.601, 0, 0, 0.77778],
3457    "8593": [1e-05, 0.6, 0, 0, 0.66667],
3458    "8595": [1e-05, 0.6, 0, 0, 0.66667],
3459    "8657": [1e-05, 0.6, 0, 0, 0.77778],
3460    "8659": [1e-05, 0.6, 0, 0, 0.77778],
3461    "8719": [0.25001, 0.75, 0, 0, 0.94445],
3462    "8720": [0.25001, 0.75, 0, 0, 0.94445],
3463    "8721": [0.25001, 0.75, 0, 0, 1.05556],
3464    "8730": [0.35001, 0.85, 0, 0, 1.0],
3465    "8739": [-0.00599, 0.606, 0, 0, 0.33333],
3466    "8741": [-0.00599, 0.606, 0, 0, 0.55556],
3467    "8747": [0.30612, 0.805, 0.19445, 0, 0.47222],
3468    "8748": [0.306, 0.805, 0.19445, 0, 0.47222],
3469    "8749": [0.306, 0.805, 0.19445, 0, 0.47222],
3470    "8750": [0.30612, 0.805, 0.19445, 0, 0.47222],
3471    "8896": [0.25001, 0.75, 0, 0, 0.83334],
3472    "8897": [0.25001, 0.75, 0, 0, 0.83334],
3473    "8898": [0.25001, 0.75, 0, 0, 0.83334],
3474    "8899": [0.25001, 0.75, 0, 0, 0.83334],
3475    "8968": [0.35001, 0.85, 0, 0, 0.47222],
3476    "8969": [0.35001, 0.85, 0, 0, 0.47222],
3477    "8970": [0.35001, 0.85, 0, 0, 0.47222],
3478    "8971": [0.35001, 0.85, 0, 0, 0.47222],
3479    "9168": [-0.00099, 0.601, 0, 0, 0.66667],
3480    "10216": [0.35001, 0.85, 0, 0, 0.47222],
3481    "10217": [0.35001, 0.85, 0, 0, 0.47222],
3482    "10752": [0.25001, 0.75, 0, 0, 1.11111],
3483    "10753": [0.25001, 0.75, 0, 0, 1.11111],
3484    "10754": [0.25001, 0.75, 0, 0, 1.11111],
3485    "10756": [0.25001, 0.75, 0, 0, 0.83334],
3486    "10758": [0.25001, 0.75, 0, 0, 0.83334]
3487  },
3488  "Size2-Regular": {
3489    "40": [0.65002, 1.15, 0, 0, 0.59722],
3490    "41": [0.65002, 1.15, 0, 0, 0.59722],
3491    "47": [0.65002, 1.15, 0, 0, 0.81111],
3492    "91": [0.65002, 1.15, 0, 0, 0.47222],
3493    "92": [0.65002, 1.15, 0, 0, 0.81111],
3494    "93": [0.65002, 1.15, 0, 0, 0.47222],
3495    "123": [0.65002, 1.15, 0, 0, 0.66667],
3496    "125": [0.65002, 1.15, 0, 0, 0.66667],
3497    "710": [0, 0.75, 0, 0, 1.0],
3498    "732": [0, 0.75, 0, 0, 1.0],
3499    "770": [0, 0.75, 0, 0, 1.0],
3500    "771": [0, 0.75, 0, 0, 1.0],
3501    "8719": [0.55001, 1.05, 0, 0, 1.27778],
3502    "8720": [0.55001, 1.05, 0, 0, 1.27778],
3503    "8721": [0.55001, 1.05, 0, 0, 1.44445],
3504    "8730": [0.65002, 1.15, 0, 0, 1.0],
3505    "8747": [0.86225, 1.36, 0.44445, 0, 0.55556],
3506    "8748": [0.862, 1.36, 0.44445, 0, 0.55556],
3507    "8749": [0.862, 1.36, 0.44445, 0, 0.55556],
3508    "8750": [0.86225, 1.36, 0.44445, 0, 0.55556],
3509    "8896": [0.55001, 1.05, 0, 0, 1.11111],
3510    "8897": [0.55001, 1.05, 0, 0, 1.11111],
3511    "8898": [0.55001, 1.05, 0, 0, 1.11111],
3512    "8899": [0.55001, 1.05, 0, 0, 1.11111],
3513    "8968": [0.65002, 1.15, 0, 0, 0.52778],
3514    "8969": [0.65002, 1.15, 0, 0, 0.52778],
3515    "8970": [0.65002, 1.15, 0, 0, 0.52778],
3516    "8971": [0.65002, 1.15, 0, 0, 0.52778],
3517    "10216": [0.65002, 1.15, 0, 0, 0.61111],
3518    "10217": [0.65002, 1.15, 0, 0, 0.61111],
3519    "10752": [0.55001, 1.05, 0, 0, 1.51112],
3520    "10753": [0.55001, 1.05, 0, 0, 1.51112],
3521    "10754": [0.55001, 1.05, 0, 0, 1.51112],
3522    "10756": [0.55001, 1.05, 0, 0, 1.11111],
3523    "10758": [0.55001, 1.05, 0, 0, 1.11111]
3524  },
3525  "Size3-Regular": {
3526    "40": [0.95003, 1.45, 0, 0, 0.73611],
3527    "41": [0.95003, 1.45, 0, 0, 0.73611],
3528    "47": [0.95003, 1.45, 0, 0, 1.04445],
3529    "91": [0.95003, 1.45, 0, 0, 0.52778],
3530    "92": [0.95003, 1.45, 0, 0, 1.04445],
3531    "93": [0.95003, 1.45, 0, 0, 0.52778],
3532    "123": [0.95003, 1.45, 0, 0, 0.75],
3533    "125": [0.95003, 1.45, 0, 0, 0.75],
3534    "710": [0, 0.75, 0, 0, 1.44445],
3535    "732": [0, 0.75, 0, 0, 1.44445],
3536    "770": [0, 0.75, 0, 0, 1.44445],
3537    "771": [0, 0.75, 0, 0, 1.44445],
3538    "8730": [0.95003, 1.45, 0, 0, 1.0],
3539    "8968": [0.95003, 1.45, 0, 0, 0.58334],
3540    "8969": [0.95003, 1.45, 0, 0, 0.58334],
3541    "8970": [0.95003, 1.45, 0, 0, 0.58334],
3542    "8971": [0.95003, 1.45, 0, 0, 0.58334],
3543    "10216": [0.95003, 1.45, 0, 0, 0.75],
3544    "10217": [0.95003, 1.45, 0, 0, 0.75]
3545  },
3546  "Size4-Regular": {
3547    "40": [1.25003, 1.75, 0, 0, 0.79167],
3548    "41": [1.25003, 1.75, 0, 0, 0.79167],
3549    "47": [1.25003, 1.75, 0, 0, 1.27778],
3550    "91": [1.25003, 1.75, 0, 0, 0.58334],
3551    "92": [1.25003, 1.75, 0, 0, 1.27778],
3552    "93": [1.25003, 1.75, 0, 0, 0.58334],
3553    "123": [1.25003, 1.75, 0, 0, 0.80556],
3554    "125": [1.25003, 1.75, 0, 0, 0.80556],
3555    "710": [0, 0.825, 0, 0, 1.8889],
3556    "732": [0, 0.825, 0, 0, 1.8889],
3557    "770": [0, 0.825, 0, 0, 1.8889],
3558    "771": [0, 0.825, 0, 0, 1.8889],
3559    "8730": [1.25003, 1.75, 0, 0, 1.0],
3560    "8968": [1.25003, 1.75, 0, 0, 0.63889],
3561    "8969": [1.25003, 1.75, 0, 0, 0.63889],
3562    "8970": [1.25003, 1.75, 0, 0, 0.63889],
3563    "8971": [1.25003, 1.75, 0, 0, 0.63889],
3564    "9115": [0.64502, 1.155, 0, 0, 0.875],
3565    "9116": [1e-05, 0.6, 0, 0, 0.875],
3566    "9117": [0.64502, 1.155, 0, 0, 0.875],
3567    "9118": [0.64502, 1.155, 0, 0, 0.875],
3568    "9119": [1e-05, 0.6, 0, 0, 0.875],
3569    "9120": [0.64502, 1.155, 0, 0, 0.875],
3570    "9121": [0.64502, 1.155, 0, 0, 0.66667],
3571    "9122": [-0.00099, 0.601, 0, 0, 0.66667],
3572    "9123": [0.64502, 1.155, 0, 0, 0.66667],
3573    "9124": [0.64502, 1.155, 0, 0, 0.66667],
3574    "9125": [-0.00099, 0.601, 0, 0, 0.66667],
3575    "9126": [0.64502, 1.155, 0, 0, 0.66667],
3576    "9127": [1e-05, 0.9, 0, 0, 0.88889],
3577    "9128": [0.65002, 1.15, 0, 0, 0.88889],
3578    "9129": [0.90001, 0, 0, 0, 0.88889],
3579    "9130": [0, 0.3, 0, 0, 0.88889],
3580    "9131": [1e-05, 0.9, 0, 0, 0.88889],
3581    "9132": [0.65002, 1.15, 0, 0, 0.88889],
3582    "9133": [0.90001, 0, 0, 0, 0.88889],
3583    "9143": [0.88502, 0.915, 0, 0, 1.05556],
3584    "10216": [1.25003, 1.75, 0, 0, 0.80556],
3585    "10217": [1.25003, 1.75, 0, 0, 0.80556],
3586    "57344": [-0.00499, 0.605, 0, 0, 1.05556],
3587    "57345": [-0.00499, 0.605, 0, 0, 1.05556],
3588    "57680": [0, 0.12, 0, 0, 0.45],
3589    "57681": [0, 0.12, 0, 0, 0.45],
3590    "57682": [0, 0.12, 0, 0, 0.45],
3591    "57683": [0, 0.12, 0, 0, 0.45]
3592  },
3593  "Typewriter-Regular": {
3594    "32": [0, 0, 0, 0, 0.525],
3595    "33": [0, 0.61111, 0, 0, 0.525],
3596    "34": [0, 0.61111, 0, 0, 0.525],
3597    "35": [0, 0.61111, 0, 0, 0.525],
3598    "36": [0.08333, 0.69444, 0, 0, 0.525],
3599    "37": [0.08333, 0.69444, 0, 0, 0.525],
3600    "38": [0, 0.61111, 0, 0, 0.525],
3601    "39": [0, 0.61111, 0, 0, 0.525],
3602    "40": [0.08333, 0.69444, 0, 0, 0.525],
3603    "41": [0.08333, 0.69444, 0, 0, 0.525],
3604    "42": [0, 0.52083, 0, 0, 0.525],
3605    "43": [-0.08056, 0.53055, 0, 0, 0.525],
3606    "44": [0.13889, 0.125, 0, 0, 0.525],
3607    "45": [-0.08056, 0.53055, 0, 0, 0.525],
3608    "46": [0, 0.125, 0, 0, 0.525],
3609    "47": [0.08333, 0.69444, 0, 0, 0.525],
3610    "48": [0, 0.61111, 0, 0, 0.525],
3611    "49": [0, 0.61111, 0, 0, 0.525],
3612    "50": [0, 0.61111, 0, 0, 0.525],
3613    "51": [0, 0.61111, 0, 0, 0.525],
3614    "52": [0, 0.61111, 0, 0, 0.525],
3615    "53": [0, 0.61111, 0, 0, 0.525],
3616    "54": [0, 0.61111, 0, 0, 0.525],
3617    "55": [0, 0.61111, 0, 0, 0.525],
3618    "56": [0, 0.61111, 0, 0, 0.525],
3619    "57": [0, 0.61111, 0, 0, 0.525],
3620    "58": [0, 0.43056, 0, 0, 0.525],
3621    "59": [0.13889, 0.43056, 0, 0, 0.525],
3622    "60": [-0.05556, 0.55556, 0, 0, 0.525],
3623    "61": [-0.19549, 0.41562, 0, 0, 0.525],
3624    "62": [-0.05556, 0.55556, 0, 0, 0.525],
3625    "63": [0, 0.61111, 0, 0, 0.525],
3626    "64": [0, 0.61111, 0, 0, 0.525],
3627    "65": [0, 0.61111, 0, 0, 0.525],
3628    "66": [0, 0.61111, 0, 0, 0.525],
3629    "67": [0, 0.61111, 0, 0, 0.525],
3630    "68": [0, 0.61111, 0, 0, 0.525],
3631    "69": [0, 0.61111, 0, 0, 0.525],
3632    "70": [0, 0.61111, 0, 0, 0.525],
3633    "71": [0, 0.61111, 0, 0, 0.525],
3634    "72": [0, 0.61111, 0, 0, 0.525],
3635    "73": [0, 0.61111, 0, 0, 0.525],
3636    "74": [0, 0.61111, 0, 0, 0.525],
3637    "75": [0, 0.61111, 0, 0, 0.525],
3638    "76": [0, 0.61111, 0, 0, 0.525],
3639    "77": [0, 0.61111, 0, 0, 0.525],
3640    "78": [0, 0.61111, 0, 0, 0.525],
3641    "79": [0, 0.61111, 0, 0, 0.525],
3642    "80": [0, 0.61111, 0, 0, 0.525],
3643    "81": [0.13889, 0.61111, 0, 0, 0.525],
3644    "82": [0, 0.61111, 0, 0, 0.525],
3645    "83": [0, 0.61111, 0, 0, 0.525],
3646    "84": [0, 0.61111, 0, 0, 0.525],
3647    "85": [0, 0.61111, 0, 0, 0.525],
3648    "86": [0, 0.61111, 0, 0, 0.525],
3649    "87": [0, 0.61111, 0, 0, 0.525],
3650    "88": [0, 0.61111, 0, 0, 0.525],
3651    "89": [0, 0.61111, 0, 0, 0.525],
3652    "90": [0, 0.61111, 0, 0, 0.525],
3653    "91": [0.08333, 0.69444, 0, 0, 0.525],
3654    "92": [0.08333, 0.69444, 0, 0, 0.525],
3655    "93": [0.08333, 0.69444, 0, 0, 0.525],
3656    "94": [0, 0.61111, 0, 0, 0.525],
3657    "95": [0.09514, 0, 0, 0, 0.525],
3658    "96": [0, 0.61111, 0, 0, 0.525],
3659    "97": [0, 0.43056, 0, 0, 0.525],
3660    "98": [0, 0.61111, 0, 0, 0.525],
3661    "99": [0, 0.43056, 0, 0, 0.525],
3662    "100": [0, 0.61111, 0, 0, 0.525],
3663    "101": [0, 0.43056, 0, 0, 0.525],
3664    "102": [0, 0.61111, 0, 0, 0.525],
3665    "103": [0.22222, 0.43056, 0, 0, 0.525],
3666    "104": [0, 0.61111, 0, 0, 0.525],
3667    "105": [0, 0.61111, 0, 0, 0.525],
3668    "106": [0.22222, 0.61111, 0, 0, 0.525],
3669    "107": [0, 0.61111, 0, 0, 0.525],
3670    "108": [0, 0.61111, 0, 0, 0.525],
3671    "109": [0, 0.43056, 0, 0, 0.525],
3672    "110": [0, 0.43056, 0, 0, 0.525],
3673    "111": [0, 0.43056, 0, 0, 0.525],
3674    "112": [0.22222, 0.43056, 0, 0, 0.525],
3675    "113": [0.22222, 0.43056, 0, 0, 0.525],
3676    "114": [0, 0.43056, 0, 0, 0.525],
3677    "115": [0, 0.43056, 0, 0, 0.525],
3678    "116": [0, 0.55358, 0, 0, 0.525],
3679    "117": [0, 0.43056, 0, 0, 0.525],
3680    "118": [0, 0.43056, 0, 0, 0.525],
3681    "119": [0, 0.43056, 0, 0, 0.525],
3682    "120": [0, 0.43056, 0, 0, 0.525],
3683    "121": [0.22222, 0.43056, 0, 0, 0.525],
3684    "122": [0, 0.43056, 0, 0, 0.525],
3685    "123": [0.08333, 0.69444, 0, 0, 0.525],
3686    "124": [0.08333, 0.69444, 0, 0, 0.525],
3687    "125": [0.08333, 0.69444, 0, 0, 0.525],
3688    "126": [0, 0.61111, 0, 0, 0.525],
3689    "127": [0, 0.61111, 0, 0, 0.525],
3690    "160": [0, 0, 0, 0, 0.525],
3691    "176": [0, 0.61111, 0, 0, 0.525],
3692    "184": [0.19445, 0, 0, 0, 0.525],
3693    "305": [0, 0.43056, 0, 0, 0.525],
3694    "567": [0.22222, 0.43056, 0, 0, 0.525],
3695    "711": [0, 0.56597, 0, 0, 0.525],
3696    "713": [0, 0.56555, 0, 0, 0.525],
3697    "714": [0, 0.61111, 0, 0, 0.525],
3698    "715": [0, 0.61111, 0, 0, 0.525],
3699    "728": [0, 0.61111, 0, 0, 0.525],
3700    "730": [0, 0.61111, 0, 0, 0.525],
3701    "770": [0, 0.61111, 0, 0, 0.525],
3702    "771": [0, 0.61111, 0, 0, 0.525],
3703    "776": [0, 0.61111, 0, 0, 0.525],
3704    "915": [0, 0.61111, 0, 0, 0.525],
3705    "916": [0, 0.61111, 0, 0, 0.525],
3706    "920": [0, 0.61111, 0, 0, 0.525],
3707    "923": [0, 0.61111, 0, 0, 0.525],
3708    "926": [0, 0.61111, 0, 0, 0.525],
3709    "928": [0, 0.61111, 0, 0, 0.525],
3710    "931": [0, 0.61111, 0, 0, 0.525],
3711    "933": [0, 0.61111, 0, 0, 0.525],
3712    "934": [0, 0.61111, 0, 0, 0.525],
3713    "936": [0, 0.61111, 0, 0, 0.525],
3714    "937": [0, 0.61111, 0, 0, 0.525],
3715    "8216": [0, 0.61111, 0, 0, 0.525],
3716    "8217": [0, 0.61111, 0, 0, 0.525],
3717    "8242": [0, 0.61111, 0, 0, 0.525],
3718    "9251": [0.11111, 0.21944, 0, 0, 0.525]
3719  }
3720};
3721
3722/**
3723 * This file contains metrics regarding fonts and individual symbols. The sigma
3724 * and xi variables, as well as the metricMap map contain data extracted from
3725 * TeX, TeX font metrics, and the TTF files. These data are then exposed via the
3726 * `metrics` variable and the getCharacterMetrics function.
3727 */
3728// In TeX, there are actually three sets of dimensions, one for each of
3729// textstyle (size index 5 and higher: >=9pt), scriptstyle (size index 3 and 4:
3730// 7-8pt), and scriptscriptstyle (size index 1 and 2: 5-6pt).  These are
3731// provided in the the arrays below, in that order.
3732//
3733// The font metrics are stored in fonts cmsy10, cmsy7, and cmsy5 respsectively.
3734// This was determined by running the following script:
3735//
3736//     latex -interaction=nonstopmode \
3737//     '\documentclass{article}\usepackage{amsmath}\begin{document}' \
3738//     '$a$ \expandafter\show\the\textfont2' \
3739//     '\expandafter\show\the\scriptfont2' \
3740//     '\expandafter\show\the\scriptscriptfont2' \
3741//     '\stop'
3742//
3743// The metrics themselves were retreived using the following commands:
3744//
3745//     tftopl cmsy10
3746//     tftopl cmsy7
3747//     tftopl cmsy5
3748//
3749// The output of each of these commands is quite lengthy.  The only part we
3750// care about is the FONTDIMEN section. Each value is measured in EMs.
3751const sigmasAndXis = {
3752  slant: [0.250, 0.250, 0.250],
3753  // sigma1
3754  space: [0.000, 0.000, 0.000],
3755  // sigma2
3756  stretch: [0.000, 0.000, 0.000],
3757  // sigma3
3758  shrink: [0.000, 0.000, 0.000],
3759  // sigma4
3760  xHeight: [0.431, 0.431, 0.431],
3761  // sigma5
3762  quad: [1.000, 1.171, 1.472],
3763  // sigma6
3764  extraSpace: [0.000, 0.000, 0.000],
3765  // sigma7
3766  num1: [0.677, 0.732, 0.925],
3767  // sigma8
3768  num2: [0.394, 0.384, 0.387],
3769  // sigma9
3770  num3: [0.444, 0.471, 0.504],
3771  // sigma10
3772  denom1: [0.686, 0.752, 1.025],
3773  // sigma11
3774  denom2: [0.345, 0.344, 0.532],
3775  // sigma12
3776  sup1: [0.413, 0.503, 0.504],
3777  // sigma13
3778  sup2: [0.363, 0.431, 0.404],
3779  // sigma14
3780  sup3: [0.289, 0.286, 0.294],
3781  // sigma15
3782  sub1: [0.150, 0.143, 0.200],
3783  // sigma16
3784  sub2: [0.247, 0.286, 0.400],
3785  // sigma17
3786  supDrop: [0.386, 0.353, 0.494],
3787  // sigma18
3788  subDrop: [0.050, 0.071, 0.100],
3789  // sigma19
3790  delim1: [2.390, 1.700, 1.980],
3791  // sigma20
3792  delim2: [1.010, 1.157, 1.420],
3793  // sigma21
3794  axisHeight: [0.250, 0.250, 0.250],
3795  // sigma22
3796  // These font metrics are extracted from TeX by using tftopl on cmex10.tfm;
3797  // they correspond to the font parameters of the extension fonts (family 3).
3798  // See the TeXbook, page 441. In AMSTeX, the extension fonts scale; to
3799  // match cmex7, we'd use cmex7.tfm values for script and scriptscript
3800  // values.
3801  defaultRuleThickness: [0.04, 0.049, 0.049],
3802  // xi8; cmex7: 0.049
3803  bigOpSpacing1: [0.111, 0.111, 0.111],
3804  // xi9
3805  bigOpSpacing2: [0.166, 0.166, 0.166],
3806  // xi10
3807  bigOpSpacing3: [0.2, 0.2, 0.2],
3808  // xi11
3809  bigOpSpacing4: [0.6, 0.611, 0.611],
3810  // xi12; cmex7: 0.611
3811  bigOpSpacing5: [0.1, 0.143, 0.143],
3812  // xi13; cmex7: 0.143
3813  // The \sqrt rule width is taken from the height of the surd character.
3814  // Since we use the same font at all sizes, this thickness doesn't scale.
3815  sqrtRuleThickness: [0.04, 0.04, 0.04],
3816  // This value determines how large a pt is, for metrics which are defined
3817  // in terms of pts.
3818  // This value is also used in katex.less; if you change it make sure the
3819  // values match.
3820  ptPerEm: [10.0, 10.0, 10.0],
3821  // The space between adjacent `|` columns in an array definition. From
3822  // `\showthe\doublerulesep` in LaTeX. Equals 2.0 / ptPerEm.
3823  doubleRuleSep: [0.2, 0.2, 0.2],
3824  // The width of separator lines in {array} environments. From
3825  // `\showthe\arrayrulewidth` in LaTeX. Equals 0.4 / ptPerEm.
3826  arrayRuleWidth: [0.04, 0.04, 0.04],
3827  // Two values from LaTeX source2e:
3828  fboxsep: [0.3, 0.3, 0.3],
3829  //        3 pt / ptPerEm
3830  fboxrule: [0.04, 0.04, 0.04] // 0.4 pt / ptPerEm
3831
3832}; // This map contains a mapping from font name and character code to character
3833// should have Latin-1 and Cyrillic characters, but may not depending on the
3834// operating system.  The metrics do not account for extra height from the
3835// accents.  In the case of Cyrillic characters which have both ascenders and
3836// descenders we prefer approximations with ascenders, primarily to prevent
3837// the fraction bar or root line from intersecting the glyph.
3838// TODO(kevinb) allow union of multiple glyph metrics for better accuracy.
3839
3840const extraCharacterMap = {
3841  // Latin-1
3842  'Å': 'A',
3843  'Ç': 'C',
3844  'Ð': 'D',
3845  'Þ': 'o',
3846  'å': 'a',
3847  'ç': 'c',
3848  'ð': 'd',
3849  'þ': 'o',
3850  // Cyrillic
3851  'А': 'A',
3852  'Б': 'B',
3853  'В': 'B',
3854  'Г': 'F',
3855  'Д': 'A',
3856  'Е': 'E',
3857  'Ж': 'K',
3858  'З': '3',
3859  'И': 'N',
3860  'Й': 'N',
3861  'К': 'K',
3862  'Л': 'N',
3863  'М': 'M',
3864  'Н': 'H',
3865  'О': 'O',
3866  'П': 'N',
3867  'Р': 'P',
3868  'С': 'C',
3869  'Т': 'T',
3870  'У': 'y',
3871  'Ф': 'O',
3872  'Х': 'X',
3873  'Ц': 'U',
3874  'Ч': 'h',
3875  'Ш': 'W',
3876  'Щ': 'W',
3877  'Ъ': 'B',
3878  'Ы': 'X',
3879  'Ь': 'B',
3880  'Э': '3',
3881  'Ю': 'X',
3882  'Я': 'R',
3883  'а': 'a',
3884  'б': 'b',
3885  'в': 'a',
3886  'г': 'r',
3887  'д': 'y',
3888  'е': 'e',
3889  'ж': 'm',
3890  'з': 'e',
3891  'и': 'n',
3892  'й': 'n',
3893  'к': 'n',
3894  'л': 'n',
3895  'м': 'm',
3896  'н': 'n',
3897  'о': 'o',
3898  'п': 'n',
3899  'р': 'p',
3900  'с': 'c',
3901  'т': 'o',
3902  'у': 'y',
3903  'ф': 'b',
3904  'х': 'x',
3905  'ц': 'n',
3906  'ч': 'n',
3907  'ш': 'w',
3908  'щ': 'w',
3909  'ъ': 'a',
3910  'ы': 'm',
3911  'ь': 'a',
3912  'э': 'e',
3913  'ю': 'm',
3914  'я': 'r'
3915};
3916
3917/**
3918 * This function adds new font metrics to default metricMap
3919 * It can also override existing metrics
3920 */
3921function setFontMetrics(fontName, metrics) {
3922  metricMap[fontName] = metrics;
3923}
3924/**
3925 * This function is a convenience function for looking up information in the
3926 * metricMap table. It takes a character as a string, and a font.
3927 *
3928 * Note: the `width` property may be undefined if fontMetricsData.js wasn't
3929 * built using `Make extended_metrics`.
3930 */
3931
3932function getCharacterMetrics(character, font, mode) {
3933  if (!metricMap[font]) {
3934    throw new Error(`Font metrics not found for font: ${font}.`);
3935  }
3936
3937  let ch = character.charCodeAt(0);
3938  let metrics = metricMap[font][ch];
3939
3940  if (!metrics && character[0] in extraCharacterMap) {
3941    ch = extraCharacterMap[character[0]].charCodeAt(0);
3942    metrics = metricMap[font][ch];
3943  }
3944
3945  if (!metrics && mode === 'text') {
3946    // We don't typically have font metrics for Asian scripts.
3947    // But since we support them in text mode, we need to return
3948    // some sort of metrics.
3949    // So if the character is in a script we support but we
3950    // don't have metrics for it, just use the metrics for
3951    // the Latin capital letter M. This is close enough because
3952    // we (currently) only care about the height of the glpyh
3953    // not its width.
3954    if (supportedCodepoint(ch)) {
3955      metrics = metricMap[font][77]; // 77 is the charcode for 'M'
3956    }
3957  }
3958
3959  if (metrics) {
3960    return {
3961      depth: metrics[0],
3962      height: metrics[1],
3963      italic: metrics[2],
3964      skew: metrics[3],
3965      width: metrics[4]
3966    };
3967  }
3968}
3969const fontMetricsBySizeIndex = {};
3970/**
3971 * Get the font metrics for a given size.
3972 */
3973
3974function getGlobalMetrics(size) {
3975  let sizeIndex;
3976
3977  if (size >= 5) {
3978    sizeIndex = 0;
3979  } else if (size >= 3) {
3980    sizeIndex = 1;
3981  } else {
3982    sizeIndex = 2;
3983  }
3984
3985  if (!fontMetricsBySizeIndex[sizeIndex]) {
3986    const metrics = fontMetricsBySizeIndex[sizeIndex] = {
3987      cssEmPerMu: sigmasAndXis.quad[sizeIndex] / 18
3988    };
3989
3990    for (const key in sigmasAndXis) {
3991      if (sigmasAndXis.hasOwnProperty(key)) {
3992        metrics[key] = sigmasAndXis[key][sizeIndex];
3993      }
3994    }
3995  }
3996
3997  return fontMetricsBySizeIndex[sizeIndex];
3998}
3999
4000/**
4001 * This file holds a list of all no-argument functions and single-character
4002 * symbols (like 'a' or ';').
4003 *
4004 * For each of the symbols, there are three properties they can have:
4005 * - font (required): the font to be used for this symbol. Either "main" (the
4006     normal font), or "ams" (the ams fonts).
4007 * - group (required): the ParseNode group type the symbol should have (i.e.
4008     "textord", "mathord", etc).
4009     See https://github.com/KaTeX/KaTeX/wiki/Examining-TeX#group-types
4010 * - replace: the character that this symbol or function should be
4011 *   replaced with (i.e. "\phi" has a replace value of "\u03d5", the phi
4012 *   character in the main font).
4013 *
4014 * The outermost map in the table indicates what mode the symbols should be
4015 * accepted in (e.g. "math" or "text").
4016 */
4017// Some of these have a "-token" suffix since these are also used as `ParseNode`
4018// types for raw text tokens, and we want to avoid conflicts with higher-level
4019// `ParseNode` types. These `ParseNode`s are constructed within `Parser` by
4020// looking up the `symbols` map.
4021const ATOMS = {
4022  "bin": 1,
4023  "close": 1,
4024  "inner": 1,
4025  "open": 1,
4026  "punct": 1,
4027  "rel": 1
4028};
4029const NON_ATOMS = {
4030  "accent-token": 1,
4031  "mathord": 1,
4032  "op-token": 1,
4033  "spacing": 1,
4034  "textord": 1
4035};
4036const symbols = {
4037  "math": {},
4038  "text": {}
4039};
4040/** `acceptUnicodeChar = true` is only applicable if `replace` is set. */
4041
4042function defineSymbol(mode, font, group, replace, name, acceptUnicodeChar) {
4043  symbols[mode][name] = {
4044    font,
4045    group,
4046    replace
4047  };
4048
4049  if (acceptUnicodeChar && replace) {
4050    symbols[mode][replace] = symbols[mode][name];
4051  }
4052} // Some abbreviations for commonly used strings.
4053// This helps minify the code, and also spotting typos using jshint.
4054// modes:
4055
4056const math = "math";
4057const text$1 = "text"; // fonts:
4058
4059const main = "main";
4060const ams = "ams"; // groups:
4061
4062const accent = "accent-token";
4063const bin = "bin";
4064const close = "close";
4065const inner = "inner";
4066const mathord = "mathord";
4067const op = "op-token";
4068const open = "open";
4069const punct = "punct";
4070const rel = "rel";
4071const spacing = "spacing";
4072const textord = "textord"; // Now comes the symbol table
4073// Relation Symbols
4074
4075defineSymbol(math, main, rel, "\u2261", "\\equiv", true);
4076defineSymbol(math, main, rel, "\u227a", "\\prec", true);
4077defineSymbol(math, main, rel, "\u227b", "\\succ", true);
4078defineSymbol(math, main, rel, "\u223c", "\\sim", true);
4079defineSymbol(math, main, rel, "\u22a5", "\\perp");
4080defineSymbol(math, main, rel, "\u2aaf", "\\preceq", true);
4081defineSymbol(math, main, rel, "\u2ab0", "\\succeq", true);
4082defineSymbol(math, main, rel, "\u2243", "\\simeq", true);
4083defineSymbol(math, main, rel, "\u2223", "\\mid", true);
4084defineSymbol(math, main, rel, "\u226a", "\\ll", true);
4085defineSymbol(math, main, rel, "\u226b", "\\gg", true);
4086defineSymbol(math, main, rel, "\u224d", "\\asymp", true);
4087defineSymbol(math, main, rel, "\u2225", "\\parallel");
4088defineSymbol(math, main, rel, "\u22c8", "\\bowtie", true);
4089defineSymbol(math, main, rel, "\u2323", "\\smile", true);
4090defineSymbol(math, main, rel, "\u2291", "\\sqsubseteq", true);
4091defineSymbol(math, main, rel, "\u2292", "\\sqsupseteq", true);
4092defineSymbol(math, main, rel, "\u2250", "\\doteq", true);
4093defineSymbol(math, main, rel, "\u2322", "\\frown", true);
4094defineSymbol(math, main, rel, "\u220b", "\\ni", true);
4095defineSymbol(math, main, rel, "\u221d", "\\propto", true);
4096defineSymbol(math, main, rel, "\u22a2", "\\vdash", true);
4097defineSymbol(math, main, rel, "\u22a3", "\\dashv", true);
4098defineSymbol(math, main, rel, "\u220b", "\\owns"); // Punctuation
4099
4100defineSymbol(math, main, punct, "\u002e", "\\ldotp");
4101defineSymbol(math, main, punct, "\u22c5", "\\cdotp"); // Misc Symbols
4102
4103defineSymbol(math, main, textord, "\u0023", "\\#");
4104defineSymbol(text$1, main, textord, "\u0023", "\\#");
4105defineSymbol(math, main, textord, "\u0026", "\\&");
4106defineSymbol(text$1, main, textord, "\u0026", "\\&");
4107defineSymbol(math, main, textord, "\u2135", "\\aleph", true);
4108defineSymbol(math, main, textord, "\u2200", "\\forall", true);
4109defineSymbol(math, main, textord, "\u210f", "\\hbar", true);
4110defineSymbol(math, main, textord, "\u2203", "\\exists", true);
4111defineSymbol(math, main, textord, "\u2207", "\\nabla", true);
4112defineSymbol(math, main, textord, "\u266d", "\\flat", true);
4113defineSymbol(math, main, textord, "\u2113", "\\ell", true);
4114defineSymbol(math, main, textord, "\u266e", "\\natural", true);
4115defineSymbol(math, main, textord, "\u2663", "\\clubsuit", true);
4116defineSymbol(math, main, textord, "\u2118", "\\wp", true);
4117defineSymbol(math, main, textord, "\u266f", "\\sharp", true);
4118defineSymbol(math, main, textord, "\u2662", "\\diamondsuit", true);
4119defineSymbol(math, main, textord, "\u211c", "\\Re", true);
4120defineSymbol(math, main, textord, "\u2661", "\\heartsuit", true);
4121defineSymbol(math, main, textord, "\u2111", "\\Im", true);
4122defineSymbol(math, main, textord, "\u2660", "\\spadesuit", true);
4123defineSymbol(text$1, main, textord, "\u00a7", "\\S", true);
4124defineSymbol(text$1, main, textord, "\u00b6", "\\P", true); // Math and Text
4125
4126defineSymbol(math, main, textord, "\u2020", "\\dag");
4127defineSymbol(text$1, main, textord, "\u2020", "\\dag");
4128defineSymbol(text$1, main, textord, "\u2020", "\\textdagger");
4129defineSymbol(math, main, textord, "\u2021", "\\ddag");
4130defineSymbol(text$1, main, textord, "\u2021", "\\ddag");
4131defineSymbol(text$1, main, textord, "\u2021", "\\textdaggerdbl"); // Large Delimiters
4132
4133defineSymbol(math, main, close, "\u23b1", "\\rmoustache", true);
4134defineSymbol(math, main, open, "\u23b0", "\\lmoustache", true);
4135defineSymbol(math, main, close, "\u27ef", "\\rgroup", true);
4136defineSymbol(math, main, open, "\u27ee", "\\lgroup", true); // Binary Operators
4137
4138defineSymbol(math, main, bin, "\u2213", "\\mp", true);
4139defineSymbol(math, main, bin, "\u2296", "\\ominus", true);
4140defineSymbol(math, main, bin, "\u228e", "\\uplus", true);
4141defineSymbol(math, main, bin, "\u2293", "\\sqcap", true);
4142defineSymbol(math, main, bin, "\u2217", "\\ast");
4143defineSymbol(math, main, bin, "\u2294", "\\sqcup", true);
4144defineSymbol(math, main, bin, "\u25ef", "\\bigcirc");
4145defineSymbol(math, main, bin, "\u2219", "\\bullet");
4146defineSymbol(math, main, bin, "\u2021", "\\ddagger");
4147defineSymbol(math, main, bin, "\u2240", "\\wr", true);
4148defineSymbol(math, main, bin, "\u2a3f", "\\amalg");
4149defineSymbol(math, main, bin, "\u0026", "\\And"); // from amsmath
4150// Arrow Symbols
4151
4152defineSymbol(math, main, rel, "\u27f5", "\\longleftarrow", true);
4153defineSymbol(math, main, rel, "\u21d0", "\\Leftarrow", true);
4154defineSymbol(math, main, rel, "\u27f8", "\\Longleftarrow", true);
4155defineSymbol(math, main, rel, "\u27f6", "\\longrightarrow", true);
4156defineSymbol(math, main, rel, "\u21d2", "\\Rightarrow", true);
4157defineSymbol(math, main, rel, "\u27f9", "\\Longrightarrow", true);
4158defineSymbol(math, main, rel, "\u2194", "\\leftrightarrow", true);
4159defineSymbol(math, main, rel, "\u27f7", "\\longleftrightarrow", true);
4160defineSymbol(math, main, rel, "\u21d4", "\\Leftrightarrow", true);
4161defineSymbol(math, main, rel, "\u27fa", "\\Longleftrightarrow", true);
4162defineSymbol(math, main, rel, "\u21a6", "\\mapsto", true);
4163defineSymbol(math, main, rel, "\u27fc", "\\longmapsto", true);
4164defineSymbol(math, main, rel, "\u2197", "\\nearrow", true);
4165defineSymbol(math, main, rel, "\u21a9", "\\hookleftarrow", true);
4166defineSymbol(math, main, rel, "\u21aa", "\\hookrightarrow", true);
4167defineSymbol(math, main, rel, "\u2198", "\\searrow", true);
4168defineSymbol(math, main, rel, "\u21bc", "\\leftharpoonup", true);
4169defineSymbol(math, main, rel, "\u21c0", "\\rightharpoonup", true);
4170defineSymbol(math, main, rel, "\u2199", "\\swarrow", true);
4171defineSymbol(math, main, rel, "\u21bd", "\\leftharpoondown", true);
4172defineSymbol(math, main, rel, "\u21c1", "\\rightharpoondown", true);
4173defineSymbol(math, main, rel, "\u2196", "\\nwarrow", true);
4174defineSymbol(math, main, rel, "\u21cc", "\\rightleftharpoons", true); // AMS Negated Binary Relations
4175
4176defineSymbol(math, ams, rel, "\u226e", "\\nless", true); // Symbol names preceeded by "@" each have a corresponding macro.
4177
4178defineSymbol(math, ams, rel, "\ue010", "\\@nleqslant");
4179defineSymbol(math, ams, rel, "\ue011", "\\@nleqq");
4180defineSymbol(math, ams, rel, "\u2a87", "\\lneq", true);
4181defineSymbol(math, ams, rel, "\u2268", "\\lneqq", true);
4182defineSymbol(math, ams, rel, "\ue00c", "\\@lvertneqq");
4183defineSymbol(math, ams, rel, "\u22e6", "\\lnsim", true);
4184defineSymbol(math, ams, rel, "\u2a89", "\\lnapprox", true);
4185defineSymbol(math, ams, rel, "\u2280", "\\nprec", true); // unicode-math maps \u22e0 to \npreccurlyeq. We'll use the AMS synonym.
4186
4187defineSymbol(math, ams, rel, "\u22e0", "\\npreceq", true);
4188defineSymbol(math, ams, rel, "\u22e8", "\\precnsim", true);
4189defineSymbol(math, ams, rel, "\u2ab9", "\\precnapprox", true);
4190defineSymbol(math, ams, rel, "\u2241", "\\nsim", true);
4191defineSymbol(math, ams, rel, "\ue006", "\\@nshortmid");
4192defineSymbol(math, ams, rel, "\u2224", "\\nmid", true);
4193defineSymbol(math, ams, rel, "\u22ac", "\\nvdash", true);
4194defineSymbol(math, ams, rel, "\u22ad", "\\nvDash", true);
4195defineSymbol(math, ams, rel, "\u22ea", "\\ntriangleleft");
4196defineSymbol(math, ams, rel, "\u22ec", "\\ntrianglelefteq", true);
4197defineSymbol(math, ams, rel, "\u228a", "\\subsetneq", true);
4198defineSymbol(math, ams, rel, "\ue01a", "\\@varsubsetneq");
4199defineSymbol(math, ams, rel, "\u2acb", "\\subsetneqq", true);
4200defineSymbol(math, ams, rel, "\ue017", "\\@varsubsetneqq");
4201defineSymbol(math, ams, rel, "\u226f", "\\ngtr", true);
4202defineSymbol(math, ams, rel, "\ue00f", "\\@ngeqslant");
4203defineSymbol(math, ams, rel, "\ue00e", "\\@ngeqq");
4204defineSymbol(math, ams, rel, "\u2a88", "\\gneq", true);
4205defineSymbol(math, ams, rel, "\u2269", "\\gneqq", true);
4206defineSymbol(math, ams, rel, "\ue00d", "\\@gvertneqq");
4207defineSymbol(math, ams, rel, "\u22e7", "\\gnsim", true);
4208defineSymbol(math, ams, rel, "\u2a8a", "\\gnapprox", true);
4209defineSymbol(math, ams, rel, "\u2281", "\\nsucc", true); // unicode-math maps \u22e1 to \nsucccurlyeq. We'll use the AMS synonym.
4210
4211defineSymbol(math, ams, rel, "\u22e1", "\\nsucceq", true);
4212defineSymbol(math, ams, rel, "\u22e9", "\\succnsim", true);
4213defineSymbol(math, ams, rel, "\u2aba", "\\succnapprox", true); // unicode-math maps \u2246 to \simneqq. We'll use the AMS synonym.
4214
4215defineSymbol(math, ams, rel, "\u2246", "\\ncong", true);
4216defineSymbol(math, ams, rel, "\ue007", "\\@nshortparallel");
4217defineSymbol(math, ams, rel, "\u2226", "\\nparallel", true);
4218defineSymbol(math, ams, rel, "\u22af", "\\nVDash", true);
4219defineSymbol(math, ams, rel, "\u22eb", "\\ntriangleright");
4220defineSymbol(math, ams, rel, "\u22ed", "\\ntrianglerighteq", true);
4221defineSymbol(math, ams, rel, "\ue018", "\\@nsupseteqq");
4222defineSymbol(math, ams, rel, "\u228b", "\\supsetneq", true);
4223defineSymbol(math, ams, rel, "\ue01b", "\\@varsupsetneq");
4224defineSymbol(math, ams, rel, "\u2acc", "\\supsetneqq", true);
4225defineSymbol(math, ams, rel, "\ue019", "\\@varsupsetneqq");
4226defineSymbol(math, ams, rel, "\u22ae", "\\nVdash", true);
4227defineSymbol(math, ams, rel, "\u2ab5", "\\precneqq", true);
4228defineSymbol(math, ams, rel, "\u2ab6", "\\succneqq", true);
4229defineSymbol(math, ams, rel, "\ue016", "\\@nsubseteqq");
4230defineSymbol(math, ams, bin, "\u22b4", "\\unlhd");
4231defineSymbol(math, ams, bin, "\u22b5", "\\unrhd"); // AMS Negated Arrows
4232
4233defineSymbol(math, ams, rel, "\u219a", "\\nleftarrow", true);
4234defineSymbol(math, ams, rel, "\u219b", "\\nrightarrow", true);
4235defineSymbol(math, ams, rel, "\u21cd", "\\nLeftarrow", true);
4236defineSymbol(math, ams, rel, "\u21cf", "\\nRightarrow", true);
4237defineSymbol(math, ams, rel, "\u21ae", "\\nleftrightarrow", true);
4238defineSymbol(math, ams, rel, "\u21ce", "\\nLeftrightarrow", true); // AMS Misc
4239
4240defineSymbol(math, ams, rel, "\u25b3", "\\vartriangle");
4241defineSymbol(math, ams, textord, "\u210f", "\\hslash");
4242defineSymbol(math, ams, textord, "\u25bd", "\\triangledown");
4243defineSymbol(math, ams, textord, "\u25ca", "\\lozenge");
4244defineSymbol(math, ams, textord, "\u24c8", "\\circledS");
4245defineSymbol(math, ams, textord, "\u00ae", "\\circledR");
4246defineSymbol(text$1, ams, textord, "\u00ae", "\\circledR");
4247defineSymbol(math, ams, textord, "\u2221", "\\measuredangle", true);
4248defineSymbol(math, ams, textord, "\u2204", "\\nexists");
4249defineSymbol(math, ams, textord, "\u2127", "\\mho");
4250defineSymbol(math, ams, textord, "\u2132", "\\Finv", true);
4251defineSymbol(math, ams, textord, "\u2141", "\\Game", true);
4252defineSymbol(math, ams, textord, "\u2035", "\\backprime");
4253defineSymbol(math, ams, textord, "\u25b2", "\\blacktriangle");
4254defineSymbol(math, ams, textord, "\u25bc", "\\blacktriangledown");
4255defineSymbol(math, ams, textord, "\u25a0", "\\blacksquare");
4256defineSymbol(math, ams, textord, "\u29eb", "\\blacklozenge");
4257defineSymbol(math, ams, textord, "\u2605", "\\bigstar");
4258defineSymbol(math, ams, textord, "\u2222", "\\sphericalangle", true);
4259defineSymbol(math, ams, textord, "\u2201", "\\complement", true); // unicode-math maps U+F0 (ð) to \matheth. We map to AMS function \eth
4260
4261defineSymbol(math, ams, textord, "\u00f0", "\\eth", true);
4262defineSymbol(math, ams, textord, "\u2571", "\\diagup");
4263defineSymbol(math, ams, textord, "\u2572", "\\diagdown");
4264defineSymbol(math, ams, textord, "\u25a1", "\\square");
4265defineSymbol(math, ams, textord, "\u25a1", "\\Box");
4266defineSymbol(math, ams, textord, "\u25ca", "\\Diamond"); // unicode-math maps U+A5 to \mathyen. We map to AMS function \yen
4267
4268defineSymbol(math, ams, textord, "\u00a5", "\\yen", true);
4269defineSymbol(text$1, ams, textord, "\u00a5", "\\yen", true);
4270defineSymbol(math, ams, textord, "\u2713", "\\checkmark", true);
4271defineSymbol(text$1, ams, textord, "\u2713", "\\checkmark"); // AMS Hebrew
4272
4273defineSymbol(math, ams, textord, "\u2136", "\\beth", true);
4274defineSymbol(math, ams, textord, "\u2138", "\\daleth", true);
4275defineSymbol(math, ams, textord, "\u2137", "\\gimel", true); // AMS Greek
4276
4277defineSymbol(math, ams, textord, "\u03dd", "\\digamma", true);
4278defineSymbol(math, ams, textord, "\u03f0", "\\varkappa"); // AMS Delimiters
4279
4280defineSymbol(math, ams, open, "\u250c", "\\ulcorner", true);
4281defineSymbol(math, ams, close, "\u2510", "\\urcorner", true);
4282defineSymbol(math, ams, open, "\u2514", "\\llcorner", true);
4283defineSymbol(math, ams, close, "\u2518", "\\lrcorner", true); // AMS Binary Relations
4284
4285defineSymbol(math, ams, rel, "\u2266", "\\leqq", true);
4286defineSymbol(math, ams, rel, "\u2a7d", "\\leqslant", true);
4287defineSymbol(math, ams, rel, "\u2a95", "\\eqslantless", true);
4288defineSymbol(math, ams, rel, "\u2272", "\\lesssim", true);
4289defineSymbol(math, ams, rel, "\u2a85", "\\lessapprox", true);
4290defineSymbol(math, ams, rel, "\u224a", "\\approxeq", true);
4291defineSymbol(math, ams, bin, "\u22d6", "\\lessdot");
4292defineSymbol(math, ams, rel, "\u22d8", "\\lll", true);
4293defineSymbol(math, ams, rel, "\u2276", "\\lessgtr", true);
4294defineSymbol(math, ams, rel, "\u22da", "\\lesseqgtr", true);
4295defineSymbol(math, ams, rel, "\u2a8b", "\\lesseqqgtr", true);
4296defineSymbol(math, ams, rel, "\u2251", "\\doteqdot");
4297defineSymbol(math, ams, rel, "\u2253", "\\risingdotseq", true);
4298defineSymbol(math, ams, rel, "\u2252", "\\fallingdotseq", true);
4299defineSymbol(math, ams, rel, "\u223d", "\\backsim", true);
4300defineSymbol(math, ams, rel, "\u22cd", "\\backsimeq", true);
4301defineSymbol(math, ams, rel, "\u2ac5", "\\subseteqq", true);
4302defineSymbol(math, ams, rel, "\u22d0", "\\Subset", true);
4303defineSymbol(math, ams, rel, "\u228f", "\\sqsubset", true);
4304defineSymbol(math, ams, rel, "\u227c", "\\preccurlyeq", true);
4305defineSymbol(math, ams, rel, "\u22de", "\\curlyeqprec", true);
4306defineSymbol(math, ams, rel, "\u227e", "\\precsim", true);
4307defineSymbol(math, ams, rel, "\u2ab7", "\\precapprox", true);
4308defineSymbol(math, ams, rel, "\u22b2", "\\vartriangleleft");
4309defineSymbol(math, ams, rel, "\u22b4", "\\trianglelefteq");
4310defineSymbol(math, ams, rel, "\u22a8", "\\vDash", true);
4311defineSymbol(math, ams, rel, "\u22aa", "\\Vvdash", true);
4312defineSymbol(math, ams, rel, "\u2323", "\\smallsmile");
4313defineSymbol(math, ams, rel, "\u2322", "\\smallfrown");
4314defineSymbol(math, ams, rel, "\u224f", "\\bumpeq", true);
4315defineSymbol(math, ams, rel, "\u224e", "\\Bumpeq", true);
4316defineSymbol(math, ams, rel, "\u2267", "\\geqq", true);
4317defineSymbol(math, ams, rel, "\u2a7e", "\\geqslant", true);
4318defineSymbol(math, ams, rel, "\u2a96", "\\eqslantgtr", true);
4319defineSymbol(math, ams, rel, "\u2273", "\\gtrsim", true);
4320defineSymbol(math, ams, rel, "\u2a86", "\\gtrapprox", true);
4321defineSymbol(math, ams, bin, "\u22d7", "\\gtrdot");
4322defineSymbol(math, ams, rel, "\u22d9", "\\ggg", true);
4323defineSymbol(math, ams, rel, "\u2277", "\\gtrless", true);
4324defineSymbol(math, ams, rel, "\u22db", "\\gtreqless", true);
4325defineSymbol(math, ams, rel, "\u2a8c", "\\gtreqqless", true);
4326defineSymbol(math, ams, rel, "\u2256", "\\eqcirc", true);
4327defineSymbol(math, ams, rel, "\u2257", "\\circeq", true);
4328defineSymbol(math, ams, rel, "\u225c", "\\triangleq", true);
4329defineSymbol(math, ams, rel, "\u223c", "\\thicksim");
4330defineSymbol(math, ams, rel, "\u2248", "\\thickapprox");
4331defineSymbol(math, ams, rel, "\u2ac6", "\\supseteqq", true);
4332defineSymbol(math, ams, rel, "\u22d1", "\\Supset", true);
4333defineSymbol(math, ams, rel, "\u2290", "\\sqsupset", true);
4334defineSymbol(math, ams, rel, "\u227d", "\\succcurlyeq", true);
4335defineSymbol(math, ams, rel, "\u22df", "\\curlyeqsucc", true);
4336defineSymbol(math, ams, rel, "\u227f", "\\succsim", true);
4337defineSymbol(math, ams, rel, "\u2ab8", "\\succapprox", true);
4338defineSymbol(math, ams, rel, "\u22b3", "\\vartriangleright");
4339defineSymbol(math, ams, rel, "\u22b5", "\\trianglerighteq");
4340defineSymbol(math, ams, rel, "\u22a9", "\\Vdash", true);
4341defineSymbol(math, ams, rel, "\u2223", "\\shortmid");
4342defineSymbol(math, ams, rel, "\u2225", "\\shortparallel");
4343defineSymbol(math, ams, rel, "\u226c", "\\between", true);
4344defineSymbol(math, ams, rel, "\u22d4", "\\pitchfork", true);
4345defineSymbol(math, ams, rel, "\u221d", "\\varpropto");
4346defineSymbol(math, ams, rel, "\u25c0", "\\blacktriangleleft"); // unicode-math says that \therefore is a mathord atom.
4347// We kept the amssymb atom type, which is rel.
4348
4349defineSymbol(math, ams, rel, "\u2234", "\\therefore", true);
4350defineSymbol(math, ams, rel, "\u220d", "\\backepsilon");
4351defineSymbol(math, ams, rel, "\u25b6", "\\blacktriangleright"); // unicode-math says that \because is a mathord atom.
4352// We kept the amssymb atom type, which is rel.
4353
4354defineSymbol(math, ams, rel, "\u2235", "\\because", true);
4355defineSymbol(math, ams, rel, "\u22d8", "\\llless");
4356defineSymbol(math, ams, rel, "\u22d9", "\\gggtr");
4357defineSymbol(math, ams, bin, "\u22b2", "\\lhd");
4358defineSymbol(math, ams, bin, "\u22b3", "\\rhd");
4359defineSymbol(math, ams, rel, "\u2242", "\\eqsim", true);
4360defineSymbol(math, main, rel, "\u22c8", "\\Join");
4361defineSymbol(math, ams, rel, "\u2251", "\\Doteq", true); // AMS Binary Operators
4362
4363defineSymbol(math, ams, bin, "\u2214", "\\dotplus", true);
4364defineSymbol(math, ams, bin, "\u2216", "\\smallsetminus");
4365defineSymbol(math, ams, bin, "\u22d2", "\\Cap", true);
4366defineSymbol(math, ams, bin, "\u22d3", "\\Cup", true);
4367defineSymbol(math, ams, bin, "\u2a5e", "\\doublebarwedge", true);
4368defineSymbol(math, ams, bin, "\u229f", "\\boxminus", true);
4369defineSymbol(math, ams, bin, "\u229e", "\\boxplus", true);
4370defineSymbol(math, ams, bin, "\u22c7", "\\divideontimes", true);
4371defineSymbol(math, ams, bin, "\u22c9", "\\ltimes", true);
4372defineSymbol(math, ams, bin, "\u22ca", "\\rtimes", true);
4373defineSymbol(math, ams, bin, "\u22cb", "\\leftthreetimes", true);
4374defineSymbol(math, ams, bin, "\u22cc", "\\rightthreetimes", true);
4375defineSymbol(math, ams, bin, "\u22cf", "\\curlywedge", true);
4376defineSymbol(math, ams, bin, "\u22ce", "\\curlyvee", true);
4377defineSymbol(math, ams, bin, "\u229d", "\\circleddash", true);
4378defineSymbol(math, ams, bin, "\u229b", "\\circledast", true);
4379defineSymbol(math, ams, bin, "\u22c5", "\\centerdot");
4380defineSymbol(math, ams, bin, "\u22ba", "\\intercal", true);
4381defineSymbol(math, ams, bin, "\u22d2", "\\doublecap");
4382defineSymbol(math, ams, bin, "\u22d3", "\\doublecup");
4383defineSymbol(math, ams, bin, "\u22a0", "\\boxtimes", true); // AMS Arrows
4384// Note: unicode-math maps \u21e2 to their own function \rightdasharrow.
4385// We'll map it to AMS function \dashrightarrow. It produces the same atom.
4386
4387defineSymbol(math, ams, rel, "\u21e2", "\\dashrightarrow", true); // unicode-math maps \u21e0 to \leftdasharrow. We'll use the AMS synonym.
4388
4389defineSymbol(math, ams, rel, "\u21e0", "\\dashleftarrow", true);
4390defineSymbol(math, ams, rel, "\u21c7", "\\leftleftarrows", true);
4391defineSymbol(math, ams, rel, "\u21c6", "\\leftrightarrows", true);
4392defineSymbol(math, ams, rel, "\u21da", "\\Lleftarrow", true);
4393defineSymbol(math, ams, rel, "\u219e", "\\twoheadleftarrow", true);
4394defineSymbol(math, ams, rel, "\u21a2", "\\leftarrowtail", true);
4395defineSymbol(math, ams, rel, "\u21ab", "\\looparrowleft", true);
4396defineSymbol(math, ams, rel, "\u21cb", "\\leftrightharpoons", true);
4397defineSymbol(math, ams, rel, "\u21b6", "\\curvearrowleft", true); // unicode-math maps \u21ba to \acwopencirclearrow. We'll use the AMS synonym.
4398
4399defineSymbol(math, ams, rel, "\u21ba", "\\circlearrowleft", true);
4400defineSymbol(math, ams, rel, "\u21b0", "\\Lsh", true);
4401defineSymbol(math, ams, rel, "\u21c8", "\\upuparrows", true);
4402defineSymbol(math, ams, rel, "\u21bf", "\\upharpoonleft", true);
4403defineSymbol(math, ams, rel, "\u21c3", "\\downharpoonleft", true);
4404defineSymbol(math, ams, rel, "\u22b8", "\\multimap", true);
4405defineSymbol(math, ams, rel, "\u21ad", "\\leftrightsquigarrow", true);
4406defineSymbol(math, ams, rel, "\u21c9", "\\rightrightarrows", true);
4407defineSymbol(math, ams, rel, "\u21c4", "\\rightleftarrows", true);
4408defineSymbol(math, ams, rel, "\u21a0", "\\twoheadrightarrow", true);
4409defineSymbol(math, ams, rel, "\u21a3", "\\rightarrowtail", true);
4410defineSymbol(math, ams, rel, "\u21ac", "\\looparrowright", true);
4411defineSymbol(math, ams, rel, "\u21b7", "\\curvearrowright", true); // unicode-math maps \u21bb to \cwopencirclearrow. We'll use the AMS synonym.
4412
4413defineSymbol(math, ams, rel, "\u21bb", "\\circlearrowright", true);
4414defineSymbol(math, ams, rel, "\u21b1", "\\Rsh", true);
4415defineSymbol(math, ams, rel, "\u21ca", "\\downdownarrows", true);
4416defineSymbol(math, ams, rel, "\u21be", "\\upharpoonright", true);
4417defineSymbol(math, ams, rel, "\u21c2", "\\downharpoonright", true);
4418defineSymbol(math, ams, rel, "\u21dd", "\\rightsquigarrow", true);
4419defineSymbol(math, ams, rel, "\u21dd", "\\leadsto");
4420defineSymbol(math, ams, rel, "\u21db", "\\Rrightarrow", true);
4421defineSymbol(math, ams, rel, "\u21be", "\\restriction");
4422defineSymbol(math, main, textord, "\u2018", "`");
4423defineSymbol(math, main, textord, "$", "\\$");
4424defineSymbol(text$1, main, textord, "$", "\\$");
4425defineSymbol(text$1, main, textord, "$", "\\textdollar");
4426defineSymbol(math, main, textord, "%", "\\%");
4427defineSymbol(text$1, main, textord, "%", "\\%");
4428defineSymbol(math, main, textord, "_", "\\_");
4429defineSymbol(text$1, main, textord, "_", "\\_");
4430defineSymbol(text$1, main, textord, "_", "\\textunderscore");
4431defineSymbol(math, main, textord, "\u2220", "\\angle", true);
4432defineSymbol(math, main, textord, "\u221e", "\\infty", true);
4433defineSymbol(math, main, textord, "\u2032", "\\prime");
4434defineSymbol(math, main, textord, "\u25b3", "\\triangle");
4435defineSymbol(math, main, textord, "\u0393", "\\Gamma", true);
4436defineSymbol(math, main, textord, "\u0394", "\\Delta", true);
4437defineSymbol(math, main, textord, "\u0398", "\\Theta", true);
4438defineSymbol(math, main, textord, "\u039b", "\\Lambda", true);
4439defineSymbol(math, main, textord, "\u039e", "\\Xi", true);
4440defineSymbol(math, main, textord, "\u03a0", "\\Pi", true);
4441defineSymbol(math, main, textord, "\u03a3", "\\Sigma", true);
4442defineSymbol(math, main, textord, "\u03a5", "\\Upsilon", true);
4443defineSymbol(math, main, textord, "\u03a6", "\\Phi", true);
4444defineSymbol(math, main, textord, "\u03a8", "\\Psi", true);
4445defineSymbol(math, main, textord, "\u03a9", "\\Omega", true);
4446defineSymbol(math, main, textord, "A", "\u0391");
4447defineSymbol(math, main, textord, "B", "\u0392");
4448defineSymbol(math, main, textord, "E", "\u0395");
4449defineSymbol(math, main, textord, "Z", "\u0396");
4450defineSymbol(math, main, textord, "H", "\u0397");
4451defineSymbol(math, main, textord, "I", "\u0399");
4452defineSymbol(math, main, textord, "K", "\u039A");
4453defineSymbol(math, main, textord, "M", "\u039C");
4454defineSymbol(math, main, textord, "N", "\u039D");
4455defineSymbol(math, main, textord, "O", "\u039F");
4456defineSymbol(math, main, textord, "P", "\u03A1");
4457defineSymbol(math, main, textord, "T", "\u03A4");
4458defineSymbol(math, main, textord, "X", "\u03A7");
4459defineSymbol(math, main, textord, "\u00ac", "\\neg", true);
4460defineSymbol(math, main, textord, "\u00ac", "\\lnot");
4461defineSymbol(math, main, textord, "\u22a4", "\\top");
4462defineSymbol(math, main, textord, "\u22a5", "\\bot");
4463defineSymbol(math, main, textord, "\u2205", "\\emptyset");
4464defineSymbol(math, ams, textord, "\u2205", "\\varnothing");
4465defineSymbol(math, main, mathord, "\u03b1", "\\alpha", true);
4466defineSymbol(math, main, mathord, "\u03b2", "\\beta", true);
4467defineSymbol(math, main, mathord, "\u03b3", "\\gamma", true);
4468defineSymbol(math, main, mathord, "\u03b4", "\\delta", true);
4469defineSymbol(math, main, mathord, "\u03f5", "\\epsilon", true);
4470defineSymbol(math, main, mathord, "\u03b6", "\\zeta", true);
4471defineSymbol(math, main, mathord, "\u03b7", "\\eta", true);
4472defineSymbol(math, main, mathord, "\u03b8", "\\theta", true);
4473defineSymbol(math, main, mathord, "\u03b9", "\\iota", true);
4474defineSymbol(math, main, mathord, "\u03ba", "\\kappa", true);
4475defineSymbol(math, main, mathord, "\u03bb", "\\lambda", true);
4476defineSymbol(math, main, mathord, "\u03bc", "\\mu", true);
4477defineSymbol(math, main, mathord, "\u03bd", "\\nu", true);
4478defineSymbol(math, main, mathord, "\u03be", "\\xi", true);
4479defineSymbol(math, main, mathord, "\u03bf", "\\omicron", true);
4480defineSymbol(math, main, mathord, "\u03c0", "\\pi", true);
4481defineSymbol(math, main, mathord, "\u03c1", "\\rho", true);
4482defineSymbol(math, main, mathord, "\u03c3", "\\sigma", true);
4483defineSymbol(math, main, mathord, "\u03c4", "\\tau", true);
4484defineSymbol(math, main, mathord, "\u03c5", "\\upsilon", true);
4485defineSymbol(math, main, mathord, "\u03d5", "\\phi", true);
4486defineSymbol(math, main, mathord, "\u03c7", "\\chi", true);
4487defineSymbol(math, main, mathord, "\u03c8", "\\psi", true);
4488defineSymbol(math, main, mathord, "\u03c9", "\\omega", true);
4489defineSymbol(math, main, mathord, "\u03b5", "\\varepsilon", true);
4490defineSymbol(math, main, mathord, "\u03d1", "\\vartheta", true);
4491defineSymbol(math, main, mathord, "\u03d6", "\\varpi", true);
4492defineSymbol(math, main, mathord, "\u03f1", "\\varrho", true);
4493defineSymbol(math, main, mathord, "\u03c2", "\\varsigma", true);
4494defineSymbol(math, main, mathord, "\u03c6", "\\varphi", true);
4495defineSymbol(math, main, bin, "\u2217", "*");
4496defineSymbol(math, main, bin, "+", "+");
4497defineSymbol(math, main, bin, "\u2212", "-");
4498defineSymbol(math, main, bin, "\u22c5", "\\cdot", true);
4499defineSymbol(math, main, bin, "\u2218", "\\circ");
4500defineSymbol(math, main, bin, "\u00f7", "\\div", true);
4501defineSymbol(math, main, bin, "\u00b1", "\\pm", true);
4502defineSymbol(math, main, bin, "\u00d7", "\\times", true);
4503defineSymbol(math, main, bin, "\u2229", "\\cap", true);
4504defineSymbol(math, main, bin, "\u222a", "\\cup", true);
4505defineSymbol(math, main, bin, "\u2216", "\\setminus");
4506defineSymbol(math, main, bin, "\u2227", "\\land");
4507defineSymbol(math, main, bin, "\u2228", "\\lor");
4508defineSymbol(math, main, bin, "\u2227", "\\wedge", true);
4509defineSymbol(math, main, bin, "\u2228", "\\vee", true);
4510defineSymbol(math, main, textord, "\u221a", "\\surd");
4511defineSymbol(math, main, open, "(", "(");
4512defineSymbol(math, main, open, "[", "[");
4513defineSymbol(math, main, open, "\u27e8", "\\langle", true);
4514defineSymbol(math, main, open, "\u2223", "\\lvert");
4515defineSymbol(math, main, open, "\u2225", "\\lVert");
4516defineSymbol(math, main, close, ")", ")");
4517defineSymbol(math, main, close, "]", "]");
4518defineSymbol(math, main, close, "?", "?");
4519defineSymbol(math, main, close, "!", "!");
4520defineSymbol(math, main, close, "\u27e9", "\\rangle", true);
4521defineSymbol(math, main, close, "\u2223", "\\rvert");
4522defineSymbol(math, main, close, "\u2225", "\\rVert");
4523defineSymbol(math, main, rel, "=", "=");
4524defineSymbol(math, main, rel, "<", "<");
4525defineSymbol(math, main, rel, ">", ">");
4526defineSymbol(math, main, rel, ":", ":");
4527defineSymbol(math, main, rel, "\u2248", "\\approx", true);
4528defineSymbol(math, main, rel, "\u2245", "\\cong", true);
4529defineSymbol(math, main, rel, "\u2265", "\\ge");
4530defineSymbol(math, main, rel, "\u2265", "\\geq", true);
4531defineSymbol(math, main, rel, "\u2190", "\\gets");
4532defineSymbol(math, main, rel, ">", "\\gt");
4533defineSymbol(math, main, rel, "\u2208", "\\in", true);
4534defineSymbol(math, main, rel, "\ue020", "\\@not");
4535defineSymbol(math, main, rel, "\u2282", "\\subset", true);
4536defineSymbol(math, main, rel, "\u2283", "\\supset", true);
4537defineSymbol(math, main, rel, "\u2286", "\\subseteq", true);
4538defineSymbol(math, main, rel, "\u2287", "\\supseteq", true);
4539defineSymbol(math, ams, rel, "\u2288", "\\nsubseteq", true);
4540defineSymbol(math, ams, rel, "\u2289", "\\nsupseteq", true);
4541defineSymbol(math, main, rel, "\u22a8", "\\models");
4542defineSymbol(math, main, rel, "\u2190", "\\leftarrow", true);
4543defineSymbol(math, main, rel, "\u2264", "\\le");
4544defineSymbol(math, main, rel, "\u2264", "\\leq", true);
4545defineSymbol(math, main, rel, "<", "\\lt");
4546defineSymbol(math, main, rel, "\u2192", "\\rightarrow", true);
4547defineSymbol(math, main, rel, "\u2192", "\\to");
4548defineSymbol(math, ams, rel, "\u2271", "\\ngeq", true);
4549defineSymbol(math, ams, rel, "\u2270", "\\nleq", true);
4550defineSymbol(math, main, spacing, "\u00a0", "\\ ");
4551defineSymbol(math, main, spacing, "\u00a0", "~");
4552defineSymbol(math, main, spacing, "\u00a0", "\\space"); // Ref: LaTeX Source 2e: \DeclareRobustCommand{\nobreakspace}{%
4553
4554defineSymbol(math, main, spacing, "\u00a0", "\\nobreakspace");
4555defineSymbol(text$1, main, spacing, "\u00a0", "\\ ");
4556defineSymbol(text$1, main, spacing, "\u00a0", "~");
4557defineSymbol(text$1, main, spacing, "\u00a0", "\\space");
4558defineSymbol(text$1, main, spacing, "\u00a0", "\\nobreakspace");
4559defineSymbol(math, main, spacing, null, "\\nobreak");
4560defineSymbol(math, main, spacing, null, "\\allowbreak");
4561defineSymbol(math, main, punct, ",", ",");
4562defineSymbol(math, main, punct, ";", ";");
4563defineSymbol(math, ams, bin, "\u22bc", "\\barwedge", true);
4564defineSymbol(math, ams, bin, "\u22bb", "\\veebar", true);
4565defineSymbol(math, main, bin, "\u2299", "\\odot", true);
4566defineSymbol(math, main, bin, "\u2295", "\\oplus", true);
4567defineSymbol(math, main, bin, "\u2297", "\\otimes", true);
4568defineSymbol(math, main, textord, "\u2202", "\\partial", true);
4569defineSymbol(math, main, bin, "\u2298", "\\oslash", true);
4570defineSymbol(math, ams, bin, "\u229a", "\\circledcirc", true);
4571defineSymbol(math, ams, bin, "\u22a1", "\\boxdot", true);
4572defineSymbol(math, main, bin, "\u25b3", "\\bigtriangleup");
4573defineSymbol(math, main, bin, "\u25bd", "\\bigtriangledown");
4574defineSymbol(math, main, bin, "\u2020", "\\dagger");
4575defineSymbol(math, main, bin, "\u22c4", "\\diamond");
4576defineSymbol(math, main, bin, "\u22c6", "\\star");
4577defineSymbol(math, main, bin, "\u25c3", "\\triangleleft");
4578defineSymbol(math, main, bin, "\u25b9", "\\triangleright");
4579defineSymbol(math, main, open, "{", "\\{");
4580defineSymbol(text$1, main, textord, "{", "\\{");
4581defineSymbol(text$1, main, textord, "{", "\\textbraceleft");
4582defineSymbol(math, main, close, "}", "\\}");
4583defineSymbol(text$1, main, textord, "}", "\\}");
4584defineSymbol(text$1, main, textord, "}", "\\textbraceright");
4585defineSymbol(math, main, open, "{", "\\lbrace");
4586defineSymbol(math, main, close, "}", "\\rbrace");
4587defineSymbol(math, main, open, "[", "\\lbrack");
4588defineSymbol(text$1, main, textord, "[", "\\lbrack");
4589defineSymbol(math, main, close, "]", "\\rbrack");
4590defineSymbol(text$1, main, textord, "]", "\\rbrack");
4591defineSymbol(math, main, open, "(", "\\lparen");
4592defineSymbol(math, main, close, ")", "\\rparen");
4593defineSymbol(text$1, main, textord, "<", "\\textless"); // in T1 fontenc
4594
4595defineSymbol(text$1, main, textord, ">", "\\textgreater"); // in T1 fontenc
4596
4597defineSymbol(math, main, open, "\u230a", "\\lfloor", true);
4598defineSymbol(math, main, close, "\u230b", "\\rfloor", true);
4599defineSymbol(math, main, open, "\u2308", "\\lceil", true);
4600defineSymbol(math, main, close, "\u2309", "\\rceil", true);
4601defineSymbol(math, main, textord, "\\", "\\backslash");
4602defineSymbol(math, main, textord, "\u2223", "|");
4603defineSymbol(math, main, textord, "\u2223", "\\vert");
4604defineSymbol(text$1, main, textord, "|", "\\textbar"); // in T1 fontenc
4605
4606defineSymbol(math, main, textord, "\u2225", "\\|");
4607defineSymbol(math, main, textord, "\u2225", "\\Vert");
4608defineSymbol(text$1, main, textord, "\u2225", "\\textbardbl");
4609defineSymbol(text$1, main, textord, "~", "\\textasciitilde");
4610defineSymbol(text$1, main, textord, "\\", "\\textbackslash");
4611defineSymbol(text$1, main, textord, "^", "\\textasciicircum");
4612defineSymbol(math, main, rel, "\u2191", "\\uparrow", true);
4613defineSymbol(math, main, rel, "\u21d1", "\\Uparrow", true);
4614defineSymbol(math, main, rel, "\u2193", "\\downarrow", true);
4615defineSymbol(math, main, rel, "\u21d3", "\\Downarrow", true);
4616defineSymbol(math, main, rel, "\u2195", "\\updownarrow", true);
4617defineSymbol(math, main, rel, "\u21d5", "\\Updownarrow", true);
4618defineSymbol(math, main, op, "\u2210", "\\coprod");
4619defineSymbol(math, main, op, "\u22c1", "\\bigvee");
4620defineSymbol(math, main, op, "\u22c0", "\\bigwedge");
4621defineSymbol(math, main, op, "\u2a04", "\\biguplus");
4622defineSymbol(math, main, op, "\u22c2", "\\bigcap");
4623defineSymbol(math, main, op, "\u22c3", "\\bigcup");
4624defineSymbol(math, main, op, "\u222b", "\\int");
4625defineSymbol(math, main, op, "\u222b", "\\intop");
4626defineSymbol(math, main, op, "\u222c", "\\iint");
4627defineSymbol(math, main, op, "\u222d", "\\iiint");
4628defineSymbol(math, main, op, "\u220f", "\\prod");
4629defineSymbol(math, main, op, "\u2211", "\\sum");
4630defineSymbol(math, main, op, "\u2a02", "\\bigotimes");
4631defineSymbol(math, main, op, "\u2a01", "\\bigoplus");
4632defineSymbol(math, main, op, "\u2a00", "\\bigodot");
4633defineSymbol(math, main, op, "\u222e", "\\oint");
4634defineSymbol(math, main, op, "\u222f", "\\oiint");
4635defineSymbol(math, main, op, "\u2230", "\\oiiint");
4636defineSymbol(math, main, op, "\u2a06", "\\bigsqcup");
4637defineSymbol(math, main, op, "\u222b", "\\smallint");
4638defineSymbol(text$1, main, inner, "\u2026", "\\textellipsis");
4639defineSymbol(math, main, inner, "\u2026", "\\mathellipsis");
4640defineSymbol(text$1, main, inner, "\u2026", "\\ldots", true);
4641defineSymbol(math, main, inner, "\u2026", "\\ldots", true);
4642defineSymbol(math, main, inner, "\u22ef", "\\@cdots", true);
4643defineSymbol(math, main, inner, "\u22f1", "\\ddots", true);
4644defineSymbol(math, main, textord, "\u22ee", "\\varvdots"); // \vdots is a macro
4645
4646defineSymbol(math, main, accent, "\u02ca", "\\acute");
4647defineSymbol(math, main, accent, "\u02cb", "\\grave");
4648defineSymbol(math, main, accent, "\u00a8", "\\ddot");
4649defineSymbol(math, main, accent, "\u007e", "\\tilde");
4650defineSymbol(math, main, accent, "\u02c9", "\\bar");
4651defineSymbol(math, main, accent, "\u02d8", "\\breve");
4652defineSymbol(math, main, accent, "\u02c7", "\\check");
4653defineSymbol(math, main, accent, "\u005e", "\\hat");
4654defineSymbol(math, main, accent, "\u20d7", "\\vec");
4655defineSymbol(math, main, accent, "\u02d9", "\\dot");
4656defineSymbol(math, main, accent, "\u02da", "\\mathring");
4657defineSymbol(math, main, mathord, "\u0131", "\\imath", true);
4658defineSymbol(math, main, mathord, "\u0237", "\\jmath", true);
4659defineSymbol(text$1, main, textord, "\u0131", "\\i", true);
4660defineSymbol(text$1, main, textord, "\u0237", "\\j", true);
4661defineSymbol(text$1, main, textord, "\u00df", "\\ss", true);
4662defineSymbol(text$1, main, textord, "\u00e6", "\\ae", true);
4663defineSymbol(text$1, main, textord, "\u00e6", "\\ae", true);
4664defineSymbol(text$1, main, textord, "\u0153", "\\oe", true);
4665defineSymbol(text$1, main, textord, "\u00f8", "\\o", true);
4666defineSymbol(text$1, main, textord, "\u00c6", "\\AE", true);
4667defineSymbol(text$1, main, textord, "\u0152", "\\OE", true);
4668defineSymbol(text$1, main, textord, "\u00d8", "\\O", true);
4669defineSymbol(text$1, main, accent, "\u02ca", "\\'"); // acute
4670
4671defineSymbol(text$1, main, accent, "\u02cb", "\\`"); // grave
4672
4673defineSymbol(text$1, main, accent, "\u02c6", "\\^"); // circumflex
4674
4675defineSymbol(text$1, main, accent, "\u02dc", "\\~"); // tilde
4676
4677defineSymbol(text$1, main, accent, "\u02c9", "\\="); // macron
4678
4679defineSymbol(text$1, main, accent, "\u02d8", "\\u"); // breve
4680
4681defineSymbol(text$1, main, accent, "\u02d9", "\\."); // dot above
4682
4683defineSymbol(text$1, main, accent, "\u02da", "\\r"); // ring above
4684
4685defineSymbol(text$1, main, accent, "\u02c7", "\\v"); // caron
4686
4687defineSymbol(text$1, main, accent, "\u00a8", '\\"'); // diaresis
4688
4689defineSymbol(text$1, main, accent, "\u02dd", "\\H"); // double acute
4690
4691defineSymbol(text$1, main, accent, "\u25ef", "\\textcircled"); // \bigcirc glyph
4692// These ligatures are detected and created in Parser.js's `formLigatures`.
4693
4694const ligatures = {
4695  "--": true,
4696  "---": true,
4697  "``": true,
4698  "''": true
4699};
4700defineSymbol(text$1, main, textord, "\u2013", "--");
4701defineSymbol(text$1, main, textord, "\u2013", "\\textendash");
4702defineSymbol(text$1, main, textord, "\u2014", "---");
4703defineSymbol(text$1, main, textord, "\u2014", "\\textemdash");
4704defineSymbol(text$1, main, textord, "\u2018", "`");
4705defineSymbol(text$1, main, textord, "\u2018", "\\textquoteleft");
4706defineSymbol(text$1, main, textord, "\u2019", "'");
4707defineSymbol(text$1, main, textord, "\u2019", "\\textquoteright");
4708defineSymbol(text$1, main, textord, "\u201c", "``");
4709defineSymbol(text$1, main, textord, "\u201c", "\\textquotedblleft");
4710defineSymbol(text$1, main, textord, "\u201d", "''");
4711defineSymbol(text$1, main, textord, "\u201d", "\\textquotedblright"); //  \degree from gensymb package
4712
4713defineSymbol(math, main, textord, "\u00b0", "\\degree", true);
4714defineSymbol(text$1, main, textord, "\u00b0", "\\degree"); // \textdegree from inputenc package
4715
4716defineSymbol(text$1, main, textord, "\u00b0", "\\textdegree", true); // TODO: In LaTeX, \pounds can generate a different character in text and math
4717// mode, but among our fonts, only Main-Italic defines this character "163".
4718
4719defineSymbol(math, main, mathord, "\u00a3", "\\pounds");
4720defineSymbol(math, main, mathord, "\u00a3", "\\mathsterling", true);
4721defineSymbol(text$1, main, mathord, "\u00a3", "\\pounds");
4722defineSymbol(text$1, main, mathord, "\u00a3", "\\textsterling", true);
4723defineSymbol(math, ams, textord, "\u2720", "\\maltese");
4724defineSymbol(text$1, ams, textord, "\u2720", "\\maltese");
4725defineSymbol(text$1, main, spacing, "\u00a0", "\\ ");
4726defineSymbol(text$1, main, spacing, "\u00a0", " ");
4727defineSymbol(text$1, main, spacing, "\u00a0", "~"); // There are lots of symbols which are the same, so we add them in afterwards.
4728// All of these are textords in math mode
4729
4730const mathTextSymbols = "0123456789/@.\"";
4731
4732for (let i = 0; i < mathTextSymbols.length; i++) {
4733  const ch = mathTextSymbols.charAt(i);
4734  defineSymbol(math, main, textord, ch, ch);
4735} // All of these are textords in text mode
4736
4737
4738const textSymbols = "0123456789!@*()-=+[]<>|\";:?/.,";
4739
4740for (let i = 0; i < textSymbols.length; i++) {
4741  const ch = textSymbols.charAt(i);
4742  defineSymbol(text$1, main, textord, ch, ch);
4743} // All of these are textords in text mode, and mathords in math mode
4744
4745
4746const letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
4747
4748for (let i = 0; i < letters.length; i++) {
4749  const ch = letters.charAt(i);
4750  defineSymbol(math, main, mathord, ch, ch);
4751  defineSymbol(text$1, main, textord, ch, ch);
4752} // Blackboard bold and script letters in Unicode range
4753
4754
4755defineSymbol(math, ams, textord, "C", "\u2102"); // blackboard bold
4756
4757defineSymbol(text$1, ams, textord, "C", "\u2102");
4758defineSymbol(math, ams, textord, "H", "\u210D");
4759defineSymbol(text$1, ams, textord, "H", "\u210D");
4760defineSymbol(math, ams, textord, "N", "\u2115");
4761defineSymbol(text$1, ams, textord, "N", "\u2115");
4762defineSymbol(math, ams, textord, "P", "\u2119");
4763defineSymbol(text$1, ams, textord, "P", "\u2119");
4764defineSymbol(math, ams, textord, "Q", "\u211A");
4765defineSymbol(text$1, ams, textord, "Q", "\u211A");
4766defineSymbol(math, ams, textord, "R", "\u211D");
4767defineSymbol(text$1, ams, textord, "R", "\u211D");
4768defineSymbol(math, ams, textord, "Z", "\u2124");
4769defineSymbol(text$1, ams, textord, "Z", "\u2124");
4770defineSymbol(math, main, mathord, "h", "\u210E"); // italic h, Planck constant
4771
4772defineSymbol(text$1, main, mathord, "h", "\u210E"); // The next loop loads wide (surrogate pair) characters.
4773// We support some letters in the Unicode range U+1D400 to U+1D7FF,
4774// Mathematical Alphanumeric Symbols.
4775// Some editors do not deal well with wide characters. So don't write the
4776// string into this file. Instead, create the string from the surrogate pair.
4777
4778let wideChar = "";
4779
4780for (let i = 0; i < letters.length; i++) {
4781  const ch = letters.charAt(i); // The hex numbers in the next line are a surrogate pair.
4782  // 0xD835 is the high surrogate for all letters in the range we support.
4783  // 0xDC00 is the low surrogate for bold A.
4784
4785  wideChar = String.fromCharCode(0xD835, 0xDC00 + i); // A-Z a-z bold
4786
4787  defineSymbol(math, main, mathord, ch, wideChar);
4788  defineSymbol(text$1, main, textord, ch, wideChar);
4789  wideChar = String.fromCharCode(0xD835, 0xDC34 + i); // A-Z a-z italic
4790
4791  defineSymbol(math, main, mathord, ch, wideChar);
4792  defineSymbol(text$1, main, textord, ch, wideChar);
4793  wideChar = String.fromCharCode(0xD835, 0xDC68 + i); // A-Z a-z bold italic
4794
4795  defineSymbol(math, main, mathord, ch, wideChar);
4796  defineSymbol(text$1, main, textord, ch, wideChar);
4797  wideChar = String.fromCharCode(0xD835, 0xDD04 + i); // A-Z a-z Fractur
4798
4799  defineSymbol(math, main, mathord, ch, wideChar);
4800  defineSymbol(text$1, main, textord, ch, wideChar);
4801  wideChar = String.fromCharCode(0xD835, 0xDDA0 + i); // A-Z a-z sans-serif
4802
4803  defineSymbol(math, main, mathord, ch, wideChar);
4804  defineSymbol(text$1, main, textord, ch, wideChar);
4805  wideChar = String.fromCharCode(0xD835, 0xDDD4 + i); // A-Z a-z sans bold
4806
4807  defineSymbol(math, main, mathord, ch, wideChar);
4808  defineSymbol(text$1, main, textord, ch, wideChar);
4809  wideChar = String.fromCharCode(0xD835, 0xDE08 + i); // A-Z a-z sans italic
4810
4811  defineSymbol(math, main, mathord, ch, wideChar);
4812  defineSymbol(text$1, main, textord, ch, wideChar);
4813  wideChar = String.fromCharCode(0xD835, 0xDE70 + i); // A-Z a-z monospace
4814
4815  defineSymbol(math, main, mathord, ch, wideChar);
4816  defineSymbol(text$1, main, textord, ch, wideChar);
4817
4818  if (i < 26) {
4819    // KaTeX fonts have only capital letters for blackboard bold and script.
4820    // See exception for k below.
4821    wideChar = String.fromCharCode(0xD835, 0xDD38 + i); // A-Z double struck
4822
4823    defineSymbol(math, main, mathord, ch, wideChar);
4824    defineSymbol(text$1, main, textord, ch, wideChar);
4825    wideChar = String.fromCharCode(0xD835, 0xDC9C + i); // A-Z script
4826
4827    defineSymbol(math, main, mathord, ch, wideChar);
4828    defineSymbol(text$1, main, textord, ch, wideChar);
4829  } // TODO: Add bold script when it is supported by a KaTeX font.
4830
4831} // "k" is the only double struck lower case letter in the KaTeX fonts.
4832
4833
4834wideChar = String.fromCharCode(0xD835, 0xDD5C); // k double struck
4835
4836defineSymbol(math, main, mathord, "k", wideChar);
4837defineSymbol(text$1, main, textord, "k", wideChar); // Next, some wide character numerals
4838
4839for (let i = 0; i < 10; i++) {
4840  const ch = i.toString();
4841  wideChar = String.fromCharCode(0xD835, 0xDFCE + i); // 0-9 bold
4842
4843  defineSymbol(math, main, mathord, ch, wideChar);
4844  defineSymbol(text$1, main, textord, ch, wideChar);
4845  wideChar = String.fromCharCode(0xD835, 0xDFE2 + i); // 0-9 sans serif
4846
4847  defineSymbol(math, main, mathord, ch, wideChar);
4848  defineSymbol(text$1, main, textord, ch, wideChar);
4849  wideChar = String.fromCharCode(0xD835, 0xDFEC + i); // 0-9 bold sans
4850
4851  defineSymbol(math, main, mathord, ch, wideChar);
4852  defineSymbol(text$1, main, textord, ch, wideChar);
4853  wideChar = String.fromCharCode(0xD835, 0xDFF6 + i); // 0-9 monospace
4854
4855  defineSymbol(math, main, mathord, ch, wideChar);
4856  defineSymbol(text$1, main, textord, ch, wideChar);
4857} // We add these Latin-1 letters as symbols for backwards-compatibility,
4858// but they are not actually in the font, nor are they supported by the
4859// Unicode accent mechanism, so they fall back to Times font and look ugly.
4860// TODO(edemaine): Fix this.
4861
4862
4863const extraLatin = "ÇÐÞçþ";
4864
4865for (let i = 0; i < extraLatin.length; i++) {
4866  const ch = extraLatin.charAt(i);
4867  defineSymbol(math, main, mathord, ch, ch);
4868  defineSymbol(text$1, main, textord, ch, ch);
4869}
4870
4871defineSymbol(text$1, main, textord, "ð", "ð"); // Unicode versions of existing characters
4872
4873defineSymbol(text$1, main, textord, "\u2013", "–");
4874defineSymbol(text$1, main, textord, "\u2014", "—");
4875defineSymbol(text$1, main, textord, "\u2018", "‘");
4876defineSymbol(text$1, main, textord, "\u2019", "’");
4877defineSymbol(text$1, main, textord, "\u201c", "“");
4878defineSymbol(text$1, main, textord, "\u201d", "”");
4879
4880/**
4881 * This file provides support for Unicode range U+1D400 to U+1D7FF,
4882 * Mathematical Alphanumeric Symbols.
4883 *
4884 * Function wideCharacterFont takes a wide character as input and returns
4885 * the font information necessary to render it properly.
4886 */
4887/**
4888 * Data below is from https://www.unicode.org/charts/PDF/U1D400.pdf
4889 * That document sorts characters into groups by font type, say bold or italic.
4890 *
4891 * In the arrays below, each subarray consists three elements:
4892 *      * The CSS class of that group when in math mode.
4893 *      * The CSS class of that group when in text mode.
4894 *      * The font name, so that KaTeX can get font metrics.
4895 */
4896
4897const wideLatinLetterData = [["mathbf", "textbf", "Main-Bold"], // A-Z bold upright
4898["mathbf", "textbf", "Main-Bold"], // a-z bold upright
4899["mathdefault", "textit", "Math-Italic"], // A-Z italic
4900["mathdefault", "textit", "Math-Italic"], // a-z italic
4901["boldsymbol", "boldsymbol", "Main-BoldItalic"], // A-Z bold italic
4902["boldsymbol", "boldsymbol", "Main-BoldItalic"], // a-z bold italic
4903// Map fancy A-Z letters to script, not calligraphic.
4904// This aligns with unicode-math and math fonts (except Cambria Math).
4905["mathscr", "textscr", "Script-Regular"], // A-Z script
4906["", "", ""], // a-z script.  No font
4907["", "", ""], // A-Z bold script. No font
4908["", "", ""], // a-z bold script. No font
4909["mathfrak", "textfrak", "Fraktur-Regular"], // A-Z Fraktur
4910["mathfrak", "textfrak", "Fraktur-Regular"], // a-z Fraktur
4911["mathbb", "textbb", "AMS-Regular"], // A-Z double-struck
4912["mathbb", "textbb", "AMS-Regular"], // k double-struck
4913["", "", ""], // A-Z bold Fraktur No font metrics
4914["", "", ""], // a-z bold Fraktur.   No font.
4915["mathsf", "textsf", "SansSerif-Regular"], // A-Z sans-serif
4916["mathsf", "textsf", "SansSerif-Regular"], // a-z sans-serif
4917["mathboldsf", "textboldsf", "SansSerif-Bold"], // A-Z bold sans-serif
4918["mathboldsf", "textboldsf", "SansSerif-Bold"], // a-z bold sans-serif
4919["mathitsf", "textitsf", "SansSerif-Italic"], // A-Z italic sans-serif
4920["mathitsf", "textitsf", "SansSerif-Italic"], // a-z italic sans-serif
4921["", "", ""], // A-Z bold italic sans. No font
4922["", "", ""], // a-z bold italic sans. No font
4923["mathtt", "texttt", "Typewriter-Regular"], // A-Z monospace
4924["mathtt", "texttt", "Typewriter-Regular"]];
4925const wideNumeralData = [["mathbf", "textbf", "Main-Bold"], // 0-9 bold
4926["", "", ""], // 0-9 double-struck. No KaTeX font.
4927["mathsf", "textsf", "SansSerif-Regular"], // 0-9 sans-serif
4928["mathboldsf", "textboldsf", "SansSerif-Bold"], // 0-9 bold sans-serif
4929["mathtt", "texttt", "Typewriter-Regular"]];
4930const wideCharacterFont = function wideCharacterFont(wideChar, mode) {
4931  // IE doesn't support codePointAt(). So work with the surrogate pair.
4932  const H = wideChar.charCodeAt(0); // high surrogate
4933
4934  const L = wideChar.charCodeAt(1); // low surrogate
4935
4936  const codePoint = (H - 0xD800) * 0x400 + (L - 0xDC00) + 0x10000;
4937  const j = mode === "math" ? 0 : 1; // column index for CSS class.
4938
4939  if (0x1D400 <= codePoint && codePoint < 0x1D6A4) {
4940    // wideLatinLetterData contains exactly 26 chars on each row.
4941    // So we can calculate the relevant row. No traverse necessary.
4942    const i = Math.floor((codePoint - 0x1D400) / 26);
4943    return [wideLatinLetterData[i][2], wideLatinLetterData[i][j]];
4944  } else if (0x1D7CE <= codePoint && codePoint <= 0x1D7FF) {
4945    // Numerals, ten per row.
4946    const i = Math.floor((codePoint - 0x1D7CE) / 10);
4947    return [wideNumeralData[i][2], wideNumeralData[i][j]];
4948  } else if (codePoint === 0x1D6A5 || codePoint === 0x1D6A6) {
4949    // dotless i or j
4950    return [wideLatinLetterData[0][2], wideLatinLetterData[0][j]];
4951  } else if (0x1D6A6 < codePoint && codePoint < 0x1D7CE) {
4952    // Greek letters. Not supported, yet.
4953    return ["", ""];
4954  } else {
4955    // We don't support any wide characters outside 1D400–1D7FF.
4956    throw new ParseError("Unsupported character: " + wideChar);
4957  }
4958};
4959
4960/**
4961 * This file contains information about the options that the Parser carries
4962 * around with it while parsing. Data is held in an `Options` object, and when
4963 * recursing, a new `Options` object can be created with the `.with*` and
4964 * `.reset` functions.
4965 */
4966const sizeStyleMap = [// Each element contains [textsize, scriptsize, scriptscriptsize].
4967// The size mappings are taken from TeX with \normalsize=10pt.
4968[1, 1, 1], // size1: [5, 5, 5]              \tiny
4969[2, 1, 1], // size2: [6, 5, 5]
4970[3, 1, 1], // size3: [7, 5, 5]              \scriptsize
4971[4, 2, 1], // size4: [8, 6, 5]              \footnotesize
4972[5, 2, 1], // size5: [9, 6, 5]              \small
4973[6, 3, 1], // size6: [10, 7, 5]             \normalsize
4974[7, 4, 2], // size7: [12, 8, 6]             \large
4975[8, 6, 3], // size8: [14.4, 10, 7]          \Large
4976[9, 7, 6], // size9: [17.28, 12, 10]        \LARGE
4977[10, 8, 7], // size10: [20.74, 14.4, 12]     \huge
4978[11, 10, 9]];
4979const sizeMultipliers = [// fontMetrics.js:getGlobalMetrics also uses size indexes, so if
4980// you change size indexes, change that function.
49810.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.2, 1.44, 1.728, 2.074, 2.488];
4982
4983const sizeAtStyle = function sizeAtStyle(size, style) {
4984  return style.size < 2 ? size : sizeStyleMap[size - 1][style.size - 1];
4985}; // In these types, "" (empty string) means "no change".
4986
4987
4988/**
4989 * This is the main options class. It contains the current style, size, color,
4990 * and font.
4991 *
4992 * Options objects should not be modified. To create a new Options with
4993 * different properties, call a `.having*` method.
4994 */
4995class Options {
4996  // A font family applies to a group of fonts (i.e. SansSerif), while a font
4997  // represents a specific font (i.e. SansSerif Bold).
4998  // See: https://tex.stackexchange.com/questions/22350/difference-between-textrm-and-mathrm
4999
5000  /**
5001   * The base size index.
5002   */
5003  constructor(data) {
5004    this.style = void 0;
5005    this.color = void 0;
5006    this.size = void 0;
5007    this.textSize = void 0;
5008    this.phantom = void 0;
5009    this.font = void 0;
5010    this.fontFamily = void 0;
5011    this.fontWeight = void 0;
5012    this.fontShape = void 0;
5013    this.sizeMultiplier = void 0;
5014    this.maxSize = void 0;
5015    this.minRuleThickness = void 0;
5016    this._fontMetrics = void 0;
5017    this.style = data.style;
5018    this.color = data.color;
5019    this.size = data.size || Options.BASESIZE;
5020    this.textSize = data.textSize || this.size;
5021    this.phantom = !!data.phantom;
5022    this.font = data.font || "";
5023    this.fontFamily = data.fontFamily || "";
5024    this.fontWeight = data.fontWeight || '';
5025    this.fontShape = data.fontShape || '';
5026    this.sizeMultiplier = sizeMultipliers[this.size - 1];
5027    this.maxSize = data.maxSize;
5028    this.minRuleThickness = data.minRuleThickness;
5029    this._fontMetrics = undefined;
5030  }
5031  /**
5032   * Returns a new options object with the same properties as "this".  Properties
5033   * from "extension" will be copied to the new options object.
5034   */
5035
5036
5037  extend(extension) {
5038    const data = {
5039      style: this.style,
5040      size: this.size,
5041      textSize: this.textSize,
5042      color: this.color,
5043      phantom: this.phantom,
5044      font: this.font,
5045      fontFamily: this.fontFamily,
5046      fontWeight: this.fontWeight,
5047      fontShape: this.fontShape,
5048      maxSize: this.maxSize,
5049      minRuleThickness: this.minRuleThickness
5050    };
5051
5052    for (const key in extension) {
5053      if (extension.hasOwnProperty(key)) {
5054        data[key] = extension[key];
5055      }
5056    }
5057
5058    return new Options(data);
5059  }
5060  /**
5061   * Return an options object with the given style. If `this.style === style`,
5062   * returns `this`.
5063   */
5064
5065
5066  havingStyle(style) {
5067    if (this.style === style) {
5068      return this;
5069    } else {
5070      return this.extend({
5071        style: style,
5072        size: sizeAtStyle(this.textSize, style)
5073      });
5074    }
5075  }
5076  /**
5077   * Return an options object with a cramped version of the current style. If
5078   * the current style is cramped, returns `this`.
5079   */
5080
5081
5082  havingCrampedStyle() {
5083    return this.havingStyle(this.style.cramp());
5084  }
5085  /**
5086   * Return an options object with the given size and in at least `\textstyle`.
5087   * Returns `this` if appropriate.
5088   */
5089
5090
5091  havingSize(size) {
5092    if (this.size === size && this.textSize === size) {
5093      return this;
5094    } else {
5095      return this.extend({
5096        style: this.style.text(),
5097        size: size,
5098        textSize: size,
5099        sizeMultiplier: sizeMultipliers[size - 1]
5100      });
5101    }
5102  }
5103  /**
5104   * Like `this.havingSize(BASESIZE).havingStyle(style)`. If `style` is omitted,
5105   * changes to at least `\textstyle`.
5106   */
5107
5108
5109  havingBaseStyle(style) {
5110    style = style || this.style.text();
5111    const wantSize = sizeAtStyle(Options.BASESIZE, style);
5112
5113    if (this.size === wantSize && this.textSize === Options.BASESIZE && this.style === style) {
5114      return this;
5115    } else {
5116      return this.extend({
5117        style: style,
5118        size: wantSize
5119      });
5120    }
5121  }
5122  /**
5123   * Remove the effect of sizing changes such as \Huge.
5124   * Keep the effect of the current style, such as \scriptstyle.
5125   */
5126
5127
5128  havingBaseSizing() {
5129    let size;
5130
5131    switch (this.style.id) {
5132      case 4:
5133      case 5:
5134        size = 3; // normalsize in scriptstyle
5135
5136        break;
5137
5138      case 6:
5139      case 7:
5140        size = 1; // normalsize in scriptscriptstyle
5141
5142        break;
5143
5144      default:
5145        size = 6;
5146      // normalsize in textstyle or displaystyle
5147    }
5148
5149    return this.extend({
5150      style: this.style.text(),
5151      size: size
5152    });
5153  }
5154  /**
5155   * Create a new options object with the given color.
5156   */
5157
5158
5159  withColor(color) {
5160    return this.extend({
5161      color: color
5162    });
5163  }
5164  /**
5165   * Create a new options object with "phantom" set to true.
5166   */
5167
5168
5169  withPhantom() {
5170    return this.extend({
5171      phantom: true
5172    });
5173  }
5174  /**
5175   * Creates a new options object with the given math font or old text font.
5176   * @type {[type]}
5177   */
5178
5179
5180  withFont(font) {
5181    return this.extend({
5182      font
5183    });
5184  }
5185  /**
5186   * Create a new options objects with the given fontFamily.
5187   */
5188
5189
5190  withTextFontFamily(fontFamily) {
5191    return this.extend({
5192      fontFamily,
5193      font: ""
5194    });
5195  }
5196  /**
5197   * Creates a new options object with the given font weight
5198   */
5199
5200
5201  withTextFontWeight(fontWeight) {
5202    return this.extend({
5203      fontWeight,
5204      font: ""
5205    });
5206  }
5207  /**
5208   * Creates a new options object with the given font weight
5209   */
5210
5211
5212  withTextFontShape(fontShape) {
5213    return this.extend({
5214      fontShape,
5215      font: ""
5216    });
5217  }
5218  /**
5219   * Return the CSS sizing classes required to switch from enclosing options
5220   * `oldOptions` to `this`. Returns an array of classes.
5221   */
5222
5223
5224  sizingClasses(oldOptions) {
5225    if (oldOptions.size !== this.size) {
5226      return ["sizing", "reset-size" + oldOptions.size, "size" + this.size];
5227    } else {
5228      return [];
5229    }
5230  }
5231  /**
5232   * Return the CSS sizing classes required to switch to the base size. Like
5233   * `this.havingSize(BASESIZE).sizingClasses(this)`.
5234   */
5235
5236
5237  baseSizingClasses() {
5238    if (this.size !== Options.BASESIZE) {
5239      return ["sizing", "reset-size" + this.size, "size" + Options.BASESIZE];
5240    } else {
5241      return [];
5242    }
5243  }
5244  /**
5245   * Return the font metrics for this size.
5246   */
5247
5248
5249  fontMetrics() {
5250    if (!this._fontMetrics) {
5251      this._fontMetrics = getGlobalMetrics(this.size);
5252    }
5253
5254    return this._fontMetrics;
5255  }
5256  /**
5257   * Gets the CSS color of the current options object
5258   */
5259
5260
5261  getColor() {
5262    if (this.phantom) {
5263      return "transparent";
5264    } else {
5265      return this.color;
5266    }
5267  }
5268
5269}
5270
5271Options.BASESIZE = 6;
5272
5273/**
5274 * This file does conversion between units.  In particular, it provides
5275 * calculateSize to convert other units into ems.
5276 */
5277// Thus, multiplying a length by this number converts the length from units
5278// into pts.  Dividing the result by ptPerEm gives the number of ems
5279// *assuming* a font size of ptPerEm (normal size, normal style).
5280
5281const ptPerUnit = {
5282  // https://en.wikibooks.org/wiki/LaTeX/Lengths and
5283  // https://tex.stackexchange.com/a/8263
5284  "pt": 1,
5285  // TeX point
5286  "mm": 7227 / 2540,
5287  // millimeter
5288  "cm": 7227 / 254,
5289  // centimeter
5290  "in": 72.27,
5291  // inch
5292  "bp": 803 / 800,
5293  // big (PostScript) points
5294  "pc": 12,
5295  // pica
5296  "dd": 1238 / 1157,
5297  // didot
5298  "cc": 14856 / 1157,
5299  // cicero (12 didot)
5300  "nd": 685 / 642,
5301  // new didot
5302  "nc": 1370 / 107,
5303  // new cicero (12 new didot)
5304  "sp": 1 / 65536,
5305  // scaled point (TeX's internal smallest unit)
5306  // https://tex.stackexchange.com/a/41371
5307  "px": 803 / 800 // \pdfpxdimen defaults to 1 bp in pdfTeX and LuaTeX
5308
5309}; // Dictionary of relative units, for fast validity testing.
5310
5311const relativeUnit = {
5312  "ex": true,
5313  "em": true,
5314  "mu": true
5315};
5316
5317/**
5318 * Determine whether the specified unit (either a string defining the unit
5319 * or a "size" parse node containing a unit field) is valid.
5320 */
5321const validUnit = function validUnit(unit) {
5322  if (typeof unit !== "string") {
5323    unit = unit.unit;
5324  }
5325
5326  return unit in ptPerUnit || unit in relativeUnit || unit === "ex";
5327};
5328/*
5329 * Convert a "size" parse node (with numeric "number" and string "unit" fields,
5330 * as parsed by functions.js argType "size") into a CSS em value for the
5331 * current style/scale.  `options` gives the current options.
5332 */
5333
5334const calculateSize = function calculateSize(sizeValue, options) {
5335  let scale;
5336
5337  if (sizeValue.unit in ptPerUnit) {
5338    // Absolute units
5339    scale = ptPerUnit[sizeValue.unit] // Convert unit to pt
5340    / options.fontMetrics().ptPerEm // Convert pt to CSS em
5341    / options.sizeMultiplier; // Unscale to make absolute units
5342  } else if (sizeValue.unit === "mu") {
5343    // `mu` units scale with scriptstyle/scriptscriptstyle.
5344    scale = options.fontMetrics().cssEmPerMu;
5345  } else {
5346    // Other relative units always refer to the *textstyle* font
5347    // in the current size.
5348    let unitOptions;
5349
5350    if (options.style.isTight()) {
5351      // isTight() means current style is script/scriptscript.
5352      unitOptions = options.havingStyle(options.style.text());
5353    } else {
5354      unitOptions = options;
5355    } // TODO: In TeX these units are relative to the quad of the current
5356    // *text* font, e.g. cmr10. KaTeX instead uses values from the
5357    // comparably-sized *Computer Modern symbol* font. At 10pt, these
5358    // match. At 7pt and 5pt, they differ: cmr7=1.138894, cmsy7=1.170641;
5359    // cmr5=1.361133, cmsy5=1.472241. Consider $\scriptsize a\kern1emb$.
5360    // TeX \showlists shows a kern of 1.13889 * fontsize;
5361    // KaTeX shows a kern of 1.171 * fontsize.
5362
5363
5364    if (sizeValue.unit === "ex") {
5365      scale = unitOptions.fontMetrics().xHeight;
5366    } else if (sizeValue.unit === "em") {
5367      scale = unitOptions.fontMetrics().quad;
5368    } else {
5369      throw new ParseError("Invalid unit: '" + sizeValue.unit + "'");
5370    }
5371
5372    if (unitOptions !== options) {
5373      scale *= unitOptions.sizeMultiplier / options.sizeMultiplier;
5374    }
5375  }
5376
5377  return Math.min(sizeValue.number * scale, options.maxSize);
5378};
5379
5380/* eslint no-console:0 */
5381// The following have to be loaded from Main-Italic font, using class mathit
5382const mathitLetters = ["\\imath", "ı", // dotless i
5383"\\jmath", "ȷ", // dotless j
5384"\\pounds", "\\mathsterling", "\\textsterling", "£"];
5385/**
5386 * Looks up the given symbol in fontMetrics, after applying any symbol
5387 * replacements defined in symbol.js
5388 */
5389
5390const lookupSymbol = function lookupSymbol(value, // TODO(#963): Use a union type for this.
5391fontName, mode) {
5392  // Replace the value with its replaced value from symbol.js
5393  if (symbols[mode][value] && symbols[mode][value].replace) {
5394    value = symbols[mode][value].replace;
5395  }
5396
5397  return {
5398    value: value,
5399    metrics: getCharacterMetrics(value, fontName, mode)
5400  };
5401};
5402/**
5403 * Makes a symbolNode after translation via the list of symbols in symbols.js.
5404 * Correctly pulls out metrics for the character, and optionally takes a list of
5405 * classes to be attached to the node.
5406 *
5407 * TODO: make argument order closer to makeSpan
5408 * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which
5409 * should if present come first in `classes`.
5410 * TODO(#953): Make `options` mandatory and always pass it in.
5411 */
5412
5413
5414const makeSymbol = function makeSymbol(value, fontName, mode, options, classes) {
5415  const lookup = lookupSymbol(value, fontName, mode);
5416  const metrics = lookup.metrics;
5417  value = lookup.value;
5418  let symbolNode;
5419
5420  if (metrics) {
5421    let italic = metrics.italic;
5422
5423    if (mode === "text" || options && options.font === "mathit") {
5424      italic = 0;
5425    }
5426
5427    symbolNode = new SymbolNode(value, metrics.height, metrics.depth, italic, metrics.skew, metrics.width, classes);
5428  } else {
5429    // TODO(emily): Figure out a good way to only print this in development
5430    typeof console !== "undefined" && console.warn("No character metrics " + `for '${value}' in style '${fontName}' and mode '${mode}'`);
5431    symbolNode = new SymbolNode(value, 0, 0, 0, 0, 0, classes);
5432  }
5433
5434  if (options) {
5435    symbolNode.maxFontSize = options.sizeMultiplier;
5436
5437    if (options.style.isTight()) {
5438      symbolNode.classes.push("mtight");
5439    }
5440
5441    const color = options.getColor();
5442
5443    if (color) {
5444      symbolNode.style.color = color;
5445    }
5446  }
5447
5448  return symbolNode;
5449};
5450/**
5451 * Makes a symbol in Main-Regular or AMS-Regular.
5452 * Used for rel, bin, open, close, inner, and punct.
5453 */
5454
5455
5456const mathsym = function mathsym(value, mode, options, classes) {
5457  if (classes === void 0) {
5458    classes = [];
5459  }
5460
5461  // Decide what font to render the symbol in by its entry in the symbols
5462  // table.
5463  // Have a special case for when the value = \ because the \ is used as a
5464  // textord in unsupported command errors but cannot be parsed as a regular
5465  // text ordinal and is therefore not present as a symbol in the symbols
5466  // table for text, as well as a special case for boldsymbol because it
5467  // can be used for bold + and -
5468  if (options.font === "boldsymbol" && lookupSymbol(value, "Main-Bold", mode).metrics) {
5469    return makeSymbol(value, "Main-Bold", mode, options, classes.concat(["mathbf"]));
5470  } else if (value === "\\" || symbols[mode][value].font === "main") {
5471    return makeSymbol(value, "Main-Regular", mode, options, classes);
5472  } else {
5473    return makeSymbol(value, "AMS-Regular", mode, options, classes.concat(["amsrm"]));
5474  }
5475};
5476/**
5477 * Determines which of the two font names (Main-Italic and Math-Italic) and
5478 * corresponding style tags (maindefault or mathit) to use for default math font,
5479 * depending on the symbol.
5480 */
5481
5482
5483const mathdefault = function mathdefault(value, mode, options, classes) {
5484  if (/[0-9]/.test(value.charAt(0)) || // glyphs for \imath and \jmath do not exist in Math-Italic so we
5485  // need to use Main-Italic instead
5486  utils.contains(mathitLetters, value)) {
5487    return {
5488      fontName: "Main-Italic",
5489      fontClass: "mathit"
5490    };
5491  } else {
5492    return {
5493      fontName: "Math-Italic",
5494      fontClass: "mathdefault"
5495    };
5496  }
5497};
5498/**
5499 * Determines which of the font names (Main-Italic, Math-Italic, and Caligraphic)
5500 * and corresponding style tags (mathit, mathdefault, or mathcal) to use for font
5501 * "mathnormal", depending on the symbol.  Use this function instead of fontMap for
5502 * font "mathnormal".
5503 */
5504
5505
5506const mathnormal = function mathnormal(value, mode, options, classes) {
5507  if (utils.contains(mathitLetters, value)) {
5508    return {
5509      fontName: "Main-Italic",
5510      fontClass: "mathit"
5511    };
5512  } else if (/[0-9]/.test(value.charAt(0))) {
5513    return {
5514      fontName: "Caligraphic-Regular",
5515      fontClass: "mathcal"
5516    };
5517  } else {
5518    return {
5519      fontName: "Math-Italic",
5520      fontClass: "mathdefault"
5521    };
5522  }
5523};
5524/**
5525 * Determines which of the two font names (Main-Bold and Math-BoldItalic) and
5526 * corresponding style tags (mathbf or boldsymbol) to use for font "boldsymbol",
5527 * depending on the symbol.  Use this function instead of fontMap for font
5528 * "boldsymbol".
5529 */
5530
5531
5532const boldsymbol = function boldsymbol(value, mode, options, classes) {
5533  if (lookupSymbol(value, "Math-BoldItalic", mode).metrics) {
5534    return {
5535      fontName: "Math-BoldItalic",
5536      fontClass: "boldsymbol"
5537    };
5538  } else {
5539    // Some glyphs do not exist in Math-BoldItalic so we need to use
5540    // Main-Bold instead.
5541    return {
5542      fontName: "Main-Bold",
5543      fontClass: "mathbf"
5544    };
5545  }
5546};
5547/**
5548 * Makes either a mathord or textord in the correct font and color.
5549 */
5550
5551
5552const makeOrd = function makeOrd(group, options, type) {
5553  const mode = group.mode;
5554  const text = group.text;
5555  const classes = ["mord"]; // Math mode or Old font (i.e. \rm)
5556
5557  const isFont = mode === "math" || mode === "text" && options.font;
5558  const fontOrFamily = isFont ? options.font : options.fontFamily;
5559
5560  if (text.charCodeAt(0) === 0xD835) {
5561    // surrogate pairs get special treatment
5562    const _wideCharacterFont = wideCharacterFont(text, mode),
5563          wideFontName = _wideCharacterFont[0],
5564          wideFontClass = _wideCharacterFont[1];
5565
5566    return makeSymbol(text, wideFontName, mode, options, classes.concat(wideFontClass));
5567  } else if (fontOrFamily) {
5568    let fontName;
5569    let fontClasses;
5570
5571    if (fontOrFamily === "boldsymbol" || fontOrFamily === "mathnormal") {
5572      const fontData = fontOrFamily === "boldsymbol" ? boldsymbol(text, mode, options, classes) : mathnormal(text, mode, options, classes);
5573      fontName = fontData.fontName;
5574      fontClasses = [fontData.fontClass];
5575    } else if (utils.contains(mathitLetters, text)) {
5576      fontName = "Main-Italic";
5577      fontClasses = ["mathit"];
5578    } else if (isFont) {
5579      fontName = fontMap[fontOrFamily].fontName;
5580      fontClasses = [fontOrFamily];
5581    } else {
5582      fontName = retrieveTextFontName(fontOrFamily, options.fontWeight, options.fontShape);
5583      fontClasses = [fontOrFamily, options.fontWeight, options.fontShape];
5584    }
5585
5586    if (lookupSymbol(text, fontName, mode).metrics) {
5587      return makeSymbol(text, fontName, mode, options, classes.concat(fontClasses));
5588    } else if (ligatures.hasOwnProperty(text) && fontName.substr(0, 10) === "Typewriter") {
5589      // Deconstruct ligatures in monospace fonts (\texttt, \tt).
5590      const parts = [];
5591
5592      for (let i = 0; i < text.length; i++) {
5593        parts.push(makeSymbol(text[i], fontName, mode, options, classes.concat(fontClasses)));
5594      }
5595
5596      return makeFragment(parts);
5597    }
5598  } // Makes a symbol in the default font for mathords and textords.
5599
5600
5601  if (type === "mathord") {
5602    const fontLookup = mathdefault(text, mode, options, classes);
5603    return makeSymbol(text, fontLookup.fontName, mode, options, classes.concat([fontLookup.fontClass]));
5604  } else if (type === "textord") {
5605    const font = symbols[mode][text] && symbols[mode][text].font;
5606
5607    if (font === "ams") {
5608      const fontName = retrieveTextFontName("amsrm", options.fontWeight, options.fontShape);
5609      return makeSymbol(text, fontName, mode, options, classes.concat("amsrm", options.fontWeight, options.fontShape));
5610    } else if (font === "main" || !font) {
5611      const fontName = retrieveTextFontName("textrm", options.fontWeight, options.fontShape);
5612      return makeSymbol(text, fontName, mode, options, classes.concat(options.fontWeight, options.fontShape));
5613    } else {
5614      // fonts added by plugins
5615      const fontName = retrieveTextFontName(font, options.fontWeight, options.fontShape); // We add font name as a css class
5616
5617      return makeSymbol(text, fontName, mode, options, classes.concat(fontName, options.fontWeight, options.fontShape));
5618    }
5619  } else {
5620    throw new Error("unexpected type: " + type + " in makeOrd");
5621  }
5622};
5623/**
5624 * Returns true if subsequent symbolNodes have the same classes, skew, maxFont,
5625 * and styles.
5626 */
5627
5628
5629const canCombine = (prev, next) => {
5630  if (createClass(prev.classes) !== createClass(next.classes) || prev.skew !== next.skew || prev.maxFontSize !== next.maxFontSize) {
5631    return false;
5632  }
5633
5634  for (const style in prev.style) {
5635    if (prev.style.hasOwnProperty(style) && prev.style[style] !== next.style[style]) {
5636      return false;
5637    }
5638  }
5639
5640  for (const style in next.style) {
5641    if (next.style.hasOwnProperty(style) && prev.style[style] !== next.style[style]) {
5642      return false;
5643    }
5644  }
5645
5646  return true;
5647};
5648/**
5649 * Combine consequetive domTree.symbolNodes into a single symbolNode.
5650 * Note: this function mutates the argument.
5651 */
5652
5653
5654const tryCombineChars = chars => {
5655  for (let i = 0; i < chars.length - 1; i++) {
5656    const prev = chars[i];
5657    const next = chars[i + 1];
5658
5659    if (prev instanceof SymbolNode && next instanceof SymbolNode && canCombine(prev, next)) {
5660      prev.text += next.text;
5661      prev.height = Math.max(prev.height, next.height);
5662      prev.depth = Math.max(prev.depth, next.depth); // Use the last character's italic correction since we use
5663      // it to add padding to the right of the span created from
5664      // the combined characters.
5665
5666      prev.italic = next.italic;
5667      chars.splice(i + 1, 1);
5668      i--;
5669    }
5670  }
5671
5672  return chars;
5673};
5674/**
5675 * Calculate the height, depth, and maxFontSize of an element based on its
5676 * children.
5677 */
5678
5679
5680const sizeElementFromChildren = function sizeElementFromChildren(elem) {
5681  let height = 0;
5682  let depth = 0;
5683  let maxFontSize = 0;
5684
5685  for (let i = 0; i < elem.children.length; i++) {
5686    const child = elem.children[i];
5687
5688    if (child.height > height) {
5689      height = child.height;
5690    }
5691
5692    if (child.depth > depth) {
5693      depth = child.depth;
5694    }
5695
5696    if (child.maxFontSize > maxFontSize) {
5697      maxFontSize = child.maxFontSize;
5698    }
5699  }
5700
5701  elem.height = height;
5702  elem.depth = depth;
5703  elem.maxFontSize = maxFontSize;
5704};
5705/**
5706 * Makes a span with the given list of classes, list of children, and options.
5707 *
5708 * TODO(#953): Ensure that `options` is always provided (currently some call
5709 * sites don't pass it) and make the type below mandatory.
5710 * TODO: add a separate argument for math class (e.g. `mop`, `mbin`), which
5711 * should if present come first in `classes`.
5712 */
5713
5714
5715const makeSpan = function makeSpan(classes, children, options, style) {
5716  const span = new Span(classes, children, options, style);
5717  sizeElementFromChildren(span);
5718  return span;
5719}; // SVG one is simpler -- doesn't require height, depth, max-font setting.
5720// This is also a separate method for typesafety.
5721
5722
5723const makeSvgSpan = (classes, children, options, style) => new Span(classes, children, options, style);
5724
5725const makeLineSpan = function makeLineSpan(className, options, thickness) {
5726  const line = makeSpan([className], [], options);
5727  line.height = Math.max(thickness || options.fontMetrics().defaultRuleThickness, options.minRuleThickness);
5728  line.style.borderBottomWidth = line.height + "em";
5729  line.maxFontSize = 1.0;
5730  return line;
5731};
5732/**
5733 * Makes an anchor with the given href, list of classes, list of children,
5734 * and options.
5735 */
5736
5737
5738const makeAnchor = function makeAnchor(href, classes, children, options) {
5739  const anchor = new Anchor(href, classes, children, options);
5740  sizeElementFromChildren(anchor);
5741  return anchor;
5742};
5743/**
5744 * Makes a document fragment with the given list of children.
5745 */
5746
5747
5748const makeFragment = function makeFragment(children) {
5749  const fragment = new DocumentFragment(children);
5750  sizeElementFromChildren(fragment);
5751  return fragment;
5752};
5753/**
5754 * Wraps group in a span if it's a document fragment, allowing to apply classes
5755 * and styles
5756 */
5757
5758
5759const wrapFragment = function wrapFragment(group, options) {
5760  if (group instanceof DocumentFragment) {
5761    return makeSpan([], [group], options);
5762  }
5763
5764  return group;
5765}; // These are exact object types to catch typos in the names of the optional fields.
5766
5767
5768// Computes the updated `children` list and the overall depth.
5769//
5770// This helper function for makeVList makes it easier to enforce type safety by
5771// allowing early exits (returns) in the logic.
5772const getVListChildrenAndDepth = function getVListChildrenAndDepth(params) {
5773  if (params.positionType === "individualShift") {
5774    const oldChildren = params.children;
5775    const children = [oldChildren[0]]; // Add in kerns to the list of params.children to get each element to be
5776    // shifted to the correct specified shift
5777
5778    const depth = -oldChildren[0].shift - oldChildren[0].elem.depth;
5779    let currPos = depth;
5780
5781    for (let i = 1; i < oldChildren.length; i++) {
5782      const diff = -oldChildren[i].shift - currPos - oldChildren[i].elem.depth;
5783      const size = diff - (oldChildren[i - 1].elem.height + oldChildren[i - 1].elem.depth);
5784      currPos = currPos + diff;
5785      children.push({
5786        type: "kern",
5787        size
5788      });
5789      children.push(oldChildren[i]);
5790    }
5791
5792    return {
5793      children,
5794      depth
5795    };
5796  }
5797
5798  let depth;
5799
5800  if (params.positionType === "top") {
5801    // We always start at the bottom, so calculate the bottom by adding up
5802    // all the sizes
5803    let bottom = params.positionData;
5804
5805    for (let i = 0; i < params.children.length; i++) {
5806      const child = params.children[i];
5807      bottom -= child.type === "kern" ? child.size : child.elem.height + child.elem.depth;
5808    }
5809
5810    depth = bottom;
5811  } else if (params.positionType === "bottom") {
5812    depth = -params.positionData;
5813  } else {
5814    const firstChild = params.children[0];
5815
5816    if (firstChild.type !== "elem") {
5817      throw new Error('First child must have type "elem".');
5818    }
5819
5820    if (params.positionType === "shift") {
5821      depth = -firstChild.elem.depth - params.positionData;
5822    } else if (params.positionType === "firstBaseline") {
5823      depth = -firstChild.elem.depth;
5824    } else {
5825      throw new Error(`Invalid positionType ${params.positionType}.`);
5826    }
5827  }
5828
5829  return {
5830    children: params.children,
5831    depth
5832  };
5833};
5834/**
5835 * Makes a vertical list by stacking elements and kerns on top of each other.
5836 * Allows for many different ways of specifying the positioning method.
5837 *
5838 * See VListParam documentation above.
5839 */
5840
5841
5842const makeVList = function makeVList(params, options) {
5843  const _getVListChildrenAndD = getVListChildrenAndDepth(params),
5844        children = _getVListChildrenAndD.children,
5845        depth = _getVListChildrenAndD.depth; // Create a strut that is taller than any list item. The strut is added to
5846  // each item, where it will determine the item's baseline. Since it has
5847  // `overflow:hidden`, the strut's top edge will sit on the item's line box's
5848  // top edge and the strut's bottom edge will sit on the item's baseline,
5849  // with no additional line-height spacing. This allows the item baseline to
5850  // be positioned precisely without worrying about font ascent and
5851  // line-height.
5852
5853
5854  let pstrutSize = 0;
5855
5856  for (let i = 0; i < children.length; i++) {
5857    const child = children[i];
5858
5859    if (child.type === "elem") {
5860      const elem = child.elem;
5861      pstrutSize = Math.max(pstrutSize, elem.maxFontSize, elem.height);
5862    }
5863  }
5864
5865  pstrutSize += 2;
5866  const pstrut = makeSpan(["pstrut"], []);
5867  pstrut.style.height = pstrutSize + "em"; // Create a new list of actual children at the correct offsets
5868
5869  const realChildren = [];
5870  let minPos = depth;
5871  let maxPos = depth;
5872  let currPos = depth;
5873
5874  for (let i = 0; i < children.length; i++) {
5875    const child = children[i];
5876
5877    if (child.type === "kern") {
5878      currPos += child.size;
5879    } else {
5880      const elem = child.elem;
5881      const classes = child.wrapperClasses || [];
5882      const style = child.wrapperStyle || {};
5883      const childWrap = makeSpan(classes, [pstrut, elem], undefined, style);
5884      childWrap.style.top = -pstrutSize - currPos - elem.depth + "em";
5885
5886      if (child.marginLeft) {
5887        childWrap.style.marginLeft = child.marginLeft;
5888      }
5889
5890      if (child.marginRight) {
5891        childWrap.style.marginRight = child.marginRight;
5892      }
5893
5894      realChildren.push(childWrap);
5895      currPos += elem.height + elem.depth;
5896    }
5897
5898    minPos = Math.min(minPos, currPos);
5899    maxPos = Math.max(maxPos, currPos);
5900  } // The vlist contents go in a table-cell with `vertical-align:bottom`.
5901  // This cell's bottom edge will determine the containing table's baseline
5902  // without overly expanding the containing line-box.
5903
5904
5905  const vlist = makeSpan(["vlist"], realChildren);
5906  vlist.style.height = maxPos + "em"; // A second row is used if necessary to represent the vlist's depth.
5907
5908  let rows;
5909
5910  if (minPos < 0) {
5911    // We will define depth in an empty span with display: table-cell.
5912    // It should render with the height that we define. But Chrome, in
5913    // contenteditable mode only, treats that span as if it contains some
5914    // text content. And that min-height over-rides our desired height.
5915    // So we put another empty span inside the depth strut span.
5916    const emptySpan = makeSpan([], []);
5917    const depthStrut = makeSpan(["vlist"], [emptySpan]);
5918    depthStrut.style.height = -minPos + "em"; // Safari wants the first row to have inline content; otherwise it
5919    // puts the bottom of the *second* row on the baseline.
5920
5921    const topStrut = makeSpan(["vlist-s"], [new SymbolNode("\u200b")]);
5922    rows = [makeSpan(["vlist-r"], [vlist, topStrut]), makeSpan(["vlist-r"], [depthStrut])];
5923  } else {
5924    rows = [makeSpan(["vlist-r"], [vlist])];
5925  }
5926
5927  const vtable = makeSpan(["vlist-t"], rows);
5928
5929  if (rows.length === 2) {
5930    vtable.classes.push("vlist-t2");
5931  }
5932
5933  vtable.height = maxPos;
5934  vtable.depth = -minPos;
5935  return vtable;
5936}; // Glue is a concept from TeX which is a flexible space between elements in
5937// either a vertical or horizontal list. In KaTeX, at least for now, it's
5938// static space between elements in a horizontal layout.
5939
5940
5941const makeGlue = (measurement, options) => {
5942  // Make an empty span for the space
5943  const rule = makeSpan(["mspace"], [], options);
5944  const size = calculateSize(measurement, options);
5945  rule.style.marginRight = `${size}em`;
5946  return rule;
5947}; // Takes font options, and returns the appropriate fontLookup name
5948
5949
5950const retrieveTextFontName = function retrieveTextFontName(fontFamily, fontWeight, fontShape) {
5951  let baseFontName = "";
5952
5953  switch (fontFamily) {
5954    case "amsrm":
5955      baseFontName = "AMS";
5956      break;
5957
5958    case "textrm":
5959      baseFontName = "Main";
5960      break;
5961
5962    case "textsf":
5963      baseFontName = "SansSerif";
5964      break;
5965
5966    case "texttt":
5967      baseFontName = "Typewriter";
5968      break;
5969
5970    default:
5971      baseFontName = fontFamily;
5972    // use fonts added by a plugin
5973  }
5974
5975  let fontStylesName;
5976
5977  if (fontWeight === "textbf" && fontShape === "textit") {
5978    fontStylesName = "BoldItalic";
5979  } else if (fontWeight === "textbf") {
5980    fontStylesName = "Bold";
5981  } else if (fontWeight === "textit") {
5982    fontStylesName = "Italic";
5983  } else {
5984    fontStylesName = "Regular";
5985  }
5986
5987  return `${baseFontName}-${fontStylesName}`;
5988};
5989/**
5990 * Maps TeX font commands to objects containing:
5991 * - variant: string used for "mathvariant" attribute in buildMathML.js
5992 * - fontName: the "style" parameter to fontMetrics.getCharacterMetrics
5993 */
5994// A map between tex font commands an MathML mathvariant attribute values
5995
5996
5997const fontMap = {
5998  // styles
5999  "mathbf": {
6000    variant: "bold",
6001    fontName: "Main-Bold"
6002  },
6003  "mathrm": {
6004    variant: "normal",
6005    fontName: "Main-Regular"
6006  },
6007  "textit": {
6008    variant: "italic",
6009    fontName: "Main-Italic"
6010  },
6011  "mathit": {
6012    variant: "italic",
6013    fontName: "Main-Italic"
6014  },
6015  // Default math font, "mathnormal" and "boldsymbol" are missing because they
6016  // require the use of several fonts: Main-Italic and Math-Italic for default
6017  // math font, Main-Italic, Math-Italic, Caligraphic for "mathnormal", and
6018  // Math-BoldItalic and Main-Bold for "boldsymbol".  This is handled by a
6019  // special case in makeOrd which ends up calling mathdefault, mathnormal,
6020  // and boldsymbol.
6021  // families
6022  "mathbb": {
6023    variant: "double-struck",
6024    fontName: "AMS-Regular"
6025  },
6026  "mathcal": {
6027    variant: "script",
6028    fontName: "Caligraphic-Regular"
6029  },
6030  "mathfrak": {
6031    variant: "fraktur",
6032    fontName: "Fraktur-Regular"
6033  },
6034  "mathscr": {
6035    variant: "script",
6036    fontName: "Script-Regular"
6037  },
6038  "mathsf": {
6039    variant: "sans-serif",
6040    fontName: "SansSerif-Regular"
6041  },
6042  "mathtt": {
6043    variant: "monospace",
6044    fontName: "Typewriter-Regular"
6045  }
6046};
6047const svgData = {
6048  //   path, width, height
6049  vec: ["vec", 0.471, 0.714],
6050  // values from the font glyph
6051  oiintSize1: ["oiintSize1", 0.957, 0.499],
6052  // oval to overlay the integrand
6053  oiintSize2: ["oiintSize2", 1.472, 0.659],
6054  oiiintSize1: ["oiiintSize1", 1.304, 0.499],
6055  oiiintSize2: ["oiiintSize2", 1.98, 0.659]
6056};
6057
6058const staticSvg = function staticSvg(value, options) {
6059  // Create a span with inline SVG for the element.
6060  const _svgData$value = svgData[value],
6061        pathName = _svgData$value[0],
6062        width = _svgData$value[1],
6063        height = _svgData$value[2];
6064  const path = new PathNode(pathName);
6065  const svgNode = new SvgNode([path], {
6066    "width": width + "em",
6067    "height": height + "em",
6068    // Override CSS rule `.katex svg { width: 100% }`
6069    "style": "width:" + width + "em",
6070    "viewBox": "0 0 " + 1000 * width + " " + 1000 * height,
6071    "preserveAspectRatio": "xMinYMin"
6072  });
6073  const span = makeSvgSpan(["overlay"], [svgNode], options);
6074  span.height = height;
6075  span.style.height = height + "em";
6076  span.style.width = width + "em";
6077  return span;
6078};
6079
6080var buildCommon = {
6081  fontMap,
6082  makeSymbol,
6083  mathsym,
6084  makeSpan,
6085  makeSvgSpan,
6086  makeLineSpan,
6087  makeAnchor,
6088  makeFragment,
6089  wrapFragment,
6090  makeVList,
6091  makeOrd,
6092  makeGlue,
6093  staticSvg,
6094  svgData,
6095  tryCombineChars
6096};
6097
6098/**
6099 * Asserts that the node is of the given type and returns it with stricter
6100 * typing. Throws if the node's type does not match.
6101 */
6102function assertNodeType(node, type) {
6103  const typedNode = checkNodeType(node, type);
6104
6105  if (!typedNode) {
6106    throw new Error(`Expected node of type ${type}, but got ` + (node ? `node of type ${node.type}` : String(node)));
6107  } // $FlowFixMe: Unsure why.
6108
6109
6110  return typedNode;
6111}
6112/**
6113 * Returns the node more strictly typed iff it is of the given type. Otherwise,
6114 * returns null.
6115 */
6116
6117function checkNodeType(node, type) {
6118  if (node && node.type === type) {
6119    // The definition of ParseNode<TYPE> doesn't communicate to flow that
6120    // `type: TYPE` (as that's not explicitly mentioned anywhere), though that
6121    // happens to be true for all our value types.
6122    // $FlowFixMe
6123    return node;
6124  }
6125
6126  return null;
6127}
6128/**
6129 * Asserts that the node is of the given type and returns it with stricter
6130 * typing. Throws if the node's type does not match.
6131 */
6132
6133function assertAtomFamily(node, family) {
6134  const typedNode = checkAtomFamily(node, family);
6135
6136  if (!typedNode) {
6137    throw new Error(`Expected node of type "atom" and family "${family}", but got ` + (node ? node.type === "atom" ? `atom of family ${node.family}` : `node of type ${node.type}` : String(node)));
6138  }
6139
6140  return typedNode;
6141}
6142/**
6143 * Returns the node more strictly typed iff it is of the given type. Otherwise,
6144 * returns null.
6145 */
6146
6147function checkAtomFamily(node, family) {
6148  return node && node.type === "atom" && node.family === family ? node : null;
6149}
6150/**
6151 * Returns the node more strictly typed iff it is of the given type. Otherwise,
6152 * returns null.
6153 */
6154
6155function assertSymbolNodeType(node) {
6156  const typedNode = checkSymbolNodeType(node);
6157
6158  if (!typedNode) {
6159    throw new Error(`Expected node of symbol group type, but got ` + (node ? `node of type ${node.type}` : String(node)));
6160  }
6161
6162  return typedNode;
6163}
6164/**
6165 * Returns the node more strictly typed iff it is of the given type. Otherwise,
6166 * returns null.
6167 */
6168
6169function checkSymbolNodeType(node) {
6170  if (node && (node.type === "atom" || NON_ATOMS.hasOwnProperty(node.type))) {
6171    // $FlowFixMe
6172    return node;
6173  }
6174
6175  return null;
6176}
6177
6178/**
6179 * Describes spaces between different classes of atoms.
6180 */
6181const thinspace = {
6182  number: 3,
6183  unit: "mu"
6184};
6185const mediumspace = {
6186  number: 4,
6187  unit: "mu"
6188};
6189const thickspace = {
6190  number: 5,
6191  unit: "mu"
6192}; // Making the type below exact with all optional fields doesn't work due to
6193// - https://github.com/facebook/flow/issues/4582
6194// - https://github.com/facebook/flow/issues/5688
6195// However, since *all* fields are optional, $Shape<> works as suggested in 5688
6196// above.
6197
6198// Spacing relationships for display and text styles
6199const spacings = {
6200  mord: {
6201    mop: thinspace,
6202    mbin: mediumspace,
6203    mrel: thickspace,
6204    minner: thinspace
6205  },
6206  mop: {
6207    mord: thinspace,
6208    mop: thinspace,
6209    mrel: thickspace,
6210    minner: thinspace
6211  },
6212  mbin: {
6213    mord: mediumspace,
6214    mop: mediumspace,
6215    mopen: mediumspace,
6216    minner: mediumspace
6217  },
6218  mrel: {
6219    mord: thickspace,
6220    mop: thickspace,
6221    mopen: thickspace,
6222    minner: thickspace
6223  },
6224  mopen: {},
6225  mclose: {
6226    mop: thinspace,
6227    mbin: mediumspace,
6228    mrel: thickspace,
6229    minner: thinspace
6230  },
6231  mpunct: {
6232    mord: thinspace,
6233    mop: thinspace,
6234    mrel: thickspace,
6235    mopen: thinspace,
6236    mclose: thinspace,
6237    mpunct: thinspace,
6238    minner: thinspace
6239  },
6240  minner: {
6241    mord: thinspace,
6242    mop: thinspace,
6243    mbin: mediumspace,
6244    mrel: thickspace,
6245    mopen: thinspace,
6246    mpunct: thinspace,
6247    minner: thinspace
6248  }
6249}; // Spacing relationships for script and scriptscript styles
6250
6251const tightSpacings = {
6252  mord: {
6253    mop: thinspace
6254  },
6255  mop: {
6256    mord: thinspace,
6257    mop: thinspace
6258  },
6259  mbin: {},
6260  mrel: {},
6261  mopen: {},
6262  mclose: {
6263    mop: thinspace
6264  },
6265  mpunct: {},
6266  minner: {
6267    mop: thinspace
6268  }
6269};
6270
6271/**
6272 * All registered functions.
6273 * `functions.js` just exports this same dictionary again and makes it public.
6274 * `Parser.js` requires this dictionary.
6275 */
6276const _functions = {};
6277/**
6278 * All HTML builders. Should be only used in the `define*` and the `build*ML`
6279 * functions.
6280 */
6281
6282const _htmlGroupBuilders = {};
6283/**
6284 * All MathML builders. Should be only used in the `define*` and the `build*ML`
6285 * functions.
6286 */
6287
6288const _mathmlGroupBuilders = {};
6289function defineFunction(_ref) {
6290  let type = _ref.type,
6291      names = _ref.names,
6292      props = _ref.props,
6293      handler = _ref.handler,
6294      htmlBuilder = _ref.htmlBuilder,
6295      mathmlBuilder = _ref.mathmlBuilder;
6296  // Set default values of functions
6297  const data = {
6298    type,
6299    numArgs: props.numArgs,
6300    argTypes: props.argTypes,
6301    greediness: props.greediness === undefined ? 1 : props.greediness,
6302    allowedInText: !!props.allowedInText,
6303    allowedInMath: props.allowedInMath === undefined ? true : props.allowedInMath,
6304    numOptionalArgs: props.numOptionalArgs || 0,
6305    infix: !!props.infix,
6306    handler: handler
6307  };
6308
6309  for (let i = 0; i < names.length; ++i) {
6310    _functions[names[i]] = data;
6311  }
6312
6313  if (type) {
6314    if (htmlBuilder) {
6315      _htmlGroupBuilders[type] = htmlBuilder;
6316    }
6317
6318    if (mathmlBuilder) {
6319      _mathmlGroupBuilders[type] = mathmlBuilder;
6320    }
6321  }
6322}
6323/**
6324 * Use this to register only the HTML and MathML builders for a function (e.g.
6325 * if the function's ParseNode is generated in Parser.js rather than via a
6326 * stand-alone handler provided to `defineFunction`).
6327 */
6328
6329function defineFunctionBuilders(_ref2) {
6330  let type = _ref2.type,
6331      htmlBuilder = _ref2.htmlBuilder,
6332      mathmlBuilder = _ref2.mathmlBuilder;
6333  defineFunction({
6334    type,
6335    names: [],
6336    props: {
6337      numArgs: 0
6338    },
6339
6340    handler() {
6341      throw new Error('Should never be called.');
6342    },
6343
6344    htmlBuilder,
6345    mathmlBuilder
6346  });
6347} // Since the corresponding buildHTML/buildMathML function expects a
6348// list of elements, we normalize for different kinds of arguments
6349
6350const ordargument = function ordargument(arg) {
6351  const node = checkNodeType(arg, "ordgroup");
6352  return node ? node.body : [arg];
6353};
6354
6355/**
6356 * This file does the main work of building a domTree structure from a parse
6357 * tree. The entry point is the `buildHTML` function, which takes a parse tree.
6358 * Then, the buildExpression, buildGroup, and various groupBuilders functions
6359 * are called, to produce a final HTML tree.
6360 */
6361const makeSpan$1 = buildCommon.makeSpan; // Binary atoms (first class `mbin`) change into ordinary atoms (`mord`)
6362// depending on their surroundings. See TeXbook pg. 442-446, Rules 5 and 6,
6363// and the text before Rule 19.
6364
6365const binLeftCanceller = ["leftmost", "mbin", "mopen", "mrel", "mop", "mpunct"];
6366const binRightCanceller = ["rightmost", "mrel", "mclose", "mpunct"];
6367const styleMap = {
6368  "display": Style$1.DISPLAY,
6369  "text": Style$1.TEXT,
6370  "script": Style$1.SCRIPT,
6371  "scriptscript": Style$1.SCRIPTSCRIPT
6372};
6373const DomEnum = {
6374  mord: "mord",
6375  mop: "mop",
6376  mbin: "mbin",
6377  mrel: "mrel",
6378  mopen: "mopen",
6379  mclose: "mclose",
6380  mpunct: "mpunct",
6381  minner: "minner"
6382};
6383
6384/**
6385 * Take a list of nodes, build them in order, and return a list of the built
6386 * nodes. documentFragments are flattened into their contents, so the
6387 * returned list contains no fragments. `isRealGroup` is true if `expression`
6388 * is a real group (no atoms will be added on either side), as opposed to
6389 * a partial group (e.g. one created by \color). `surrounding` is an array
6390 * consisting type of nodes that will be added to the left and right.
6391 */
6392const buildExpression = function buildExpression(expression, options, isRealGroup, surrounding) {
6393  if (surrounding === void 0) {
6394    surrounding = [null, null];
6395  }
6396
6397  // Parse expressions into `groups`.
6398  const groups = [];
6399
6400  for (let i = 0; i < expression.length; i++) {
6401    const output = buildGroup(expression[i], options);
6402
6403    if (output instanceof DocumentFragment) {
6404      const children = output.children;
6405      groups.push(...children);
6406    } else {
6407      groups.push(output);
6408    }
6409  } // If `expression` is a partial group, let the parent handle spacings
6410  // to avoid processing groups multiple times.
6411
6412
6413  if (!isRealGroup) {
6414    return groups;
6415  }
6416
6417  let glueOptions = options;
6418
6419  if (expression.length === 1) {
6420    const node = checkNodeType(expression[0], "sizing") || checkNodeType(expression[0], "styling");
6421
6422    if (!node) ; else if (node.type === "sizing") {
6423      glueOptions = options.havingSize(node.size);
6424    } else if (node.type === "styling") {
6425      glueOptions = options.havingStyle(styleMap[node.style]);
6426    }
6427  } // Dummy spans for determining spacings between surrounding atoms.
6428  // If `expression` has no atoms on the left or right, class "leftmost"
6429  // or "rightmost", respectively, is used to indicate it.
6430
6431
6432  const dummyPrev = makeSpan$1([surrounding[0] || "leftmost"], [], options);
6433  const dummyNext = makeSpan$1([surrounding[1] || "rightmost"], [], options); // TODO: These code assumes that a node's math class is the first element
6434  // of its `classes` array. A later cleanup should ensure this, for
6435  // instance by changing the signature of `makeSpan`.
6436  // Before determining what spaces to insert, perform bin cancellation.
6437  // Binary operators change to ordinary symbols in some contexts.
6438
6439  traverseNonSpaceNodes(groups, (node, prev) => {
6440    const prevType = prev.classes[0];
6441    const type = node.classes[0];
6442
6443    if (prevType === "mbin" && utils.contains(binRightCanceller, type)) {
6444      prev.classes[0] = "mord";
6445    } else if (type === "mbin" && utils.contains(binLeftCanceller, prevType)) {
6446      node.classes[0] = "mord";
6447    }
6448  }, {
6449    node: dummyPrev
6450  }, dummyNext);
6451  traverseNonSpaceNodes(groups, (node, prev) => {
6452    const prevType = getTypeOfDomTree(prev);
6453    const type = getTypeOfDomTree(node); // 'mtight' indicates that the node is script or scriptscript style.
6454
6455    const space = prevType && type ? node.hasClass("mtight") ? tightSpacings[prevType][type] : spacings[prevType][type] : null;
6456
6457    if (space) {
6458      // Insert glue (spacing) after the `prev`.
6459      return buildCommon.makeGlue(space, glueOptions);
6460    }
6461  }, {
6462    node: dummyPrev
6463  }, dummyNext);
6464  return groups;
6465}; // Depth-first traverse non-space `nodes`, calling `callback` with the current and
6466// previous node as arguments, optionally returning a node to insert after the
6467// previous node. `prev` is an object with the previous node and `insertAfter`
6468// function to insert after it. `next` is a node that will be added to the right.
6469// Used for bin cancellation and inserting spacings.
6470
6471const traverseNonSpaceNodes = function traverseNonSpaceNodes(nodes, callback, prev, next) {
6472  if (next) {
6473    // temporarily append the right node, if exists
6474    nodes.push(next);
6475  }
6476
6477  let i = 0;
6478
6479  for (; i < nodes.length; i++) {
6480    const node = nodes[i];
6481    const partialGroup = checkPartialGroup(node);
6482
6483    if (partialGroup) {
6484      // Recursive DFS
6485      // $FlowFixMe: make nodes a $ReadOnlyArray by returning a new array
6486      traverseNonSpaceNodes(partialGroup.children, callback, prev);
6487      continue;
6488    } // Ignore explicit spaces (e.g., \;, \,) when determining what implicit
6489    // spacing should go between atoms of different classes
6490
6491
6492    if (node.classes[0] === "mspace") {
6493      continue;
6494    }
6495
6496    const result = callback(node, prev.node);
6497
6498    if (result) {
6499      if (prev.insertAfter) {
6500        prev.insertAfter(result);
6501      } else {
6502        // insert at front
6503        nodes.unshift(result);
6504        i++;
6505      }
6506    }
6507
6508    prev.node = node;
6509
6510    prev.insertAfter = (index => n => {
6511      nodes.splice(index + 1, 0, n);
6512      i++;
6513    })(i);
6514  }
6515
6516  if (next) {
6517    nodes.pop();
6518  }
6519}; // Check if given node is a partial group, i.e., does not affect spacing around.
6520
6521
6522const checkPartialGroup = function checkPartialGroup(node) {
6523  if (node instanceof DocumentFragment || node instanceof Anchor) {
6524    return node;
6525  }
6526
6527  return null;
6528}; // Return the outermost node of a domTree.
6529
6530
6531const getOutermostNode = function getOutermostNode(node, side) {
6532  const partialGroup = checkPartialGroup(node);
6533
6534  if (partialGroup) {
6535    const children = partialGroup.children;
6536
6537    if (children.length) {
6538      if (side === "right") {
6539        return getOutermostNode(children[children.length - 1], "right");
6540      } else if (side === "left") {
6541        return getOutermostNode(children[0], "left");
6542      }
6543    }
6544  }
6545
6546  return node;
6547}; // Return math atom class (mclass) of a domTree.
6548// If `side` is given, it will get the type of the outermost node at given side.
6549
6550
6551const getTypeOfDomTree = function getTypeOfDomTree(node, side) {
6552  if (!node) {
6553    return null;
6554  }
6555
6556  if (side) {
6557    node = getOutermostNode(node, side);
6558  } // This makes a lot of assumptions as to where the type of atom
6559  // appears.  We should do a better job of enforcing this.
6560
6561
6562  return DomEnum[node.classes[0]] || null;
6563};
6564const makeNullDelimiter = function makeNullDelimiter(options, classes) {
6565  const moreClasses = ["nulldelimiter"].concat(options.baseSizingClasses());
6566  return makeSpan$1(classes.concat(moreClasses));
6567};
6568/**
6569 * buildGroup is the function that takes a group and calls the correct groupType
6570 * function for it. It also handles the interaction of size and style changes
6571 * between parents and children.
6572 */
6573
6574const buildGroup = function buildGroup(group, options, baseOptions) {
6575  if (!group) {
6576    return makeSpan$1();
6577  }
6578
6579  if (_htmlGroupBuilders[group.type]) {
6580    // Call the groupBuilders function
6581    let groupNode = _htmlGroupBuilders[group.type](group, options); // If the size changed between the parent and the current group, account
6582    // for that size difference.
6583
6584    if (baseOptions && options.size !== baseOptions.size) {
6585      groupNode = makeSpan$1(options.sizingClasses(baseOptions), [groupNode], options);
6586      const multiplier = options.sizeMultiplier / baseOptions.sizeMultiplier;
6587      groupNode.height *= multiplier;
6588      groupNode.depth *= multiplier;
6589    }
6590
6591    return groupNode;
6592  } else {
6593    throw new ParseError("Got group of unknown type: '" + group.type + "'");
6594  }
6595};
6596/**
6597 * Combine an array of HTML DOM nodes (e.g., the output of `buildExpression`)
6598 * into an unbreakable HTML node of class .base, with proper struts to
6599 * guarantee correct vertical extent.  `buildHTML` calls this repeatedly to
6600 * make up the entire expression as a sequence of unbreakable units.
6601 */
6602
6603function buildHTMLUnbreakable(children, options) {
6604  // Compute height and depth of this chunk.
6605  const body = makeSpan$1(["base"], children, options); // Add strut, which ensures that the top of the HTML element falls at
6606  // the height of the expression, and the bottom of the HTML element
6607  // falls at the depth of the expression.
6608  // We used to have separate top and bottom struts, where the bottom strut
6609  // would like to use `vertical-align: top`, but in IE 9 this lowers the
6610  // baseline of the box to the bottom of this strut (instead of staying in
6611  // the normal place) so we use an absolute value for vertical-align instead.
6612
6613  const strut = makeSpan$1(["strut"]);
6614  strut.style.height = body.height + body.depth + "em";
6615  strut.style.verticalAlign = -body.depth + "em";
6616  body.children.unshift(strut);
6617  return body;
6618}
6619/**
6620 * Take an entire parse tree, and build it into an appropriate set of HTML
6621 * nodes.
6622 */
6623
6624
6625function buildHTML(tree, options) {
6626  // Strip off outer tag wrapper for processing below.
6627  let tag = null;
6628
6629  if (tree.length === 1 && tree[0].type === "tag") {
6630    tag = tree[0].tag;
6631    tree = tree[0].body;
6632  } // Build the expression contained in the tree
6633
6634
6635  const expression = buildExpression(tree, options, true);
6636  const children = []; // Create one base node for each chunk between potential line breaks.
6637  // The TeXBook [p.173] says "A formula will be broken only after a
6638  // relation symbol like $=$ or $<$ or $\rightarrow$, or after a binary
6639  // operation symbol like $+$ or $-$ or $\times$, where the relation or
6640  // binary operation is on the ``outer level'' of the formula (i.e., not
6641  // enclosed in {...} and not part of an \over construction)."
6642
6643  let parts = [];
6644
6645  for (let i = 0; i < expression.length; i++) {
6646    parts.push(expression[i]);
6647
6648    if (expression[i].hasClass("mbin") || expression[i].hasClass("mrel") || expression[i].hasClass("allowbreak")) {
6649      // Put any post-operator glue on same line as operator.
6650      // Watch for \nobreak along the way, and stop at \newline.
6651      let nobreak = false;
6652
6653      while (i < expression.length - 1 && expression[i + 1].hasClass("mspace") && !expression[i + 1].hasClass("newline")) {
6654        i++;
6655        parts.push(expression[i]);
6656
6657        if (expression[i].hasClass("nobreak")) {
6658          nobreak = true;
6659        }
6660      } // Don't allow break if \nobreak among the post-operator glue.
6661
6662
6663      if (!nobreak) {
6664        children.push(buildHTMLUnbreakable(parts, options));
6665        parts = [];
6666      }
6667    } else if (expression[i].hasClass("newline")) {
6668      // Write the line except the newline
6669      parts.pop();
6670
6671      if (parts.length > 0) {
6672        children.push(buildHTMLUnbreakable(parts, options));
6673        parts = [];
6674      } // Put the newline at the top level
6675
6676
6677      children.push(expression[i]);
6678    }
6679  }
6680
6681  if (parts.length > 0) {
6682    children.push(buildHTMLUnbreakable(parts, options));
6683  } // Now, if there was a tag, build it too and append it as a final child.
6684
6685
6686  let tagChild;
6687
6688  if (tag) {
6689    tagChild = buildHTMLUnbreakable(buildExpression(tag, options, true));
6690    tagChild.classes = ["tag"];
6691    children.push(tagChild);
6692  }
6693
6694  const htmlNode = makeSpan$1(["katex-html"], children);
6695  htmlNode.setAttribute("aria-hidden", "true"); // Adjust the strut of the tag to be the maximum height of all children
6696  // (the height of the enclosing htmlNode) for proper vertical alignment.
6697
6698  if (tagChild) {
6699    const strut = tagChild.children[0];
6700    strut.style.height = htmlNode.height + htmlNode.depth + "em";
6701    strut.style.verticalAlign = -htmlNode.depth + "em";
6702  }
6703
6704  return htmlNode;
6705}
6706
6707/**
6708 * These objects store data about MathML nodes. This is the MathML equivalent
6709 * of the types in domTree.js. Since MathML handles its own rendering, and
6710 * since we're mainly using MathML to improve accessibility, we don't manage
6711 * any of the styling state that the plain DOM nodes do.
6712 *
6713 * The `toNode` and `toMarkup` functions work simlarly to how they do in
6714 * domTree.js, creating namespaced DOM nodes and HTML text markup respectively.
6715 */
6716function newDocumentFragment(children) {
6717  return new DocumentFragment(children);
6718}
6719/**
6720 * This node represents a general purpose MathML node of any type. The
6721 * constructor requires the type of node to create (for example, `"mo"` or
6722 * `"mspace"`, corresponding to `<mo>` and `<mspace>` tags).
6723 */
6724
6725class MathNode {
6726  constructor(type, children) {
6727    this.type = void 0;
6728    this.attributes = void 0;
6729    this.children = void 0;
6730    this.type = type;
6731    this.attributes = {};
6732    this.children = children || [];
6733  }
6734  /**
6735   * Sets an attribute on a MathML node. MathML depends on attributes to convey a
6736   * semantic content, so this is used heavily.
6737   */
6738
6739
6740  setAttribute(name, value) {
6741    this.attributes[name] = value;
6742  }
6743  /**
6744   * Gets an attribute on a MathML node.
6745   */
6746
6747
6748  getAttribute(name) {
6749    return this.attributes[name];
6750  }
6751  /**
6752   * Converts the math node into a MathML-namespaced DOM element.
6753   */
6754
6755
6756  toNode() {
6757    const node = document.createElementNS("http://www.w3.org/1998/Math/MathML", this.type);
6758
6759    for (const attr in this.attributes) {
6760      if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
6761        node.setAttribute(attr, this.attributes[attr]);
6762      }
6763    }
6764
6765    for (let i = 0; i < this.children.length; i++) {
6766      node.appendChild(this.children[i].toNode());
6767    }
6768
6769    return node;
6770  }
6771  /**
6772   * Converts the math node into an HTML markup string.
6773   */
6774
6775
6776  toMarkup() {
6777    let markup = "<" + this.type; // Add the attributes
6778
6779    for (const attr in this.attributes) {
6780      if (Object.prototype.hasOwnProperty.call(this.attributes, attr)) {
6781        markup += " " + attr + "=\"";
6782        markup += utils.escape(this.attributes[attr]);
6783        markup += "\"";
6784      }
6785    }
6786
6787    markup += ">";
6788
6789    for (let i = 0; i < this.children.length; i++) {
6790      markup += this.children[i].toMarkup();
6791    }
6792
6793    markup += "</" + this.type + ">";
6794    return markup;
6795  }
6796  /**
6797   * Converts the math node into a string, similar to innerText, but escaped.
6798   */
6799
6800
6801  toText() {
6802    return this.children.map(child => child.toText()).join("");
6803  }
6804
6805}
6806/**
6807 * This node represents a piece of text.
6808 */
6809
6810class TextNode {
6811  constructor(text) {
6812    this.text = void 0;
6813    this.text = text;
6814  }
6815  /**
6816   * Converts the text node into a DOM text node.
6817   */
6818
6819
6820  toNode() {
6821    return document.createTextNode(this.text);
6822  }
6823  /**
6824   * Converts the text node into escaped HTML markup
6825   * (representing the text itself).
6826   */
6827
6828
6829  toMarkup() {
6830    return utils.escape(this.toText());
6831  }
6832  /**
6833   * Converts the text node into a string
6834   * (representing the text iteself).
6835   */
6836
6837
6838  toText() {
6839    return this.text;
6840  }
6841
6842}
6843/**
6844 * This node represents a space, but may render as <mspace.../> or as text,
6845 * depending on the width.
6846 */
6847
6848class SpaceNode {
6849  /**
6850   * Create a Space node with width given in CSS ems.
6851   */
6852  constructor(width) {
6853    this.width = void 0;
6854    this.character = void 0;
6855    this.width = width; // See https://www.w3.org/TR/2000/WD-MathML2-20000328/chapter6.html
6856    // for a table of space-like characters.  We use Unicode
6857    // representations instead of &LongNames; as it's not clear how to
6858    // make the latter via document.createTextNode.
6859
6860    if (width >= 0.05555 && width <= 0.05556) {
6861      this.character = "\u200a"; // &VeryThinSpace;
6862    } else if (width >= 0.1666 && width <= 0.1667) {
6863      this.character = "\u2009"; // &ThinSpace;
6864    } else if (width >= 0.2222 && width <= 0.2223) {
6865      this.character = "\u2005"; // &MediumSpace;
6866    } else if (width >= 0.2777 && width <= 0.2778) {
6867      this.character = "\u2005\u200a"; // &ThickSpace;
6868    } else if (width >= -0.05556 && width <= -0.05555) {
6869      this.character = "\u200a\u2063"; // &NegativeVeryThinSpace;
6870    } else if (width >= -0.1667 && width <= -0.1666) {
6871      this.character = "\u2009\u2063"; // &NegativeThinSpace;
6872    } else if (width >= -0.2223 && width <= -0.2222) {
6873      this.character = "\u205f\u2063"; // &NegativeMediumSpace;
6874    } else if (width >= -0.2778 && width <= -0.2777) {
6875      this.character = "\u2005\u2063"; // &NegativeThickSpace;
6876    } else {
6877      this.character = null;
6878    }
6879  }
6880  /**
6881   * Converts the math node into a MathML-namespaced DOM element.
6882   */
6883
6884
6885  toNode() {
6886    if (this.character) {
6887      return document.createTextNode(this.character);
6888    } else {
6889      const node = document.createElementNS("http://www.w3.org/1998/Math/MathML", "mspace");
6890      node.setAttribute("width", this.width + "em");
6891      return node;
6892    }
6893  }
6894  /**
6895   * Converts the math node into an HTML markup string.
6896   */
6897
6898
6899  toMarkup() {
6900    if (this.character) {
6901      return `<mtext>${this.character}</mtext>`;
6902    } else {
6903      return `<mspace width="${this.width}em"/>`;
6904    }
6905  }
6906  /**
6907   * Converts the math node into a string, similar to innerText.
6908   */
6909
6910
6911  toText() {
6912    if (this.character) {
6913      return this.character;
6914    } else {
6915      return " ";
6916    }
6917  }
6918
6919}
6920
6921var mathMLTree = {
6922  MathNode,
6923  TextNode,
6924  SpaceNode,
6925  newDocumentFragment
6926};
6927
6928/**
6929 * This file converts a parse tree into a cooresponding MathML tree. The main
6930 * entry point is the `buildMathML` function, which takes a parse tree from the
6931 * parser.
6932 */
6933
6934/**
6935 * Takes a symbol and converts it into a MathML text node after performing
6936 * optional replacement from symbols.js.
6937 */
6938const makeText = function makeText(text, mode, options) {
6939  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"))) {
6940    text = symbols[mode][text].replace;
6941  }
6942
6943  return new mathMLTree.TextNode(text);
6944};
6945/**
6946 * Wrap the given array of nodes in an <mrow> node if needed, i.e.,
6947 * unless the array has length 1.  Always returns a single node.
6948 */
6949
6950const makeRow = function makeRow(body) {
6951  if (body.length === 1) {
6952    return body[0];
6953  } else {
6954    return new mathMLTree.MathNode("mrow", body);
6955  }
6956};
6957/**
6958 * Returns the math variant as a string or null if none is required.
6959 */
6960
6961const getVariant = function getVariant(group, options) {
6962  // Handle \text... font specifiers as best we can.
6963  // MathML has a limited list of allowable mathvariant specifiers; see
6964  // https://www.w3.org/TR/MathML3/chapter3.html#presm.commatt
6965  if (options.fontFamily === "texttt") {
6966    return "monospace";
6967  } else if (options.fontFamily === "textsf") {
6968    if (options.fontShape === "textit" && options.fontWeight === "textbf") {
6969      return "sans-serif-bold-italic";
6970    } else if (options.fontShape === "textit") {
6971      return "sans-serif-italic";
6972    } else if (options.fontWeight === "textbf") {
6973      return "bold-sans-serif";
6974    } else {
6975      return "sans-serif";
6976    }
6977  } else if (options.fontShape === "textit" && options.fontWeight === "textbf") {
6978    return "bold-italic";
6979  } else if (options.fontShape === "textit") {
6980    return "italic";
6981  } else if (options.fontWeight === "textbf") {
6982    return "bold";
6983  }
6984
6985  const font = options.font;
6986
6987  if (!font || font === "mathnormal") {
6988    return null;
6989  }
6990
6991  const mode = group.mode;
6992
6993  if (font === "mathit") {
6994    return "italic";
6995  } else if (font === "boldsymbol") {
6996    return "bold-italic";
6997  } else if (font === "mathbf") {
6998    return "bold";
6999  } else if (font === "mathbb") {
7000    return "double-struck";
7001  } else if (font === "mathfrak") {
7002    return "fraktur";
7003  } else if (font === "mathscr" || font === "mathcal") {
7004    // MathML makes no distinction between script and caligrahpic
7005    return "script";
7006  } else if (font === "mathsf") {
7007    return "sans-serif";
7008  } else if (font === "mathtt") {
7009    return "monospace";
7010  }
7011
7012  let text = group.text;
7013
7014  if (utils.contains(["\\imath", "\\jmath"], text)) {
7015    return null;
7016  }
7017
7018  if (symbols[mode][text] && symbols[mode][text].replace) {
7019    text = symbols[mode][text].replace;
7020  }
7021
7022  const fontName = buildCommon.fontMap[font].fontName;
7023
7024  if (getCharacterMetrics(text, fontName, mode)) {
7025    return buildCommon.fontMap[font].variant;
7026  }
7027
7028  return null;
7029};
7030/**
7031 * Takes a list of nodes, builds them, and returns a list of the generated
7032 * MathML nodes.  Also combine consecutive <mtext> outputs into a single
7033 * <mtext> tag.
7034 */
7035
7036const buildExpression$1 = function buildExpression(expression, options, isOrdgroup) {
7037  if (expression.length === 1) {
7038    const group = buildGroup$1(expression[0], options);
7039
7040    if (isOrdgroup && group instanceof MathNode && group.type === "mo") {
7041      // When TeX writers want to suppress spacing on an operator,
7042      // they often put the operator by itself inside braces.
7043      group.setAttribute("lspace", "0em");
7044      group.setAttribute("rspace", "0em");
7045    }
7046
7047    return [group];
7048  }
7049
7050  const groups = [];
7051  let lastGroup;
7052
7053  for (let i = 0; i < expression.length; i++) {
7054    const group = buildGroup$1(expression[i], options);
7055
7056    if (group instanceof MathNode && lastGroup instanceof MathNode) {
7057      // Concatenate adjacent <mtext>s
7058      if (group.type === 'mtext' && lastGroup.type === 'mtext' && group.getAttribute('mathvariant') === lastGroup.getAttribute('mathvariant')) {
7059        lastGroup.children.push(...group.children);
7060        continue; // Concatenate adjacent <mn>s
7061      } else if (group.type === 'mn' && lastGroup.type === 'mn') {
7062        lastGroup.children.push(...group.children);
7063        continue; // Concatenate <mn>...</mn> followed by <mi>.</mi>
7064      } else if (group.type === 'mi' && group.children.length === 1 && lastGroup.type === 'mn') {
7065        const child = group.children[0];
7066
7067        if (child instanceof TextNode && child.text === '.') {
7068          lastGroup.children.push(...group.children);
7069          continue;
7070        }
7071      } else if (lastGroup.type === 'mi' && lastGroup.children.length === 1) {
7072        const lastChild = lastGroup.children[0];
7073
7074        if (lastChild instanceof TextNode && lastChild.text === '\u0338' && (group.type === 'mo' || group.type === 'mi' || group.type === 'mn')) {
7075          const child = group.children[0];
7076
7077          if (child instanceof TextNode && child.text.length > 0) {
7078            // Overlay with combining character long solidus
7079            child.text = child.text.slice(0, 1) + "\u0338" + child.text.slice(1);
7080            groups.pop();
7081          }
7082        }
7083      }
7084    }
7085
7086    groups.push(group);
7087    lastGroup = group;
7088  }
7089
7090  return groups;
7091};
7092/**
7093 * Equivalent to buildExpression, but wraps the elements in an <mrow>
7094 * if there's more than one.  Returns a single node instead of an array.
7095 */
7096
7097const buildExpressionRow = function buildExpressionRow(expression, options, isOrdgroup) {
7098  return makeRow(buildExpression$1(expression, options, isOrdgroup));
7099};
7100/**
7101 * Takes a group from the parser and calls the appropriate groupBuilders function
7102 * on it to produce a MathML node.
7103 */
7104
7105const buildGroup$1 = function buildGroup(group, options) {
7106  if (!group) {
7107    return new mathMLTree.MathNode("mrow");
7108  }
7109
7110  if (_mathmlGroupBuilders[group.type]) {
7111    // Call the groupBuilders function
7112    const result = _mathmlGroupBuilders[group.type](group, options);
7113    return result;
7114  } else {
7115    throw new ParseError("Got group of unknown type: '" + group.type + "'");
7116  }
7117};
7118/**
7119 * Takes a full parse tree and settings and builds a MathML representation of
7120 * it. In particular, we put the elements from building the parse tree into a
7121 * <semantics> tag so we can also include that TeX source as an annotation.
7122 *
7123 * Note that we actually return a domTree element with a `<math>` inside it so
7124 * we can do appropriate styling.
7125 */
7126
7127function buildMathML(tree, texExpression, options, forMathmlOnly) {
7128  const expression = buildExpression$1(tree, options); // Wrap up the expression in an mrow so it is presented in the semantics
7129  // tag correctly, unless it's a single <mrow> or <mtable>.
7130
7131  let wrapper;
7132
7133  if (expression.length === 1 && expression[0] instanceof MathNode && utils.contains(["mrow", "mtable"], expression[0].type)) {
7134    wrapper = expression[0];
7135  } else {
7136    wrapper = new mathMLTree.MathNode("mrow", expression);
7137  } // Build a TeX annotation of the source
7138
7139
7140  const annotation = new mathMLTree.MathNode("annotation", [new mathMLTree.TextNode(texExpression)]);
7141  annotation.setAttribute("encoding", "application/x-tex");
7142  const semantics = new mathMLTree.MathNode("semantics", [wrapper, annotation]);
7143  const math = new mathMLTree.MathNode("math", [semantics]);
7144  math.setAttribute("xmlns", "http://www.w3.org/1998/Math/MathML"); // You can't style <math> nodes, so we wrap the node in a span.
7145  // NOTE: The span class is not typed to have <math> nodes as children, and
7146  // we don't want to make the children type more generic since the children
7147  // of span are expected to have more fields in `buildHtml` contexts.
7148
7149  const wrapperClass = forMathmlOnly ? "katex" : "katex-mathml"; // $FlowFixMe
7150
7151  return buildCommon.makeSpan([wrapperClass], [math]);
7152}
7153
7154const optionsFromSettings = function optionsFromSettings(settings) {
7155  return new Options({
7156    style: settings.displayMode ? Style$1.DISPLAY : Style$1.TEXT,
7157    maxSize: settings.maxSize,
7158    minRuleThickness: settings.minRuleThickness
7159  });
7160};
7161
7162const displayWrap = function displayWrap(node, settings) {
7163  if (settings.displayMode) {
7164    const classes = ["katex-display"];
7165
7166    if (settings.leqno) {
7167      classes.push("leqno");
7168    }
7169
7170    if (settings.fleqn) {
7171      classes.push("fleqn");
7172    }
7173
7174    node = buildCommon.makeSpan(classes, [node]);
7175  }
7176
7177  return node;
7178};
7179
7180const buildTree = function buildTree(tree, expression, settings) {
7181  const options = optionsFromSettings(settings);
7182  let katexNode;
7183
7184  if (settings.output === "mathml") {
7185    return buildMathML(tree, expression, options, true);
7186  } else if (settings.output === "html") {
7187    const htmlNode = buildHTML(tree, options);
7188    katexNode = buildCommon.makeSpan(["katex"], [htmlNode]);
7189  } else {
7190    const mathMLNode = buildMathML(tree, expression, options, false);
7191    const htmlNode = buildHTML(tree, options);
7192    katexNode = buildCommon.makeSpan(["katex"], [mathMLNode, htmlNode]);
7193  }
7194
7195  return displayWrap(katexNode, settings);
7196};
7197const buildHTMLTree = function buildHTMLTree(tree, expression, settings) {
7198  const options = optionsFromSettings(settings);
7199  const htmlNode = buildHTML(tree, options);
7200  const katexNode = buildCommon.makeSpan(["katex"], [htmlNode]);
7201  return displayWrap(katexNode, settings);
7202};
7203
7204/**
7205 * This file provides support to buildMathML.js and buildHTML.js
7206 * for stretchy wide elements rendered from SVG files
7207 * and other CSS trickery.
7208 */
7209const stretchyCodePoint = {
7210  widehat: "^",
7211  widecheck: "ˇ",
7212  widetilde: "~",
7213  utilde: "~",
7214  overleftarrow: "\u2190",
7215  underleftarrow: "\u2190",
7216  xleftarrow: "\u2190",
7217  overrightarrow: "\u2192",
7218  underrightarrow: "\u2192",
7219  xrightarrow: "\u2192",
7220  underbrace: "\u23df",
7221  overbrace: "\u23de",
7222  overgroup: "\u23e0",
7223  undergroup: "\u23e1",
7224  overleftrightarrow: "\u2194",
7225  underleftrightarrow: "\u2194",
7226  xleftrightarrow: "\u2194",
7227  Overrightarrow: "\u21d2",
7228  xRightarrow: "\u21d2",
7229  overleftharpoon: "\u21bc",
7230  xleftharpoonup: "\u21bc",
7231  overrightharpoon: "\u21c0",
7232  xrightharpoonup: "\u21c0",
7233  xLeftarrow: "\u21d0",
7234  xLeftrightarrow: "\u21d4",
7235  xhookleftarrow: "\u21a9",
7236  xhookrightarrow: "\u21aa",
7237  xmapsto: "\u21a6",
7238  xrightharpoondown: "\u21c1",
7239  xleftharpoondown: "\u21bd",
7240  xrightleftharpoons: "\u21cc",
7241  xleftrightharpoons: "\u21cb",
7242  xtwoheadleftarrow: "\u219e",
7243  xtwoheadrightarrow: "\u21a0",
7244  xlongequal: "=",
7245  xtofrom: "\u21c4",
7246  xrightleftarrows: "\u21c4",
7247  xrightequilibrium: "\u21cc",
7248  // Not a perfect match.
7249  xleftequilibrium: "\u21cb" // None better available.
7250
7251};
7252
7253const mathMLnode = function mathMLnode(label) {
7254  const node = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode(stretchyCodePoint[label.substr(1)])]);
7255  node.setAttribute("stretchy", "true");
7256  return node;
7257}; // Many of the KaTeX SVG images have been adapted from glyphs in KaTeX fonts.
7258// Copyright (c) 2009-2010, Design Science, Inc. (<www.mathjax.org>)
7259// Copyright (c) 2014-2017 Khan Academy (<www.khanacademy.org>)
7260// Licensed under the SIL Open Font License, Version 1.1.
7261// See \nhttp://scripts.sil.org/OFL
7262// Very Long SVGs
7263//    Many of the KaTeX stretchy wide elements use a long SVG image and an
7264//    overflow: hidden tactic to achieve a stretchy image while avoiding
7265//    distortion of arrowheads or brace corners.
7266//    The SVG typically contains a very long (400 em) arrow.
7267//    The SVG is in a container span that has overflow: hidden, so the span
7268//    acts like a window that exposes only part of the  SVG.
7269//    The SVG always has a longer, thinner aspect ratio than the container span.
7270//    After the SVG fills 100% of the height of the container span,
7271//    there is a long arrow shaft left over. That left-over shaft is not shown.
7272//    Instead, it is sliced off because the span's CSS has overflow: hidden.
7273//    Thus, the reader sees an arrow that matches the subject matter width
7274//    without distortion.
7275//    Some functions, such as \cancel, need to vary their aspect ratio. These
7276//    functions do not get the overflow SVG treatment.
7277// Second Brush Stroke
7278//    Low resolution monitors struggle to display images in fine detail.
7279//    So browsers apply anti-aliasing. A long straight arrow shaft therefore
7280//    will sometimes appear as if it has a blurred edge.
7281//    To mitigate this, these SVG files contain a second "brush-stroke" on the
7282//    arrow shafts. That is, a second long thin rectangular SVG path has been
7283//    written directly on top of each arrow shaft. This reinforcement causes
7284//    some of the screen pixels to display as black instead of the anti-aliased
7285//    gray pixel that a  single path would generate. So we get arrow shafts
7286//    whose edges appear to be sharper.
7287// In the katexImagesData object just below, the dimensions all
7288// correspond to path geometry inside the relevant SVG.
7289// For example, \overrightarrow uses the same arrowhead as glyph U+2192
7290// from the KaTeX Main font. The scaling factor is 1000.
7291// That is, inside the font, that arrowhead is 522 units tall, which
7292// corresponds to 0.522 em inside the document.
7293
7294
7295const katexImagesData = {
7296  //   path(s), minWidth, height, align
7297  overrightarrow: [["rightarrow"], 0.888, 522, "xMaxYMin"],
7298  overleftarrow: [["leftarrow"], 0.888, 522, "xMinYMin"],
7299  underrightarrow: [["rightarrow"], 0.888, 522, "xMaxYMin"],
7300  underleftarrow: [["leftarrow"], 0.888, 522, "xMinYMin"],
7301  xrightarrow: [["rightarrow"], 1.469, 522, "xMaxYMin"],
7302  xleftarrow: [["leftarrow"], 1.469, 522, "xMinYMin"],
7303  Overrightarrow: [["doublerightarrow"], 0.888, 560, "xMaxYMin"],
7304  xRightarrow: [["doublerightarrow"], 1.526, 560, "xMaxYMin"],
7305  xLeftarrow: [["doubleleftarrow"], 1.526, 560, "xMinYMin"],
7306  overleftharpoon: [["leftharpoon"], 0.888, 522, "xMinYMin"],
7307  xleftharpoonup: [["leftharpoon"], 0.888, 522, "xMinYMin"],
7308  xleftharpoondown: [["leftharpoondown"], 0.888, 522, "xMinYMin"],
7309  overrightharpoon: [["rightharpoon"], 0.888, 522, "xMaxYMin"],
7310  xrightharpoonup: [["rightharpoon"], 0.888, 522, "xMaxYMin"],
7311  xrightharpoondown: [["rightharpoondown"], 0.888, 522, "xMaxYMin"],
7312  xlongequal: [["longequal"], 0.888, 334, "xMinYMin"],
7313  xtwoheadleftarrow: [["twoheadleftarrow"], 0.888, 334, "xMinYMin"],
7314  xtwoheadrightarrow: [["twoheadrightarrow"], 0.888, 334, "xMaxYMin"],
7315  overleftrightarrow: [["leftarrow", "rightarrow"], 0.888, 522],
7316  overbrace: [["leftbrace", "midbrace", "rightbrace"], 1.6, 548],
7317  underbrace: [["leftbraceunder", "midbraceunder", "rightbraceunder"], 1.6, 548],
7318  underleftrightarrow: [["leftarrow", "rightarrow"], 0.888, 522],
7319  xleftrightarrow: [["leftarrow", "rightarrow"], 1.75, 522],
7320  xLeftrightarrow: [["doubleleftarrow", "doublerightarrow"], 1.75, 560],
7321  xrightleftharpoons: [["leftharpoondownplus", "rightharpoonplus"], 1.75, 716],
7322  xleftrightharpoons: [["leftharpoonplus", "rightharpoondownplus"], 1.75, 716],
7323  xhookleftarrow: [["leftarrow", "righthook"], 1.08, 522],
7324  xhookrightarrow: [["lefthook", "rightarrow"], 1.08, 522],
7325  overlinesegment: [["leftlinesegment", "rightlinesegment"], 0.888, 522],
7326  underlinesegment: [["leftlinesegment", "rightlinesegment"], 0.888, 522],
7327  overgroup: [["leftgroup", "rightgroup"], 0.888, 342],
7328  undergroup: [["leftgroupunder", "rightgroupunder"], 0.888, 342],
7329  xmapsto: [["leftmapsto", "rightarrow"], 1.5, 522],
7330  xtofrom: [["leftToFrom", "rightToFrom"], 1.75, 528],
7331  // The next three arrows are from the mhchem package.
7332  // In mhchem.sty, min-length is 2.0em. But these arrows might appear in the
7333  // document as \xrightarrow or \xrightleftharpoons. Those have
7334  // min-length = 1.75em, so we set min-length on these next three to match.
7335  xrightleftarrows: [["baraboveleftarrow", "rightarrowabovebar"], 1.75, 901],
7336  xrightequilibrium: [["baraboveshortleftharpoon", "rightharpoonaboveshortbar"], 1.75, 716],
7337  xleftequilibrium: [["shortbaraboveleftharpoon", "shortrightharpoonabovebar"], 1.75, 716]
7338};
7339
7340const groupLength = function groupLength(arg) {
7341  if (arg.type === "ordgroup") {
7342    return arg.body.length;
7343  } else {
7344    return 1;
7345  }
7346};
7347
7348const svgSpan = function svgSpan(group, options) {
7349  // Create a span with inline SVG for the element.
7350  function buildSvgSpan_() {
7351    let viewBoxWidth = 400000; // default
7352
7353    const label = group.label.substr(1);
7354
7355    if (utils.contains(["widehat", "widecheck", "widetilde", "utilde"], label)) {
7356      // Each type in the `if` statement corresponds to one of the ParseNode
7357      // types below. This narrowing is required to access `grp.base`.
7358      const grp = group; // There are four SVG images available for each function.
7359      // Choose a taller image when there are more characters.
7360
7361      const numChars = groupLength(grp.base);
7362      let viewBoxHeight;
7363      let pathName;
7364      let height;
7365
7366      if (numChars > 5) {
7367        if (label === "widehat" || label === "widecheck") {
7368          viewBoxHeight = 420;
7369          viewBoxWidth = 2364;
7370          height = 0.42;
7371          pathName = label + "4";
7372        } else {
7373          viewBoxHeight = 312;
7374          viewBoxWidth = 2340;
7375          height = 0.34;
7376          pathName = "tilde4";
7377        }
7378      } else {
7379        const imgIndex = [1, 1, 2, 2, 3, 3][numChars];
7380
7381        if (label === "widehat" || label === "widecheck") {
7382          viewBoxWidth = [0, 1062, 2364, 2364, 2364][imgIndex];
7383          viewBoxHeight = [0, 239, 300, 360, 420][imgIndex];
7384          height = [0, 0.24, 0.3, 0.3, 0.36, 0.42][imgIndex];
7385          pathName = label + imgIndex;
7386        } else {
7387          viewBoxWidth = [0, 600, 1033, 2339, 2340][imgIndex];
7388          viewBoxHeight = [0, 260, 286, 306, 312][imgIndex];
7389          height = [0, 0.26, 0.286, 0.3, 0.306, 0.34][imgIndex];
7390          pathName = "tilde" + imgIndex;
7391        }
7392      }
7393
7394      const path = new PathNode(pathName);
7395      const svgNode = new SvgNode([path], {
7396        "width": "100%",
7397        "height": height + "em",
7398        "viewBox": `0 0 ${viewBoxWidth} ${viewBoxHeight}`,
7399        "preserveAspectRatio": "none"
7400      });
7401      return {
7402        span: buildCommon.makeSvgSpan([], [svgNode], options),
7403        minWidth: 0,
7404        height
7405      };
7406    } else {
7407      const spans = [];
7408      const data = katexImagesData[label];
7409      const paths = data[0],
7410            minWidth = data[1],
7411            viewBoxHeight = data[2];
7412      const height = viewBoxHeight / 1000;
7413      const numSvgChildren = paths.length;
7414      let widthClasses;
7415      let aligns;
7416
7417      if (numSvgChildren === 1) {
7418        // $FlowFixMe: All these cases must be of the 4-tuple type.
7419        const align1 = data[3];
7420        widthClasses = ["hide-tail"];
7421        aligns = [align1];
7422      } else if (numSvgChildren === 2) {
7423        widthClasses = ["halfarrow-left", "halfarrow-right"];
7424        aligns = ["xMinYMin", "xMaxYMin"];
7425      } else if (numSvgChildren === 3) {
7426        widthClasses = ["brace-left", "brace-center", "brace-right"];
7427        aligns = ["xMinYMin", "xMidYMin", "xMaxYMin"];
7428      } else {
7429        throw new Error(`Correct katexImagesData or update code here to support
7430                    ${numSvgChildren} children.`);
7431      }
7432
7433      for (let i = 0; i < numSvgChildren; i++) {
7434        const path = new PathNode(paths[i]);
7435        const svgNode = new SvgNode([path], {
7436          "width": "400em",
7437          "height": height + "em",
7438          "viewBox": `0 0 ${viewBoxWidth} ${viewBoxHeight}`,
7439          "preserveAspectRatio": aligns[i] + " slice"
7440        });
7441        const span = buildCommon.makeSvgSpan([widthClasses[i]], [svgNode], options);
7442
7443        if (numSvgChildren === 1) {
7444          return {
7445            span,
7446            minWidth,
7447            height
7448          };
7449        } else {
7450          span.style.height = height + "em";
7451          spans.push(span);
7452        }
7453      }
7454
7455      return {
7456        span: buildCommon.makeSpan(["stretchy"], spans, options),
7457        minWidth,
7458        height
7459      };
7460    }
7461  } // buildSvgSpan_()
7462
7463
7464  const _buildSvgSpan_ = buildSvgSpan_(),
7465        span = _buildSvgSpan_.span,
7466        minWidth = _buildSvgSpan_.minWidth,
7467        height = _buildSvgSpan_.height; // Note that we are returning span.depth = 0.
7468  // Any adjustments relative to the baseline must be done in buildHTML.
7469
7470
7471  span.height = height;
7472  span.style.height = height + "em";
7473
7474  if (minWidth > 0) {
7475    span.style.minWidth = minWidth + "em";
7476  }
7477
7478  return span;
7479};
7480
7481const encloseSpan = function encloseSpan(inner, label, pad, options) {
7482  // Return an image span for \cancel, \bcancel, \xcancel, or \fbox
7483  let img;
7484  const totalHeight = inner.height + inner.depth + 2 * pad;
7485
7486  if (/fbox|color/.test(label)) {
7487    img = buildCommon.makeSpan(["stretchy", label], [], options);
7488
7489    if (label === "fbox") {
7490      const color = options.color && options.getColor();
7491
7492      if (color) {
7493        img.style.borderColor = color;
7494      }
7495    }
7496  } else {
7497    // \cancel, \bcancel, or \xcancel
7498    // Since \cancel's SVG is inline and it omits the viewBox attribute,
7499    // its stroke-width will not vary with span area.
7500    const lines = [];
7501
7502    if (/^[bx]cancel$/.test(label)) {
7503      lines.push(new LineNode({
7504        "x1": "0",
7505        "y1": "0",
7506        "x2": "100%",
7507        "y2": "100%",
7508        "stroke-width": "0.046em"
7509      }));
7510    }
7511
7512    if (/^x?cancel$/.test(label)) {
7513      lines.push(new LineNode({
7514        "x1": "0",
7515        "y1": "100%",
7516        "x2": "100%",
7517        "y2": "0",
7518        "stroke-width": "0.046em"
7519      }));
7520    }
7521
7522    const svgNode = new SvgNode(lines, {
7523      "width": "100%",
7524      "height": totalHeight + "em"
7525    });
7526    img = buildCommon.makeSvgSpan([], [svgNode], options);
7527  }
7528
7529  img.height = totalHeight;
7530  img.style.height = totalHeight + "em";
7531  return img;
7532};
7533
7534var stretchy = {
7535  encloseSpan,
7536  mathMLnode,
7537  svgSpan
7538};
7539
7540// NOTE: Unlike most `htmlBuilder`s, this one handles not only "accent", but
7541const htmlBuilder = (grp, options) => {
7542  // Accents are handled in the TeXbook pg. 443, rule 12.
7543  let base;
7544  let group;
7545  const supSub = checkNodeType(grp, "supsub");
7546  let supSubGroup;
7547
7548  if (supSub) {
7549    // If our base is a character box, and we have superscripts and
7550    // subscripts, the supsub will defer to us. In particular, we want
7551    // to attach the superscripts and subscripts to the inner body (so
7552    // that the position of the superscripts and subscripts won't be
7553    // affected by the height of the accent). We accomplish this by
7554    // sticking the base of the accent into the base of the supsub, and
7555    // rendering that, while keeping track of where the accent is.
7556    // The real accent group is the base of the supsub group
7557    group = assertNodeType(supSub.base, "accent"); // The character box is the base of the accent group
7558
7559    base = group.base; // Stick the character box into the base of the supsub group
7560
7561    supSub.base = base; // Rerender the supsub group with its new base, and store that
7562    // result.
7563
7564    supSubGroup = assertSpan(buildGroup(supSub, options)); // reset original base
7565
7566    supSub.base = group;
7567  } else {
7568    group = assertNodeType(grp, "accent");
7569    base = group.base;
7570  } // Build the base group
7571
7572
7573  const body = buildGroup(base, options.havingCrampedStyle()); // Does the accent need to shift for the skew of a character?
7574
7575  const mustShift = group.isShifty && utils.isCharacterBox(base); // Calculate the skew of the accent. This is based on the line "If the
7576  // nucleus is not a single character, let s = 0; otherwise set s to the
7577  // kern amount for the nucleus followed by the \skewchar of its font."
7578  // Note that our skew metrics are just the kern between each character
7579  // and the skewchar.
7580
7581  let skew = 0;
7582
7583  if (mustShift) {
7584    // If the base is a character box, then we want the skew of the
7585    // innermost character. To do that, we find the innermost character:
7586    const baseChar = utils.getBaseElem(base); // Then, we render its group to get the symbol inside it
7587
7588    const baseGroup = buildGroup(baseChar, options.havingCrampedStyle()); // Finally, we pull the skew off of the symbol.
7589
7590    skew = assertSymbolDomNode(baseGroup).skew; // Note that we now throw away baseGroup, because the layers we
7591    // removed with getBaseElem might contain things like \color which
7592    // we can't get rid of.
7593    // TODO(emily): Find a better way to get the skew
7594  } // calculate the amount of space between the body and the accent
7595
7596
7597  let clearance = Math.min(body.height, options.fontMetrics().xHeight); // Build the accent
7598
7599  let accentBody;
7600
7601  if (!group.isStretchy) {
7602    let accent;
7603    let width;
7604
7605    if (group.label === "\\vec") {
7606      // Before version 0.9, \vec used the combining font glyph U+20D7.
7607      // But browsers, especially Safari, are not consistent in how they
7608      // render combining characters when not preceded by a character.
7609      // So now we use an SVG.
7610      // If Safari reforms, we should consider reverting to the glyph.
7611      accent = buildCommon.staticSvg("vec", options);
7612      width = buildCommon.svgData.vec[1];
7613    } else {
7614      accent = buildCommon.makeOrd({
7615        mode: group.mode,
7616        text: group.label
7617      }, options, "textord");
7618      accent = assertSymbolDomNode(accent); // Remove the italic correction of the accent, because it only serves to
7619      // shift the accent over to a place we don't want.
7620
7621      accent.italic = 0;
7622      width = accent.width;
7623    }
7624
7625    accentBody = buildCommon.makeSpan(["accent-body"], [accent]); // "Full" accents expand the width of the resulting symbol to be
7626    // at least the width of the accent, and overlap directly onto the
7627    // character without any vertical offset.
7628
7629    const accentFull = group.label === "\\textcircled";
7630
7631    if (accentFull) {
7632      accentBody.classes.push('accent-full');
7633      clearance = body.height;
7634    } // Shift the accent over by the skew.
7635
7636
7637    let left = skew; // CSS defines `.katex .accent .accent-body:not(.accent-full) { width: 0 }`
7638    // so that the accent doesn't contribute to the bounding box.
7639    // We need to shift the character by its width (effectively half
7640    // its width) to compensate.
7641
7642    if (!accentFull) {
7643      left -= width / 2;
7644    }
7645
7646    accentBody.style.left = left + "em"; // \textcircled uses the \bigcirc glyph, so it needs some
7647    // vertical adjustment to match LaTeX.
7648
7649    if (group.label === "\\textcircled") {
7650      accentBody.style.top = ".2em";
7651    }
7652
7653    accentBody = buildCommon.makeVList({
7654      positionType: "firstBaseline",
7655      children: [{
7656        type: "elem",
7657        elem: body
7658      }, {
7659        type: "kern",
7660        size: -clearance
7661      }, {
7662        type: "elem",
7663        elem: accentBody
7664      }]
7665    }, options);
7666  } else {
7667    accentBody = stretchy.svgSpan(group, options);
7668    accentBody = buildCommon.makeVList({
7669      positionType: "firstBaseline",
7670      children: [{
7671        type: "elem",
7672        elem: body
7673      }, {
7674        type: "elem",
7675        elem: accentBody,
7676        wrapperClasses: ["svg-align"],
7677        wrapperStyle: skew > 0 ? {
7678          width: `calc(100% - ${2 * skew}em)`,
7679          marginLeft: `${2 * skew}em`
7680        } : undefined
7681      }]
7682    }, options);
7683  }
7684
7685  const accentWrap = buildCommon.makeSpan(["mord", "accent"], [accentBody], options);
7686
7687  if (supSubGroup) {
7688    // Here, we replace the "base" child of the supsub with our newly
7689    // generated accent.
7690    supSubGroup.children[0] = accentWrap; // Since we don't rerun the height calculation after replacing the
7691    // accent, we manually recalculate height.
7692
7693    supSubGroup.height = Math.max(accentWrap.height, supSubGroup.height); // Accents should always be ords, even when their innards are not.
7694
7695    supSubGroup.classes[0] = "mord";
7696    return supSubGroup;
7697  } else {
7698    return accentWrap;
7699  }
7700};
7701
7702const mathmlBuilder = (group, options) => {
7703  const accentNode = group.isStretchy ? stretchy.mathMLnode(group.label) : new mathMLTree.MathNode("mo", [makeText(group.label, group.mode)]);
7704  const node = new mathMLTree.MathNode("mover", [buildGroup$1(group.base, options), accentNode]);
7705  node.setAttribute("accent", "true");
7706  return node;
7707};
7708
7709const NON_STRETCHY_ACCENT_REGEX = new RegExp(["\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve", "\\check", "\\hat", "\\vec", "\\dot", "\\mathring"].map(accent => `\\${accent}`).join("|")); // Accents
7710
7711defineFunction({
7712  type: "accent",
7713  names: ["\\acute", "\\grave", "\\ddot", "\\tilde", "\\bar", "\\breve", "\\check", "\\hat", "\\vec", "\\dot", "\\mathring", "\\widecheck", "\\widehat", "\\widetilde", "\\overrightarrow", "\\overleftarrow", "\\Overrightarrow", "\\overleftrightarrow", "\\overgroup", "\\overlinesegment", "\\overleftharpoon", "\\overrightharpoon"],
7714  props: {
7715    numArgs: 1
7716  },
7717  handler: (context, args) => {
7718    const base = args[0];
7719    const isStretchy = !NON_STRETCHY_ACCENT_REGEX.test(context.funcName);
7720    const isShifty = !isStretchy || context.funcName === "\\widehat" || context.funcName === "\\widetilde" || context.funcName === "\\widecheck";
7721    return {
7722      type: "accent",
7723      mode: context.parser.mode,
7724      label: context.funcName,
7725      isStretchy: isStretchy,
7726      isShifty: isShifty,
7727      base: base
7728    };
7729  },
7730  htmlBuilder,
7731  mathmlBuilder
7732}); // Text-mode accents
7733
7734defineFunction({
7735  type: "accent",
7736  names: ["\\'", "\\`", "\\^", "\\~", "\\=", "\\u", "\\.", '\\"', "\\r", "\\H", "\\v", "\\textcircled"],
7737  props: {
7738    numArgs: 1,
7739    allowedInText: true,
7740    allowedInMath: false
7741  },
7742  handler: (context, args) => {
7743    const base = args[0];
7744    return {
7745      type: "accent",
7746      mode: context.parser.mode,
7747      label: context.funcName,
7748      isStretchy: false,
7749      isShifty: true,
7750      base: base
7751    };
7752  },
7753  htmlBuilder,
7754  mathmlBuilder
7755});
7756
7757// Horizontal overlap functions
7758defineFunction({
7759  type: "accentUnder",
7760  names: ["\\underleftarrow", "\\underrightarrow", "\\underleftrightarrow", "\\undergroup", "\\underlinesegment", "\\utilde"],
7761  props: {
7762    numArgs: 1
7763  },
7764  handler: (_ref, args) => {
7765    let parser = _ref.parser,
7766        funcName = _ref.funcName;
7767    const base = args[0];
7768    return {
7769      type: "accentUnder",
7770      mode: parser.mode,
7771      label: funcName,
7772      base: base
7773    };
7774  },
7775  htmlBuilder: (group, options) => {
7776    // Treat under accents much like underlines.
7777    const innerGroup = buildGroup(group.base, options);
7778    const accentBody = stretchy.svgSpan(group, options);
7779    const kern = group.label === "\\utilde" ? 0.12 : 0; // Generate the vlist, with the appropriate kerns
7780
7781    const vlist = buildCommon.makeVList({
7782      positionType: "bottom",
7783      positionData: accentBody.height + kern,
7784      children: [{
7785        type: "elem",
7786        elem: accentBody,
7787        wrapperClasses: ["svg-align"]
7788      }, {
7789        type: "kern",
7790        size: kern
7791      }, {
7792        type: "elem",
7793        elem: innerGroup
7794      }]
7795    }, options);
7796    return buildCommon.makeSpan(["mord", "accentunder"], [vlist], options);
7797  },
7798  mathmlBuilder: (group, options) => {
7799    const accentNode = stretchy.mathMLnode(group.label);
7800    const node = new mathMLTree.MathNode("munder", [buildGroup$1(group.base, options), accentNode]);
7801    node.setAttribute("accentunder", "true");
7802    return node;
7803  }
7804});
7805
7806// Helper function
7807const paddedNode = group => {
7808  const node = new mathMLTree.MathNode("mpadded", group ? [group] : []);
7809  node.setAttribute("width", "+0.6em");
7810  node.setAttribute("lspace", "0.3em");
7811  return node;
7812}; // Stretchy arrows with an optional argument
7813
7814
7815defineFunction({
7816  type: "xArrow",
7817  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.
7818  // Direct use of these functions is discouraged and may break someday.
7819  "\\xrightleftarrows", "\\xrightequilibrium", "\\xleftequilibrium"],
7820  props: {
7821    numArgs: 1,
7822    numOptionalArgs: 1
7823  },
7824
7825  handler(_ref, args, optArgs) {
7826    let parser = _ref.parser,
7827        funcName = _ref.funcName;
7828    return {
7829      type: "xArrow",
7830      mode: parser.mode,
7831      label: funcName,
7832      body: args[0],
7833      below: optArgs[0]
7834    };
7835  },
7836
7837  // Flow is unable to correctly infer the type of `group`, even though it's
7838  // unamibiguously determined from the passed-in `type` above.
7839  htmlBuilder(group, options) {
7840    const style = options.style; // Build the argument groups in the appropriate style.
7841    // Ref: amsmath.dtx:   \hbox{$\scriptstyle\mkern#3mu{#6}\mkern#4mu$}%
7842    // Some groups can return document fragments.  Handle those by wrapping
7843    // them in a span.
7844
7845    let newOptions = options.havingStyle(style.sup());
7846    const upperGroup = buildCommon.wrapFragment(buildGroup(group.body, newOptions, options), options);
7847    upperGroup.classes.push("x-arrow-pad");
7848    let lowerGroup;
7849
7850    if (group.below) {
7851      // Build the lower group
7852      newOptions = options.havingStyle(style.sub());
7853      lowerGroup = buildCommon.wrapFragment(buildGroup(group.below, newOptions, options), options);
7854      lowerGroup.classes.push("x-arrow-pad");
7855    }
7856
7857    const arrowBody = stretchy.svgSpan(group, options); // Re shift: Note that stretchy.svgSpan returned arrowBody.depth = 0.
7858    // The point we want on the math axis is at 0.5 * arrowBody.height.
7859
7860    const arrowShift = -options.fontMetrics().axisHeight + 0.5 * arrowBody.height; // 2 mu kern. Ref: amsmath.dtx: #7\if0#2\else\mkern#2mu\fi
7861
7862    let upperShift = -options.fontMetrics().axisHeight - 0.5 * arrowBody.height - 0.111; // 0.111 em = 2 mu
7863
7864    if (upperGroup.depth > 0.25 || group.label === "\\xleftequilibrium") {
7865      upperShift -= upperGroup.depth; // shift up if depth encroaches
7866    } // Generate the vlist
7867
7868
7869    let vlist;
7870
7871    if (lowerGroup) {
7872      const lowerShift = -options.fontMetrics().axisHeight + lowerGroup.height + 0.5 * arrowBody.height + 0.111;
7873      vlist = buildCommon.makeVList({
7874        positionType: "individualShift",
7875        children: [{
7876          type: "elem",
7877          elem: upperGroup,
7878          shift: upperShift
7879        }, {
7880          type: "elem",
7881          elem: arrowBody,
7882          shift: arrowShift
7883        }, {
7884          type: "elem",
7885          elem: lowerGroup,
7886          shift: lowerShift
7887        }]
7888      }, options);
7889    } else {
7890      vlist = buildCommon.makeVList({
7891        positionType: "individualShift",
7892        children: [{
7893          type: "elem",
7894          elem: upperGroup,
7895          shift: upperShift
7896        }, {
7897          type: "elem",
7898          elem: arrowBody,
7899          shift: arrowShift
7900        }]
7901      }, options);
7902    } // $FlowFixMe: Replace this with passing "svg-align" into makeVList.
7903
7904
7905    vlist.children[0].children[0].children[1].classes.push("svg-align");
7906    return buildCommon.makeSpan(["mrel", "x-arrow"], [vlist], options);
7907  },
7908
7909  mathmlBuilder(group, options) {
7910    const arrowNode = stretchy.mathMLnode(group.label);
7911    let node;
7912
7913    if (group.body) {
7914      const upperNode = paddedNode(buildGroup$1(group.body, options));
7915
7916      if (group.below) {
7917        const lowerNode = paddedNode(buildGroup$1(group.below, options));
7918        node = new mathMLTree.MathNode("munderover", [arrowNode, lowerNode, upperNode]);
7919      } else {
7920        node = new mathMLTree.MathNode("mover", [arrowNode, upperNode]);
7921      }
7922    } else if (group.below) {
7923      const lowerNode = paddedNode(buildGroup$1(group.below, options));
7924      node = new mathMLTree.MathNode("munder", [arrowNode, lowerNode]);
7925    } else {
7926      // This should never happen.
7927      // Parser.js throws an error if there is no argument.
7928      node = paddedNode();
7929      node = new mathMLTree.MathNode("mover", [arrowNode, node]);
7930    }
7931
7932    return node;
7933  }
7934
7935});
7936
7937// {123} and converts into symbol with code 123.  It is used by the *macro*
7938// \char defined in macros.js.
7939
7940defineFunction({
7941  type: "textord",
7942  names: ["\\@char"],
7943  props: {
7944    numArgs: 1,
7945    allowedInText: true
7946  },
7947
7948  handler(_ref, args) {
7949    let parser = _ref.parser;
7950    const arg = assertNodeType(args[0], "ordgroup");
7951    const group = arg.body;
7952    let number = "";
7953
7954    for (let i = 0; i < group.length; i++) {
7955      const node = assertNodeType(group[i], "textord");
7956      number += node.text;
7957    }
7958
7959    const code = parseInt(number);
7960
7961    if (isNaN(code)) {
7962      throw new ParseError(`\\@char has non-numeric argument ${number}`);
7963    }
7964
7965    return {
7966      type: "textord",
7967      mode: parser.mode,
7968      text: String.fromCharCode(code)
7969    };
7970  }
7971
7972});
7973
7974const htmlBuilder$1 = (group, options) => {
7975  const elements = buildExpression(group.body, options.withColor(group.color), false); // \color isn't supposed to affect the type of the elements it contains.
7976  // To accomplish this, we wrap the results in a fragment, so the inner
7977  // elements will be able to directly interact with their neighbors. For
7978  // example, `\color{red}{2 +} 3` has the same spacing as `2 + 3`
7979
7980  return buildCommon.makeFragment(elements);
7981};
7982
7983const mathmlBuilder$1 = (group, options) => {
7984  const inner = buildExpression$1(group.body, options.withColor(group.color));
7985  const node = new mathMLTree.MathNode("mstyle", inner);
7986  node.setAttribute("mathcolor", group.color);
7987  return node;
7988};
7989
7990defineFunction({
7991  type: "color",
7992  names: ["\\textcolor"],
7993  props: {
7994    numArgs: 2,
7995    allowedInText: true,
7996    greediness: 3,
7997    argTypes: ["color", "original"]
7998  },
7999
8000  handler(_ref, args) {
8001    let parser = _ref.parser;
8002    const color = assertNodeType(args[0], "color-token").color;
8003    const body = args[1];
8004    return {
8005      type: "color",
8006      mode: parser.mode,
8007      color,
8008      body: ordargument(body)
8009    };
8010  },
8011
8012  htmlBuilder: htmlBuilder$1,
8013  mathmlBuilder: mathmlBuilder$1
8014});
8015defineFunction({
8016  type: "color",
8017  names: ["\\color"],
8018  props: {
8019    numArgs: 1,
8020    allowedInText: true,
8021    greediness: 3,
8022    argTypes: ["color"]
8023  },
8024
8025  handler(_ref2, args) {
8026    let parser = _ref2.parser,
8027        breakOnTokenText = _ref2.breakOnTokenText;
8028    const color = assertNodeType(args[0], "color-token").color; // Set macro \current@color in current namespace to store the current
8029    // color, mimicking the behavior of color.sty.
8030    // This is currently used just to correctly color a \right
8031    // that follows a \color command.
8032
8033    parser.gullet.macros.set("\\current@color", color); // Parse out the implicit body that should be colored.
8034
8035    const body = parser.parseExpression(true, breakOnTokenText);
8036    return {
8037      type: "color",
8038      mode: parser.mode,
8039      color,
8040      body
8041    };
8042  },
8043
8044  htmlBuilder: htmlBuilder$1,
8045  mathmlBuilder: mathmlBuilder$1
8046});
8047
8048// Row breaks within tabular environments, and line breaks at top level
8049// same signature, we implement them as one megafunction, with newRow
8050// indicating whether we're in the \cr case, and newLine indicating whether
8051// to break the line in the \newline case.
8052
8053defineFunction({
8054  type: "cr",
8055  names: ["\\cr", "\\newline"],
8056  props: {
8057    numArgs: 0,
8058    numOptionalArgs: 1,
8059    argTypes: ["size"],
8060    allowedInText: true
8061  },
8062
8063  handler(_ref, args, optArgs) {
8064    let parser = _ref.parser,
8065        funcName = _ref.funcName;
8066    const size = optArgs[0];
8067    const newRow = funcName === "\\cr";
8068    let newLine = false;
8069
8070    if (!newRow) {
8071      if (parser.settings.displayMode && parser.settings.useStrictBehavior("newLineInDisplayMode", "In LaTeX, \\\\ or \\newline " + "does nothing in display mode")) {
8072        newLine = false;
8073      } else {
8074        newLine = true;
8075      }
8076    }
8077
8078    return {
8079      type: "cr",
8080      mode: parser.mode,
8081      newLine,
8082      newRow,
8083      size: size && assertNodeType(size, "size").value
8084    };
8085  },
8086
8087  // The following builders are called only at the top level,
8088  // not within tabular/array environments.
8089  htmlBuilder(group, options) {
8090    if (group.newRow) {
8091      throw new ParseError("\\cr valid only within a tabular/array environment");
8092    }
8093
8094    const span = buildCommon.makeSpan(["mspace"], [], options);
8095
8096    if (group.newLine) {
8097      span.classes.push("newline");
8098
8099      if (group.size) {
8100        span.style.marginTop = calculateSize(group.size, options) + "em";
8101      }
8102    }
8103
8104    return span;
8105  },
8106
8107  mathmlBuilder(group, options) {
8108    const node = new mathMLTree.MathNode("mspace");
8109
8110    if (group.newLine) {
8111      node.setAttribute("linebreak", "newline");
8112
8113      if (group.size) {
8114        node.setAttribute("height", calculateSize(group.size, options) + "em");
8115      }
8116    }
8117
8118    return node;
8119  }
8120
8121});
8122
8123/**
8124 * This file deals with creating delimiters of various sizes. The TeXbook
8125 * discusses these routines on page 441-442, in the "Another subroutine sets box
8126 * x to a specified variable delimiter" paragraph.
8127 *
8128 * There are three main routines here. `makeSmallDelim` makes a delimiter in the
8129 * normal font, but in either text, script, or scriptscript style.
8130 * `makeLargeDelim` makes a delimiter in textstyle, but in one of the Size1,
8131 * Size2, Size3, or Size4 fonts. `makeStackedDelim` makes a delimiter out of
8132 * smaller pieces that are stacked on top of one another.
8133 *
8134 * The functions take a parameter `center`, which determines if the delimiter
8135 * should be centered around the axis.
8136 *
8137 * Then, there are three exposed functions. `sizedDelim` makes a delimiter in
8138 * one of the given sizes. This is used for things like `\bigl`.
8139 * `customSizedDelim` makes a delimiter with a given total height+depth. It is
8140 * called in places like `\sqrt`. `leftRightDelim` makes an appropriate
8141 * delimiter which surrounds an expression of a given height an depth. It is
8142 * used in `\left` and `\right`.
8143 */
8144
8145/**
8146 * Get the metrics for a given symbol and font, after transformation (i.e.
8147 * after following replacement from symbols.js)
8148 */
8149const getMetrics = function getMetrics(symbol, font, mode) {
8150  const replace = symbols.math[symbol] && symbols.math[symbol].replace;
8151  const metrics = getCharacterMetrics(replace || symbol, font, mode);
8152
8153  if (!metrics) {
8154    throw new Error(`Unsupported symbol ${symbol} and font size ${font}.`);
8155  }
8156
8157  return metrics;
8158};
8159/**
8160 * Puts a delimiter span in a given style, and adds appropriate height, depth,
8161 * and maxFontSizes.
8162 */
8163
8164
8165const styleWrap = function styleWrap(delim, toStyle, options, classes) {
8166  const newOptions = options.havingBaseStyle(toStyle);
8167  const span = buildCommon.makeSpan(classes.concat(newOptions.sizingClasses(options)), [delim], options);
8168  const delimSizeMultiplier = newOptions.sizeMultiplier / options.sizeMultiplier;
8169  span.height *= delimSizeMultiplier;
8170  span.depth *= delimSizeMultiplier;
8171  span.maxFontSize = newOptions.sizeMultiplier;
8172  return span;
8173};
8174
8175const centerSpan = function centerSpan(span, options, style) {
8176  const newOptions = options.havingBaseStyle(style);
8177  const shift = (1 - options.sizeMultiplier / newOptions.sizeMultiplier) * options.fontMetrics().axisHeight;
8178  span.classes.push("delimcenter");
8179  span.style.top = shift + "em";
8180  span.height -= shift;
8181  span.depth += shift;
8182};
8183/**
8184 * Makes a small delimiter. This is a delimiter that comes in the Main-Regular
8185 * font, but is restyled to either be in textstyle, scriptstyle, or
8186 * scriptscriptstyle.
8187 */
8188
8189
8190const makeSmallDelim = function makeSmallDelim(delim, style, center, options, mode, classes) {
8191  const text = buildCommon.makeSymbol(delim, "Main-Regular", mode, options);
8192  const span = styleWrap(text, style, options, classes);
8193
8194  if (center) {
8195    centerSpan(span, options, style);
8196  }
8197
8198  return span;
8199};
8200/**
8201 * Builds a symbol in the given font size (note size is an integer)
8202 */
8203
8204
8205const mathrmSize = function mathrmSize(value, size, mode, options) {
8206  return buildCommon.makeSymbol(value, "Size" + size + "-Regular", mode, options);
8207};
8208/**
8209 * Makes a large delimiter. This is a delimiter that comes in the Size1, Size2,
8210 * Size3, or Size4 fonts. It is always rendered in textstyle.
8211 */
8212
8213
8214const makeLargeDelim = function makeLargeDelim(delim, size, center, options, mode, classes) {
8215  const inner = mathrmSize(delim, size, mode, options);
8216  const span = styleWrap(buildCommon.makeSpan(["delimsizing", "size" + size], [inner], options), Style$1.TEXT, options, classes);
8217
8218  if (center) {
8219    centerSpan(span, options, Style$1.TEXT);
8220  }
8221
8222  return span;
8223};
8224/**
8225 * Make an inner span with the given offset and in the given font. This is used
8226 * in `makeStackedDelim` to make the stacking pieces for the delimiter.
8227 */
8228
8229
8230const makeInner = function makeInner(symbol, font, mode) {
8231  let sizeClass; // Apply the correct CSS class to choose the right font.
8232
8233  if (font === "Size1-Regular") {
8234    sizeClass = "delim-size1";
8235  } else
8236    /* if (font === "Size4-Regular") */
8237    {
8238      sizeClass = "delim-size4";
8239    }
8240
8241  const inner = buildCommon.makeSpan(["delimsizinginner", sizeClass], [buildCommon.makeSpan([], [buildCommon.makeSymbol(symbol, font, mode)])]); // Since this will be passed into `makeVList` in the end, wrap the element
8242  // in the appropriate tag that VList uses.
8243
8244  return {
8245    type: "elem",
8246    elem: inner
8247  };
8248}; // Helper for makeStackedDelim
8249
8250
8251const lap = {
8252  type: "kern",
8253  size: -0.005
8254};
8255/**
8256 * Make a stacked delimiter out of a given delimiter, with the total height at
8257 * least `heightTotal`. This routine is mentioned on page 442 of the TeXbook.
8258 */
8259
8260const makeStackedDelim = function makeStackedDelim(delim, heightTotal, center, options, mode, classes) {
8261  // There are four parts, the top, an optional middle, a repeated part, and a
8262  // bottom.
8263  let top;
8264  let middle;
8265  let repeat;
8266  let bottom;
8267  top = repeat = bottom = delim;
8268  middle = null; // Also keep track of what font the delimiters are in
8269
8270  let font = "Size1-Regular"; // We set the parts and font based on the symbol. Note that we use
8271  // '\u23d0' instead of '|' and '\u2016' instead of '\\|' for the
8272  // repeats of the arrows
8273
8274  if (delim === "\\uparrow") {
8275    repeat = bottom = "\u23d0";
8276  } else if (delim === "\\Uparrow") {
8277    repeat = bottom = "\u2016";
8278  } else if (delim === "\\downarrow") {
8279    top = repeat = "\u23d0";
8280  } else if (delim === "\\Downarrow") {
8281    top = repeat = "\u2016";
8282  } else if (delim === "\\updownarrow") {
8283    top = "\\uparrow";
8284    repeat = "\u23d0";
8285    bottom = "\\downarrow";
8286  } else if (delim === "\\Updownarrow") {
8287    top = "\\Uparrow";
8288    repeat = "\u2016";
8289    bottom = "\\Downarrow";
8290  } else if (delim === "[" || delim === "\\lbrack") {
8291    top = "\u23a1";
8292    repeat = "\u23a2";
8293    bottom = "\u23a3";
8294    font = "Size4-Regular";
8295  } else if (delim === "]" || delim === "\\rbrack") {
8296    top = "\u23a4";
8297    repeat = "\u23a5";
8298    bottom = "\u23a6";
8299    font = "Size4-Regular";
8300  } else if (delim === "\\lfloor" || delim === "\u230a") {
8301    repeat = top = "\u23a2";
8302    bottom = "\u23a3";
8303    font = "Size4-Regular";
8304  } else if (delim === "\\lceil" || delim === "\u2308") {
8305    top = "\u23a1";
8306    repeat = bottom = "\u23a2";
8307    font = "Size4-Regular";
8308  } else if (delim === "\\rfloor" || delim === "\u230b") {
8309    repeat = top = "\u23a5";
8310    bottom = "\u23a6";
8311    font = "Size4-Regular";
8312  } else if (delim === "\\rceil" || delim === "\u2309") {
8313    top = "\u23a4";
8314    repeat = bottom = "\u23a5";
8315    font = "Size4-Regular";
8316  } else if (delim === "(" || delim === "\\lparen") {
8317    top = "\u239b";
8318    repeat = "\u239c";
8319    bottom = "\u239d";
8320    font = "Size4-Regular";
8321  } else if (delim === ")" || delim === "\\rparen") {
8322    top = "\u239e";
8323    repeat = "\u239f";
8324    bottom = "\u23a0";
8325    font = "Size4-Regular";
8326  } else if (delim === "\\{" || delim === "\\lbrace") {
8327    top = "\u23a7";
8328    middle = "\u23a8";
8329    bottom = "\u23a9";
8330    repeat = "\u23aa";
8331    font = "Size4-Regular";
8332  } else if (delim === "\\}" || delim === "\\rbrace") {
8333    top = "\u23ab";
8334    middle = "\u23ac";
8335    bottom = "\u23ad";
8336    repeat = "\u23aa";
8337    font = "Size4-Regular";
8338  } else if (delim === "\\lgroup" || delim === "\u27ee") {
8339    top = "\u23a7";
8340    bottom = "\u23a9";
8341    repeat = "\u23aa";
8342    font = "Size4-Regular";
8343  } else if (delim === "\\rgroup" || delim === "\u27ef") {
8344    top = "\u23ab";
8345    bottom = "\u23ad";
8346    repeat = "\u23aa";
8347    font = "Size4-Regular";
8348  } else if (delim === "\\lmoustache" || delim === "\u23b0") {
8349    top = "\u23a7";
8350    bottom = "\u23ad";
8351    repeat = "\u23aa";
8352    font = "Size4-Regular";
8353  } else if (delim === "\\rmoustache" || delim === "\u23b1") {
8354    top = "\u23ab";
8355    bottom = "\u23a9";
8356    repeat = "\u23aa";
8357    font = "Size4-Regular";
8358  } // Get the metrics of the four sections
8359
8360
8361  const topMetrics = getMetrics(top, font, mode);
8362  const topHeightTotal = topMetrics.height + topMetrics.depth;
8363  const repeatMetrics = getMetrics(repeat, font, mode);
8364  const repeatHeightTotal = repeatMetrics.height + repeatMetrics.depth;
8365  const bottomMetrics = getMetrics(bottom, font, mode);
8366  const bottomHeightTotal = bottomMetrics.height + bottomMetrics.depth;
8367  let middleHeightTotal = 0;
8368  let middleFactor = 1;
8369
8370  if (middle !== null) {
8371    const middleMetrics = getMetrics(middle, font, mode);
8372    middleHeightTotal = middleMetrics.height + middleMetrics.depth;
8373    middleFactor = 2; // repeat symmetrically above and below middle
8374  } // Calcuate the minimal height that the delimiter can have.
8375  // It is at least the size of the top, bottom, and optional middle combined.
8376
8377
8378  const minHeight = topHeightTotal + bottomHeightTotal + middleHeightTotal; // Compute the number of copies of the repeat symbol we will need
8379
8380  const repeatCount = Math.max(0, Math.ceil((heightTotal - minHeight) / (middleFactor * repeatHeightTotal))); // Compute the total height of the delimiter including all the symbols
8381
8382  const realHeightTotal = minHeight + repeatCount * middleFactor * repeatHeightTotal; // The center of the delimiter is placed at the center of the axis. Note
8383  // that in this context, "center" means that the delimiter should be
8384  // centered around the axis in the current style, while normally it is
8385  // centered around the axis in textstyle.
8386
8387  let axisHeight = options.fontMetrics().axisHeight;
8388
8389  if (center) {
8390    axisHeight *= options.sizeMultiplier;
8391  } // Calculate the depth
8392
8393
8394  const depth = realHeightTotal / 2 - axisHeight; // This function differs from the TeX procedure in one way.
8395  // We shift each repeat element downwards by 0.005em, to prevent a gap
8396  // due to browser floating point rounding error.
8397  // Then, at the last element-to element joint, we add one extra repeat
8398  // element to cover the gap created by the shifts.
8399  // Find the shift needed to align the upper end of the extra element at a point
8400  // 0.005em above the lower end of the top element.
8401
8402  const shiftOfExtraElement = (repeatCount + 1) * 0.005 - repeatHeightTotal; // Now, we start building the pieces that will go into the vlist
8403  // Keep a list of the inner pieces
8404
8405  const inners = []; // Add the bottom symbol
8406
8407  inners.push(makeInner(bottom, font, mode));
8408
8409  if (middle === null) {
8410    // Add that many symbols
8411    for (let i = 0; i < repeatCount; i++) {
8412      inners.push(lap); // overlap
8413
8414      inners.push(makeInner(repeat, font, mode));
8415    }
8416  } else {
8417    // When there is a middle bit, we need the middle part and two repeated
8418    // sections
8419    for (let i = 0; i < repeatCount; i++) {
8420      inners.push(lap);
8421      inners.push(makeInner(repeat, font, mode));
8422    } // Insert one extra repeat element.
8423
8424
8425    inners.push({
8426      type: "kern",
8427      size: shiftOfExtraElement
8428    });
8429    inners.push(makeInner(repeat, font, mode));
8430    inners.push(lap); // Now insert the middle of the brace.
8431
8432    inners.push(makeInner(middle, font, mode));
8433
8434    for (let i = 0; i < repeatCount; i++) {
8435      inners.push(lap);
8436      inners.push(makeInner(repeat, font, mode));
8437    }
8438  } // To cover the gap create by the overlaps, insert one more repeat element,
8439  // at a position that juts 0.005 above the bottom of the top element.
8440
8441
8442  inners.push({
8443    type: "kern",
8444    size: shiftOfExtraElement
8445  });
8446  inners.push(makeInner(repeat, font, mode));
8447  inners.push(lap); // Add the top symbol
8448
8449  inners.push(makeInner(top, font, mode)); // Finally, build the vlist
8450
8451  const newOptions = options.havingBaseStyle(Style$1.TEXT);
8452  const inner = buildCommon.makeVList({
8453    positionType: "bottom",
8454    positionData: depth,
8455    children: inners
8456  }, newOptions);
8457  return styleWrap(buildCommon.makeSpan(["delimsizing", "mult"], [inner], newOptions), Style$1.TEXT, options, classes);
8458}; // All surds have 0.08em padding above the viniculum inside the SVG.
8459// That keeps browser span height rounding error from pinching the line.
8460
8461
8462const vbPad = 80; // padding above the surd, measured inside the viewBox.
8463
8464const emPad = 0.08; // padding, in ems, measured in the document.
8465
8466const sqrtSvg = function sqrtSvg(sqrtName, height, viewBoxHeight, extraViniculum, options) {
8467  const path = sqrtPath(sqrtName, extraViniculum, viewBoxHeight);
8468  const pathNode = new PathNode(sqrtName, path);
8469  const svg = new SvgNode([pathNode], {
8470    // Note: 1000:1 ratio of viewBox to document em width.
8471    "width": "400em",
8472    "height": height + "em",
8473    "viewBox": "0 0 400000 " + viewBoxHeight,
8474    "preserveAspectRatio": "xMinYMin slice"
8475  });
8476  return buildCommon.makeSvgSpan(["hide-tail"], [svg], options);
8477};
8478/**
8479 * Make a sqrt image of the given height,
8480 */
8481
8482
8483const makeSqrtImage = function makeSqrtImage(height, options) {
8484  // Define a newOptions that removes the effect of size changes such as \Huge.
8485  // We don't pick different a height surd for \Huge. For it, we scale up.
8486  const newOptions = options.havingBaseSizing(); // Pick the desired surd glyph from a sequence of surds.
8487
8488  const delim = traverseSequence("\\surd", height * newOptions.sizeMultiplier, stackLargeDelimiterSequence, newOptions);
8489  let sizeMultiplier = newOptions.sizeMultiplier; // default
8490  // The standard sqrt SVGs each have a 0.04em thick viniculum.
8491  // If Settings.minRuleThickness is larger than that, we add extraViniculum.
8492
8493  const extraViniculum = Math.max(0, options.minRuleThickness - options.fontMetrics().sqrtRuleThickness); // Create a span containing an SVG image of a sqrt symbol.
8494
8495  let span;
8496  let spanHeight = 0;
8497  let texHeight = 0;
8498  let viewBoxHeight = 0;
8499  let advanceWidth; // We create viewBoxes with 80 units of "padding" above each surd.
8500  // Then browser rounding error on the parent span height will not
8501  // encroach on the ink of the viniculum. But that padding is not
8502  // included in the TeX-like `height` used for calculation of
8503  // vertical alignment. So texHeight = span.height < span.style.height.
8504
8505  if (delim.type === "small") {
8506    // Get an SVG that is derived from glyph U+221A in font KaTeX-Main.
8507    // 1000 unit normal glyph height.
8508    viewBoxHeight = 1000 + 1000 * extraViniculum + vbPad;
8509
8510    if (height < 1.0) {
8511      sizeMultiplier = 1.0; // mimic a \textfont radical
8512    } else if (height < 1.4) {
8513      sizeMultiplier = 0.7; // mimic a \scriptfont radical
8514    }
8515
8516    spanHeight = (1.0 + extraViniculum + emPad) / sizeMultiplier;
8517    texHeight = (1.00 + extraViniculum) / sizeMultiplier;
8518    span = sqrtSvg("sqrtMain", spanHeight, viewBoxHeight, extraViniculum, options);
8519    span.style.minWidth = "0.853em";
8520    advanceWidth = 0.833 / sizeMultiplier; // from the font.
8521  } else if (delim.type === "large") {
8522    // These SVGs come from fonts: KaTeX_Size1, _Size2, etc.
8523    viewBoxHeight = (1000 + vbPad) * sizeToMaxHeight[delim.size];
8524    texHeight = (sizeToMaxHeight[delim.size] + extraViniculum) / sizeMultiplier;
8525    spanHeight = (sizeToMaxHeight[delim.size] + extraViniculum + emPad) / sizeMultiplier;
8526    span = sqrtSvg("sqrtSize" + delim.size, spanHeight, viewBoxHeight, extraViniculum, options);
8527    span.style.minWidth = "1.02em";
8528    advanceWidth = 1.0 / sizeMultiplier; // 1.0 from the font.
8529  } else {
8530    // Tall sqrt. In TeX, this would be stacked using multiple glyphs.
8531    // We'll use a single SVG to accomplish the same thing.
8532    spanHeight = height + extraViniculum + emPad;
8533    texHeight = height + extraViniculum;
8534    viewBoxHeight = Math.floor(1000 * height + extraViniculum) + vbPad;
8535    span = sqrtSvg("sqrtTall", spanHeight, viewBoxHeight, extraViniculum, options);
8536    span.style.minWidth = "0.742em";
8537    advanceWidth = 1.056;
8538  }
8539
8540  span.height = texHeight;
8541  span.style.height = spanHeight + "em";
8542  return {
8543    span,
8544    advanceWidth,
8545    // Calculate the actual line width.
8546    // This actually should depend on the chosen font -- e.g. \boldmath
8547    // should use the thicker surd symbols from e.g. KaTeX_Main-Bold, and
8548    // have thicker rules.
8549    ruleWidth: (options.fontMetrics().sqrtRuleThickness + extraViniculum) * sizeMultiplier
8550  };
8551}; // There are three kinds of delimiters, delimiters that stack when they become
8552// too large
8553
8554
8555const stackLargeDelimiters = ["(", "\\lparen", ")", "\\rparen", "[", "\\lbrack", "]", "\\rbrack", "\\{", "\\lbrace", "\\}", "\\rbrace", "\\lfloor", "\\rfloor", "\u230a", "\u230b", "\\lceil", "\\rceil", "\u2308", "\u2309", "\\surd"]; // delimiters that always stack
8556
8557const 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
8558
8559const stackNeverDelimiters = ["<", ">", "\\langle", "\\rangle", "/", "\\backslash", "\\lt", "\\gt"]; // Metrics of the different sizes. Found by looking at TeX's output of
8560// $\bigl| // \Bigl| \biggl| \Biggl| \showlists$
8561// Used to create stacked delimiters of appropriate sizes in makeSizedDelim.
8562
8563const sizeToMaxHeight = [0, 1.2, 1.8, 2.4, 3.0];
8564/**
8565 * Used to create a delimiter of a specific size, where `size` is 1, 2, 3, or 4.
8566 */
8567
8568const makeSizedDelim = function makeSizedDelim(delim, size, options, mode, classes) {
8569  // < and > turn into \langle and \rangle in delimiters
8570  if (delim === "<" || delim === "\\lt" || delim === "\u27e8") {
8571    delim = "\\langle";
8572  } else if (delim === ">" || delim === "\\gt" || delim === "\u27e9") {
8573    delim = "\\rangle";
8574  } // Sized delimiters are never centered.
8575
8576
8577  if (utils.contains(stackLargeDelimiters, delim) || utils.contains(stackNeverDelimiters, delim)) {
8578    return makeLargeDelim(delim, size, false, options, mode, classes);
8579  } else if (utils.contains(stackAlwaysDelimiters, delim)) {
8580    return makeStackedDelim(delim, sizeToMaxHeight[size], false, options, mode, classes);
8581  } else {
8582    throw new ParseError("Illegal delimiter: '" + delim + "'");
8583  }
8584};
8585/**
8586 * There are three different sequences of delimiter sizes that the delimiters
8587 * follow depending on the kind of delimiter. This is used when creating custom
8588 * sized delimiters to decide whether to create a small, large, or stacked
8589 * delimiter.
8590 *
8591 * In real TeX, these sequences aren't explicitly defined, but are instead
8592 * defined inside the font metrics. Since there are only three sequences that
8593 * are possible for the delimiters that TeX defines, it is easier to just encode
8594 * them explicitly here.
8595 */
8596
8597
8598// Delimiters that never stack try small delimiters and large delimiters only
8599const stackNeverDelimiterSequence = [{
8600  type: "small",
8601  style: Style$1.SCRIPTSCRIPT
8602}, {
8603  type: "small",
8604  style: Style$1.SCRIPT
8605}, {
8606  type: "small",
8607  style: Style$1.TEXT
8608}, {
8609  type: "large",
8610  size: 1
8611}, {
8612  type: "large",
8613  size: 2
8614}, {
8615  type: "large",
8616  size: 3
8617}, {
8618  type: "large",
8619  size: 4
8620}]; // Delimiters that always stack try the small delimiters first, then stack
8621
8622const stackAlwaysDelimiterSequence = [{
8623  type: "small",
8624  style: Style$1.SCRIPTSCRIPT
8625}, {
8626  type: "small",
8627  style: Style$1.SCRIPT
8628}, {
8629  type: "small",
8630  style: Style$1.TEXT
8631}, {
8632  type: "stack"
8633}]; // Delimiters that stack when large try the small and then large delimiters, and
8634// stack afterwards
8635
8636const stackLargeDelimiterSequence = [{
8637  type: "small",
8638  style: Style$1.SCRIPTSCRIPT
8639}, {
8640  type: "small",
8641  style: Style$1.SCRIPT
8642}, {
8643  type: "small",
8644  style: Style$1.TEXT
8645}, {
8646  type: "large",
8647  size: 1
8648}, {
8649  type: "large",
8650  size: 2
8651}, {
8652  type: "large",
8653  size: 3
8654}, {
8655  type: "large",
8656  size: 4
8657}, {
8658  type: "stack"
8659}];
8660/**
8661 * Get the font used in a delimiter based on what kind of delimiter it is.
8662 * TODO(#963) Use more specific font family return type once that is introduced.
8663 */
8664
8665const delimTypeToFont = function delimTypeToFont(type) {
8666  if (type.type === "small") {
8667    return "Main-Regular";
8668  } else if (type.type === "large") {
8669    return "Size" + type.size + "-Regular";
8670  } else if (type.type === "stack") {
8671    return "Size4-Regular";
8672  } else {
8673    throw new Error(`Add support for delim type '${type.type}' here.`);
8674  }
8675};
8676/**
8677 * Traverse a sequence of types of delimiters to decide what kind of delimiter
8678 * should be used to create a delimiter of the given height+depth.
8679 */
8680
8681
8682const traverseSequence = function traverseSequence(delim, height, sequence, options) {
8683  // Here, we choose the index we should start at in the sequences. In smaller
8684  // sizes (which correspond to larger numbers in style.size) we start earlier
8685  // in the sequence. Thus, scriptscript starts at index 3-3=0, script starts
8686  // at index 3-2=1, text starts at 3-1=2, and display starts at min(2,3-0)=2
8687  const start = Math.min(2, 3 - options.style.size);
8688
8689  for (let i = start; i < sequence.length; i++) {
8690    if (sequence[i].type === "stack") {
8691      // This is always the last delimiter, so we just break the loop now.
8692      break;
8693    }
8694
8695    const metrics = getMetrics(delim, delimTypeToFont(sequence[i]), "math");
8696    let heightDepth = metrics.height + metrics.depth; // Small delimiters are scaled down versions of the same font, so we
8697    // account for the style change size.
8698
8699    if (sequence[i].type === "small") {
8700      const newOptions = options.havingBaseStyle(sequence[i].style);
8701      heightDepth *= newOptions.sizeMultiplier;
8702    } // Check if the delimiter at this size works for the given height.
8703
8704
8705    if (heightDepth > height) {
8706      return sequence[i];
8707    }
8708  } // If we reached the end of the sequence, return the last sequence element.
8709
8710
8711  return sequence[sequence.length - 1];
8712};
8713/**
8714 * Make a delimiter of a given height+depth, with optional centering. Here, we
8715 * traverse the sequences, and create a delimiter that the sequence tells us to.
8716 */
8717
8718
8719const makeCustomSizedDelim = function makeCustomSizedDelim(delim, height, center, options, mode, classes) {
8720  if (delim === "<" || delim === "\\lt" || delim === "\u27e8") {
8721    delim = "\\langle";
8722  } else if (delim === ">" || delim === "\\gt" || delim === "\u27e9") {
8723    delim = "\\rangle";
8724  } // Decide what sequence to use
8725
8726
8727  let sequence;
8728
8729  if (utils.contains(stackNeverDelimiters, delim)) {
8730    sequence = stackNeverDelimiterSequence;
8731  } else if (utils.contains(stackLargeDelimiters, delim)) {
8732    sequence = stackLargeDelimiterSequence;
8733  } else {
8734    sequence = stackAlwaysDelimiterSequence;
8735  } // Look through the sequence
8736
8737
8738  const delimType = traverseSequence(delim, height, sequence, options); // Get the delimiter from font glyphs.
8739  // Depending on the sequence element we decided on, call the
8740  // appropriate function.
8741
8742  if (delimType.type === "small") {
8743    return makeSmallDelim(delim, delimType.style, center, options, mode, classes);
8744  } else if (delimType.type === "large") {
8745    return makeLargeDelim(delim, delimType.size, center, options, mode, classes);
8746  } else
8747    /* if (delimType.type === "stack") */
8748    {
8749      return makeStackedDelim(delim, height, center, options, mode, classes);
8750    }
8751};
8752/**
8753 * Make a delimiter for use with `\left` and `\right`, given a height and depth
8754 * of an expression that the delimiters surround.
8755 */
8756
8757
8758const makeLeftRightDelim = function makeLeftRightDelim(delim, height, depth, options, mode, classes) {
8759  // We always center \left/\right delimiters, so the axis is always shifted
8760  const axisHeight = options.fontMetrics().axisHeight * options.sizeMultiplier; // Taken from TeX source, tex.web, function make_left_right
8761
8762  const delimiterFactor = 901;
8763  const delimiterExtend = 5.0 / options.fontMetrics().ptPerEm;
8764  const maxDistFromAxis = Math.max(height - axisHeight, depth + axisHeight);
8765  const totalHeight = Math.max( // In real TeX, calculations are done using integral values which are
8766  // 65536 per pt, or 655360 per em. So, the division here truncates in
8767  // TeX but doesn't here, producing different results. If we wanted to
8768  // exactly match TeX's calculation, we could do
8769  //   Math.floor(655360 * maxDistFromAxis / 500) *
8770  //    delimiterFactor / 655360
8771  // (To see the difference, compare
8772  //    x^{x^{\left(\rule{0.1em}{0.68em}\right)}}
8773  // in TeX and KaTeX)
8774  maxDistFromAxis / 500 * delimiterFactor, 2 * maxDistFromAxis - delimiterExtend); // Finally, we defer to `makeCustomSizedDelim` with our calculated total
8775  // height
8776
8777  return makeCustomSizedDelim(delim, totalHeight, true, options, mode, classes);
8778};
8779
8780var delimiter = {
8781  sqrtImage: makeSqrtImage,
8782  sizedDelim: makeSizedDelim,
8783  customSizedDelim: makeCustomSizedDelim,
8784  leftRightDelim: makeLeftRightDelim
8785};
8786
8787// Extra data needed for the delimiter handler down below
8788const delimiterSizes = {
8789  "\\bigl": {
8790    mclass: "mopen",
8791    size: 1
8792  },
8793  "\\Bigl": {
8794    mclass: "mopen",
8795    size: 2
8796  },
8797  "\\biggl": {
8798    mclass: "mopen",
8799    size: 3
8800  },
8801  "\\Biggl": {
8802    mclass: "mopen",
8803    size: 4
8804  },
8805  "\\bigr": {
8806    mclass: "mclose",
8807    size: 1
8808  },
8809  "\\Bigr": {
8810    mclass: "mclose",
8811    size: 2
8812  },
8813  "\\biggr": {
8814    mclass: "mclose",
8815    size: 3
8816  },
8817  "\\Biggr": {
8818    mclass: "mclose",
8819    size: 4
8820  },
8821  "\\bigm": {
8822    mclass: "mrel",
8823    size: 1
8824  },
8825  "\\Bigm": {
8826    mclass: "mrel",
8827    size: 2
8828  },
8829  "\\biggm": {
8830    mclass: "mrel",
8831    size: 3
8832  },
8833  "\\Biggm": {
8834    mclass: "mrel",
8835    size: 4
8836  },
8837  "\\big": {
8838    mclass: "mord",
8839    size: 1
8840  },
8841  "\\Big": {
8842    mclass: "mord",
8843    size: 2
8844  },
8845  "\\bigg": {
8846    mclass: "mord",
8847    size: 3
8848  },
8849  "\\Bigg": {
8850    mclass: "mord",
8851    size: 4
8852  }
8853};
8854const 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", "."];
8855
8856// Delimiter functions
8857function checkDelimiter(delim, context) {
8858  const symDelim = checkSymbolNodeType(delim);
8859
8860  if (symDelim && utils.contains(delimiters, symDelim.text)) {
8861    return symDelim;
8862  } else {
8863    throw new ParseError("Invalid delimiter: '" + (symDelim ? symDelim.text : JSON.stringify(delim)) + "' after '" + context.funcName + "'", delim);
8864  }
8865}
8866
8867defineFunction({
8868  type: "delimsizing",
8869  names: ["\\bigl", "\\Bigl", "\\biggl", "\\Biggl", "\\bigr", "\\Bigr", "\\biggr", "\\Biggr", "\\bigm", "\\Bigm", "\\biggm", "\\Biggm", "\\big", "\\Big", "\\bigg", "\\Bigg"],
8870  props: {
8871    numArgs: 1
8872  },
8873  handler: (context, args) => {
8874    const delim = checkDelimiter(args[0], context);
8875    return {
8876      type: "delimsizing",
8877      mode: context.parser.mode,
8878      size: delimiterSizes[context.funcName].size,
8879      mclass: delimiterSizes[context.funcName].mclass,
8880      delim: delim.text
8881    };
8882  },
8883  htmlBuilder: (group, options) => {
8884    if (group.delim === ".") {
8885      // Empty delimiters still count as elements, even though they don't
8886      // show anything.
8887      return buildCommon.makeSpan([group.mclass]);
8888    } // Use delimiter.sizedDelim to generate the delimiter.
8889
8890
8891    return delimiter.sizedDelim(group.delim, group.size, options, group.mode, [group.mclass]);
8892  },
8893  mathmlBuilder: group => {
8894    const children = [];
8895
8896    if (group.delim !== ".") {
8897      children.push(makeText(group.delim, group.mode));
8898    }
8899
8900    const node = new mathMLTree.MathNode("mo", children);
8901
8902    if (group.mclass === "mopen" || group.mclass === "mclose") {
8903      // Only some of the delimsizing functions act as fences, and they
8904      // return "mopen" or "mclose" mclass.
8905      node.setAttribute("fence", "true");
8906    } else {
8907      // Explicitly disable fencing if it's not a fence, to override the
8908      // defaults.
8909      node.setAttribute("fence", "false");
8910    }
8911
8912    return node;
8913  }
8914});
8915
8916function assertParsed(group) {
8917  if (!group.body) {
8918    throw new Error("Bug: The leftright ParseNode wasn't fully parsed.");
8919  }
8920}
8921
8922defineFunction({
8923  type: "leftright-right",
8924  names: ["\\right"],
8925  props: {
8926    numArgs: 1
8927  },
8928  handler: (context, args) => {
8929    // \left case below triggers parsing of \right in
8930    //   `const right = parser.parseFunction();`
8931    // uses this return value.
8932    const color = context.parser.gullet.macros.get("\\current@color");
8933
8934    if (color && typeof color !== "string") {
8935      throw new ParseError("\\current@color set to non-string in \\right");
8936    }
8937
8938    return {
8939      type: "leftright-right",
8940      mode: context.parser.mode,
8941      delim: checkDelimiter(args[0], context).text,
8942      color // undefined if not set via \color
8943
8944    };
8945  }
8946});
8947defineFunction({
8948  type: "leftright",
8949  names: ["\\left"],
8950  props: {
8951    numArgs: 1
8952  },
8953  handler: (context, args) => {
8954    const delim = checkDelimiter(args[0], context);
8955    const parser = context.parser; // Parse out the implicit body
8956
8957    ++parser.leftrightDepth; // parseExpression stops before '\\right'
8958
8959    const body = parser.parseExpression(false);
8960    --parser.leftrightDepth; // Check the next token
8961
8962    parser.expect("\\right", false);
8963    const right = assertNodeType(parser.parseFunction(), "leftright-right");
8964    return {
8965      type: "leftright",
8966      mode: parser.mode,
8967      body,
8968      left: delim.text,
8969      right: right.delim,
8970      rightColor: right.color
8971    };
8972  },
8973  htmlBuilder: (group, options) => {
8974    assertParsed(group); // Build the inner expression
8975
8976    const inner = buildExpression(group.body, options, true, ["mopen", "mclose"]);
8977    let innerHeight = 0;
8978    let innerDepth = 0;
8979    let hadMiddle = false; // Calculate its height and depth
8980
8981    for (let i = 0; i < inner.length; i++) {
8982      // Property `isMiddle` not defined on `span`. See comment in
8983      // "middle"'s htmlBuilder.
8984      // $FlowFixMe
8985      if (inner[i].isMiddle) {
8986        hadMiddle = true;
8987      } else {
8988        innerHeight = Math.max(inner[i].height, innerHeight);
8989        innerDepth = Math.max(inner[i].depth, innerDepth);
8990      }
8991    } // The size of delimiters is the same, regardless of what style we are
8992    // in. Thus, to correctly calculate the size of delimiter we need around
8993    // a group, we scale down the inner size based on the size.
8994
8995
8996    innerHeight *= options.sizeMultiplier;
8997    innerDepth *= options.sizeMultiplier;
8998    let leftDelim;
8999
9000    if (group.left === ".") {
9001      // Empty delimiters in \left and \right make null delimiter spaces.
9002      leftDelim = makeNullDelimiter(options, ["mopen"]);
9003    } else {
9004      // Otherwise, use leftRightDelim to generate the correct sized
9005      // delimiter.
9006      leftDelim = delimiter.leftRightDelim(group.left, innerHeight, innerDepth, options, group.mode, ["mopen"]);
9007    } // Add it to the beginning of the expression
9008
9009
9010    inner.unshift(leftDelim); // Handle middle delimiters
9011
9012    if (hadMiddle) {
9013      for (let i = 1; i < inner.length; i++) {
9014        const middleDelim = inner[i]; // Property `isMiddle` not defined on `span`. See comment in
9015        // "middle"'s htmlBuilder.
9016        // $FlowFixMe
9017
9018        const isMiddle = middleDelim.isMiddle;
9019
9020        if (isMiddle) {
9021          // Apply the options that were active when \middle was called
9022          inner[i] = delimiter.leftRightDelim(isMiddle.delim, innerHeight, innerDepth, isMiddle.options, group.mode, []);
9023        }
9024      }
9025    }
9026
9027    let rightDelim; // Same for the right delimiter, but using color specified by \color
9028
9029    if (group.right === ".") {
9030      rightDelim = makeNullDelimiter(options, ["mclose"]);
9031    } else {
9032      const colorOptions = group.rightColor ? options.withColor(group.rightColor) : options;
9033      rightDelim = delimiter.leftRightDelim(group.right, innerHeight, innerDepth, colorOptions, group.mode, ["mclose"]);
9034    } // Add it to the end of the expression.
9035
9036
9037    inner.push(rightDelim);
9038    return buildCommon.makeSpan(["minner"], inner, options);
9039  },
9040  mathmlBuilder: (group, options) => {
9041    assertParsed(group);
9042    const inner = buildExpression$1(group.body, options);
9043
9044    if (group.left !== ".") {
9045      const leftNode = new mathMLTree.MathNode("mo", [makeText(group.left, group.mode)]);
9046      leftNode.setAttribute("fence", "true");
9047      inner.unshift(leftNode);
9048    }
9049
9050    if (group.right !== ".") {
9051      const rightNode = new mathMLTree.MathNode("mo", [makeText(group.right, group.mode)]);
9052      rightNode.setAttribute("fence", "true");
9053
9054      if (group.rightColor) {
9055        rightNode.setAttribute("mathcolor", group.rightColor);
9056      }
9057
9058      inner.push(rightNode);
9059    }
9060
9061    return makeRow(inner);
9062  }
9063});
9064defineFunction({
9065  type: "middle",
9066  names: ["\\middle"],
9067  props: {
9068    numArgs: 1
9069  },
9070  handler: (context, args) => {
9071    const delim = checkDelimiter(args[0], context);
9072
9073    if (!context.parser.leftrightDepth) {
9074      throw new ParseError("\\middle without preceding \\left", delim);
9075    }
9076
9077    return {
9078      type: "middle",
9079      mode: context.parser.mode,
9080      delim: delim.text
9081    };
9082  },
9083  htmlBuilder: (group, options) => {
9084    let middleDelim;
9085
9086    if (group.delim === ".") {
9087      middleDelim = makeNullDelimiter(options, []);
9088    } else {
9089      middleDelim = delimiter.sizedDelim(group.delim, 1, options, group.mode, []);
9090      const isMiddle = {
9091        delim: group.delim,
9092        options
9093      }; // Property `isMiddle` not defined on `span`. It is only used in
9094      // this file above.
9095      // TODO: Fix this violation of the `span` type and possibly rename
9096      // things since `isMiddle` sounds like a boolean, but is a struct.
9097      // $FlowFixMe
9098
9099      middleDelim.isMiddle = isMiddle;
9100    }
9101
9102    return middleDelim;
9103  },
9104  mathmlBuilder: (group, options) => {
9105    // A Firefox \middle will strech a character vertically only if it
9106    // is in the fence part of the operator dictionary at:
9107    // https://www.w3.org/TR/MathML3/appendixc.html.
9108    // So we need to avoid U+2223 and use plain "|" instead.
9109    const textNode = group.delim === "\\vert" || group.delim === "|" ? makeText("|", "text") : makeText(group.delim, group.mode);
9110    const middleNode = new mathMLTree.MathNode("mo", [textNode]);
9111    middleNode.setAttribute("fence", "true"); // MathML gives 5/18em spacing to each <mo> element.
9112    // \middle should get delimiter spacing instead.
9113
9114    middleNode.setAttribute("lspace", "0.05em");
9115    middleNode.setAttribute("rspace", "0.05em");
9116    return middleNode;
9117  }
9118});
9119
9120const htmlBuilder$2 = (group, options) => {
9121  // \cancel, \bcancel, \xcancel, \sout, \fbox, \colorbox, \fcolorbox
9122  // Some groups can return document fragments.  Handle those by wrapping
9123  // them in a span.
9124  const inner = buildCommon.wrapFragment(buildGroup(group.body, options), options);
9125  const label = group.label.substr(1);
9126  const scale = options.sizeMultiplier;
9127  let img;
9128  let imgShift = 0; // In the LaTeX cancel package, line geometry is slightly different
9129  // depending on whether the subject is wider than it is tall, or vice versa.
9130  // We don't know the width of a group, so as a proxy, we test if
9131  // the subject is a single character. This captures most of the
9132  // subjects that should get the "tall" treatment.
9133
9134  const isSingleChar = utils.isCharacterBox(group.body);
9135
9136  if (label === "sout") {
9137    img = buildCommon.makeSpan(["stretchy", "sout"]);
9138    img.height = options.fontMetrics().defaultRuleThickness / scale;
9139    imgShift = -0.5 * options.fontMetrics().xHeight;
9140  } else {
9141    // Add horizontal padding
9142    if (/cancel/.test(label)) {
9143      if (!isSingleChar) {
9144        inner.classes.push("cancel-pad");
9145      }
9146    } else {
9147      inner.classes.push("boxpad");
9148    } // Add vertical padding
9149
9150
9151    let vertPad = 0;
9152    let ruleThickness = 0; // ref: cancel package: \advance\totalheight2\p@ % "+2"
9153
9154    if (/box/.test(label)) {
9155      ruleThickness = Math.max(options.fontMetrics().fboxrule, // default
9156      options.minRuleThickness // User override.
9157      );
9158      vertPad = options.fontMetrics().fboxsep + (label === "colorbox" ? 0 : ruleThickness);
9159    } else {
9160      vertPad = isSingleChar ? 0.2 : 0;
9161    }
9162
9163    img = stretchy.encloseSpan(inner, label, vertPad, options);
9164
9165    if (/fbox|boxed|fcolorbox/.test(label)) {
9166      img.style.borderStyle = "solid";
9167      img.style.borderWidth = `${ruleThickness}em`;
9168    }
9169
9170    imgShift = inner.depth + vertPad;
9171
9172    if (group.backgroundColor) {
9173      img.style.backgroundColor = group.backgroundColor;
9174
9175      if (group.borderColor) {
9176        img.style.borderColor = group.borderColor;
9177      }
9178    }
9179  }
9180
9181  let vlist;
9182
9183  if (group.backgroundColor) {
9184    vlist = buildCommon.makeVList({
9185      positionType: "individualShift",
9186      children: [// Put the color background behind inner;
9187      {
9188        type: "elem",
9189        elem: img,
9190        shift: imgShift
9191      }, {
9192        type: "elem",
9193        elem: inner,
9194        shift: 0
9195      }]
9196    }, options);
9197  } else {
9198    vlist = buildCommon.makeVList({
9199      positionType: "individualShift",
9200      children: [// Write the \cancel stroke on top of inner.
9201      {
9202        type: "elem",
9203        elem: inner,
9204        shift: 0
9205      }, {
9206        type: "elem",
9207        elem: img,
9208        shift: imgShift,
9209        wrapperClasses: /cancel/.test(label) ? ["svg-align"] : []
9210      }]
9211    }, options);
9212  }
9213
9214  if (/cancel/.test(label)) {
9215    // The cancel package documentation says that cancel lines add their height
9216    // to the expression, but tests show that isn't how it actually works.
9217    vlist.height = inner.height;
9218    vlist.depth = inner.depth;
9219  }
9220
9221  if (/cancel/.test(label) && !isSingleChar) {
9222    // cancel does not create horiz space for its line extension.
9223    return buildCommon.makeSpan(["mord", "cancel-lap"], [vlist], options);
9224  } else {
9225    return buildCommon.makeSpan(["mord"], [vlist], options);
9226  }
9227};
9228
9229const mathmlBuilder$2 = (group, options) => {
9230  let fboxsep = 0;
9231  const node = new mathMLTree.MathNode(group.label.indexOf("colorbox") > -1 ? "mpadded" : "menclose", [buildGroup$1(group.body, options)]);
9232
9233  switch (group.label) {
9234    case "\\cancel":
9235      node.setAttribute("notation", "updiagonalstrike");
9236      break;
9237
9238    case "\\bcancel":
9239      node.setAttribute("notation", "downdiagonalstrike");
9240      break;
9241
9242    case "\\sout":
9243      node.setAttribute("notation", "horizontalstrike");
9244      break;
9245
9246    case "\\fbox":
9247      node.setAttribute("notation", "box");
9248      break;
9249
9250    case "\\fcolorbox":
9251    case "\\colorbox":
9252      // <menclose> doesn't have a good notation option. So use <mpadded>
9253      // instead. Set some attributes that come included with <menclose>.
9254      fboxsep = options.fontMetrics().fboxsep * options.fontMetrics().ptPerEm;
9255      node.setAttribute("width", `+${2 * fboxsep}pt`);
9256      node.setAttribute("height", `+${2 * fboxsep}pt`);
9257      node.setAttribute("lspace", `${fboxsep}pt`); //
9258
9259      node.setAttribute("voffset", `${fboxsep}pt`);
9260
9261      if (group.label === "\\fcolorbox") {
9262        const thk = Math.max(options.fontMetrics().fboxrule, // default
9263        options.minRuleThickness // user override
9264        );
9265        node.setAttribute("style", "border: " + thk + "em solid " + String(group.borderColor));
9266      }
9267
9268      break;
9269
9270    case "\\xcancel":
9271      node.setAttribute("notation", "updiagonalstrike downdiagonalstrike");
9272      break;
9273  }
9274
9275  if (group.backgroundColor) {
9276    node.setAttribute("mathbackground", group.backgroundColor);
9277  }
9278
9279  return node;
9280};
9281
9282defineFunction({
9283  type: "enclose",
9284  names: ["\\colorbox"],
9285  props: {
9286    numArgs: 2,
9287    allowedInText: true,
9288    greediness: 3,
9289    argTypes: ["color", "text"]
9290  },
9291
9292  handler(_ref, args, optArgs) {
9293    let parser = _ref.parser,
9294        funcName = _ref.funcName;
9295    const color = assertNodeType(args[0], "color-token").color;
9296    const body = args[1];
9297    return {
9298      type: "enclose",
9299      mode: parser.mode,
9300      label: funcName,
9301      backgroundColor: color,
9302      body
9303    };
9304  },
9305
9306  htmlBuilder: htmlBuilder$2,
9307  mathmlBuilder: mathmlBuilder$2
9308});
9309defineFunction({
9310  type: "enclose",
9311  names: ["\\fcolorbox"],
9312  props: {
9313    numArgs: 3,
9314    allowedInText: true,
9315    greediness: 3,
9316    argTypes: ["color", "color", "text"]
9317  },
9318
9319  handler(_ref2, args, optArgs) {
9320    let parser = _ref2.parser,
9321        funcName = _ref2.funcName;
9322    const borderColor = assertNodeType(args[0], "color-token").color;
9323    const backgroundColor = assertNodeType(args[1], "color-token").color;
9324    const body = args[2];
9325    return {
9326      type: "enclose",
9327      mode: parser.mode,
9328      label: funcName,
9329      backgroundColor,
9330      borderColor,
9331      body
9332    };
9333  },
9334
9335  htmlBuilder: htmlBuilder$2,
9336  mathmlBuilder: mathmlBuilder$2
9337});
9338defineFunction({
9339  type: "enclose",
9340  names: ["\\fbox"],
9341  props: {
9342    numArgs: 1,
9343    argTypes: ["hbox"],
9344    allowedInText: true
9345  },
9346
9347  handler(_ref3, args) {
9348    let parser = _ref3.parser;
9349    return {
9350      type: "enclose",
9351      mode: parser.mode,
9352      label: "\\fbox",
9353      body: args[0]
9354    };
9355  }
9356
9357});
9358defineFunction({
9359  type: "enclose",
9360  names: ["\\cancel", "\\bcancel", "\\xcancel", "\\sout"],
9361  props: {
9362    numArgs: 1
9363  },
9364
9365  handler(_ref4, args, optArgs) {
9366    let parser = _ref4.parser,
9367        funcName = _ref4.funcName;
9368    const body = args[0];
9369    return {
9370      type: "enclose",
9371      mode: parser.mode,
9372      label: funcName,
9373      body
9374    };
9375  },
9376
9377  htmlBuilder: htmlBuilder$2,
9378  mathmlBuilder: mathmlBuilder$2
9379});
9380
9381/**
9382 * All registered environments.
9383 * `environments.js` exports this same dictionary again and makes it public.
9384 * `Parser.js` requires this dictionary via `environments.js`.
9385 */
9386const _environments = {};
9387function defineEnvironment(_ref) {
9388  let type = _ref.type,
9389      names = _ref.names,
9390      props = _ref.props,
9391      handler = _ref.handler,
9392      htmlBuilder = _ref.htmlBuilder,
9393      mathmlBuilder = _ref.mathmlBuilder;
9394  // Set default values of environments.
9395  const data = {
9396    type,
9397    numArgs: props.numArgs || 0,
9398    greediness: 1,
9399    allowedInText: false,
9400    numOptionalArgs: 0,
9401    handler
9402  };
9403
9404  for (let i = 0; i < names.length; ++i) {
9405    // TODO: The value type of _environments should be a type union of all
9406    // possible `EnvSpec<>` possibilities instead of `EnvSpec<*>`, which is
9407    // an existential type.
9408    // $FlowFixMe
9409    _environments[names[i]] = data;
9410  }
9411
9412  if (htmlBuilder) {
9413    _htmlGroupBuilders[type] = htmlBuilder;
9414  }
9415
9416  if (mathmlBuilder) {
9417    _mathmlGroupBuilders[type] = mathmlBuilder;
9418  }
9419}
9420
9421function getHLines(parser) {
9422  // Return an array. The array length = number of hlines.
9423  // Each element in the array tells if the line is dashed.
9424  const hlineInfo = [];
9425  parser.consumeSpaces();
9426  let nxt = parser.fetch().text;
9427
9428  while (nxt === "\\hline" || nxt === "\\hdashline") {
9429    parser.consume();
9430    hlineInfo.push(nxt === "\\hdashline");
9431    parser.consumeSpaces();
9432    nxt = parser.fetch().text;
9433  }
9434
9435  return hlineInfo;
9436}
9437/**
9438 * Parse the body of the environment, with rows delimited by \\ and
9439 * columns delimited by &, and create a nested list in row-major order
9440 * with one group per cell.  If given an optional argument style
9441 * ("text", "display", etc.), then each cell is cast into that style.
9442 */
9443
9444
9445function parseArray(parser, _ref, style) {
9446  let hskipBeforeAndAfter = _ref.hskipBeforeAndAfter,
9447      addJot = _ref.addJot,
9448      cols = _ref.cols,
9449      arraystretch = _ref.arraystretch,
9450      colSeparationType = _ref.colSeparationType;
9451  // Parse body of array with \\ temporarily mapped to \cr
9452  parser.gullet.beginGroup();
9453  parser.gullet.macros.set("\\\\", "\\cr"); // Get current arraystretch if it's not set by the environment
9454
9455  if (!arraystretch) {
9456    const stretch = parser.gullet.expandMacroAsText("\\arraystretch");
9457
9458    if (stretch == null) {
9459      // Default \arraystretch from lttab.dtx
9460      arraystretch = 1;
9461    } else {
9462      arraystretch = parseFloat(stretch);
9463
9464      if (!arraystretch || arraystretch < 0) {
9465        throw new ParseError(`Invalid \\arraystretch: ${stretch}`);
9466      }
9467    }
9468  } // Start group for first cell
9469
9470
9471  parser.gullet.beginGroup();
9472  let row = [];
9473  const body = [row];
9474  const rowGaps = [];
9475  const hLinesBeforeRow = []; // Test for \hline at the top of the array.
9476
9477  hLinesBeforeRow.push(getHLines(parser));
9478
9479  while (true) {
9480    // eslint-disable-line no-constant-condition
9481    // Parse each cell in its own group (namespace)
9482    let cell = parser.parseExpression(false, "\\cr");
9483    parser.gullet.endGroup();
9484    parser.gullet.beginGroup();
9485    cell = {
9486      type: "ordgroup",
9487      mode: parser.mode,
9488      body: cell
9489    };
9490
9491    if (style) {
9492      cell = {
9493        type: "styling",
9494        mode: parser.mode,
9495        style,
9496        body: [cell]
9497      };
9498    }
9499
9500    row.push(cell);
9501    const next = parser.fetch().text;
9502
9503    if (next === "&") {
9504      parser.consume();
9505    } else if (next === "\\end") {
9506      // Arrays terminate newlines with `\crcr` which consumes a `\cr` if
9507      // the last line is empty.
9508      // NOTE: Currently, `cell` is the last item added into `row`.
9509      if (row.length === 1 && cell.type === "styling" && cell.body[0].body.length === 0) {
9510        body.pop();
9511      }
9512
9513      if (hLinesBeforeRow.length < body.length + 1) {
9514        hLinesBeforeRow.push([]);
9515      }
9516
9517      break;
9518    } else if (next === "\\cr") {
9519      const cr = assertNodeType(parser.parseFunction(), "cr");
9520      rowGaps.push(cr.size); // check for \hline(s) following the row separator
9521
9522      hLinesBeforeRow.push(getHLines(parser));
9523      row = [];
9524      body.push(row);
9525    } else {
9526      throw new ParseError("Expected & or \\\\ or \\cr or \\end", parser.nextToken);
9527    }
9528  } // End cell group
9529
9530
9531  parser.gullet.endGroup(); // End array group defining \\
9532
9533  parser.gullet.endGroup();
9534  return {
9535    type: "array",
9536    mode: parser.mode,
9537    addJot,
9538    arraystretch,
9539    body,
9540    cols,
9541    rowGaps,
9542    hskipBeforeAndAfter,
9543    hLinesBeforeRow,
9544    colSeparationType
9545  };
9546} // Decides on a style for cells in an array according to whether the given
9547// environment name starts with the letter 'd'.
9548
9549
9550function dCellStyle(envName) {
9551  if (envName.substr(0, 1) === "d") {
9552    return "display";
9553  } else {
9554    return "text";
9555  }
9556}
9557
9558const htmlBuilder$3 = function htmlBuilder(group, options) {
9559  let r;
9560  let c;
9561  const nr = group.body.length;
9562  const hLinesBeforeRow = group.hLinesBeforeRow;
9563  let nc = 0;
9564  let body = new Array(nr);
9565  const hlines = [];
9566  const ruleThickness = Math.max( // From LaTeX \showthe\arrayrulewidth. Equals 0.04 em.
9567  options.fontMetrics().arrayRuleWidth, options.minRuleThickness // User override.
9568  ); // Horizontal spacing
9569
9570  const pt = 1 / options.fontMetrics().ptPerEm;
9571  let arraycolsep = 5 * pt; // default value, i.e. \arraycolsep in article.cls
9572
9573  if (group.colSeparationType && group.colSeparationType === "small") {
9574    // We're in a {smallmatrix}. Default column space is \thickspace,
9575    // i.e. 5/18em = 0.2778em, per amsmath.dtx for {smallmatrix}.
9576    // But that needs adjustment because LaTeX applies \scriptstyle to the
9577    // entire array, including the colspace, but this function applies
9578    // \scriptstyle only inside each element.
9579    const localMultiplier = options.havingStyle(Style$1.SCRIPT).sizeMultiplier;
9580    arraycolsep = 0.2778 * (localMultiplier / options.sizeMultiplier);
9581  } // Vertical spacing
9582
9583
9584  const baselineskip = 12 * pt; // see size10.clo
9585  // Default \jot from ltmath.dtx
9586  // TODO(edemaine): allow overriding \jot via \setlength (#687)
9587
9588  const jot = 3 * pt;
9589  const arrayskip = group.arraystretch * baselineskip;
9590  const arstrutHeight = 0.7 * arrayskip; // \strutbox in ltfsstrc.dtx and
9591
9592  const arstrutDepth = 0.3 * arrayskip; // \@arstrutbox in lttab.dtx
9593
9594  let totalHeight = 0; // Set a position for \hline(s) at the top of the array, if any.
9595
9596  function setHLinePos(hlinesInGap) {
9597    for (let i = 0; i < hlinesInGap.length; ++i) {
9598      if (i > 0) {
9599        totalHeight += 0.25;
9600      }
9601
9602      hlines.push({
9603        pos: totalHeight,
9604        isDashed: hlinesInGap[i]
9605      });
9606    }
9607  }
9608
9609  setHLinePos(hLinesBeforeRow[0]);
9610
9611  for (r = 0; r < group.body.length; ++r) {
9612    const inrow = group.body[r];
9613    let height = arstrutHeight; // \@array adds an \@arstrut
9614
9615    let depth = arstrutDepth; // to each tow (via the template)
9616
9617    if (nc < inrow.length) {
9618      nc = inrow.length;
9619    }
9620
9621    const outrow = new Array(inrow.length);
9622
9623    for (c = 0; c < inrow.length; ++c) {
9624      const elt = buildGroup(inrow[c], options);
9625
9626      if (depth < elt.depth) {
9627        depth = elt.depth;
9628      }
9629
9630      if (height < elt.height) {
9631        height = elt.height;
9632      }
9633
9634      outrow[c] = elt;
9635    }
9636
9637    const rowGap = group.rowGaps[r];
9638    let gap = 0;
9639
9640    if (rowGap) {
9641      gap = calculateSize(rowGap, options);
9642
9643      if (gap > 0) {
9644        // \@argarraycr
9645        gap += arstrutDepth;
9646
9647        if (depth < gap) {
9648          depth = gap; // \@xargarraycr
9649        }
9650
9651        gap = 0;
9652      }
9653    } // In AMS multiline environments such as aligned and gathered, rows
9654    // correspond to lines that have additional \jot added to the
9655    // \baselineskip via \openup.
9656
9657
9658    if (group.addJot) {
9659      depth += jot;
9660    }
9661
9662    outrow.height = height;
9663    outrow.depth = depth;
9664    totalHeight += height;
9665    outrow.pos = totalHeight;
9666    totalHeight += depth + gap; // \@yargarraycr
9667
9668    body[r] = outrow; // Set a position for \hline(s), if any.
9669
9670    setHLinePos(hLinesBeforeRow[r + 1]);
9671  }
9672
9673  const offset = totalHeight / 2 + options.fontMetrics().axisHeight;
9674  const colDescriptions = group.cols || [];
9675  const cols = [];
9676  let colSep;
9677  let colDescrNum;
9678
9679  for (c = 0, colDescrNum = 0; // Continue while either there are more columns or more column
9680  // descriptions, so trailing separators don't get lost.
9681  c < nc || colDescrNum < colDescriptions.length; ++c, ++colDescrNum) {
9682    let colDescr = colDescriptions[colDescrNum] || {};
9683    let firstSeparator = true;
9684
9685    while (colDescr.type === "separator") {
9686      // If there is more than one separator in a row, add a space
9687      // between them.
9688      if (!firstSeparator) {
9689        colSep = buildCommon.makeSpan(["arraycolsep"], []);
9690        colSep.style.width = options.fontMetrics().doubleRuleSep + "em";
9691        cols.push(colSep);
9692      }
9693
9694      if (colDescr.separator === "|" || colDescr.separator === ":") {
9695        const lineType = colDescr.separator === "|" ? "solid" : "dashed";
9696        const separator = buildCommon.makeSpan(["vertical-separator"], [], options);
9697        separator.style.height = totalHeight + "em";
9698        separator.style.borderRightWidth = `${ruleThickness}em`;
9699        separator.style.borderRightStyle = lineType;
9700        separator.style.margin = `0 -${ruleThickness / 2}em`;
9701        separator.style.verticalAlign = -(totalHeight - offset) + "em";
9702        cols.push(separator);
9703      } else {
9704        throw new ParseError("Invalid separator type: " + colDescr.separator);
9705      }
9706
9707      colDescrNum++;
9708      colDescr = colDescriptions[colDescrNum] || {};
9709      firstSeparator = false;
9710    }
9711
9712    if (c >= nc) {
9713      continue;
9714    }
9715
9716    let sepwidth;
9717
9718    if (c > 0 || group.hskipBeforeAndAfter) {
9719      sepwidth = utils.deflt(colDescr.pregap, arraycolsep);
9720
9721      if (sepwidth !== 0) {
9722        colSep = buildCommon.makeSpan(["arraycolsep"], []);
9723        colSep.style.width = sepwidth + "em";
9724        cols.push(colSep);
9725      }
9726    }
9727
9728    let col = [];
9729
9730    for (r = 0; r < nr; ++r) {
9731      const row = body[r];
9732      const elem = row[c];
9733
9734      if (!elem) {
9735        continue;
9736      }
9737
9738      const shift = row.pos - offset;
9739      elem.depth = row.depth;
9740      elem.height = row.height;
9741      col.push({
9742        type: "elem",
9743        elem: elem,
9744        shift: shift
9745      });
9746    }
9747
9748    col = buildCommon.makeVList({
9749      positionType: "individualShift",
9750      children: col
9751    }, options);
9752    col = buildCommon.makeSpan(["col-align-" + (colDescr.align || "c")], [col]);
9753    cols.push(col);
9754
9755    if (c < nc - 1 || group.hskipBeforeAndAfter) {
9756      sepwidth = utils.deflt(colDescr.postgap, arraycolsep);
9757
9758      if (sepwidth !== 0) {
9759        colSep = buildCommon.makeSpan(["arraycolsep"], []);
9760        colSep.style.width = sepwidth + "em";
9761        cols.push(colSep);
9762      }
9763    }
9764  }
9765
9766  body = buildCommon.makeSpan(["mtable"], cols); // Add \hline(s), if any.
9767
9768  if (hlines.length > 0) {
9769    const line = buildCommon.makeLineSpan("hline", options, ruleThickness);
9770    const dashes = buildCommon.makeLineSpan("hdashline", options, ruleThickness);
9771    const vListElems = [{
9772      type: "elem",
9773      elem: body,
9774      shift: 0
9775    }];
9776
9777    while (hlines.length > 0) {
9778      const hline = hlines.pop();
9779      const lineShift = hline.pos - offset;
9780
9781      if (hline.isDashed) {
9782        vListElems.push({
9783          type: "elem",
9784          elem: dashes,
9785          shift: lineShift
9786        });
9787      } else {
9788        vListElems.push({
9789          type: "elem",
9790          elem: line,
9791          shift: lineShift
9792        });
9793      }
9794    }
9795
9796    body = buildCommon.makeVList({
9797      positionType: "individualShift",
9798      children: vListElems
9799    }, options);
9800  }
9801
9802  return buildCommon.makeSpan(["mord"], [body], options);
9803};
9804
9805const alignMap = {
9806  c: "center ",
9807  l: "left ",
9808  r: "right "
9809};
9810
9811const mathmlBuilder$3 = function mathmlBuilder(group, options) {
9812  let table = new mathMLTree.MathNode("mtable", group.body.map(function (row) {
9813    return new mathMLTree.MathNode("mtr", row.map(function (cell) {
9814      return new mathMLTree.MathNode("mtd", [buildGroup$1(cell, options)]);
9815    }));
9816  })); // Set column alignment, row spacing, column spacing, and
9817  // array lines by setting attributes on the table element.
9818  // Set the row spacing. In MathML, we specify a gap distance.
9819  // We do not use rowGap[] because MathML automatically increases
9820  // cell height with the height/depth of the element content.
9821  // LaTeX \arraystretch multiplies the row baseline-to-baseline distance.
9822  // We simulate this by adding (arraystretch - 1)em to the gap. This
9823  // does a reasonable job of adjusting arrays containing 1 em tall content.
9824  // The 0.16 and 0.09 values are found emprically. They produce an array
9825  // similar to LaTeX and in which content does not interfere with \hines.
9826
9827  const gap = group.arraystretch === 0.5 ? 0.1 // {smallmatrix}, {subarray}
9828  : 0.16 + group.arraystretch - 1 + (group.addJot ? 0.09 : 0);
9829  table.setAttribute("rowspacing", gap + "em"); // MathML table lines go only between cells.
9830  // To place a line on an edge we'll use <menclose>, if necessary.
9831
9832  let menclose = "";
9833  let align = "";
9834
9835  if (group.cols) {
9836    // Find column alignment, column spacing, and  vertical lines.
9837    const cols = group.cols;
9838    let columnLines = "";
9839    let prevTypeWasAlign = false;
9840    let iStart = 0;
9841    let iEnd = cols.length;
9842
9843    if (cols[0].type === "separator") {
9844      menclose += "top ";
9845      iStart = 1;
9846    }
9847
9848    if (cols[cols.length - 1].type === "separator") {
9849      menclose += "bottom ";
9850      iEnd -= 1;
9851    }
9852
9853    for (let i = iStart; i < iEnd; i++) {
9854      if (cols[i].type === "align") {
9855        align += alignMap[cols[i].align];
9856
9857        if (prevTypeWasAlign) {
9858          columnLines += "none ";
9859        }
9860
9861        prevTypeWasAlign = true;
9862      } else if (cols[i].type === "separator") {
9863        // MathML accepts only single lines between cells.
9864        // So we read only the first of consecutive separators.
9865        if (prevTypeWasAlign) {
9866          columnLines += cols[i].separator === "|" ? "solid " : "dashed ";
9867          prevTypeWasAlign = false;
9868        }
9869      }
9870    }
9871
9872    table.setAttribute("columnalign", align.trim());
9873
9874    if (/[sd]/.test(columnLines)) {
9875      table.setAttribute("columnlines", columnLines.trim());
9876    }
9877  } // Set column spacing.
9878
9879
9880  if (group.colSeparationType === "align") {
9881    const cols = group.cols || [];
9882    let spacing = "";
9883
9884    for (let i = 1; i < cols.length; i++) {
9885      spacing += i % 2 ? "0em " : "1em ";
9886    }
9887
9888    table.setAttribute("columnspacing", spacing.trim());
9889  } else if (group.colSeparationType === "alignat") {
9890    table.setAttribute("columnspacing", "0em");
9891  } else if (group.colSeparationType === "small") {
9892    table.setAttribute("columnspacing", "0.2778em");
9893  } else {
9894    table.setAttribute("columnspacing", "1em");
9895  } // Address \hline and \hdashline
9896
9897
9898  let rowLines = "";
9899  const hlines = group.hLinesBeforeRow;
9900  menclose += hlines[0].length > 0 ? "left " : "";
9901  menclose += hlines[hlines.length - 1].length > 0 ? "right " : "";
9902
9903  for (let i = 1; i < hlines.length - 1; i++) {
9904    rowLines += hlines[i].length === 0 ? "none " // MathML accepts only a single line between rows. Read one element.
9905    : hlines[i][0] ? "dashed " : "solid ";
9906  }
9907
9908  if (/[sd]/.test(rowLines)) {
9909    table.setAttribute("rowlines", rowLines.trim());
9910  }
9911
9912  if (menclose !== "") {
9913    table = new mathMLTree.MathNode("menclose", [table]);
9914    table.setAttribute("notation", menclose.trim());
9915  }
9916
9917  if (group.arraystretch && group.arraystretch < 1) {
9918    // A small array. Wrap in scriptstyle so row gap is not too large.
9919    table = new mathMLTree.MathNode("mstyle", [table]);
9920    table.setAttribute("scriptlevel", "1");
9921  }
9922
9923  return table;
9924}; // Convenience function for aligned and alignedat environments.
9925
9926
9927const alignedHandler = function alignedHandler(context, args) {
9928  const cols = [];
9929  const res = parseArray(context.parser, {
9930    cols,
9931    addJot: true
9932  }, "display"); // Determining number of columns.
9933  // 1. If the first argument is given, we use it as a number of columns,
9934  //    and makes sure that each row doesn't exceed that number.
9935  // 2. Otherwise, just count number of columns = maximum number
9936  //    of cells in each row ("aligned" mode -- isAligned will be true).
9937  //
9938  // At the same time, prepend empty group {} at beginning of every second
9939  // cell in each row (starting with second cell) so that operators become
9940  // binary.  This behavior is implemented in amsmath's \start@aligned.
9941
9942  let numMaths;
9943  let numCols = 0;
9944  const emptyGroup = {
9945    type: "ordgroup",
9946    mode: context.mode,
9947    body: []
9948  };
9949  const ordgroup = checkNodeType(args[0], "ordgroup");
9950
9951  if (ordgroup) {
9952    let arg0 = "";
9953
9954    for (let i = 0; i < ordgroup.body.length; i++) {
9955      const textord = assertNodeType(ordgroup.body[i], "textord");
9956      arg0 += textord.text;
9957    }
9958
9959    numMaths = Number(arg0);
9960    numCols = numMaths * 2;
9961  }
9962
9963  const isAligned = !numCols;
9964  res.body.forEach(function (row) {
9965    for (let i = 1; i < row.length; i += 2) {
9966      // Modify ordgroup node within styling node
9967      const styling = assertNodeType(row[i], "styling");
9968      const ordgroup = assertNodeType(styling.body[0], "ordgroup");
9969      ordgroup.body.unshift(emptyGroup);
9970    }
9971
9972    if (!isAligned) {
9973      // Case 1
9974      const curMaths = row.length / 2;
9975
9976      if (numMaths < curMaths) {
9977        throw new ParseError("Too many math in a row: " + `expected ${numMaths}, but got ${curMaths}`, row[0]);
9978      }
9979    } else if (numCols < row.length) {
9980      // Case 2
9981      numCols = row.length;
9982    }
9983  }); // Adjusting alignment.
9984  // In aligned mode, we add one \qquad between columns;
9985  // otherwise we add nothing.
9986
9987  for (let i = 0; i < numCols; ++i) {
9988    let align = "r";
9989    let pregap = 0;
9990
9991    if (i % 2 === 1) {
9992      align = "l";
9993    } else if (i > 0 && isAligned) {
9994      // "aligned" mode.
9995      pregap = 1; // add one \quad
9996    }
9997
9998    cols[i] = {
9999      type: "align",
10000      align: align,
10001      pregap: pregap,
10002      postgap: 0
10003    };
10004  }
10005
10006  res.colSeparationType = isAligned ? "align" : "alignat";
10007  return res;
10008}; // Arrays are part of LaTeX, defined in lttab.dtx so its documentation
10009// is part of the source2e.pdf file of LaTeX2e source documentation.
10010// {darray} is an {array} environment where cells are set in \displaystyle,
10011// as defined in nccmath.sty.
10012
10013
10014defineEnvironment({
10015  type: "array",
10016  names: ["array", "darray"],
10017  props: {
10018    numArgs: 1
10019  },
10020
10021  handler(context, args) {
10022    // Since no types are specified above, the two possibilities are
10023    // - The argument is wrapped in {} or [], in which case Parser's
10024    //   parseGroup() returns an "ordgroup" wrapping some symbol node.
10025    // - The argument is a bare symbol node.
10026    const symNode = checkSymbolNodeType(args[0]);
10027    const colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body;
10028    const cols = colalign.map(function (nde) {
10029      const node = assertSymbolNodeType(nde);
10030      const ca = node.text;
10031
10032      if ("lcr".indexOf(ca) !== -1) {
10033        return {
10034          type: "align",
10035          align: ca
10036        };
10037      } else if (ca === "|") {
10038        return {
10039          type: "separator",
10040          separator: "|"
10041        };
10042      } else if (ca === ":") {
10043        return {
10044          type: "separator",
10045          separator: ":"
10046        };
10047      }
10048
10049      throw new ParseError("Unknown column alignment: " + ca, nde);
10050    });
10051    const res = {
10052      cols,
10053      hskipBeforeAndAfter: true // \@preamble in lttab.dtx
10054
10055    };
10056    return parseArray(context.parser, res, dCellStyle(context.envName));
10057  },
10058
10059  htmlBuilder: htmlBuilder$3,
10060  mathmlBuilder: mathmlBuilder$3
10061}); // The matrix environments of amsmath builds on the array environment
10062// of LaTeX, which is discussed above.
10063
10064defineEnvironment({
10065  type: "array",
10066  names: ["matrix", "pmatrix", "bmatrix", "Bmatrix", "vmatrix", "Vmatrix"],
10067  props: {
10068    numArgs: 0
10069  },
10070
10071  handler(context) {
10072    const delimiters = {
10073      "matrix": null,
10074      "pmatrix": ["(", ")"],
10075      "bmatrix": ["[", "]"],
10076      "Bmatrix": ["\\{", "\\}"],
10077      "vmatrix": ["|", "|"],
10078      "Vmatrix": ["\\Vert", "\\Vert"]
10079    }[context.envName]; // \hskip -\arraycolsep in amsmath
10080
10081    const payload = {
10082      hskipBeforeAndAfter: false
10083    };
10084    const res = parseArray(context.parser, payload, dCellStyle(context.envName));
10085    return delimiters ? {
10086      type: "leftright",
10087      mode: context.mode,
10088      body: [res],
10089      left: delimiters[0],
10090      right: delimiters[1],
10091      rightColor: undefined // \right uninfluenced by \color in array
10092
10093    } : res;
10094  },
10095
10096  htmlBuilder: htmlBuilder$3,
10097  mathmlBuilder: mathmlBuilder$3
10098});
10099defineEnvironment({
10100  type: "array",
10101  names: ["smallmatrix"],
10102  props: {
10103    numArgs: 0
10104  },
10105
10106  handler(context) {
10107    const payload = {
10108      arraystretch: 0.5
10109    };
10110    const res = parseArray(context.parser, payload, "script");
10111    res.colSeparationType = "small";
10112    return res;
10113  },
10114
10115  htmlBuilder: htmlBuilder$3,
10116  mathmlBuilder: mathmlBuilder$3
10117});
10118defineEnvironment({
10119  type: "array",
10120  names: ["subarray"],
10121  props: {
10122    numArgs: 1
10123  },
10124
10125  handler(context, args) {
10126    // Parsing of {subarray} is similar to {array}
10127    const symNode = checkSymbolNodeType(args[0]);
10128    const colalign = symNode ? [args[0]] : assertNodeType(args[0], "ordgroup").body;
10129    const cols = colalign.map(function (nde) {
10130      const node = assertSymbolNodeType(nde);
10131      const ca = node.text; // {subarray} only recognizes "l" & "c"
10132
10133      if ("lc".indexOf(ca) !== -1) {
10134        return {
10135          type: "align",
10136          align: ca
10137        };
10138      }
10139
10140      throw new ParseError("Unknown column alignment: " + ca, nde);
10141    });
10142
10143    if (cols.length > 1) {
10144      throw new ParseError("{subarray} can contain only one column");
10145    }
10146
10147    let res = {
10148      cols,
10149      hskipBeforeAndAfter: false,
10150      arraystretch: 0.5
10151    };
10152    res = parseArray(context.parser, res, "script");
10153
10154    if (res.body[0].length > 1) {
10155      throw new ParseError("{subarray} can contain only one column");
10156    }
10157
10158    return res;
10159  },
10160
10161  htmlBuilder: htmlBuilder$3,
10162  mathmlBuilder: mathmlBuilder$3
10163}); // A cases environment (in amsmath.sty) is almost equivalent to
10164// \def\arraystretch{1.2}%
10165// \left\{\begin{array}{@{}l@{\quad}l@{}} … \end{array}\right.
10166// {dcases} is a {cases} environment where cells are set in \displaystyle,
10167// as defined in mathtools.sty.
10168
10169defineEnvironment({
10170  type: "array",
10171  names: ["cases", "dcases"],
10172  props: {
10173    numArgs: 0
10174  },
10175
10176  handler(context) {
10177    const payload = {
10178      arraystretch: 1.2,
10179      cols: [{
10180        type: "align",
10181        align: "l",
10182        pregap: 0,
10183        // TODO(kevinb) get the current style.
10184        // For now we use the metrics for TEXT style which is what we were
10185        // doing before.  Before attempting to get the current style we
10186        // should look at TeX's behavior especially for \over and matrices.
10187        postgap: 1.0
10188        /* 1em quad */
10189
10190      }, {
10191        type: "align",
10192        align: "l",
10193        pregap: 0,
10194        postgap: 0
10195      }]
10196    };
10197    const res = parseArray(context.parser, payload, dCellStyle(context.envName));
10198    return {
10199      type: "leftright",
10200      mode: context.mode,
10201      body: [res],
10202      left: "\\{",
10203      right: ".",
10204      rightColor: undefined
10205    };
10206  },
10207
10208  htmlBuilder: htmlBuilder$3,
10209  mathmlBuilder: mathmlBuilder$3
10210}); // An aligned environment is like the align* environment
10211// except it operates within math mode.
10212// Note that we assume \nomallineskiplimit to be zero,
10213// so that \strut@ is the same as \strut.
10214
10215defineEnvironment({
10216  type: "array",
10217  names: ["aligned"],
10218  props: {
10219    numArgs: 0
10220  },
10221  handler: alignedHandler,
10222  htmlBuilder: htmlBuilder$3,
10223  mathmlBuilder: mathmlBuilder$3
10224}); // A gathered environment is like an array environment with one centered
10225// column, but where rows are considered lines so get \jot line spacing
10226// and contents are set in \displaystyle.
10227
10228defineEnvironment({
10229  type: "array",
10230  names: ["gathered"],
10231  props: {
10232    numArgs: 0
10233  },
10234
10235  handler(context) {
10236    const res = {
10237      cols: [{
10238        type: "align",
10239        align: "c"
10240      }],
10241      addJot: true
10242    };
10243    return parseArray(context.parser, res, "display");
10244  },
10245
10246  htmlBuilder: htmlBuilder$3,
10247  mathmlBuilder: mathmlBuilder$3
10248}); // alignat environment is like an align environment, but one must explicitly
10249// specify maximum number of columns in each row, and can adjust spacing between
10250// each columns.
10251
10252defineEnvironment({
10253  type: "array",
10254  names: ["alignedat"],
10255  // One for numbered and for unnumbered;
10256  // but, KaTeX doesn't supports math numbering yet,
10257  // they make no difference for now.
10258  props: {
10259    numArgs: 1
10260  },
10261  handler: alignedHandler,
10262  htmlBuilder: htmlBuilder$3,
10263  mathmlBuilder: mathmlBuilder$3
10264}); // Catch \hline outside array environment
10265
10266defineFunction({
10267  type: "text",
10268  // Doesn't matter what this is.
10269  names: ["\\hline", "\\hdashline"],
10270  props: {
10271    numArgs: 0,
10272    allowedInText: true,
10273    allowedInMath: true
10274  },
10275
10276  handler(context, args) {
10277    throw new ParseError(`${context.funcName} valid only within array environment`);
10278  }
10279
10280});
10281
10282const environments = _environments;
10283
10284// defineEnvironment definitions.
10285// $FlowFixMe, "environment" handler returns an environment ParseNode
10286
10287defineFunction({
10288  type: "environment",
10289  names: ["\\begin", "\\end"],
10290  props: {
10291    numArgs: 1,
10292    argTypes: ["text"]
10293  },
10294
10295  handler(_ref, args) {
10296    let parser = _ref.parser,
10297        funcName = _ref.funcName;
10298    const nameGroup = args[0];
10299
10300    if (nameGroup.type !== "ordgroup") {
10301      throw new ParseError("Invalid environment name", nameGroup);
10302    }
10303
10304    let envName = "";
10305
10306    for (let i = 0; i < nameGroup.body.length; ++i) {
10307      envName += assertNodeType(nameGroup.body[i], "textord").text;
10308    }
10309
10310    if (funcName === "\\begin") {
10311      // begin...end is similar to left...right
10312      if (!environments.hasOwnProperty(envName)) {
10313        throw new ParseError("No such environment: " + envName, nameGroup);
10314      } // Build the environment object. Arguments and other information will
10315      // be made available to the begin and end methods using properties.
10316
10317
10318      const env = environments[envName];
10319
10320      const _parser$parseArgument = parser.parseArguments("\\begin{" + envName + "}", env),
10321            args = _parser$parseArgument.args,
10322            optArgs = _parser$parseArgument.optArgs;
10323
10324      const context = {
10325        mode: parser.mode,
10326        envName,
10327        parser
10328      };
10329      const result = env.handler(context, args, optArgs);
10330      parser.expect("\\end", false);
10331      const endNameToken = parser.nextToken;
10332      const end = assertNodeType(parser.parseFunction(), "environment");
10333
10334      if (end.name !== envName) {
10335        throw new ParseError(`Mismatch: \\begin{${envName}} matched by \\end{${end.name}}`, endNameToken);
10336      }
10337
10338      return result;
10339    }
10340
10341    return {
10342      type: "environment",
10343      mode: parser.mode,
10344      name: envName,
10345      nameGroup
10346    };
10347  }
10348
10349});
10350
10351const makeSpan$2 = buildCommon.makeSpan;
10352
10353function htmlBuilder$4(group, options) {
10354  const elements = buildExpression(group.body, options, true);
10355  return makeSpan$2([group.mclass], elements, options);
10356}
10357
10358function mathmlBuilder$4(group, options) {
10359  let node;
10360  const inner = buildExpression$1(group.body, options);
10361
10362  if (group.mclass === "minner") {
10363    return mathMLTree.newDocumentFragment(inner);
10364  } else if (group.mclass === "mord") {
10365    if (group.isCharacterBox) {
10366      node = inner[0];
10367      node.type = "mi";
10368    } else {
10369      node = new mathMLTree.MathNode("mi", inner);
10370    }
10371  } else {
10372    if (group.isCharacterBox) {
10373      node = inner[0];
10374      node.type = "mo";
10375    } else {
10376      node = new mathMLTree.MathNode("mo", inner);
10377    } // Set spacing based on what is the most likely adjacent atom type.
10378    // See TeXbook p170.
10379
10380
10381    if (group.mclass === "mbin") {
10382      node.attributes.lspace = "0.22em"; // medium space
10383
10384      node.attributes.rspace = "0.22em";
10385    } else if (group.mclass === "mpunct") {
10386      node.attributes.lspace = "0em";
10387      node.attributes.rspace = "0.17em"; // thinspace
10388    } else if (group.mclass === "mopen" || group.mclass === "mclose") {
10389      node.attributes.lspace = "0em";
10390      node.attributes.rspace = "0em";
10391    } // MathML <mo> default space is 5/18 em, so <mrel> needs no action.
10392    // Ref: https://developer.mozilla.org/en-US/docs/Web/MathML/Element/mo
10393
10394  }
10395
10396  return node;
10397} // Math class commands except \mathop
10398
10399
10400defineFunction({
10401  type: "mclass",
10402  names: ["\\mathord", "\\mathbin", "\\mathrel", "\\mathopen", "\\mathclose", "\\mathpunct", "\\mathinner"],
10403  props: {
10404    numArgs: 1
10405  },
10406
10407  handler(_ref, args) {
10408    let parser = _ref.parser,
10409        funcName = _ref.funcName;
10410    const body = args[0];
10411    return {
10412      type: "mclass",
10413      mode: parser.mode,
10414      mclass: "m" + funcName.substr(5),
10415      // TODO(kevinb): don't prefix with 'm'
10416      body: ordargument(body),
10417      isCharacterBox: utils.isCharacterBox(body)
10418    };
10419  },
10420
10421  htmlBuilder: htmlBuilder$4,
10422  mathmlBuilder: mathmlBuilder$4
10423});
10424const binrelClass = arg => {
10425  // \binrel@ spacing varies with (bin|rel|ord) of the atom in the argument.
10426  // (by rendering separately and with {}s before and after, and measuring
10427  // the change in spacing).  We'll do roughly the same by detecting the
10428  // atom type directly.
10429  const atom = arg.type === "ordgroup" && arg.body.length ? arg.body[0] : arg;
10430
10431  if (atom.type === "atom" && (atom.family === "bin" || atom.family === "rel")) {
10432    return "m" + atom.family;
10433  } else {
10434    return "mord";
10435  }
10436}; // \@binrel{x}{y} renders like y but as mbin/mrel/mord if x is mbin/mrel/mord.
10437// This is equivalent to \binrel@{x}\binrel@@{y} in AMSTeX.
10438
10439defineFunction({
10440  type: "mclass",
10441  names: ["\\@binrel"],
10442  props: {
10443    numArgs: 2
10444  },
10445
10446  handler(_ref2, args) {
10447    let parser = _ref2.parser;
10448    return {
10449      type: "mclass",
10450      mode: parser.mode,
10451      mclass: binrelClass(args[0]),
10452      body: [args[1]],
10453      isCharacterBox: utils.isCharacterBox(args[1])
10454    };
10455  }
10456
10457}); // Build a relation or stacked op by placing one symbol on top of another
10458
10459defineFunction({
10460  type: "mclass",
10461  names: ["\\stackrel", "\\overset", "\\underset"],
10462  props: {
10463    numArgs: 2
10464  },
10465
10466  handler(_ref3, args) {
10467    let parser = _ref3.parser,
10468        funcName = _ref3.funcName;
10469    const baseArg = args[1];
10470    const shiftedArg = args[0];
10471    let mclass;
10472
10473    if (funcName !== "\\stackrel") {
10474      // LaTeX applies \binrel spacing to \overset and \underset.
10475      mclass = binrelClass(baseArg);
10476    } else {
10477      mclass = "mrel"; // for \stackrel
10478    }
10479
10480    const baseOp = {
10481      type: "op",
10482      mode: baseArg.mode,
10483      limits: true,
10484      alwaysHandleSupSub: true,
10485      parentIsSupSub: false,
10486      symbol: false,
10487      suppressBaseShift: funcName !== "\\stackrel",
10488      body: ordargument(baseArg)
10489    };
10490    const supsub = {
10491      type: "supsub",
10492      mode: shiftedArg.mode,
10493      base: baseOp,
10494      sup: funcName === "\\underset" ? null : shiftedArg,
10495      sub: funcName === "\\underset" ? shiftedArg : null
10496    };
10497    return {
10498      type: "mclass",
10499      mode: parser.mode,
10500      mclass,
10501      body: [supsub],
10502      isCharacterBox: utils.isCharacterBox(supsub)
10503    };
10504  },
10505
10506  htmlBuilder: htmlBuilder$4,
10507  mathmlBuilder: mathmlBuilder$4
10508});
10509
10510// TODO(kevinb): implement \\sl and \\sc
10511
10512const htmlBuilder$5 = (group, options) => {
10513  const font = group.font;
10514  const newOptions = options.withFont(font);
10515  return buildGroup(group.body, newOptions);
10516};
10517
10518const mathmlBuilder$5 = (group, options) => {
10519  const font = group.font;
10520  const newOptions = options.withFont(font);
10521  return buildGroup$1(group.body, newOptions);
10522};
10523
10524const fontAliases = {
10525  "\\Bbb": "\\mathbb",
10526  "\\bold": "\\mathbf",
10527  "\\frak": "\\mathfrak",
10528  "\\bm": "\\boldsymbol"
10529};
10530defineFunction({
10531  type: "font",
10532  names: [// styles, except \boldsymbol defined below
10533  "\\mathrm", "\\mathit", "\\mathbf", "\\mathnormal", // families
10534  "\\mathbb", "\\mathcal", "\\mathfrak", "\\mathscr", "\\mathsf", "\\mathtt", // aliases, except \bm defined below
10535  "\\Bbb", "\\bold", "\\frak"],
10536  props: {
10537    numArgs: 1,
10538    greediness: 2
10539  },
10540  handler: (_ref, args) => {
10541    let parser = _ref.parser,
10542        funcName = _ref.funcName;
10543    const body = args[0];
10544    let func = funcName;
10545
10546    if (func in fontAliases) {
10547      func = fontAliases[func];
10548    }
10549
10550    return {
10551      type: "font",
10552      mode: parser.mode,
10553      font: func.slice(1),
10554      body
10555    };
10556  },
10557  htmlBuilder: htmlBuilder$5,
10558  mathmlBuilder: mathmlBuilder$5
10559});
10560defineFunction({
10561  type: "mclass",
10562  names: ["\\boldsymbol", "\\bm"],
10563  props: {
10564    numArgs: 1,
10565    greediness: 2
10566  },
10567  handler: (_ref2, args) => {
10568    let parser = _ref2.parser;
10569    const body = args[0];
10570    const isCharacterBox = utils.isCharacterBox(body); // amsbsy.sty's \boldsymbol uses \binrel spacing to inherit the
10571    // argument's bin|rel|ord status
10572
10573    return {
10574      type: "mclass",
10575      mode: parser.mode,
10576      mclass: binrelClass(body),
10577      body: [{
10578        type: "font",
10579        mode: parser.mode,
10580        font: "boldsymbol",
10581        body
10582      }],
10583      isCharacterBox: isCharacterBox
10584    };
10585  }
10586}); // Old font changing functions
10587
10588defineFunction({
10589  type: "font",
10590  names: ["\\rm", "\\sf", "\\tt", "\\bf", "\\it"],
10591  props: {
10592    numArgs: 0,
10593    allowedInText: true
10594  },
10595  handler: (_ref3, args) => {
10596    let parser = _ref3.parser,
10597        funcName = _ref3.funcName,
10598        breakOnTokenText = _ref3.breakOnTokenText;
10599    const mode = parser.mode;
10600    const body = parser.parseExpression(true, breakOnTokenText);
10601    const style = `math${funcName.slice(1)}`;
10602    return {
10603      type: "font",
10604      mode: mode,
10605      font: style,
10606      body: {
10607        type: "ordgroup",
10608        mode: parser.mode,
10609        body
10610      }
10611    };
10612  },
10613  htmlBuilder: htmlBuilder$5,
10614  mathmlBuilder: mathmlBuilder$5
10615});
10616
10617const adjustStyle = (size, originalStyle) => {
10618  // Figure out what style this fraction should be in based on the
10619  // function used
10620  let style = originalStyle;
10621
10622  if (size === "display") {
10623    // Get display style as a default.
10624    // If incoming style is sub/sup, use style.text() to get correct size.
10625    style = style.id >= Style$1.SCRIPT.id ? style.text() : Style$1.DISPLAY;
10626  } else if (size === "text" && style.size === Style$1.DISPLAY.size) {
10627    // We're in a \tfrac but incoming style is displaystyle, so:
10628    style = Style$1.TEXT;
10629  } else if (size === "script") {
10630    style = Style$1.SCRIPT;
10631  } else if (size === "scriptscript") {
10632    style = Style$1.SCRIPTSCRIPT;
10633  }
10634
10635  return style;
10636};
10637
10638const htmlBuilder$6 = (group, options) => {
10639  // Fractions are handled in the TeXbook on pages 444-445, rules 15(a-e).
10640  const style = adjustStyle(group.size, options.style);
10641  const nstyle = style.fracNum();
10642  const dstyle = style.fracDen();
10643  let newOptions;
10644  newOptions = options.havingStyle(nstyle);
10645  const numerm = buildGroup(group.numer, newOptions, options);
10646
10647  if (group.continued) {
10648    // \cfrac inserts a \strut into the numerator.
10649    // Get \strut dimensions from TeXbook page 353.
10650    const hStrut = 8.5 / options.fontMetrics().ptPerEm;
10651    const dStrut = 3.5 / options.fontMetrics().ptPerEm;
10652    numerm.height = numerm.height < hStrut ? hStrut : numerm.height;
10653    numerm.depth = numerm.depth < dStrut ? dStrut : numerm.depth;
10654  }
10655
10656  newOptions = options.havingStyle(dstyle);
10657  const denomm = buildGroup(group.denom, newOptions, options);
10658  let rule;
10659  let ruleWidth;
10660  let ruleSpacing;
10661
10662  if (group.hasBarLine) {
10663    if (group.barSize) {
10664      ruleWidth = calculateSize(group.barSize, options);
10665      rule = buildCommon.makeLineSpan("frac-line", options, ruleWidth);
10666    } else {
10667      rule = buildCommon.makeLineSpan("frac-line", options);
10668    }
10669
10670    ruleWidth = rule.height;
10671    ruleSpacing = rule.height;
10672  } else {
10673    rule = null;
10674    ruleWidth = 0;
10675    ruleSpacing = options.fontMetrics().defaultRuleThickness;
10676  } // Rule 15b
10677
10678
10679  let numShift;
10680  let clearance;
10681  let denomShift;
10682
10683  if (style.size === Style$1.DISPLAY.size || group.size === "display") {
10684    numShift = options.fontMetrics().num1;
10685
10686    if (ruleWidth > 0) {
10687      clearance = 3 * ruleSpacing;
10688    } else {
10689      clearance = 7 * ruleSpacing;
10690    }
10691
10692    denomShift = options.fontMetrics().denom1;
10693  } else {
10694    if (ruleWidth > 0) {
10695      numShift = options.fontMetrics().num2;
10696      clearance = ruleSpacing;
10697    } else {
10698      numShift = options.fontMetrics().num3;
10699      clearance = 3 * ruleSpacing;
10700    }
10701
10702    denomShift = options.fontMetrics().denom2;
10703  }
10704
10705  let frac;
10706
10707  if (!rule) {
10708    // Rule 15c
10709    const candidateClearance = numShift - numerm.depth - (denomm.height - denomShift);
10710
10711    if (candidateClearance < clearance) {
10712      numShift += 0.5 * (clearance - candidateClearance);
10713      denomShift += 0.5 * (clearance - candidateClearance);
10714    }
10715
10716    frac = buildCommon.makeVList({
10717      positionType: "individualShift",
10718      children: [{
10719        type: "elem",
10720        elem: denomm,
10721        shift: denomShift
10722      }, {
10723        type: "elem",
10724        elem: numerm,
10725        shift: -numShift
10726      }]
10727    }, options);
10728  } else {
10729    // Rule 15d
10730    const axisHeight = options.fontMetrics().axisHeight;
10731
10732    if (numShift - numerm.depth - (axisHeight + 0.5 * ruleWidth) < clearance) {
10733      numShift += clearance - (numShift - numerm.depth - (axisHeight + 0.5 * ruleWidth));
10734    }
10735
10736    if (axisHeight - 0.5 * ruleWidth - (denomm.height - denomShift) < clearance) {
10737      denomShift += clearance - (axisHeight - 0.5 * ruleWidth - (denomm.height - denomShift));
10738    }
10739
10740    const midShift = -(axisHeight - 0.5 * ruleWidth);
10741    frac = buildCommon.makeVList({
10742      positionType: "individualShift",
10743      children: [{
10744        type: "elem",
10745        elem: denomm,
10746        shift: denomShift
10747      }, {
10748        type: "elem",
10749        elem: rule,
10750        shift: midShift
10751      }, {
10752        type: "elem",
10753        elem: numerm,
10754        shift: -numShift
10755      }]
10756    }, options);
10757  } // Since we manually change the style sometimes (with \dfrac or \tfrac),
10758  // account for the possible size change here.
10759
10760
10761  newOptions = options.havingStyle(style);
10762  frac.height *= newOptions.sizeMultiplier / options.sizeMultiplier;
10763  frac.depth *= newOptions.sizeMultiplier / options.sizeMultiplier; // Rule 15e
10764
10765  let delimSize;
10766
10767  if (style.size === Style$1.DISPLAY.size) {
10768    delimSize = options.fontMetrics().delim1;
10769  } else {
10770    delimSize = options.fontMetrics().delim2;
10771  }
10772
10773  let leftDelim;
10774  let rightDelim;
10775
10776  if (group.leftDelim == null) {
10777    leftDelim = makeNullDelimiter(options, ["mopen"]);
10778  } else {
10779    leftDelim = delimiter.customSizedDelim(group.leftDelim, delimSize, true, options.havingStyle(style), group.mode, ["mopen"]);
10780  }
10781
10782  if (group.continued) {
10783    rightDelim = buildCommon.makeSpan([]); // zero width for \cfrac
10784  } else if (group.rightDelim == null) {
10785    rightDelim = makeNullDelimiter(options, ["mclose"]);
10786  } else {
10787    rightDelim = delimiter.customSizedDelim(group.rightDelim, delimSize, true, options.havingStyle(style), group.mode, ["mclose"]);
10788  }
10789
10790  return buildCommon.makeSpan(["mord"].concat(newOptions.sizingClasses(options)), [leftDelim, buildCommon.makeSpan(["mfrac"], [frac]), rightDelim], options);
10791};
10792
10793const mathmlBuilder$6 = (group, options) => {
10794  let node = new mathMLTree.MathNode("mfrac", [buildGroup$1(group.numer, options), buildGroup$1(group.denom, options)]);
10795
10796  if (!group.hasBarLine) {
10797    node.setAttribute("linethickness", "0px");
10798  } else if (group.barSize) {
10799    const ruleWidth = calculateSize(group.barSize, options);
10800    node.setAttribute("linethickness", ruleWidth + "em");
10801  }
10802
10803  const style = adjustStyle(group.size, options.style);
10804
10805  if (style.size !== options.style.size) {
10806    node = new mathMLTree.MathNode("mstyle", [node]);
10807    const isDisplay = style.size === Style$1.DISPLAY.size ? "true" : "false";
10808    node.setAttribute("displaystyle", isDisplay);
10809    node.setAttribute("scriptlevel", "0");
10810  }
10811
10812  if (group.leftDelim != null || group.rightDelim != null) {
10813    const withDelims = [];
10814
10815    if (group.leftDelim != null) {
10816      const leftOp = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode(group.leftDelim.replace("\\", ""))]);
10817      leftOp.setAttribute("fence", "true");
10818      withDelims.push(leftOp);
10819    }
10820
10821    withDelims.push(node);
10822
10823    if (group.rightDelim != null) {
10824      const rightOp = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode(group.rightDelim.replace("\\", ""))]);
10825      rightOp.setAttribute("fence", "true");
10826      withDelims.push(rightOp);
10827    }
10828
10829    return makeRow(withDelims);
10830  }
10831
10832  return node;
10833};
10834
10835defineFunction({
10836  type: "genfrac",
10837  names: ["\\cfrac", "\\dfrac", "\\frac", "\\tfrac", "\\dbinom", "\\binom", "\\tbinom", "\\\\atopfrac", // can’t be entered directly
10838  "\\\\bracefrac", "\\\\brackfrac"],
10839  props: {
10840    numArgs: 2,
10841    greediness: 2
10842  },
10843  handler: (_ref, args) => {
10844    let parser = _ref.parser,
10845        funcName = _ref.funcName;
10846    const numer = args[0];
10847    const denom = args[1];
10848    let hasBarLine;
10849    let leftDelim = null;
10850    let rightDelim = null;
10851    let size = "auto";
10852
10853    switch (funcName) {
10854      case "\\cfrac":
10855      case "\\dfrac":
10856      case "\\frac":
10857      case "\\tfrac":
10858        hasBarLine = true;
10859        break;
10860
10861      case "\\\\atopfrac":
10862        hasBarLine = false;
10863        break;
10864
10865      case "\\dbinom":
10866      case "\\binom":
10867      case "\\tbinom":
10868        hasBarLine = false;
10869        leftDelim = "(";
10870        rightDelim = ")";
10871        break;
10872
10873      case "\\\\bracefrac":
10874        hasBarLine = false;
10875        leftDelim = "\\{";
10876        rightDelim = "\\}";
10877        break;
10878
10879      case "\\\\brackfrac":
10880        hasBarLine = false;
10881        leftDelim = "[";
10882        rightDelim = "]";
10883        break;
10884
10885      default:
10886        throw new Error("Unrecognized genfrac command");
10887    }
10888
10889    switch (funcName) {
10890      case "\\cfrac":
10891      case "\\dfrac":
10892      case "\\dbinom":
10893        size = "display";
10894        break;
10895
10896      case "\\tfrac":
10897      case "\\tbinom":
10898        size = "text";
10899        break;
10900    }
10901
10902    return {
10903      type: "genfrac",
10904      mode: parser.mode,
10905      continued: funcName === "\\cfrac",
10906      numer,
10907      denom,
10908      hasBarLine,
10909      leftDelim,
10910      rightDelim,
10911      size,
10912      barSize: null
10913    };
10914  },
10915  htmlBuilder: htmlBuilder$6,
10916  mathmlBuilder: mathmlBuilder$6
10917}); // Infix generalized fractions -- these are not rendered directly, but replaced
10918// immediately by one of the variants above.
10919
10920defineFunction({
10921  type: "infix",
10922  names: ["\\over", "\\choose", "\\atop", "\\brace", "\\brack"],
10923  props: {
10924    numArgs: 0,
10925    infix: true
10926  },
10927
10928  handler(_ref2) {
10929    let parser = _ref2.parser,
10930        funcName = _ref2.funcName,
10931        token = _ref2.token;
10932    let replaceWith;
10933
10934    switch (funcName) {
10935      case "\\over":
10936        replaceWith = "\\frac";
10937        break;
10938
10939      case "\\choose":
10940        replaceWith = "\\binom";
10941        break;
10942
10943      case "\\atop":
10944        replaceWith = "\\\\atopfrac";
10945        break;
10946
10947      case "\\brace":
10948        replaceWith = "\\\\bracefrac";
10949        break;
10950
10951      case "\\brack":
10952        replaceWith = "\\\\brackfrac";
10953        break;
10954
10955      default:
10956        throw new Error("Unrecognized infix genfrac command");
10957    }
10958
10959    return {
10960      type: "infix",
10961      mode: parser.mode,
10962      replaceWith,
10963      token
10964    };
10965  }
10966
10967});
10968const stylArray = ["display", "text", "script", "scriptscript"];
10969
10970const delimFromValue = function delimFromValue(delimString) {
10971  let delim = null;
10972
10973  if (delimString.length > 0) {
10974    delim = delimString;
10975    delim = delim === "." ? null : delim;
10976  }
10977
10978  return delim;
10979};
10980
10981defineFunction({
10982  type: "genfrac",
10983  names: ["\\genfrac"],
10984  props: {
10985    numArgs: 6,
10986    greediness: 6,
10987    argTypes: ["math", "math", "size", "text", "math", "math"]
10988  },
10989
10990  handler(_ref3, args) {
10991    let parser = _ref3.parser;
10992    const numer = args[4];
10993    const denom = args[5]; // Look into the parse nodes to get the desired delimiters.
10994
10995    let leftNode = checkNodeType(args[0], "atom");
10996
10997    if (leftNode) {
10998      leftNode = assertAtomFamily(args[0], "open");
10999    }
11000
11001    const leftDelim = leftNode ? delimFromValue(leftNode.text) : null;
11002    let rightNode = checkNodeType(args[1], "atom");
11003
11004    if (rightNode) {
11005      rightNode = assertAtomFamily(args[1], "close");
11006    }
11007
11008    const rightDelim = rightNode ? delimFromValue(rightNode.text) : null;
11009    const barNode = assertNodeType(args[2], "size");
11010    let hasBarLine;
11011    let barSize = null;
11012
11013    if (barNode.isBlank) {
11014      // \genfrac acts differently than \above.
11015      // \genfrac treats an empty size group as a signal to use a
11016      // standard bar size. \above would see size = 0 and omit the bar.
11017      hasBarLine = true;
11018    } else {
11019      barSize = barNode.value;
11020      hasBarLine = barSize.number > 0;
11021    } // Find out if we want displaystyle, textstyle, etc.
11022
11023
11024    let size = "auto";
11025    let styl = checkNodeType(args[3], "ordgroup");
11026
11027    if (styl) {
11028      if (styl.body.length > 0) {
11029        const textOrd = assertNodeType(styl.body[0], "textord");
11030        size = stylArray[Number(textOrd.text)];
11031      }
11032    } else {
11033      styl = assertNodeType(args[3], "textord");
11034      size = stylArray[Number(styl.text)];
11035    }
11036
11037    return {
11038      type: "genfrac",
11039      mode: parser.mode,
11040      numer,
11041      denom,
11042      continued: false,
11043      hasBarLine,
11044      barSize,
11045      leftDelim,
11046      rightDelim,
11047      size
11048    };
11049  },
11050
11051  htmlBuilder: htmlBuilder$6,
11052  mathmlBuilder: mathmlBuilder$6
11053}); // \above is an infix fraction that also defines a fraction bar size.
11054
11055defineFunction({
11056  type: "infix",
11057  names: ["\\above"],
11058  props: {
11059    numArgs: 1,
11060    argTypes: ["size"],
11061    infix: true
11062  },
11063
11064  handler(_ref4, args) {
11065    let parser = _ref4.parser,
11066        funcName = _ref4.funcName,
11067        token = _ref4.token;
11068    return {
11069      type: "infix",
11070      mode: parser.mode,
11071      replaceWith: "\\\\abovefrac",
11072      size: assertNodeType(args[0], "size").value,
11073      token
11074    };
11075  }
11076
11077});
11078defineFunction({
11079  type: "genfrac",
11080  names: ["\\\\abovefrac"],
11081  props: {
11082    numArgs: 3,
11083    argTypes: ["math", "size", "math"]
11084  },
11085  handler: (_ref5, args) => {
11086    let parser = _ref5.parser,
11087        funcName = _ref5.funcName;
11088    const numer = args[0];
11089    const barSize = assert(assertNodeType(args[1], "infix").size);
11090    const denom = args[2];
11091    const hasBarLine = barSize.number > 0;
11092    return {
11093      type: "genfrac",
11094      mode: parser.mode,
11095      numer,
11096      denom,
11097      continued: false,
11098      hasBarLine,
11099      barSize,
11100      leftDelim: null,
11101      rightDelim: null,
11102      size: "auto"
11103    };
11104  },
11105  htmlBuilder: htmlBuilder$6,
11106  mathmlBuilder: mathmlBuilder$6
11107});
11108
11109// NOTE: Unlike most `htmlBuilder`s, this one handles not only "horizBrace", but
11110const htmlBuilder$7 = (grp, options) => {
11111  const style = options.style; // Pull out the `ParseNode<"horizBrace">` if `grp` is a "supsub" node.
11112
11113  let supSubGroup;
11114  let group;
11115  const supSub = checkNodeType(grp, "supsub");
11116
11117  if (supSub) {
11118    // Ref: LaTeX source2e: }}}}\limits}
11119    // i.e. LaTeX treats the brace similar to an op and passes it
11120    // with \limits, so we need to assign supsub style.
11121    supSubGroup = supSub.sup ? buildGroup(supSub.sup, options.havingStyle(style.sup()), options) : buildGroup(supSub.sub, options.havingStyle(style.sub()), options);
11122    group = assertNodeType(supSub.base, "horizBrace");
11123  } else {
11124    group = assertNodeType(grp, "horizBrace");
11125  } // Build the base group
11126
11127
11128  const body = buildGroup(group.base, options.havingBaseStyle(Style$1.DISPLAY)); // Create the stretchy element
11129
11130  const braceBody = stretchy.svgSpan(group, options); // Generate the vlist, with the appropriate kerns        ┏━━━━━━━━┓
11131  // This first vlist contains the content and the brace:   equation
11132
11133  let vlist;
11134
11135  if (group.isOver) {
11136    vlist = buildCommon.makeVList({
11137      positionType: "firstBaseline",
11138      children: [{
11139        type: "elem",
11140        elem: body
11141      }, {
11142        type: "kern",
11143        size: 0.1
11144      }, {
11145        type: "elem",
11146        elem: braceBody
11147      }]
11148    }, options); // $FlowFixMe: Replace this with passing "svg-align" into makeVList.
11149
11150    vlist.children[0].children[0].children[1].classes.push("svg-align");
11151  } else {
11152    vlist = buildCommon.makeVList({
11153      positionType: "bottom",
11154      positionData: body.depth + 0.1 + braceBody.height,
11155      children: [{
11156        type: "elem",
11157        elem: braceBody
11158      }, {
11159        type: "kern",
11160        size: 0.1
11161      }, {
11162        type: "elem",
11163        elem: body
11164      }]
11165    }, options); // $FlowFixMe: Replace this with passing "svg-align" into makeVList.
11166
11167    vlist.children[0].children[0].children[0].classes.push("svg-align");
11168  }
11169
11170  if (supSubGroup) {
11171    // To write the supsub, wrap the first vlist in another vlist:
11172    // They can't all go in the same vlist, because the note might be
11173    // wider than the equation. We want the equation to control the
11174    // brace width.
11175    //      note          long note           long note
11176    //   ┏━━━━━━━━┓   or    ┏━━━┓     not    ┏━━━━━━━━━┓
11177    //    equation           eqn                 eqn
11178    const vSpan = buildCommon.makeSpan(["mord", group.isOver ? "mover" : "munder"], [vlist], options);
11179
11180    if (group.isOver) {
11181      vlist = buildCommon.makeVList({
11182        positionType: "firstBaseline",
11183        children: [{
11184          type: "elem",
11185          elem: vSpan
11186        }, {
11187          type: "kern",
11188          size: 0.2
11189        }, {
11190          type: "elem",
11191          elem: supSubGroup
11192        }]
11193      }, options);
11194    } else {
11195      vlist = buildCommon.makeVList({
11196        positionType: "bottom",
11197        positionData: vSpan.depth + 0.2 + supSubGroup.height + supSubGroup.depth,
11198        children: [{
11199          type: "elem",
11200          elem: supSubGroup
11201        }, {
11202          type: "kern",
11203          size: 0.2
11204        }, {
11205          type: "elem",
11206          elem: vSpan
11207        }]
11208      }, options);
11209    }
11210  }
11211
11212  return buildCommon.makeSpan(["mord", group.isOver ? "mover" : "munder"], [vlist], options);
11213};
11214
11215const mathmlBuilder$7 = (group, options) => {
11216  const accentNode = stretchy.mathMLnode(group.label);
11217  return new mathMLTree.MathNode(group.isOver ? "mover" : "munder", [buildGroup$1(group.base, options), accentNode]);
11218}; // Horizontal stretchy braces
11219
11220
11221defineFunction({
11222  type: "horizBrace",
11223  names: ["\\overbrace", "\\underbrace"],
11224  props: {
11225    numArgs: 1
11226  },
11227
11228  handler(_ref, args) {
11229    let parser = _ref.parser,
11230        funcName = _ref.funcName;
11231    return {
11232      type: "horizBrace",
11233      mode: parser.mode,
11234      label: funcName,
11235      isOver: /^\\over/.test(funcName),
11236      base: args[0]
11237    };
11238  },
11239
11240  htmlBuilder: htmlBuilder$7,
11241  mathmlBuilder: mathmlBuilder$7
11242});
11243
11244defineFunction({
11245  type: "href",
11246  names: ["\\href"],
11247  props: {
11248    numArgs: 2,
11249    argTypes: ["url", "original"],
11250    allowedInText: true
11251  },
11252  handler: (_ref, args) => {
11253    let parser = _ref.parser;
11254    const body = args[1];
11255    const href = assertNodeType(args[0], "url").url;
11256
11257    if (!parser.settings.isTrusted({
11258      command: "\\href",
11259      url: href
11260    })) {
11261      return parser.formatUnsupportedCmd("\\href");
11262    }
11263
11264    return {
11265      type: "href",
11266      mode: parser.mode,
11267      href,
11268      body: ordargument(body)
11269    };
11270  },
11271  htmlBuilder: (group, options) => {
11272    const elements = buildExpression(group.body, options, false);
11273    return buildCommon.makeAnchor(group.href, [], elements, options);
11274  },
11275  mathmlBuilder: (group, options) => {
11276    let math = buildExpressionRow(group.body, options);
11277
11278    if (!(math instanceof MathNode)) {
11279      math = new MathNode("mrow", [math]);
11280    }
11281
11282    math.setAttribute("href", group.href);
11283    return math;
11284  }
11285});
11286defineFunction({
11287  type: "href",
11288  names: ["\\url"],
11289  props: {
11290    numArgs: 1,
11291    argTypes: ["url"],
11292    allowedInText: true
11293  },
11294  handler: (_ref2, args) => {
11295    let parser = _ref2.parser;
11296    const href = assertNodeType(args[0], "url").url;
11297
11298    if (!parser.settings.isTrusted({
11299      command: "\\url",
11300      url: href
11301    })) {
11302      return parser.formatUnsupportedCmd("\\url");
11303    }
11304
11305    const chars = [];
11306
11307    for (let i = 0; i < href.length; i++) {
11308      let c = href[i];
11309
11310      if (c === "~") {
11311        c = "\\textasciitilde";
11312      }
11313
11314      chars.push({
11315        type: "textord",
11316        mode: "text",
11317        text: c
11318      });
11319    }
11320
11321    const body = {
11322      type: "text",
11323      mode: parser.mode,
11324      font: "\\texttt",
11325      body: chars
11326    };
11327    return {
11328      type: "href",
11329      mode: parser.mode,
11330      href,
11331      body: ordargument(body)
11332    };
11333  }
11334});
11335
11336defineFunction({
11337  type: "htmlmathml",
11338  names: ["\\html@mathml"],
11339  props: {
11340    numArgs: 2,
11341    allowedInText: true
11342  },
11343  handler: (_ref, args) => {
11344    let parser = _ref.parser;
11345    return {
11346      type: "htmlmathml",
11347      mode: parser.mode,
11348      html: ordargument(args[0]),
11349      mathml: ordargument(args[1])
11350    };
11351  },
11352  htmlBuilder: (group, options) => {
11353    const elements = buildExpression(group.html, options, false);
11354    return buildCommon.makeFragment(elements);
11355  },
11356  mathmlBuilder: (group, options) => {
11357    return buildExpressionRow(group.mathml, options);
11358  }
11359});
11360
11361const sizeData = function sizeData(str) {
11362  if (/^[-+]? *(\d+(\.\d*)?|\.\d+)$/.test(str)) {
11363    // str is a number with no unit specified.
11364    // default unit is bp, per graphix package.
11365    return {
11366      number: +str,
11367      unit: "bp"
11368    };
11369  } else {
11370    const match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(str);
11371
11372    if (!match) {
11373      throw new ParseError("Invalid size: '" + str + "' in \\includegraphics");
11374    }
11375
11376    const data = {
11377      number: +(match[1] + match[2]),
11378      // sign + magnitude, cast to number
11379      unit: match[3]
11380    };
11381
11382    if (!validUnit(data)) {
11383      throw new ParseError("Invalid unit: '" + data.unit + "' in \\includegraphics.");
11384    }
11385
11386    return data;
11387  }
11388};
11389
11390defineFunction({
11391  type: "includegraphics",
11392  names: ["\\includegraphics"],
11393  props: {
11394    numArgs: 1,
11395    numOptionalArgs: 1,
11396    argTypes: ["raw", "url"],
11397    allowedInText: false
11398  },
11399  handler: (_ref, args, optArgs) => {
11400    let parser = _ref.parser;
11401    let width = {
11402      number: 0,
11403      unit: "em"
11404    };
11405    let height = {
11406      number: 0.9,
11407      unit: "em"
11408    }; // sorta character sized.
11409
11410    let totalheight = {
11411      number: 0,
11412      unit: "em"
11413    };
11414    let alt = "";
11415
11416    if (optArgs[0]) {
11417      const attributeStr = assertNodeType(optArgs[0], "raw").string; // Parser.js does not parse key/value pairs. We get a string.
11418
11419      const attributes = attributeStr.split(",");
11420
11421      for (let i = 0; i < attributes.length; i++) {
11422        const keyVal = attributes[i].split("=");
11423
11424        if (keyVal.length === 2) {
11425          const str = keyVal[1].trim();
11426
11427          switch (keyVal[0].trim()) {
11428            case "alt":
11429              alt = str;
11430              break;
11431
11432            case "width":
11433              width = sizeData(str);
11434              break;
11435
11436            case "height":
11437              height = sizeData(str);
11438              break;
11439
11440            case "totalheight":
11441              totalheight = sizeData(str);
11442              break;
11443
11444            default:
11445              throw new ParseError("Invalid key: '" + keyVal[0] + "' in \\includegraphics.");
11446          }
11447        }
11448      }
11449    }
11450
11451    const src = assertNodeType(args[0], "url").url;
11452
11453    if (alt === "") {
11454      // No alt given. Use the file name. Strip away the path.
11455      alt = src;
11456      alt = alt.replace(/^.*[\\/]/, '');
11457      alt = alt.substring(0, alt.lastIndexOf('.'));
11458    }
11459
11460    if (!parser.settings.isTrusted({
11461      command: "\\includegraphics",
11462      url: src
11463    })) {
11464      return parser.formatUnsupportedCmd("\\includegraphics");
11465    }
11466
11467    return {
11468      type: "includegraphics",
11469      mode: parser.mode,
11470      alt: alt,
11471      width: width,
11472      height: height,
11473      totalheight: totalheight,
11474      src: src
11475    };
11476  },
11477  htmlBuilder: (group, options) => {
11478    const height = calculateSize(group.height, options);
11479    let depth = 0;
11480
11481    if (group.totalheight.number > 0) {
11482      depth = calculateSize(group.totalheight, options) - height;
11483      depth = Number(depth.toFixed(2));
11484    }
11485
11486    let width = 0;
11487
11488    if (group.width.number > 0) {
11489      width = calculateSize(group.width, options);
11490    }
11491
11492    const style = {
11493      height: height + depth + "em"
11494    };
11495
11496    if (width > 0) {
11497      style.width = width + "em";
11498    }
11499
11500    if (depth > 0) {
11501      style.verticalAlign = -depth + "em";
11502    }
11503
11504    const node = new Img(group.src, group.alt, style);
11505    node.height = height;
11506    node.depth = depth;
11507    return node;
11508  },
11509  mathmlBuilder: (group, options) => {
11510    const node = new mathMLTree.MathNode("mglyph", []);
11511    node.setAttribute("alt", group.alt);
11512    const height = calculateSize(group.height, options);
11513    let depth = 0;
11514
11515    if (group.totalheight.number > 0) {
11516      depth = calculateSize(group.totalheight, options) - height;
11517      depth = depth.toFixed(2);
11518      node.setAttribute("valign", "-" + depth + "em");
11519    }
11520
11521    node.setAttribute("height", height + depth + "em");
11522
11523    if (group.width.number > 0) {
11524      const width = calculateSize(group.width, options);
11525      node.setAttribute("width", width + "em");
11526    }
11527
11528    node.setAttribute("src", group.src);
11529    return node;
11530  }
11531});
11532
11533// Horizontal spacing commands
11534
11535defineFunction({
11536  type: "kern",
11537  names: ["\\kern", "\\mkern", "\\hskip", "\\mskip"],
11538  props: {
11539    numArgs: 1,
11540    argTypes: ["size"],
11541    allowedInText: true
11542  },
11543
11544  handler(_ref, args) {
11545    let parser = _ref.parser,
11546        funcName = _ref.funcName;
11547    const size = assertNodeType(args[0], "size");
11548
11549    if (parser.settings.strict) {
11550      const mathFunction = funcName[1] === 'm'; // \mkern, \mskip
11551
11552      const muUnit = size.value.unit === 'mu';
11553
11554      if (mathFunction) {
11555        if (!muUnit) {
11556          parser.settings.reportNonstrict("mathVsTextUnits", `LaTeX's ${funcName} supports only mu units, ` + `not ${size.value.unit} units`);
11557        }
11558
11559        if (parser.mode !== "math") {
11560          parser.settings.reportNonstrict("mathVsTextUnits", `LaTeX's ${funcName} works only in math mode`);
11561        }
11562      } else {
11563        // !mathFunction
11564        if (muUnit) {
11565          parser.settings.reportNonstrict("mathVsTextUnits", `LaTeX's ${funcName} doesn't support mu units`);
11566        }
11567      }
11568    }
11569
11570    return {
11571      type: "kern",
11572      mode: parser.mode,
11573      dimension: size.value
11574    };
11575  },
11576
11577  htmlBuilder(group, options) {
11578    return buildCommon.makeGlue(group.dimension, options);
11579  },
11580
11581  mathmlBuilder(group, options) {
11582    const dimension = calculateSize(group.dimension, options);
11583    return new mathMLTree.SpaceNode(dimension);
11584  }
11585
11586});
11587
11588// Horizontal overlap functions
11589defineFunction({
11590  type: "lap",
11591  names: ["\\mathllap", "\\mathrlap", "\\mathclap"],
11592  props: {
11593    numArgs: 1,
11594    allowedInText: true
11595  },
11596  handler: (_ref, args) => {
11597    let parser = _ref.parser,
11598        funcName = _ref.funcName;
11599    const body = args[0];
11600    return {
11601      type: "lap",
11602      mode: parser.mode,
11603      alignment: funcName.slice(5),
11604      body
11605    };
11606  },
11607  htmlBuilder: (group, options) => {
11608    // mathllap, mathrlap, mathclap
11609    let inner;
11610
11611    if (group.alignment === "clap") {
11612      // ref: https://www.math.lsu.edu/~aperlis/publications/mathclap/
11613      inner = buildCommon.makeSpan([], [buildGroup(group.body, options)]); // wrap, since CSS will center a .clap > .inner > span
11614
11615      inner = buildCommon.makeSpan(["inner"], [inner], options);
11616    } else {
11617      inner = buildCommon.makeSpan(["inner"], [buildGroup(group.body, options)]);
11618    }
11619
11620    const fix = buildCommon.makeSpan(["fix"], []);
11621    let node = buildCommon.makeSpan([group.alignment], [inner, fix], options); // At this point, we have correctly set horizontal alignment of the
11622    // two items involved in the lap.
11623    // Next, use a strut to set the height of the HTML bounding box.
11624    // Otherwise, a tall argument may be misplaced.
11625
11626    const strut = buildCommon.makeSpan(["strut"]);
11627    strut.style.height = node.height + node.depth + "em";
11628    strut.style.verticalAlign = -node.depth + "em";
11629    node.children.unshift(strut); // Next, prevent vertical misplacement when next to something tall.
11630
11631    node = buildCommon.makeVList({
11632      positionType: "firstBaseline",
11633      children: [{
11634        type: "elem",
11635        elem: node
11636      }]
11637    }, options); // Get the horizontal spacing correct relative to adjacent items.
11638
11639    return buildCommon.makeSpan(["mord"], [node], options);
11640  },
11641  mathmlBuilder: (group, options) => {
11642    // mathllap, mathrlap, mathclap
11643    const node = new mathMLTree.MathNode("mpadded", [buildGroup$1(group.body, options)]);
11644
11645    if (group.alignment !== "rlap") {
11646      const offset = group.alignment === "llap" ? "-1" : "-0.5";
11647      node.setAttribute("lspace", offset + "width");
11648    }
11649
11650    node.setAttribute("width", "0px");
11651    return node;
11652  }
11653});
11654
11655defineFunction({
11656  type: "styling",
11657  names: ["\\(", "$"],
11658  props: {
11659    numArgs: 0,
11660    allowedInText: true,
11661    allowedInMath: false
11662  },
11663
11664  handler(_ref, args) {
11665    let funcName = _ref.funcName,
11666        parser = _ref.parser;
11667    const outerMode = parser.mode;
11668    parser.switchMode("math");
11669    const close = funcName === "\\(" ? "\\)" : "$";
11670    const body = parser.parseExpression(false, close);
11671    parser.expect(close);
11672    parser.switchMode(outerMode);
11673    return {
11674      type: "styling",
11675      mode: parser.mode,
11676      style: "text",
11677      body
11678    };
11679  }
11680
11681}); // Check for extra closing math delimiters
11682
11683defineFunction({
11684  type: "text",
11685  // Doesn't matter what this is.
11686  names: ["\\)", "\\]"],
11687  props: {
11688    numArgs: 0,
11689    allowedInText: true,
11690    allowedInMath: false
11691  },
11692
11693  handler(context, args) {
11694    throw new ParseError(`Mismatched ${context.funcName}`);
11695  }
11696
11697});
11698
11699const chooseMathStyle = (group, options) => {
11700  switch (options.style.size) {
11701    case Style$1.DISPLAY.size:
11702      return group.display;
11703
11704    case Style$1.TEXT.size:
11705      return group.text;
11706
11707    case Style$1.SCRIPT.size:
11708      return group.script;
11709
11710    case Style$1.SCRIPTSCRIPT.size:
11711      return group.scriptscript;
11712
11713    default:
11714      return group.text;
11715  }
11716};
11717
11718defineFunction({
11719  type: "mathchoice",
11720  names: ["\\mathchoice"],
11721  props: {
11722    numArgs: 4
11723  },
11724  handler: (_ref, args) => {
11725    let parser = _ref.parser;
11726    return {
11727      type: "mathchoice",
11728      mode: parser.mode,
11729      display: ordargument(args[0]),
11730      text: ordargument(args[1]),
11731      script: ordargument(args[2]),
11732      scriptscript: ordargument(args[3])
11733    };
11734  },
11735  htmlBuilder: (group, options) => {
11736    const body = chooseMathStyle(group, options);
11737    const elements = buildExpression(body, options, false);
11738    return buildCommon.makeFragment(elements);
11739  },
11740  mathmlBuilder: (group, options) => {
11741    const body = chooseMathStyle(group, options);
11742    return buildExpressionRow(body, options);
11743  }
11744});
11745
11746// For an operator with limits, assemble the base, sup, and sub into a span.
11747const assembleSupSub = (base, supGroup, subGroup, options, style, slant, baseShift) => {
11748  // IE 8 clips \int if it is in a display: inline-block. We wrap it
11749  // in a new span so it is an inline, and works.
11750  base = buildCommon.makeSpan([], [base]);
11751  let sub;
11752  let sup; // We manually have to handle the superscripts and subscripts. This,
11753  // aside from the kern calculations, is copied from supsub.
11754
11755  if (supGroup) {
11756    const elem = buildGroup(supGroup, options.havingStyle(style.sup()), options);
11757    sup = {
11758      elem,
11759      kern: Math.max(options.fontMetrics().bigOpSpacing1, options.fontMetrics().bigOpSpacing3 - elem.depth)
11760    };
11761  }
11762
11763  if (subGroup) {
11764    const elem = buildGroup(subGroup, options.havingStyle(style.sub()), options);
11765    sub = {
11766      elem,
11767      kern: Math.max(options.fontMetrics().bigOpSpacing2, options.fontMetrics().bigOpSpacing4 - elem.height)
11768    };
11769  } // Build the final group as a vlist of the possible subscript, base,
11770  // and possible superscript.
11771
11772
11773  let finalGroup;
11774
11775  if (sup && sub) {
11776    const bottom = options.fontMetrics().bigOpSpacing5 + sub.elem.height + sub.elem.depth + sub.kern + base.depth + baseShift;
11777    finalGroup = buildCommon.makeVList({
11778      positionType: "bottom",
11779      positionData: bottom,
11780      children: [{
11781        type: "kern",
11782        size: options.fontMetrics().bigOpSpacing5
11783      }, {
11784        type: "elem",
11785        elem: sub.elem,
11786        marginLeft: -slant + "em"
11787      }, {
11788        type: "kern",
11789        size: sub.kern
11790      }, {
11791        type: "elem",
11792        elem: base
11793      }, {
11794        type: "kern",
11795        size: sup.kern
11796      }, {
11797        type: "elem",
11798        elem: sup.elem,
11799        marginLeft: slant + "em"
11800      }, {
11801        type: "kern",
11802        size: options.fontMetrics().bigOpSpacing5
11803      }]
11804    }, options);
11805  } else if (sub) {
11806    const top = base.height - baseShift; // Shift the limits by the slant of the symbol. Note
11807    // that we are supposed to shift the limits by 1/2 of the slant,
11808    // but since we are centering the limits adding a full slant of
11809    // margin will shift by 1/2 that.
11810
11811    finalGroup = buildCommon.makeVList({
11812      positionType: "top",
11813      positionData: top,
11814      children: [{
11815        type: "kern",
11816        size: options.fontMetrics().bigOpSpacing5
11817      }, {
11818        type: "elem",
11819        elem: sub.elem,
11820        marginLeft: -slant + "em"
11821      }, {
11822        type: "kern",
11823        size: sub.kern
11824      }, {
11825        type: "elem",
11826        elem: base
11827      }]
11828    }, options);
11829  } else if (sup) {
11830    const bottom = base.depth + baseShift;
11831    finalGroup = buildCommon.makeVList({
11832      positionType: "bottom",
11833      positionData: bottom,
11834      children: [{
11835        type: "elem",
11836        elem: base
11837      }, {
11838        type: "kern",
11839        size: sup.kern
11840      }, {
11841        type: "elem",
11842        elem: sup.elem,
11843        marginLeft: slant + "em"
11844      }, {
11845        type: "kern",
11846        size: options.fontMetrics().bigOpSpacing5
11847      }]
11848    }, options);
11849  } else {
11850    // This case probably shouldn't occur (this would mean the
11851    // supsub was sending us a group with no superscript or
11852    // subscript) but be safe.
11853    return base;
11854  }
11855
11856  return buildCommon.makeSpan(["mop", "op-limits"], [finalGroup], options);
11857};
11858
11859// Limits, symbols
11860// Most operators have a large successor symbol, but these don't.
11861const noSuccessor = ["\\smallint"]; // NOTE: Unlike most `htmlBuilder`s, this one handles not only "op", but also
11862// "supsub" since some of them (like \int) can affect super/subscripting.
11863
11864const htmlBuilder$8 = (grp, options) => {
11865  // Operators are handled in the TeXbook pg. 443-444, rule 13(a).
11866  let supGroup;
11867  let subGroup;
11868  let hasLimits = false;
11869  let group;
11870  const supSub = checkNodeType(grp, "supsub");
11871
11872  if (supSub) {
11873    // If we have limits, supsub will pass us its group to handle. Pull
11874    // out the superscript and subscript and set the group to the op in
11875    // its base.
11876    supGroup = supSub.sup;
11877    subGroup = supSub.sub;
11878    group = assertNodeType(supSub.base, "op");
11879    hasLimits = true;
11880  } else {
11881    group = assertNodeType(grp, "op");
11882  }
11883
11884  const style = options.style;
11885  let large = false;
11886
11887  if (style.size === Style$1.DISPLAY.size && group.symbol && !utils.contains(noSuccessor, group.name)) {
11888    // Most symbol operators get larger in displaystyle (rule 13)
11889    large = true;
11890  }
11891
11892  let base;
11893
11894  if (group.symbol) {
11895    // If this is a symbol, create the symbol.
11896    const fontName = large ? "Size2-Regular" : "Size1-Regular";
11897    let stash = "";
11898
11899    if (group.name === "\\oiint" || group.name === "\\oiiint") {
11900      // No font glyphs yet, so use a glyph w/o the oval.
11901      // TODO: When font glyphs are available, delete this code.
11902      stash = group.name.substr(1); // $FlowFixMe
11903
11904      group.name = stash === "oiint" ? "\\iint" : "\\iiint";
11905    }
11906
11907    base = buildCommon.makeSymbol(group.name, fontName, "math", options, ["mop", "op-symbol", large ? "large-op" : "small-op"]);
11908
11909    if (stash.length > 0) {
11910      // We're in \oiint or \oiiint. Overlay the oval.
11911      // TODO: When font glyphs are available, delete this code.
11912      const italic = base.italic;
11913      const oval = buildCommon.staticSvg(stash + "Size" + (large ? "2" : "1"), options);
11914      base = buildCommon.makeVList({
11915        positionType: "individualShift",
11916        children: [{
11917          type: "elem",
11918          elem: base,
11919          shift: 0
11920        }, {
11921          type: "elem",
11922          elem: oval,
11923          shift: large ? 0.08 : 0
11924        }]
11925      }, options); // $FlowFixMe
11926
11927      group.name = "\\" + stash;
11928      base.classes.unshift("mop"); // $FlowFixMe
11929
11930      base.italic = italic;
11931    }
11932  } else if (group.body) {
11933    // If this is a list, compose that list.
11934    const inner = buildExpression(group.body, options, true);
11935
11936    if (inner.length === 1 && inner[0] instanceof SymbolNode) {
11937      base = inner[0];
11938      base.classes[0] = "mop"; // replace old mclass
11939    } else {
11940      base = buildCommon.makeSpan(["mop"], buildCommon.tryCombineChars(inner), options);
11941    }
11942  } else {
11943    // Otherwise, this is a text operator. Build the text from the
11944    // operator's name.
11945    // TODO(emily): Add a space in the middle of some of these
11946    // operators, like \limsup
11947    const output = [];
11948
11949    for (let i = 1; i < group.name.length; i++) {
11950      output.push(buildCommon.mathsym(group.name[i], group.mode, options));
11951    }
11952
11953    base = buildCommon.makeSpan(["mop"], output, options);
11954  } // If content of op is a single symbol, shift it vertically.
11955
11956
11957  let baseShift = 0;
11958  let slant = 0;
11959
11960  if ((base instanceof SymbolNode || group.name === "\\oiint" || group.name === "\\oiiint") && !group.suppressBaseShift) {
11961    // We suppress the shift of the base of \overset and \underset. Otherwise,
11962    // shift the symbol so its center lies on the axis (rule 13). It
11963    // appears that our fonts have the centers of the symbols already
11964    // almost on the axis, so these numbers are very small. Note we
11965    // don't actually apply this here, but instead it is used either in
11966    // the vlist creation or separately when there are no limits.
11967    baseShift = (base.height - base.depth) / 2 - options.fontMetrics().axisHeight; // The slant of the symbol is just its italic correction.
11968    // $FlowFixMe
11969
11970    slant = base.italic;
11971  }
11972
11973  if (hasLimits) {
11974    return assembleSupSub(base, supGroup, subGroup, options, style, slant, baseShift);
11975  } else {
11976    if (baseShift) {
11977      base.style.position = "relative";
11978      base.style.top = baseShift + "em";
11979    }
11980
11981    return base;
11982  }
11983};
11984
11985const mathmlBuilder$8 = (group, options) => {
11986  let node;
11987
11988  if (group.symbol) {
11989    // This is a symbol. Just add the symbol.
11990    node = new MathNode("mo", [makeText(group.name, group.mode)]);
11991
11992    if (utils.contains(noSuccessor, group.name)) {
11993      node.setAttribute("largeop", "false");
11994    }
11995  } else if (group.body) {
11996    // This is an operator with children. Add them.
11997    node = new MathNode("mo", buildExpression$1(group.body, options));
11998  } else {
11999    // This is a text operator. Add all of the characters from the
12000    // operator's name.
12001    node = new MathNode("mi", [new TextNode(group.name.slice(1))]); // Append an <mo>&ApplyFunction;</mo>.
12002    // ref: https://www.w3.org/TR/REC-MathML/chap3_2.html#sec3.2.4
12003
12004    const operator = new MathNode("mo", [makeText("\u2061", "text")]);
12005
12006    if (group.parentIsSupSub) {
12007      node = new MathNode("mo", [node, operator]);
12008    } else {
12009      node = newDocumentFragment([node, operator]);
12010    }
12011  }
12012
12013  return node;
12014};
12015
12016const singleCharBigOps = {
12017  "\u220F": "\\prod",
12018  "\u2210": "\\coprod",
12019  "\u2211": "\\sum",
12020  "\u22c0": "\\bigwedge",
12021  "\u22c1": "\\bigvee",
12022  "\u22c2": "\\bigcap",
12023  "\u22c3": "\\bigcup",
12024  "\u2a00": "\\bigodot",
12025  "\u2a01": "\\bigoplus",
12026  "\u2a02": "\\bigotimes",
12027  "\u2a04": "\\biguplus",
12028  "\u2a06": "\\bigsqcup"
12029};
12030defineFunction({
12031  type: "op",
12032  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"],
12033  props: {
12034    numArgs: 0
12035  },
12036  handler: (_ref, args) => {
12037    let parser = _ref.parser,
12038        funcName = _ref.funcName;
12039    let fName = funcName;
12040
12041    if (fName.length === 1) {
12042      fName = singleCharBigOps[fName];
12043    }
12044
12045    return {
12046      type: "op",
12047      mode: parser.mode,
12048      limits: true,
12049      parentIsSupSub: false,
12050      symbol: true,
12051      name: fName
12052    };
12053  },
12054  htmlBuilder: htmlBuilder$8,
12055  mathmlBuilder: mathmlBuilder$8
12056}); // Note: calling defineFunction with a type that's already been defined only
12057// works because the same htmlBuilder and mathmlBuilder are being used.
12058
12059defineFunction({
12060  type: "op",
12061  names: ["\\mathop"],
12062  props: {
12063    numArgs: 1
12064  },
12065  handler: (_ref2, args) => {
12066    let parser = _ref2.parser;
12067    const body = args[0];
12068    return {
12069      type: "op",
12070      mode: parser.mode,
12071      limits: false,
12072      parentIsSupSub: false,
12073      symbol: false,
12074      body: ordargument(body)
12075    };
12076  },
12077  htmlBuilder: htmlBuilder$8,
12078  mathmlBuilder: mathmlBuilder$8
12079}); // There are 2 flags for operators; whether they produce limits in
12080// displaystyle, and whether they are symbols and should grow in
12081// displaystyle. These four groups cover the four possible choices.
12082
12083const singleCharIntegrals = {
12084  "\u222b": "\\int",
12085  "\u222c": "\\iint",
12086  "\u222d": "\\iiint",
12087  "\u222e": "\\oint",
12088  "\u222f": "\\oiint",
12089  "\u2230": "\\oiiint"
12090}; // No limits, not symbols
12091
12092defineFunction({
12093  type: "op",
12094  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"],
12095  props: {
12096    numArgs: 0
12097  },
12098
12099  handler(_ref3) {
12100    let parser = _ref3.parser,
12101        funcName = _ref3.funcName;
12102    return {
12103      type: "op",
12104      mode: parser.mode,
12105      limits: false,
12106      parentIsSupSub: false,
12107      symbol: false,
12108      name: funcName
12109    };
12110  },
12111
12112  htmlBuilder: htmlBuilder$8,
12113  mathmlBuilder: mathmlBuilder$8
12114}); // Limits, not symbols
12115
12116defineFunction({
12117  type: "op",
12118  names: ["\\det", "\\gcd", "\\inf", "\\lim", "\\max", "\\min", "\\Pr", "\\sup"],
12119  props: {
12120    numArgs: 0
12121  },
12122
12123  handler(_ref4) {
12124    let parser = _ref4.parser,
12125        funcName = _ref4.funcName;
12126    return {
12127      type: "op",
12128      mode: parser.mode,
12129      limits: true,
12130      parentIsSupSub: false,
12131      symbol: false,
12132      name: funcName
12133    };
12134  },
12135
12136  htmlBuilder: htmlBuilder$8,
12137  mathmlBuilder: mathmlBuilder$8
12138}); // No limits, symbols
12139
12140defineFunction({
12141  type: "op",
12142  names: ["\\int", "\\iint", "\\iiint", "\\oint", "\\oiint", "\\oiiint", "\u222b", "\u222c", "\u222d", "\u222e", "\u222f", "\u2230"],
12143  props: {
12144    numArgs: 0
12145  },
12146
12147  handler(_ref5) {
12148    let parser = _ref5.parser,
12149        funcName = _ref5.funcName;
12150    let fName = funcName;
12151
12152    if (fName.length === 1) {
12153      fName = singleCharIntegrals[fName];
12154    }
12155
12156    return {
12157      type: "op",
12158      mode: parser.mode,
12159      limits: false,
12160      parentIsSupSub: false,
12161      symbol: true,
12162      name: fName
12163    };
12164  },
12165
12166  htmlBuilder: htmlBuilder$8,
12167  mathmlBuilder: mathmlBuilder$8
12168});
12169
12170// NOTE: Unlike most `htmlBuilder`s, this one handles not only
12171// "operatorname", but also  "supsub" since \operatorname* can
12172const htmlBuilder$9 = (grp, options) => {
12173  // Operators are handled in the TeXbook pg. 443-444, rule 13(a).
12174  let supGroup;
12175  let subGroup;
12176  let hasLimits = false;
12177  let group;
12178  const supSub = checkNodeType(grp, "supsub");
12179
12180  if (supSub) {
12181    // If we have limits, supsub will pass us its group to handle. Pull
12182    // out the superscript and subscript and set the group to the op in
12183    // its base.
12184    supGroup = supSub.sup;
12185    subGroup = supSub.sub;
12186    group = assertNodeType(supSub.base, "operatorname");
12187    hasLimits = true;
12188  } else {
12189    group = assertNodeType(grp, "operatorname");
12190  }
12191
12192  let base;
12193
12194  if (group.body.length > 0) {
12195    const body = group.body.map(child => {
12196      // $FlowFixMe: Check if the node has a string `text` property.
12197      const childText = child.text;
12198
12199      if (typeof childText === "string") {
12200        return {
12201          type: "textord",
12202          mode: child.mode,
12203          text: childText
12204        };
12205      } else {
12206        return child;
12207      }
12208    }); // Consolidate function names into symbol characters.
12209
12210    const expression = buildExpression(body, options.withFont("mathrm"), true);
12211
12212    for (let i = 0; i < expression.length; i++) {
12213      const child = expression[i];
12214
12215      if (child instanceof SymbolNode) {
12216        // Per amsopn package,
12217        // change minus to hyphen and \ast to asterisk
12218        child.text = child.text.replace(/\u2212/, "-").replace(/\u2217/, "*");
12219      }
12220    }
12221
12222    base = buildCommon.makeSpan(["mop"], expression, options);
12223  } else {
12224    base = buildCommon.makeSpan(["mop"], [], options);
12225  }
12226
12227  if (hasLimits) {
12228    return assembleSupSub(base, supGroup, subGroup, options, options.style, 0, 0);
12229  } else {
12230    return base;
12231  }
12232};
12233
12234const mathmlBuilder$9 = (group, options) => {
12235  // The steps taken here are similar to the html version.
12236  let expression = buildExpression$1(group.body, options.withFont("mathrm")); // Is expression a string or has it something like a fraction?
12237
12238  let isAllString = true; // default
12239
12240  for (let i = 0; i < expression.length; i++) {
12241    const node = expression[i];
12242
12243    if (node instanceof mathMLTree.SpaceNode) ; else if (node instanceof mathMLTree.MathNode) {
12244      switch (node.type) {
12245        case "mi":
12246        case "mn":
12247        case "ms":
12248        case "mspace":
12249        case "mtext":
12250          break;
12251        // Do nothing yet.
12252
12253        case "mo":
12254          {
12255            const child = node.children[0];
12256
12257            if (node.children.length === 1 && child instanceof mathMLTree.TextNode) {
12258              child.text = child.text.replace(/\u2212/, "-").replace(/\u2217/, "*");
12259            } else {
12260              isAllString = false;
12261            }
12262
12263            break;
12264          }
12265
12266        default:
12267          isAllString = false;
12268      }
12269    } else {
12270      isAllString = false;
12271    }
12272  }
12273
12274  if (isAllString) {
12275    // Write a single TextNode instead of multiple nested tags.
12276    const word = expression.map(node => node.toText()).join("");
12277    expression = [new mathMLTree.TextNode(word)];
12278  }
12279
12280  const identifier = new mathMLTree.MathNode("mi", expression);
12281  identifier.setAttribute("mathvariant", "normal"); // \u2061 is the same as &ApplyFunction;
12282  // ref: https://www.w3schools.com/charsets/ref_html_entities_a.asp
12283
12284  const operator = new mathMLTree.MathNode("mo", [makeText("\u2061", "text")]);
12285
12286  if (group.parentIsSupSub) {
12287    return new mathMLTree.MathNode("mo", [identifier, operator]);
12288  } else {
12289    return mathMLTree.newDocumentFragment([identifier, operator]);
12290  }
12291}; // \operatorname
12292// amsopn.dtx: \mathop{#1\kern\z@\operator@font#3}\newmcodes@
12293
12294
12295defineFunction({
12296  type: "operatorname",
12297  names: ["\\operatorname", "\\operatorname*"],
12298  props: {
12299    numArgs: 1
12300  },
12301  handler: (_ref, args) => {
12302    let parser = _ref.parser,
12303        funcName = _ref.funcName;
12304    const body = args[0];
12305    return {
12306      type: "operatorname",
12307      mode: parser.mode,
12308      body: ordargument(body),
12309      alwaysHandleSupSub: funcName === "\\operatorname*",
12310      limits: false,
12311      parentIsSupSub: false
12312    };
12313  },
12314  htmlBuilder: htmlBuilder$9,
12315  mathmlBuilder: mathmlBuilder$9
12316});
12317
12318defineFunctionBuilders({
12319  type: "ordgroup",
12320
12321  htmlBuilder(group, options) {
12322    if (group.semisimple) {
12323      return buildCommon.makeFragment(buildExpression(group.body, options, false));
12324    }
12325
12326    return buildCommon.makeSpan(["mord"], buildExpression(group.body, options, true), options);
12327  },
12328
12329  mathmlBuilder(group, options) {
12330    return buildExpressionRow(group.body, options, true);
12331  }
12332
12333});
12334
12335defineFunction({
12336  type: "overline",
12337  names: ["\\overline"],
12338  props: {
12339    numArgs: 1
12340  },
12341
12342  handler(_ref, args) {
12343    let parser = _ref.parser;
12344    const body = args[0];
12345    return {
12346      type: "overline",
12347      mode: parser.mode,
12348      body
12349    };
12350  },
12351
12352  htmlBuilder(group, options) {
12353    // Overlines are handled in the TeXbook pg 443, Rule 9.
12354    // Build the inner group in the cramped style.
12355    const innerGroup = buildGroup(group.body, options.havingCrampedStyle()); // Create the line above the body
12356
12357    const line = buildCommon.makeLineSpan("overline-line", options); // Generate the vlist, with the appropriate kerns
12358
12359    const defaultRuleThickness = options.fontMetrics().defaultRuleThickness;
12360    const vlist = buildCommon.makeVList({
12361      positionType: "firstBaseline",
12362      children: [{
12363        type: "elem",
12364        elem: innerGroup
12365      }, {
12366        type: "kern",
12367        size: 3 * defaultRuleThickness
12368      }, {
12369        type: "elem",
12370        elem: line
12371      }, {
12372        type: "kern",
12373        size: defaultRuleThickness
12374      }]
12375    }, options);
12376    return buildCommon.makeSpan(["mord", "overline"], [vlist], options);
12377  },
12378
12379  mathmlBuilder(group, options) {
12380    const operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u203e")]);
12381    operator.setAttribute("stretchy", "true");
12382    const node = new mathMLTree.MathNode("mover", [buildGroup$1(group.body, options), operator]);
12383    node.setAttribute("accent", "true");
12384    return node;
12385  }
12386
12387});
12388
12389defineFunction({
12390  type: "phantom",
12391  names: ["\\phantom"],
12392  props: {
12393    numArgs: 1,
12394    allowedInText: true
12395  },
12396  handler: (_ref, args) => {
12397    let parser = _ref.parser;
12398    const body = args[0];
12399    return {
12400      type: "phantom",
12401      mode: parser.mode,
12402      body: ordargument(body)
12403    };
12404  },
12405  htmlBuilder: (group, options) => {
12406    const elements = buildExpression(group.body, options.withPhantom(), false); // \phantom isn't supposed to affect the elements it contains.
12407    // See "color" for more details.
12408
12409    return buildCommon.makeFragment(elements);
12410  },
12411  mathmlBuilder: (group, options) => {
12412    const inner = buildExpression$1(group.body, options);
12413    return new mathMLTree.MathNode("mphantom", inner);
12414  }
12415});
12416defineFunction({
12417  type: "hphantom",
12418  names: ["\\hphantom"],
12419  props: {
12420    numArgs: 1,
12421    allowedInText: true
12422  },
12423  handler: (_ref2, args) => {
12424    let parser = _ref2.parser;
12425    const body = args[0];
12426    return {
12427      type: "hphantom",
12428      mode: parser.mode,
12429      body
12430    };
12431  },
12432  htmlBuilder: (group, options) => {
12433    let node = buildCommon.makeSpan([], [buildGroup(group.body, options.withPhantom())]);
12434    node.height = 0;
12435    node.depth = 0;
12436
12437    if (node.children) {
12438      for (let i = 0; i < node.children.length; i++) {
12439        node.children[i].height = 0;
12440        node.children[i].depth = 0;
12441      }
12442    } // See smash for comment re: use of makeVList
12443
12444
12445    node = buildCommon.makeVList({
12446      positionType: "firstBaseline",
12447      children: [{
12448        type: "elem",
12449        elem: node
12450      }]
12451    }, options); // For spacing, TeX treats \smash as a math group (same spacing as ord).
12452
12453    return buildCommon.makeSpan(["mord"], [node], options);
12454  },
12455  mathmlBuilder: (group, options) => {
12456    const inner = buildExpression$1(ordargument(group.body), options);
12457    const phantom = new mathMLTree.MathNode("mphantom", inner);
12458    const node = new mathMLTree.MathNode("mpadded", [phantom]);
12459    node.setAttribute("height", "0px");
12460    node.setAttribute("depth", "0px");
12461    return node;
12462  }
12463});
12464defineFunction({
12465  type: "vphantom",
12466  names: ["\\vphantom"],
12467  props: {
12468    numArgs: 1,
12469    allowedInText: true
12470  },
12471  handler: (_ref3, args) => {
12472    let parser = _ref3.parser;
12473    const body = args[0];
12474    return {
12475      type: "vphantom",
12476      mode: parser.mode,
12477      body
12478    };
12479  },
12480  htmlBuilder: (group, options) => {
12481    const inner = buildCommon.makeSpan(["inner"], [buildGroup(group.body, options.withPhantom())]);
12482    const fix = buildCommon.makeSpan(["fix"], []);
12483    return buildCommon.makeSpan(["mord", "rlap"], [inner, fix], options);
12484  },
12485  mathmlBuilder: (group, options) => {
12486    const inner = buildExpression$1(ordargument(group.body), options);
12487    const phantom = new mathMLTree.MathNode("mphantom", inner);
12488    const node = new mathMLTree.MathNode("mpadded", [phantom]);
12489    node.setAttribute("width", "0px");
12490    return node;
12491  }
12492});
12493
12494defineFunction({
12495  type: "raisebox",
12496  names: ["\\raisebox"],
12497  props: {
12498    numArgs: 2,
12499    argTypes: ["size", "hbox"],
12500    allowedInText: true
12501  },
12502
12503  handler(_ref, args) {
12504    let parser = _ref.parser;
12505    const amount = assertNodeType(args[0], "size").value;
12506    const body = args[1];
12507    return {
12508      type: "raisebox",
12509      mode: parser.mode,
12510      dy: amount,
12511      body
12512    };
12513  },
12514
12515  htmlBuilder(group, options) {
12516    const body = buildGroup(group.body, options);
12517    const dy = calculateSize(group.dy, options);
12518    return buildCommon.makeVList({
12519      positionType: "shift",
12520      positionData: -dy,
12521      children: [{
12522        type: "elem",
12523        elem: body
12524      }]
12525    }, options);
12526  },
12527
12528  mathmlBuilder(group, options) {
12529    const node = new mathMLTree.MathNode("mpadded", [buildGroup$1(group.body, options)]);
12530    const dy = group.dy.number + group.dy.unit;
12531    node.setAttribute("voffset", dy);
12532    return node;
12533  }
12534
12535});
12536
12537defineFunction({
12538  type: "rule",
12539  names: ["\\rule"],
12540  props: {
12541    numArgs: 2,
12542    numOptionalArgs: 1,
12543    argTypes: ["size", "size", "size"]
12544  },
12545
12546  handler(_ref, args, optArgs) {
12547    let parser = _ref.parser;
12548    const shift = optArgs[0];
12549    const width = assertNodeType(args[0], "size");
12550    const height = assertNodeType(args[1], "size");
12551    return {
12552      type: "rule",
12553      mode: parser.mode,
12554      shift: shift && assertNodeType(shift, "size").value,
12555      width: width.value,
12556      height: height.value
12557    };
12558  },
12559
12560  htmlBuilder(group, options) {
12561    // Make an empty span for the rule
12562    const rule = buildCommon.makeSpan(["mord", "rule"], [], options); // Calculate the shift, width, and height of the rule, and account for units
12563
12564    const width = calculateSize(group.width, options);
12565    const height = calculateSize(group.height, options);
12566    const shift = group.shift ? calculateSize(group.shift, options) : 0; // Style the rule to the right size
12567
12568    rule.style.borderRightWidth = width + "em";
12569    rule.style.borderTopWidth = height + "em";
12570    rule.style.bottom = shift + "em"; // Record the height and width
12571
12572    rule.width = width;
12573    rule.height = height + shift;
12574    rule.depth = -shift; // Font size is the number large enough that the browser will
12575    // reserve at least `absHeight` space above the baseline.
12576    // The 1.125 factor was empirically determined
12577
12578    rule.maxFontSize = height * 1.125 * options.sizeMultiplier;
12579    return rule;
12580  },
12581
12582  mathmlBuilder(group, options) {
12583    const width = calculateSize(group.width, options);
12584    const height = calculateSize(group.height, options);
12585    const shift = group.shift ? calculateSize(group.shift, options) : 0;
12586    const color = options.color && options.getColor() || "black";
12587    const rule = new mathMLTree.MathNode("mspace");
12588    rule.setAttribute("mathbackground", color);
12589    rule.setAttribute("width", width + "em");
12590    rule.setAttribute("height", height + "em");
12591    const wrapper = new mathMLTree.MathNode("mpadded", [rule]);
12592
12593    if (shift >= 0) {
12594      wrapper.setAttribute("height", "+" + shift + "em");
12595    } else {
12596      wrapper.setAttribute("height", shift + "em");
12597      wrapper.setAttribute("depth", "+" + -shift + "em");
12598    }
12599
12600    wrapper.setAttribute("voffset", shift + "em");
12601    return wrapper;
12602  }
12603
12604});
12605
12606function sizingGroup(value, options, baseOptions) {
12607  const inner = buildExpression(value, options, false);
12608  const multiplier = options.sizeMultiplier / baseOptions.sizeMultiplier; // Add size-resetting classes to the inner list and set maxFontSize
12609  // manually. Handle nested size changes.
12610
12611  for (let i = 0; i < inner.length; i++) {
12612    const pos = inner[i].classes.indexOf("sizing");
12613
12614    if (pos < 0) {
12615      Array.prototype.push.apply(inner[i].classes, options.sizingClasses(baseOptions));
12616    } else if (inner[i].classes[pos + 1] === "reset-size" + options.size) {
12617      // This is a nested size change: e.g., inner[i] is the "b" in
12618      // `\Huge a \small b`. Override the old size (the `reset-` class)
12619      // but not the new size.
12620      inner[i].classes[pos + 1] = "reset-size" + baseOptions.size;
12621    }
12622
12623    inner[i].height *= multiplier;
12624    inner[i].depth *= multiplier;
12625  }
12626
12627  return buildCommon.makeFragment(inner);
12628}
12629const sizeFuncs = ["\\tiny", "\\sixptsize", "\\scriptsize", "\\footnotesize", "\\small", "\\normalsize", "\\large", "\\Large", "\\LARGE", "\\huge", "\\Huge"];
12630const htmlBuilder$a = (group, options) => {
12631  // Handle sizing operators like \Huge. Real TeX doesn't actually allow
12632  // these functions inside of math expressions, so we do some special
12633  // handling.
12634  const newOptions = options.havingSize(group.size);
12635  return sizingGroup(group.body, newOptions, options);
12636};
12637defineFunction({
12638  type: "sizing",
12639  names: sizeFuncs,
12640  props: {
12641    numArgs: 0,
12642    allowedInText: true
12643  },
12644  handler: (_ref, args) => {
12645    let breakOnTokenText = _ref.breakOnTokenText,
12646        funcName = _ref.funcName,
12647        parser = _ref.parser;
12648    const body = parser.parseExpression(false, breakOnTokenText);
12649    return {
12650      type: "sizing",
12651      mode: parser.mode,
12652      // Figure out what size to use based on the list of functions above
12653      size: sizeFuncs.indexOf(funcName) + 1,
12654      body
12655    };
12656  },
12657  htmlBuilder: htmlBuilder$a,
12658  mathmlBuilder: (group, options) => {
12659    const newOptions = options.havingSize(group.size);
12660    const inner = buildExpression$1(group.body, newOptions);
12661    const node = new mathMLTree.MathNode("mstyle", inner); // TODO(emily): This doesn't produce the correct size for nested size
12662    // changes, because we don't keep state of what style we're currently
12663    // in, so we can't reset the size to normal before changing it.  Now
12664    // that we're passing an options parameter we should be able to fix
12665    // this.
12666
12667    node.setAttribute("mathsize", newOptions.sizeMultiplier + "em");
12668    return node;
12669  }
12670});
12671
12672// smash, with optional [tb], as in AMS
12673defineFunction({
12674  type: "smash",
12675  names: ["\\smash"],
12676  props: {
12677    numArgs: 1,
12678    numOptionalArgs: 1,
12679    allowedInText: true
12680  },
12681  handler: (_ref, args, optArgs) => {
12682    let parser = _ref.parser;
12683    let smashHeight = false;
12684    let smashDepth = false;
12685    const tbArg = optArgs[0] && assertNodeType(optArgs[0], "ordgroup");
12686
12687    if (tbArg) {
12688      // Optional [tb] argument is engaged.
12689      // ref: amsmath: \renewcommand{\smash}[1][tb]{%
12690      //               def\mb@t{\ht}\def\mb@b{\dp}\def\mb@tb{\ht\z@\z@\dp}%
12691      let letter = "";
12692
12693      for (let i = 0; i < tbArg.body.length; ++i) {
12694        const node = tbArg.body[i]; // $FlowFixMe: Not every node type has a `text` property.
12695
12696        letter = node.text;
12697
12698        if (letter === "t") {
12699          smashHeight = true;
12700        } else if (letter === "b") {
12701          smashDepth = true;
12702        } else {
12703          smashHeight = false;
12704          smashDepth = false;
12705          break;
12706        }
12707      }
12708    } else {
12709      smashHeight = true;
12710      smashDepth = true;
12711    }
12712
12713    const body = args[0];
12714    return {
12715      type: "smash",
12716      mode: parser.mode,
12717      body,
12718      smashHeight,
12719      smashDepth
12720    };
12721  },
12722  htmlBuilder: (group, options) => {
12723    const node = buildCommon.makeSpan([], [buildGroup(group.body, options)]);
12724
12725    if (!group.smashHeight && !group.smashDepth) {
12726      return node;
12727    }
12728
12729    if (group.smashHeight) {
12730      node.height = 0; // In order to influence makeVList, we have to reset the children.
12731
12732      if (node.children) {
12733        for (let i = 0; i < node.children.length; i++) {
12734          node.children[i].height = 0;
12735        }
12736      }
12737    }
12738
12739    if (group.smashDepth) {
12740      node.depth = 0;
12741
12742      if (node.children) {
12743        for (let i = 0; i < node.children.length; i++) {
12744          node.children[i].depth = 0;
12745        }
12746      }
12747    } // At this point, we've reset the TeX-like height and depth values.
12748    // But the span still has an HTML line height.
12749    // makeVList applies "display: table-cell", which prevents the browser
12750    // from acting on that line height. So we'll call makeVList now.
12751
12752
12753    const smashedNode = buildCommon.makeVList({
12754      positionType: "firstBaseline",
12755      children: [{
12756        type: "elem",
12757        elem: node
12758      }]
12759    }, options); // For spacing, TeX treats \hphantom as a math group (same spacing as ord).
12760
12761    return buildCommon.makeSpan(["mord"], [smashedNode], options);
12762  },
12763  mathmlBuilder: (group, options) => {
12764    const node = new mathMLTree.MathNode("mpadded", [buildGroup$1(group.body, options)]);
12765
12766    if (group.smashHeight) {
12767      node.setAttribute("height", "0px");
12768    }
12769
12770    if (group.smashDepth) {
12771      node.setAttribute("depth", "0px");
12772    }
12773
12774    return node;
12775  }
12776});
12777
12778defineFunction({
12779  type: "sqrt",
12780  names: ["\\sqrt"],
12781  props: {
12782    numArgs: 1,
12783    numOptionalArgs: 1
12784  },
12785
12786  handler(_ref, args, optArgs) {
12787    let parser = _ref.parser;
12788    const index = optArgs[0];
12789    const body = args[0];
12790    return {
12791      type: "sqrt",
12792      mode: parser.mode,
12793      body,
12794      index
12795    };
12796  },
12797
12798  htmlBuilder(group, options) {
12799    // Square roots are handled in the TeXbook pg. 443, Rule 11.
12800    // First, we do the same steps as in overline to build the inner group
12801    // and line
12802    let inner = buildGroup(group.body, options.havingCrampedStyle());
12803
12804    if (inner.height === 0) {
12805      // Render a small surd.
12806      inner.height = options.fontMetrics().xHeight;
12807    } // Some groups can return document fragments.  Handle those by wrapping
12808    // them in a span.
12809
12810
12811    inner = buildCommon.wrapFragment(inner, options); // Calculate the minimum size for the \surd delimiter
12812
12813    const metrics = options.fontMetrics();
12814    const theta = metrics.defaultRuleThickness;
12815    let phi = theta;
12816
12817    if (options.style.id < Style$1.TEXT.id) {
12818      phi = options.fontMetrics().xHeight;
12819    } // Calculate the clearance between the body and line
12820
12821
12822    let lineClearance = theta + phi / 4;
12823    const minDelimiterHeight = inner.height + inner.depth + lineClearance + theta; // Create a sqrt SVG of the required minimum size
12824
12825    const _delimiter$sqrtImage = delimiter.sqrtImage(minDelimiterHeight, options),
12826          img = _delimiter$sqrtImage.span,
12827          ruleWidth = _delimiter$sqrtImage.ruleWidth,
12828          advanceWidth = _delimiter$sqrtImage.advanceWidth;
12829
12830    const delimDepth = img.height - ruleWidth; // Adjust the clearance based on the delimiter size
12831
12832    if (delimDepth > inner.height + inner.depth + lineClearance) {
12833      lineClearance = (lineClearance + delimDepth - inner.height - inner.depth) / 2;
12834    } // Shift the sqrt image
12835
12836
12837    const imgShift = img.height - inner.height - lineClearance - ruleWidth;
12838    inner.style.paddingLeft = advanceWidth + "em"; // Overlay the image and the argument.
12839
12840    const body = buildCommon.makeVList({
12841      positionType: "firstBaseline",
12842      children: [{
12843        type: "elem",
12844        elem: inner,
12845        wrapperClasses: ["svg-align"]
12846      }, {
12847        type: "kern",
12848        size: -(inner.height + imgShift)
12849      }, {
12850        type: "elem",
12851        elem: img
12852      }, {
12853        type: "kern",
12854        size: ruleWidth
12855      }]
12856    }, options);
12857
12858    if (!group.index) {
12859      return buildCommon.makeSpan(["mord", "sqrt"], [body], options);
12860    } else {
12861      // Handle the optional root index
12862      // The index is always in scriptscript style
12863      const newOptions = options.havingStyle(Style$1.SCRIPTSCRIPT);
12864      const rootm = buildGroup(group.index, newOptions, options); // The amount the index is shifted by. This is taken from the TeX
12865      // source, in the definition of `\r@@t`.
12866
12867      const toShift = 0.6 * (body.height - body.depth); // Build a VList with the superscript shifted up correctly
12868
12869      const rootVList = buildCommon.makeVList({
12870        positionType: "shift",
12871        positionData: -toShift,
12872        children: [{
12873          type: "elem",
12874          elem: rootm
12875        }]
12876      }, options); // Add a class surrounding it so we can add on the appropriate
12877      // kerning
12878
12879      const rootVListWrap = buildCommon.makeSpan(["root"], [rootVList]);
12880      return buildCommon.makeSpan(["mord", "sqrt"], [rootVListWrap, body], options);
12881    }
12882  },
12883
12884  mathmlBuilder(group, options) {
12885    const body = group.body,
12886          index = group.index;
12887    return index ? new mathMLTree.MathNode("mroot", [buildGroup$1(body, options), buildGroup$1(index, options)]) : new mathMLTree.MathNode("msqrt", [buildGroup$1(body, options)]);
12888  }
12889
12890});
12891
12892const styleMap$1 = {
12893  "display": Style$1.DISPLAY,
12894  "text": Style$1.TEXT,
12895  "script": Style$1.SCRIPT,
12896  "scriptscript": Style$1.SCRIPTSCRIPT
12897};
12898defineFunction({
12899  type: "styling",
12900  names: ["\\displaystyle", "\\textstyle", "\\scriptstyle", "\\scriptscriptstyle"],
12901  props: {
12902    numArgs: 0,
12903    allowedInText: true
12904  },
12905
12906  handler(_ref, args) {
12907    let breakOnTokenText = _ref.breakOnTokenText,
12908        funcName = _ref.funcName,
12909        parser = _ref.parser;
12910    // parse out the implicit body
12911    const body = parser.parseExpression(true, breakOnTokenText); // TODO: Refactor to avoid duplicating styleMap in multiple places (e.g.
12912    // here and in buildHTML and de-dupe the enumeration of all the styles).
12913    // $FlowFixMe: The names above exactly match the styles.
12914
12915    const style = funcName.slice(1, funcName.length - 5);
12916    return {
12917      type: "styling",
12918      mode: parser.mode,
12919      // Figure out what style to use by pulling out the style from
12920      // the function name
12921      style,
12922      body
12923    };
12924  },
12925
12926  htmlBuilder(group, options) {
12927    // Style changes are handled in the TeXbook on pg. 442, Rule 3.
12928    const newStyle = styleMap$1[group.style];
12929    const newOptions = options.havingStyle(newStyle).withFont('');
12930    return sizingGroup(group.body, newOptions, options);
12931  },
12932
12933  mathmlBuilder(group, options) {
12934    // Figure out what style we're changing to.
12935    const newStyle = styleMap$1[group.style];
12936    const newOptions = options.havingStyle(newStyle);
12937    const inner = buildExpression$1(group.body, newOptions);
12938    const node = new mathMLTree.MathNode("mstyle", inner);
12939    const styleAttributes = {
12940      "display": ["0", "true"],
12941      "text": ["0", "false"],
12942      "script": ["1", "false"],
12943      "scriptscript": ["2", "false"]
12944    };
12945    const attr = styleAttributes[group.style];
12946    node.setAttribute("scriptlevel", attr[0]);
12947    node.setAttribute("displaystyle", attr[1]);
12948    return node;
12949  }
12950
12951});
12952
12953/**
12954 * Sometimes, groups perform special rules when they have superscripts or
12955 * subscripts attached to them. This function lets the `supsub` group know that
12956 * Sometimes, groups perform special rules when they have superscripts or
12957 * its inner element should handle the superscripts and subscripts instead of
12958 * handling them itself.
12959 */
12960const htmlBuilderDelegate = function htmlBuilderDelegate(group, options) {
12961  const base = group.base;
12962
12963  if (!base) {
12964    return null;
12965  } else if (base.type === "op") {
12966    // Operators handle supsubs differently when they have limits
12967    // (e.g. `\displaystyle\sum_2^3`)
12968    const delegate = base.limits && (options.style.size === Style$1.DISPLAY.size || base.alwaysHandleSupSub);
12969    return delegate ? htmlBuilder$8 : null;
12970  } else if (base.type === "operatorname") {
12971    const delegate = base.alwaysHandleSupSub && (options.style.size === Style$1.DISPLAY.size || base.limits);
12972    return delegate ? htmlBuilder$9 : null;
12973  } else if (base.type === "accent") {
12974    return utils.isCharacterBox(base.base) ? htmlBuilder : null;
12975  } else if (base.type === "horizBrace") {
12976    const isSup = !group.sub;
12977    return isSup === base.isOver ? htmlBuilder$7 : null;
12978  } else {
12979    return null;
12980  }
12981}; // Super scripts and subscripts, whose precise placement can depend on other
12982// functions that precede them.
12983
12984
12985defineFunctionBuilders({
12986  type: "supsub",
12987
12988  htmlBuilder(group, options) {
12989    // Superscript and subscripts are handled in the TeXbook on page
12990    // 445-446, rules 18(a-f).
12991    // Here is where we defer to the inner group if it should handle
12992    // superscripts and subscripts itself.
12993    const builderDelegate = htmlBuilderDelegate(group, options);
12994
12995    if (builderDelegate) {
12996      return builderDelegate(group, options);
12997    }
12998
12999    const valueBase = group.base,
13000          valueSup = group.sup,
13001          valueSub = group.sub;
13002    const base = buildGroup(valueBase, options);
13003    let supm;
13004    let subm;
13005    const metrics = options.fontMetrics(); // Rule 18a
13006
13007    let supShift = 0;
13008    let subShift = 0;
13009    const isCharacterBox = valueBase && utils.isCharacterBox(valueBase);
13010
13011    if (valueSup) {
13012      const newOptions = options.havingStyle(options.style.sup());
13013      supm = buildGroup(valueSup, newOptions, options);
13014
13015      if (!isCharacterBox) {
13016        supShift = base.height - newOptions.fontMetrics().supDrop * newOptions.sizeMultiplier / options.sizeMultiplier;
13017      }
13018    }
13019
13020    if (valueSub) {
13021      const newOptions = options.havingStyle(options.style.sub());
13022      subm = buildGroup(valueSub, newOptions, options);
13023
13024      if (!isCharacterBox) {
13025        subShift = base.depth + newOptions.fontMetrics().subDrop * newOptions.sizeMultiplier / options.sizeMultiplier;
13026      }
13027    } // Rule 18c
13028
13029
13030    let minSupShift;
13031
13032    if (options.style === Style$1.DISPLAY) {
13033      minSupShift = metrics.sup1;
13034    } else if (options.style.cramped) {
13035      minSupShift = metrics.sup3;
13036    } else {
13037      minSupShift = metrics.sup2;
13038    } // scriptspace is a font-size-independent size, so scale it
13039    // appropriately for use as the marginRight.
13040
13041
13042    const multiplier = options.sizeMultiplier;
13043    const marginRight = 0.5 / metrics.ptPerEm / multiplier + "em";
13044    let marginLeft = null;
13045
13046    if (subm) {
13047      // Subscripts shouldn't be shifted by the base's italic correction.
13048      // Account for that by shifting the subscript back the appropriate
13049      // amount. Note we only do this when the base is a single symbol.
13050      const isOiint = group.base && group.base.type === "op" && group.base.name && (group.base.name === "\\oiint" || group.base.name === "\\oiiint");
13051
13052      if (base instanceof SymbolNode || isOiint) {
13053        // $FlowFixMe
13054        marginLeft = -base.italic + "em";
13055      }
13056    }
13057
13058    let supsub;
13059
13060    if (supm && subm) {
13061      supShift = Math.max(supShift, minSupShift, supm.depth + 0.25 * metrics.xHeight);
13062      subShift = Math.max(subShift, metrics.sub2);
13063      const ruleWidth = metrics.defaultRuleThickness; // Rule 18e
13064
13065      const maxWidth = 4 * ruleWidth;
13066
13067      if (supShift - supm.depth - (subm.height - subShift) < maxWidth) {
13068        subShift = maxWidth - (supShift - supm.depth) + subm.height;
13069        const psi = 0.8 * metrics.xHeight - (supShift - supm.depth);
13070
13071        if (psi > 0) {
13072          supShift += psi;
13073          subShift -= psi;
13074        }
13075      }
13076
13077      const vlistElem = [{
13078        type: "elem",
13079        elem: subm,
13080        shift: subShift,
13081        marginRight,
13082        marginLeft
13083      }, {
13084        type: "elem",
13085        elem: supm,
13086        shift: -supShift,
13087        marginRight
13088      }];
13089      supsub = buildCommon.makeVList({
13090        positionType: "individualShift",
13091        children: vlistElem
13092      }, options);
13093    } else if (subm) {
13094      // Rule 18b
13095      subShift = Math.max(subShift, metrics.sub1, subm.height - 0.8 * metrics.xHeight);
13096      const vlistElem = [{
13097        type: "elem",
13098        elem: subm,
13099        marginLeft,
13100        marginRight
13101      }];
13102      supsub = buildCommon.makeVList({
13103        positionType: "shift",
13104        positionData: subShift,
13105        children: vlistElem
13106      }, options);
13107    } else if (supm) {
13108      // Rule 18c, d
13109      supShift = Math.max(supShift, minSupShift, supm.depth + 0.25 * metrics.xHeight);
13110      supsub = buildCommon.makeVList({
13111        positionType: "shift",
13112        positionData: -supShift,
13113        children: [{
13114          type: "elem",
13115          elem: supm,
13116          marginRight
13117        }]
13118      }, options);
13119    } else {
13120      throw new Error("supsub must have either sup or sub.");
13121    } // Wrap the supsub vlist in a span.msupsub to reset text-align.
13122
13123
13124    const mclass = getTypeOfDomTree(base, "right") || "mord";
13125    return buildCommon.makeSpan([mclass], [base, buildCommon.makeSpan(["msupsub"], [supsub])], options);
13126  },
13127
13128  mathmlBuilder(group, options) {
13129    // Is the inner group a relevant horizonal brace?
13130    let isBrace = false;
13131    let isOver;
13132    let isSup;
13133    const horizBrace = checkNodeType(group.base, "horizBrace");
13134
13135    if (horizBrace) {
13136      isSup = !!group.sup;
13137
13138      if (isSup === horizBrace.isOver) {
13139        isBrace = true;
13140        isOver = horizBrace.isOver;
13141      }
13142    }
13143
13144    if (group.base && (group.base.type === "op" || group.base.type === "operatorname")) {
13145      group.base.parentIsSupSub = true;
13146    }
13147
13148    const children = [buildGroup$1(group.base, options)];
13149
13150    if (group.sub) {
13151      children.push(buildGroup$1(group.sub, options));
13152    }
13153
13154    if (group.sup) {
13155      children.push(buildGroup$1(group.sup, options));
13156    }
13157
13158    let nodeType;
13159
13160    if (isBrace) {
13161      nodeType = isOver ? "mover" : "munder";
13162    } else if (!group.sub) {
13163      const base = group.base;
13164
13165      if (base && base.type === "op" && base.limits && (options.style === Style$1.DISPLAY || base.alwaysHandleSupSub)) {
13166        nodeType = "mover";
13167      } else if (base && base.type === "operatorname" && base.alwaysHandleSupSub && (base.limits || options.style === Style$1.DISPLAY)) {
13168        nodeType = "mover";
13169      } else {
13170        nodeType = "msup";
13171      }
13172    } else if (!group.sup) {
13173      const base = group.base;
13174
13175      if (base && base.type === "op" && base.limits && (options.style === Style$1.DISPLAY || base.alwaysHandleSupSub)) {
13176        nodeType = "munder";
13177      } else if (base && base.type === "operatorname" && base.alwaysHandleSupSub && (base.limits || options.style === Style$1.DISPLAY)) {
13178        nodeType = "munder";
13179      } else {
13180        nodeType = "msub";
13181      }
13182    } else {
13183      const base = group.base;
13184
13185      if (base && base.type === "op" && base.limits && options.style === Style$1.DISPLAY) {
13186        nodeType = "munderover";
13187      } else if (base && base.type === "operatorname" && base.alwaysHandleSupSub && (options.style === Style$1.DISPLAY || base.limits)) {
13188        nodeType = "munderover";
13189      } else {
13190        nodeType = "msubsup";
13191      }
13192    }
13193
13194    const node = new mathMLTree.MathNode(nodeType, children);
13195    return node;
13196  }
13197
13198});
13199
13200defineFunctionBuilders({
13201  type: "atom",
13202
13203  htmlBuilder(group, options) {
13204    return buildCommon.mathsym(group.text, group.mode, options, ["m" + group.family]);
13205  },
13206
13207  mathmlBuilder(group, options) {
13208    const node = new mathMLTree.MathNode("mo", [makeText(group.text, group.mode)]);
13209
13210    if (group.family === "bin") {
13211      const variant = getVariant(group, options);
13212
13213      if (variant === "bold-italic") {
13214        node.setAttribute("mathvariant", variant);
13215      }
13216    } else if (group.family === "punct") {
13217      node.setAttribute("separator", "true");
13218    } else if (group.family === "open" || group.family === "close") {
13219      // Delims built here should not stretch vertically.
13220      // See delimsizing.js for stretchy delims.
13221      node.setAttribute("stretchy", "false");
13222    }
13223
13224    return node;
13225  }
13226
13227});
13228
13229// "mathord" and "textord" ParseNodes created in Parser.js from symbol Groups in
13230const defaultVariant = {
13231  "mi": "italic",
13232  "mn": "normal",
13233  "mtext": "normal"
13234};
13235defineFunctionBuilders({
13236  type: "mathord",
13237
13238  htmlBuilder(group, options) {
13239    return buildCommon.makeOrd(group, options, "mathord");
13240  },
13241
13242  mathmlBuilder(group, options) {
13243    const node = new mathMLTree.MathNode("mi", [makeText(group.text, group.mode, options)]);
13244    const variant = getVariant(group, options) || "italic";
13245
13246    if (variant !== defaultVariant[node.type]) {
13247      node.setAttribute("mathvariant", variant);
13248    }
13249
13250    return node;
13251  }
13252
13253});
13254defineFunctionBuilders({
13255  type: "textord",
13256
13257  htmlBuilder(group, options) {
13258    return buildCommon.makeOrd(group, options, "textord");
13259  },
13260
13261  mathmlBuilder(group, options) {
13262    const text = makeText(group.text, group.mode, options);
13263    const variant = getVariant(group, options) || "normal";
13264    let node;
13265
13266    if (group.mode === 'text') {
13267      node = new mathMLTree.MathNode("mtext", [text]);
13268    } else if (/[0-9]/.test(group.text)) {
13269      // TODO(kevinb) merge adjacent <mn> nodes
13270      // do it as a post processing step
13271      node = new mathMLTree.MathNode("mn", [text]);
13272    } else if (group.text === "\\prime") {
13273      node = new mathMLTree.MathNode("mo", [text]);
13274    } else {
13275      node = new mathMLTree.MathNode("mi", [text]);
13276    }
13277
13278    if (variant !== defaultVariant[node.type]) {
13279      node.setAttribute("mathvariant", variant);
13280    }
13281
13282    return node;
13283  }
13284
13285});
13286
13287const cssSpace = {
13288  "\\nobreak": "nobreak",
13289  "\\allowbreak": "allowbreak"
13290}; // A lookup table to determine whether a spacing function/symbol should be
13291// treated like a regular space character.  If a symbol or command is a key
13292// in this table, then it should be a regular space character.  Furthermore,
13293// the associated value may have a `className` specifying an extra CSS class
13294// to add to the created `span`.
13295
13296const regularSpace = {
13297  " ": {},
13298  "\\ ": {},
13299  "~": {
13300    className: "nobreak"
13301  },
13302  "\\space": {},
13303  "\\nobreakspace": {
13304    className: "nobreak"
13305  }
13306}; // ParseNode<"spacing"> created in Parser.js from the "spacing" symbol Groups in
13307// src/symbols.js.
13308
13309defineFunctionBuilders({
13310  type: "spacing",
13311
13312  htmlBuilder(group, options) {
13313    if (regularSpace.hasOwnProperty(group.text)) {
13314      const className = regularSpace[group.text].className || ""; // Spaces are generated by adding an actual space. Each of these
13315      // things has an entry in the symbols table, so these will be turned
13316      // into appropriate outputs.
13317
13318      if (group.mode === "text") {
13319        const ord = buildCommon.makeOrd(group, options, "textord");
13320        ord.classes.push(className);
13321        return ord;
13322      } else {
13323        return buildCommon.makeSpan(["mspace", className], [buildCommon.mathsym(group.text, group.mode, options)], options);
13324      }
13325    } else if (cssSpace.hasOwnProperty(group.text)) {
13326      // Spaces based on just a CSS class.
13327      return buildCommon.makeSpan(["mspace", cssSpace[group.text]], [], options);
13328    } else {
13329      throw new ParseError(`Unknown type of space "${group.text}"`);
13330    }
13331  },
13332
13333  mathmlBuilder(group, options) {
13334    let node;
13335
13336    if (regularSpace.hasOwnProperty(group.text)) {
13337      node = new mathMLTree.MathNode("mtext", [new mathMLTree.TextNode("\u00a0")]);
13338    } else if (cssSpace.hasOwnProperty(group.text)) {
13339      // CSS-based MathML spaces (\nobreak, \allowbreak) are ignored
13340      return new mathMLTree.MathNode("mspace");
13341    } else {
13342      throw new ParseError(`Unknown type of space "${group.text}"`);
13343    }
13344
13345    return node;
13346  }
13347
13348});
13349
13350const pad = () => {
13351  const padNode = new mathMLTree.MathNode("mtd", []);
13352  padNode.setAttribute("width", "50%");
13353  return padNode;
13354};
13355
13356defineFunctionBuilders({
13357  type: "tag",
13358
13359  mathmlBuilder(group, options) {
13360    const 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)])])]);
13361    table.setAttribute("width", "100%");
13362    return table; // TODO: Left-aligned tags.
13363    // Currently, the group and options passed here do not contain
13364    // enough info to set tag alignment. `leqno` is in Settings but it is
13365    // not passed to Options. On the HTML side, leqno is
13366    // set by a CSS class applied in buildTree.js. That would have worked
13367    // in MathML if browsers supported <mlabeledtr>. Since they don't, we
13368    // need to rewrite the way this function is called.
13369  }
13370
13371});
13372
13373const textFontFamilies = {
13374  "\\text": undefined,
13375  "\\textrm": "textrm",
13376  "\\textsf": "textsf",
13377  "\\texttt": "texttt",
13378  "\\textnormal": "textrm"
13379};
13380const textFontWeights = {
13381  "\\textbf": "textbf",
13382  "\\textmd": "textmd"
13383};
13384const textFontShapes = {
13385  "\\textit": "textit",
13386  "\\textup": "textup"
13387};
13388
13389const optionsWithFont = (group, options) => {
13390  const font = group.font; // Checks if the argument is a font family or a font style.
13391
13392  if (!font) {
13393    return options;
13394  } else if (textFontFamilies[font]) {
13395    return options.withTextFontFamily(textFontFamilies[font]);
13396  } else if (textFontWeights[font]) {
13397    return options.withTextFontWeight(textFontWeights[font]);
13398  } else {
13399    return options.withTextFontShape(textFontShapes[font]);
13400  }
13401};
13402
13403defineFunction({
13404  type: "text",
13405  names: [// Font families
13406  "\\text", "\\textrm", "\\textsf", "\\texttt", "\\textnormal", // Font weights
13407  "\\textbf", "\\textmd", // Font Shapes
13408  "\\textit", "\\textup"],
13409  props: {
13410    numArgs: 1,
13411    argTypes: ["text"],
13412    greediness: 2,
13413    allowedInText: true
13414  },
13415
13416  handler(_ref, args) {
13417    let parser = _ref.parser,
13418        funcName = _ref.funcName;
13419    const body = args[0];
13420    return {
13421      type: "text",
13422      mode: parser.mode,
13423      body: ordargument(body),
13424      font: funcName
13425    };
13426  },
13427
13428  htmlBuilder(group, options) {
13429    const newOptions = optionsWithFont(group, options);
13430    const inner = buildExpression(group.body, newOptions, true);
13431    return buildCommon.makeSpan(["mord", "text"], buildCommon.tryCombineChars(inner), newOptions);
13432  },
13433
13434  mathmlBuilder(group, options) {
13435    const newOptions = optionsWithFont(group, options);
13436    return buildExpressionRow(group.body, newOptions);
13437  }
13438
13439});
13440
13441defineFunction({
13442  type: "underline",
13443  names: ["\\underline"],
13444  props: {
13445    numArgs: 1,
13446    allowedInText: true
13447  },
13448
13449  handler(_ref, args) {
13450    let parser = _ref.parser;
13451    return {
13452      type: "underline",
13453      mode: parser.mode,
13454      body: args[0]
13455    };
13456  },
13457
13458  htmlBuilder(group, options) {
13459    // Underlines are handled in the TeXbook pg 443, Rule 10.
13460    // Build the inner group.
13461    const innerGroup = buildGroup(group.body, options); // Create the line to go below the body
13462
13463    const line = buildCommon.makeLineSpan("underline-line", options); // Generate the vlist, with the appropriate kerns
13464
13465    const defaultRuleThickness = options.fontMetrics().defaultRuleThickness;
13466    const vlist = buildCommon.makeVList({
13467      positionType: "top",
13468      positionData: innerGroup.height,
13469      children: [{
13470        type: "kern",
13471        size: defaultRuleThickness
13472      }, {
13473        type: "elem",
13474        elem: line
13475      }, {
13476        type: "kern",
13477        size: 3 * defaultRuleThickness
13478      }, {
13479        type: "elem",
13480        elem: innerGroup
13481      }]
13482    }, options);
13483    return buildCommon.makeSpan(["mord", "underline"], [vlist], options);
13484  },
13485
13486  mathmlBuilder(group, options) {
13487    const operator = new mathMLTree.MathNode("mo", [new mathMLTree.TextNode("\u203e")]);
13488    operator.setAttribute("stretchy", "true");
13489    const node = new mathMLTree.MathNode("munder", [buildGroup$1(group.body, options), operator]);
13490    node.setAttribute("accentunder", "true");
13491    return node;
13492  }
13493
13494});
13495
13496defineFunction({
13497  type: "verb",
13498  names: ["\\verb"],
13499  props: {
13500    numArgs: 0,
13501    allowedInText: true
13502  },
13503
13504  handler(context, args, optArgs) {
13505    // \verb and \verb* are dealt with directly in Parser.js.
13506    // If we end up here, it's because of a failure to match the two delimiters
13507    // in the regex in Lexer.js.  LaTeX raises the following error when \verb is
13508    // terminated by end of line (or file).
13509    throw new ParseError("\\verb ended by end of line instead of matching delimiter");
13510  },
13511
13512  htmlBuilder(group, options) {
13513    const text = makeVerb(group);
13514    const body = []; // \verb enters text mode and therefore is sized like \textstyle
13515
13516    const newOptions = options.havingStyle(options.style.text());
13517
13518    for (let i = 0; i < text.length; i++) {
13519      let c = text[i];
13520
13521      if (c === '~') {
13522        c = '\\textasciitilde';
13523      }
13524
13525      body.push(buildCommon.makeSymbol(c, "Typewriter-Regular", group.mode, newOptions, ["mord", "texttt"]));
13526    }
13527
13528    return buildCommon.makeSpan(["mord", "text"].concat(newOptions.sizingClasses(options)), buildCommon.tryCombineChars(body), newOptions);
13529  },
13530
13531  mathmlBuilder(group, options) {
13532    const text = new mathMLTree.TextNode(makeVerb(group));
13533    const node = new mathMLTree.MathNode("mtext", [text]);
13534    node.setAttribute("mathvariant", "monospace");
13535    return node;
13536  }
13537
13538});
13539/**
13540 * Converts verb group into body string.
13541 *
13542 * \verb* replaces each space with an open box \u2423
13543 * \verb replaces each space with a no-break space \xA0
13544 */
13545
13546const makeVerb = group => group.body.replace(/ /g, group.star ? '\u2423' : '\xA0');
13547
13548/** Include this to ensure that all functions are defined. */
13549const functions = _functions;
13550
13551/**
13552 * The Lexer class handles tokenizing the input in various ways. Since our
13553 * parser expects us to be able to backtrack, the lexer allows lexing from any
13554 * given starting point.
13555 *
13556 * Its main exposed function is the `lex` function, which takes a position to
13557 * lex from and a type of token to lex. It defers to the appropriate `_innerLex`
13558 * function.
13559 *
13560 * The various `_innerLex` functions perform the actual lexing of different
13561 * kinds.
13562 */
13563
13564/* The following tokenRegex
13565 * - matches typical whitespace (but not NBSP etc.) using its first group
13566 * - does not match any control character \x00-\x1f except whitespace
13567 * - does not match a bare backslash
13568 * - matches any ASCII character except those just mentioned
13569 * - does not match the BMP private use area \uE000-\uF8FF
13570 * - does not match bare surrogate code units
13571 * - matches any BMP character except for those just described
13572 * - matches any valid Unicode surrogate pair
13573 * - matches a backslash followed by one or more letters
13574 * - matches a backslash followed by any BMP character, including newline
13575 * Just because the Lexer matches something doesn't mean it's valid input:
13576 * If there is no matching function or symbol definition, the Parser will
13577 * still reject the input.
13578 */
13579const spaceRegexString = "[ \r\n\t]";
13580const controlWordRegexString = "\\\\[a-zA-Z@]+";
13581const controlSymbolRegexString = "\\\\[^\uD800-\uDFFF]";
13582const controlWordWhitespaceRegexString = `${controlWordRegexString}${spaceRegexString}*`;
13583const controlWordWhitespaceRegex = new RegExp(`^(${controlWordRegexString})${spaceRegexString}*$`);
13584const combiningDiacriticalMarkString = "[\u0300-\u036f]";
13585const combiningDiacriticalMarksEndRegex = new RegExp(`${combiningDiacriticalMarkString}+$`);
13586const tokenRegexString = `(${spaceRegexString}+)|` + // whitespace
13587"([!-\\[\\]-\u2027\u202A-\uD7FF\uF900-\uFFFF]" + // single codepoint
13588`${combiningDiacriticalMarkString}*` + // ...plus accents
13589"|[\uD800-\uDBFF][\uDC00-\uDFFF]" + // surrogate pair
13590`${combiningDiacriticalMarkString}*` + // ...plus accents
13591"|\\\\verb\\*([^]).*?\\3" + // \verb*
13592"|\\\\verb([^*a-zA-Z]).*?\\4" + // \verb unstarred
13593"|\\\\operatorname\\*" + // \operatorname*
13594`|${controlWordWhitespaceRegexString}` + // \macroName + spaces
13595`|${controlSymbolRegexString})`; // \\, \', etc.
13596
13597/** Main Lexer class */
13598
13599class Lexer {
13600  // category codes, only supports comment characters (14) for now
13601  constructor(input, settings) {
13602    this.input = void 0;
13603    this.settings = void 0;
13604    this.tokenRegex = void 0;
13605    this.catcodes = void 0;
13606    // Separate accents from characters
13607    this.input = input;
13608    this.settings = settings;
13609    this.tokenRegex = new RegExp(tokenRegexString, 'g');
13610    this.catcodes = {
13611      "%": 14 // comment character
13612
13613    };
13614  }
13615
13616  setCatcode(char, code) {
13617    this.catcodes[char] = code;
13618  }
13619  /**
13620   * This function lexes a single token.
13621   */
13622
13623
13624  lex() {
13625    const input = this.input;
13626    const pos = this.tokenRegex.lastIndex;
13627
13628    if (pos === input.length) {
13629      return new Token("EOF", new SourceLocation(this, pos, pos));
13630    }
13631
13632    const match = this.tokenRegex.exec(input);
13633
13634    if (match === null || match.index !== pos) {
13635      throw new ParseError(`Unexpected character: '${input[pos]}'`, new Token(input[pos], new SourceLocation(this, pos, pos + 1)));
13636    }
13637
13638    let text = match[2] || " ";
13639
13640    if (this.catcodes[text] === 14) {
13641      // comment character
13642      const nlIndex = input.indexOf('\n', this.tokenRegex.lastIndex);
13643
13644      if (nlIndex === -1) {
13645        this.tokenRegex.lastIndex = input.length; // EOF
13646
13647        this.settings.reportNonstrict("commentAtEnd", "% comment has no terminating newline; LaTeX would " + "fail because of commenting the end of math mode (e.g. $)");
13648      } else {
13649        this.tokenRegex.lastIndex = nlIndex + 1;
13650      }
13651
13652      return this.lex();
13653    } // Trim any trailing whitespace from control word match
13654
13655
13656    const controlMatch = text.match(controlWordWhitespaceRegex);
13657
13658    if (controlMatch) {
13659      text = controlMatch[1];
13660    }
13661
13662    return new Token(text, new SourceLocation(this, pos, this.tokenRegex.lastIndex));
13663  }
13664
13665}
13666
13667/**
13668 * A `Namespace` refers to a space of nameable things like macros or lengths,
13669 * which can be `set` either globally or local to a nested group, using an
13670 * undo stack similar to how TeX implements this functionality.
13671 * Performance-wise, `get` and local `set` take constant time, while global
13672 * `set` takes time proportional to the depth of group nesting.
13673 */
13674class Namespace {
13675  /**
13676   * Both arguments are optional.  The first argument is an object of
13677   * built-in mappings which never change.  The second argument is an object
13678   * of initial (global-level) mappings, which will constantly change
13679   * according to any global/top-level `set`s done.
13680   */
13681  constructor(builtins, globalMacros) {
13682    if (builtins === void 0) {
13683      builtins = {};
13684    }
13685
13686    if (globalMacros === void 0) {
13687      globalMacros = {};
13688    }
13689
13690    this.current = void 0;
13691    this.builtins = void 0;
13692    this.undefStack = void 0;
13693    this.current = globalMacros;
13694    this.builtins = builtins;
13695    this.undefStack = [];
13696  }
13697  /**
13698   * Start a new nested group, affecting future local `set`s.
13699   */
13700
13701
13702  beginGroup() {
13703    this.undefStack.push({});
13704  }
13705  /**
13706   * End current nested group, restoring values before the group began.
13707   */
13708
13709
13710  endGroup() {
13711    if (this.undefStack.length === 0) {
13712      throw new ParseError("Unbalanced namespace destruction: attempt " + "to pop global namespace; please report this as a bug");
13713    }
13714
13715    const undefs = this.undefStack.pop();
13716
13717    for (const undef in undefs) {
13718      if (undefs.hasOwnProperty(undef)) {
13719        if (undefs[undef] === undefined) {
13720          delete this.current[undef];
13721        } else {
13722          this.current[undef] = undefs[undef];
13723        }
13724      }
13725    }
13726  }
13727  /**
13728   * Detect whether `name` has a definition.  Equivalent to
13729   * `get(name) != null`.
13730   */
13731
13732
13733  has(name) {
13734    return this.current.hasOwnProperty(name) || this.builtins.hasOwnProperty(name);
13735  }
13736  /**
13737   * Get the current value of a name, or `undefined` if there is no value.
13738   *
13739   * Note: Do not use `if (namespace.get(...))` to detect whether a macro
13740   * is defined, as the definition may be the empty string which evaluates
13741   * to `false` in JavaScript.  Use `if (namespace.get(...) != null)` or
13742   * `if (namespace.has(...))`.
13743   */
13744
13745
13746  get(name) {
13747    if (this.current.hasOwnProperty(name)) {
13748      return this.current[name];
13749    } else {
13750      return this.builtins[name];
13751    }
13752  }
13753  /**
13754   * Set the current value of a name, and optionally set it globally too.
13755   * Local set() sets the current value and (when appropriate) adds an undo
13756   * operation to the undo stack.  Global set() may change the undo
13757   * operation at every level, so takes time linear in their number.
13758   */
13759
13760
13761  set(name, value, global) {
13762    if (global === void 0) {
13763      global = false;
13764    }
13765
13766    if (global) {
13767      // Global set is equivalent to setting in all groups.  Simulate this
13768      // by destroying any undos currently scheduled for this name,
13769      // and adding an undo with the *new* value (in case it later gets
13770      // locally reset within this environment).
13771      for (let i = 0; i < this.undefStack.length; i++) {
13772        delete this.undefStack[i][name];
13773      }
13774
13775      if (this.undefStack.length > 0) {
13776        this.undefStack[this.undefStack.length - 1][name] = value;
13777      }
13778    } else {
13779      // Undo this set at end of this group (possibly to `undefined`),
13780      // unless an undo is already in place, in which case that older
13781      // value is the correct one.
13782      const top = this.undefStack[this.undefStack.length - 1];
13783
13784      if (top && !top.hasOwnProperty(name)) {
13785        top[name] = this.current[name];
13786      }
13787    }
13788
13789    this.current[name] = value;
13790  }
13791
13792}
13793
13794/**
13795 * Predefined macros for KaTeX.
13796 * This can be used to define some commands in terms of others.
13797 */
13798const builtinMacros = {};
13799
13800function defineMacro(name, body) {
13801  builtinMacros[name] = body;
13802} //////////////////////////////////////////////////////////////////////
13803// macro tools
13804// LaTeX's \@firstoftwo{#1}{#2} expands to #1, skipping #2
13805// TeX source: \long\def\@firstoftwo#1#2{#1}
13806
13807defineMacro("\\@firstoftwo", function (context) {
13808  const args = context.consumeArgs(2);
13809  return {
13810    tokens: args[0],
13811    numArgs: 0
13812  };
13813}); // LaTeX's \@secondoftwo{#1}{#2} expands to #2, skipping #1
13814// TeX source: \long\def\@secondoftwo#1#2{#2}
13815
13816defineMacro("\\@secondoftwo", function (context) {
13817  const args = context.consumeArgs(2);
13818  return {
13819    tokens: args[1],
13820    numArgs: 0
13821  };
13822}); // LaTeX's \@ifnextchar{#1}{#2}{#3} looks ahead to the next (unexpanded)
13823// symbol.  If it matches #1, then the macro expands to #2; otherwise, #3.
13824// Note, however, that it does not consume the next symbol in either case.
13825
13826defineMacro("\\@ifnextchar", function (context) {
13827  const args = context.consumeArgs(3); // symbol, if, else
13828
13829  const nextToken = context.future();
13830
13831  if (args[0].length === 1 && args[0][0].text === nextToken.text) {
13832    return {
13833      tokens: args[1],
13834      numArgs: 0
13835    };
13836  } else {
13837    return {
13838      tokens: args[2],
13839      numArgs: 0
13840    };
13841  }
13842}); // LaTeX's \@ifstar{#1}{#2} looks ahead to the next (unexpanded) symbol.
13843// If it is `*`, then it consumes the symbol, and the macro expands to #1;
13844// otherwise, the macro expands to #2 (without consuming the symbol).
13845// TeX source: \def\@ifstar#1{\@ifnextchar *{\@firstoftwo{#1}}}
13846
13847defineMacro("\\@ifstar", "\\@ifnextchar *{\\@firstoftwo{#1}}"); // LaTeX's \TextOrMath{#1}{#2} expands to #1 in text mode, #2 in math mode
13848
13849defineMacro("\\TextOrMath", function (context) {
13850  const args = context.consumeArgs(2);
13851
13852  if (context.mode === 'text') {
13853    return {
13854      tokens: args[0],
13855      numArgs: 0
13856    };
13857  } else {
13858    return {
13859      tokens: args[1],
13860      numArgs: 0
13861    };
13862  }
13863}); // Lookup table for parsing numbers in base 8 through 16
13864
13865const digitToNumber = {
13866  "0": 0,
13867  "1": 1,
13868  "2": 2,
13869  "3": 3,
13870  "4": 4,
13871  "5": 5,
13872  "6": 6,
13873  "7": 7,
13874  "8": 8,
13875  "9": 9,
13876  "a": 10,
13877  "A": 10,
13878  "b": 11,
13879  "B": 11,
13880  "c": 12,
13881  "C": 12,
13882  "d": 13,
13883  "D": 13,
13884  "e": 14,
13885  "E": 14,
13886  "f": 15,
13887  "F": 15
13888}; // TeX \char makes a literal character (catcode 12) using the following forms:
13889// (see The TeXBook, p. 43)
13890//   \char123  -- decimal
13891//   \char'123 -- octal
13892//   \char"123 -- hex
13893//   \char`x   -- character that can be written (i.e. isn't active)
13894//   \char`\x  -- character that cannot be written (e.g. %)
13895// These all refer to characters from the font, so we turn them into special
13896// calls to a function \@char dealt with in the Parser.
13897
13898defineMacro("\\char", function (context) {
13899  let token = context.popToken();
13900  let base;
13901  let number = '';
13902
13903  if (token.text === "'") {
13904    base = 8;
13905    token = context.popToken();
13906  } else if (token.text === '"') {
13907    base = 16;
13908    token = context.popToken();
13909  } else if (token.text === "`") {
13910    token = context.popToken();
13911
13912    if (token.text[0] === "\\") {
13913      number = token.text.charCodeAt(1);
13914    } else if (token.text === "EOF") {
13915      throw new ParseError("\\char` missing argument");
13916    } else {
13917      number = token.text.charCodeAt(0);
13918    }
13919  } else {
13920    base = 10;
13921  }
13922
13923  if (base) {
13924    // Parse a number in the given base, starting with first `token`.
13925    number = digitToNumber[token.text];
13926
13927    if (number == null || number >= base) {
13928      throw new ParseError(`Invalid base-${base} digit ${token.text}`);
13929    }
13930
13931    let digit;
13932
13933    while ((digit = digitToNumber[context.future().text]) != null && digit < base) {
13934      number *= base;
13935      number += digit;
13936      context.popToken();
13937    }
13938  }
13939
13940  return `\\@char{${number}}`;
13941}); // Basic support for macro definitions:
13942//     \def\macro{expansion}
13943//     \def\macro#1{expansion}
13944//     \def\macro#1#2{expansion}
13945//     \def\macro#1#2#3#4#5#6#7#8#9{expansion}
13946// Also the \gdef and \global\def equivalents
13947
13948const def = (context, global) => {
13949  let arg = context.consumeArgs(1)[0];
13950
13951  if (arg.length !== 1) {
13952    throw new ParseError("\\gdef's first argument must be a macro name");
13953  }
13954
13955  const name = arg[0].text; // Count argument specifiers, and check they are in the order #1 #2 ...
13956
13957  let numArgs = 0;
13958  arg = context.consumeArgs(1)[0];
13959
13960  while (arg.length === 1 && arg[0].text === "#") {
13961    arg = context.consumeArgs(1)[0];
13962
13963    if (arg.length !== 1) {
13964      throw new ParseError(`Invalid argument number length "${arg.length}"`);
13965    }
13966
13967    if (!/^[1-9]$/.test(arg[0].text)) {
13968      throw new ParseError(`Invalid argument number "${arg[0].text}"`);
13969    }
13970
13971    numArgs++;
13972
13973    if (parseInt(arg[0].text) !== numArgs) {
13974      throw new ParseError(`Argument number "${arg[0].text}" out of order`);
13975    }
13976
13977    arg = context.consumeArgs(1)[0];
13978  } // Final arg is the expansion of the macro
13979
13980
13981  context.macros.set(name, {
13982    tokens: arg,
13983    numArgs
13984  }, global);
13985  return '';
13986};
13987
13988defineMacro("\\gdef", context => def(context, true));
13989defineMacro("\\def", context => def(context, false));
13990defineMacro("\\global", context => {
13991  const next = context.consumeArgs(1)[0];
13992
13993  if (next.length !== 1) {
13994    throw new ParseError("Invalid command after \\global");
13995  }
13996
13997  const command = next[0].text; // TODO: Should expand command
13998
13999  if (command === "\\def") {
14000    // \global\def is equivalent to \gdef
14001    return def(context, true);
14002  } else {
14003    throw new ParseError(`Invalid command '${command}' after \\global`);
14004  }
14005}); // \newcommand{\macro}[args]{definition}
14006// \renewcommand{\macro}[args]{definition}
14007// TODO: Optional arguments: \newcommand{\macro}[args][default]{definition}
14008
14009const newcommand = (context, existsOK, nonexistsOK) => {
14010  let arg = context.consumeArgs(1)[0];
14011
14012  if (arg.length !== 1) {
14013    throw new ParseError("\\newcommand's first argument must be a macro name");
14014  }
14015
14016  const name = arg[0].text;
14017  const exists = context.isDefined(name);
14018
14019  if (exists && !existsOK) {
14020    throw new ParseError(`\\newcommand{${name}} attempting to redefine ` + `${name}; use \\renewcommand`);
14021  }
14022
14023  if (!exists && !nonexistsOK) {
14024    throw new ParseError(`\\renewcommand{${name}} when command ${name} ` + `does not yet exist; use \\newcommand`);
14025  }
14026
14027  let numArgs = 0;
14028  arg = context.consumeArgs(1)[0];
14029
14030  if (arg.length === 1 && arg[0].text === "[") {
14031    let argText = '';
14032    let token = context.expandNextToken();
14033
14034    while (token.text !== "]" && token.text !== "EOF") {
14035      // TODO: Should properly expand arg, e.g., ignore {}s
14036      argText += token.text;
14037      token = context.expandNextToken();
14038    }
14039
14040    if (!argText.match(/^\s*[0-9]+\s*$/)) {
14041      throw new ParseError(`Invalid number of arguments: ${argText}`);
14042    }
14043
14044    numArgs = parseInt(argText);
14045    arg = context.consumeArgs(1)[0];
14046  } // Final arg is the expansion of the macro
14047
14048
14049  context.macros.set(name, {
14050    tokens: arg,
14051    numArgs
14052  });
14053  return '';
14054};
14055
14056defineMacro("\\newcommand", context => newcommand(context, false, true));
14057defineMacro("\\renewcommand", context => newcommand(context, true, false));
14058defineMacro("\\providecommand", context => newcommand(context, true, true)); //////////////////////////////////////////////////////////////////////
14059// Grouping
14060// \let\bgroup={ \let\egroup=}
14061
14062defineMacro("\\bgroup", "{");
14063defineMacro("\\egroup", "}"); // Symbols from latex.ltx:
14064// \def\lq{`}
14065// \def\rq{'}
14066// \def \aa {\r a}
14067// \def \AA {\r A}
14068
14069defineMacro("\\lq", "`");
14070defineMacro("\\rq", "'");
14071defineMacro("\\aa", "\\r a");
14072defineMacro("\\AA", "\\r A"); // Copyright (C) and registered (R) symbols. Use raw symbol in MathML.
14073// \DeclareTextCommandDefault{\textcopyright}{\textcircled{c}}
14074// \DeclareTextCommandDefault{\textregistered}{\textcircled{%
14075//      \check@mathfonts\fontsize\sf@size\z@\math@fontsfalse\selectfont R}}
14076// \DeclareRobustCommand{\copyright}{%
14077//    \ifmmode{\nfss@text{\textcopyright}}\else\textcopyright\fi}
14078
14079defineMacro("\\textcopyright", "\\html@mathml{\\textcircled{c}}{\\char`©}");
14080defineMacro("\\copyright", "\\TextOrMath{\\textcopyright}{\\text{\\textcopyright}}");
14081defineMacro("\\textregistered", "\\html@mathml{\\textcircled{\\scriptsize R}}{\\char`®}"); // Characters omitted from Unicode range 1D400–1D7FF
14082
14083defineMacro("\u212C", "\\mathscr{B}"); // script
14084
14085defineMacro("\u2130", "\\mathscr{E}");
14086defineMacro("\u2131", "\\mathscr{F}");
14087defineMacro("\u210B", "\\mathscr{H}");
14088defineMacro("\u2110", "\\mathscr{I}");
14089defineMacro("\u2112", "\\mathscr{L}");
14090defineMacro("\u2133", "\\mathscr{M}");
14091defineMacro("\u211B", "\\mathscr{R}");
14092defineMacro("\u212D", "\\mathfrak{C}"); // Fraktur
14093
14094defineMacro("\u210C", "\\mathfrak{H}");
14095defineMacro("\u2128", "\\mathfrak{Z}"); // Define \Bbbk with a macro that works in both HTML and MathML.
14096
14097defineMacro("\\Bbbk", "\\Bbb{k}"); // Unicode middle dot
14098// The KaTeX fonts do not contain U+00B7. Instead, \cdotp displays
14099// the dot at U+22C5 and gives it punct spacing.
14100
14101defineMacro("\u00b7", "\\cdotp"); // \llap and \rlap render their contents in text mode
14102
14103defineMacro("\\llap", "\\mathllap{\\textrm{#1}}");
14104defineMacro("\\rlap", "\\mathrlap{\\textrm{#1}}");
14105defineMacro("\\clap", "\\mathclap{\\textrm{#1}}"); // \not is defined by base/fontmath.ltx via
14106// \DeclareMathSymbol{\not}{\mathrel}{symbols}{"36}
14107// It's thus treated like a \mathrel, but defined by a symbol that has zero
14108// width but extends to the right.  We use \rlap to get that spacing.
14109// For MathML we write U+0338 here. buildMathML.js will then do the overlay.
14110
14111defineMacro("\\not", '\\html@mathml{\\mathrel{\\mathrlap\\@not}}{\\char"338}'); // Negated symbols from base/fontmath.ltx:
14112// \def\neq{\not=} \let\ne=\neq
14113// \DeclareRobustCommand
14114//   \notin{\mathrel{\m@th\mathpalette\c@ncel\in}}
14115// \def\c@ncel#1#2{\m@th\ooalign{$\hfil#1\mkern1mu/\hfil$\crcr$#1#2$}}
14116
14117defineMacro("\\neq", "\\html@mathml{\\mathrel{\\not=}}{\\mathrel{\\char`≠}}");
14118defineMacro("\\ne", "\\neq");
14119defineMacro("\u2260", "\\neq");
14120defineMacro("\\notin", "\\html@mathml{\\mathrel{{\\in}\\mathllap{/\\mskip1mu}}}" + "{\\mathrel{\\char`∉}}");
14121defineMacro("\u2209", "\\notin"); // Unicode stacked relations
14122
14123defineMacro("\u2258", "\\html@mathml{" + "\\mathrel{=\\kern{-1em}\\raisebox{0.4em}{$\\scriptsize\\frown$}}" + "}{\\mathrel{\\char`\u2258}}");
14124defineMacro("\u2259", "\\html@mathml{\\stackrel{\\tiny\\wedge}{=}}{\\mathrel{\\char`\u2258}}");
14125defineMacro("\u225A", "\\html@mathml{\\stackrel{\\tiny\\vee}{=}}{\\mathrel{\\char`\u225A}}");
14126defineMacro("\u225B", "\\html@mathml{\\stackrel{\\scriptsize\\star}{=}}" + "{\\mathrel{\\char`\u225B}}");
14127defineMacro("\u225D", "\\html@mathml{\\stackrel{\\tiny\\mathrm{def}}{=}}" + "{\\mathrel{\\char`\u225D}}");
14128defineMacro("\u225E", "\\html@mathml{\\stackrel{\\tiny\\mathrm{m}}{=}}" + "{\\mathrel{\\char`\u225E}}");
14129defineMacro("\u225F", "\\html@mathml{\\stackrel{\\tiny?}{=}}{\\mathrel{\\char`\u225F}}"); // Misc Unicode
14130
14131defineMacro("\u27C2", "\\perp");
14132defineMacro("\u203C", "\\mathclose{!\\mkern-0.8mu!}");
14133defineMacro("\u220C", "\\notni");
14134defineMacro("\u231C", "\\ulcorner");
14135defineMacro("\u231D", "\\urcorner");
14136defineMacro("\u231E", "\\llcorner");
14137defineMacro("\u231F", "\\lrcorner");
14138defineMacro("\u00A9", "\\copyright");
14139defineMacro("\u00AE", "\\textregistered");
14140defineMacro("\uFE0F", "\\textregistered"); //////////////////////////////////////////////////////////////////////
14141// LaTeX_2ε
14142// \vdots{\vbox{\baselineskip4\p@  \lineskiplimit\z@
14143// \kern6\p@\hbox{.}\hbox{.}\hbox{.}}}
14144// We'll call \varvdots, which gets a glyph from symbols.js.
14145// The zero-width rule gets us an equivalent to the vertical 6pt kern.
14146
14147defineMacro("\\vdots", "\\mathord{\\varvdots\\rule{0pt}{15pt}}");
14148defineMacro("\u22ee", "\\vdots"); //////////////////////////////////////////////////////////////////////
14149// amsmath.sty
14150// http://mirrors.concertpass.com/tex-archive/macros/latex/required/amsmath/amsmath.pdf
14151// Italic Greek capital letters.  AMS defines these with \DeclareMathSymbol,
14152// but they are equivalent to \mathit{\Letter}.
14153
14154defineMacro("\\varGamma", "\\mathit{\\Gamma}");
14155defineMacro("\\varDelta", "\\mathit{\\Delta}");
14156defineMacro("\\varTheta", "\\mathit{\\Theta}");
14157defineMacro("\\varLambda", "\\mathit{\\Lambda}");
14158defineMacro("\\varXi", "\\mathit{\\Xi}");
14159defineMacro("\\varPi", "\\mathit{\\Pi}");
14160defineMacro("\\varSigma", "\\mathit{\\Sigma}");
14161defineMacro("\\varUpsilon", "\\mathit{\\Upsilon}");
14162defineMacro("\\varPhi", "\\mathit{\\Phi}");
14163defineMacro("\\varPsi", "\\mathit{\\Psi}");
14164defineMacro("\\varOmega", "\\mathit{\\Omega}"); //\newcommand{\substack}[1]{\subarray{c}#1\endsubarray}
14165
14166defineMacro("\\substack", "\\begin{subarray}{c}#1\\end{subarray}"); // \renewcommand{\colon}{\nobreak\mskip2mu\mathpunct{}\nonscript
14167// \mkern-\thinmuskip{:}\mskip6muplus1mu\relax}
14168
14169defineMacro("\\colon", "\\nobreak\\mskip2mu\\mathpunct{}" + "\\mathchoice{\\mkern-3mu}{\\mkern-3mu}{}{}{:}\\mskip6mu"); // \newcommand{\boxed}[1]{\fbox{\m@th$\displaystyle#1$}}
14170
14171defineMacro("\\boxed", "\\fbox{$\\displaystyle{#1}$}"); // \def\iff{\DOTSB\;\Longleftrightarrow\;}
14172// \def\implies{\DOTSB\;\Longrightarrow\;}
14173// \def\impliedby{\DOTSB\;\Longleftarrow\;}
14174
14175defineMacro("\\iff", "\\DOTSB\\;\\Longleftrightarrow\\;");
14176defineMacro("\\implies", "\\DOTSB\\;\\Longrightarrow\\;");
14177defineMacro("\\impliedby", "\\DOTSB\\;\\Longleftarrow\\;"); // AMSMath's automatic \dots, based on \mdots@@ macro.
14178
14179const dotsByToken = {
14180  ',': '\\dotsc',
14181  '\\not': '\\dotsb',
14182  // \keybin@ checks for the following:
14183  '+': '\\dotsb',
14184  '=': '\\dotsb',
14185  '<': '\\dotsb',
14186  '>': '\\dotsb',
14187  '-': '\\dotsb',
14188  '*': '\\dotsb',
14189  ':': '\\dotsb',
14190  // Symbols whose definition starts with \DOTSB:
14191  '\\DOTSB': '\\dotsb',
14192  '\\coprod': '\\dotsb',
14193  '\\bigvee': '\\dotsb',
14194  '\\bigwedge': '\\dotsb',
14195  '\\biguplus': '\\dotsb',
14196  '\\bigcap': '\\dotsb',
14197  '\\bigcup': '\\dotsb',
14198  '\\prod': '\\dotsb',
14199  '\\sum': '\\dotsb',
14200  '\\bigotimes': '\\dotsb',
14201  '\\bigoplus': '\\dotsb',
14202  '\\bigodot': '\\dotsb',
14203  '\\bigsqcup': '\\dotsb',
14204  '\\And': '\\dotsb',
14205  '\\longrightarrow': '\\dotsb',
14206  '\\Longrightarrow': '\\dotsb',
14207  '\\longleftarrow': '\\dotsb',
14208  '\\Longleftarrow': '\\dotsb',
14209  '\\longleftrightarrow': '\\dotsb',
14210  '\\Longleftrightarrow': '\\dotsb',
14211  '\\mapsto': '\\dotsb',
14212  '\\longmapsto': '\\dotsb',
14213  '\\hookrightarrow': '\\dotsb',
14214  '\\doteq': '\\dotsb',
14215  // Symbols whose definition starts with \mathbin:
14216  '\\mathbin': '\\dotsb',
14217  // Symbols whose definition starts with \mathrel:
14218  '\\mathrel': '\\dotsb',
14219  '\\relbar': '\\dotsb',
14220  '\\Relbar': '\\dotsb',
14221  '\\xrightarrow': '\\dotsb',
14222  '\\xleftarrow': '\\dotsb',
14223  // Symbols whose definition starts with \DOTSI:
14224  '\\DOTSI': '\\dotsi',
14225  '\\int': '\\dotsi',
14226  '\\oint': '\\dotsi',
14227  '\\iint': '\\dotsi',
14228  '\\iiint': '\\dotsi',
14229  '\\iiiint': '\\dotsi',
14230  '\\idotsint': '\\dotsi',
14231  // Symbols whose definition starts with \DOTSX:
14232  '\\DOTSX': '\\dotsx'
14233};
14234defineMacro("\\dots", function (context) {
14235  // TODO: If used in text mode, should expand to \textellipsis.
14236  // However, in KaTeX, \textellipsis and \ldots behave the same
14237  // (in text mode), and it's unlikely we'd see any of the math commands
14238  // that affect the behavior of \dots when in text mode.  So fine for now
14239  // (until we support \ifmmode ... \else ... \fi).
14240  let thedots = '\\dotso';
14241  const next = context.expandAfterFuture().text;
14242
14243  if (next in dotsByToken) {
14244    thedots = dotsByToken[next];
14245  } else if (next.substr(0, 4) === '\\not') {
14246    thedots = '\\dotsb';
14247  } else if (next in symbols.math) {
14248    if (utils.contains(['bin', 'rel'], symbols.math[next].group)) {
14249      thedots = '\\dotsb';
14250    }
14251  }
14252
14253  return thedots;
14254});
14255const spaceAfterDots = {
14256  // \rightdelim@ checks for the following:
14257  ')': true,
14258  ']': true,
14259  '\\rbrack': true,
14260  '\\}': true,
14261  '\\rbrace': true,
14262  '\\rangle': true,
14263  '\\rceil': true,
14264  '\\rfloor': true,
14265  '\\rgroup': true,
14266  '\\rmoustache': true,
14267  '\\right': true,
14268  '\\bigr': true,
14269  '\\biggr': true,
14270  '\\Bigr': true,
14271  '\\Biggr': true,
14272  // \extra@ also tests for the following:
14273  '$': true,
14274  // \extrap@ checks for the following:
14275  ';': true,
14276  '.': true,
14277  ',': true
14278};
14279defineMacro("\\dotso", function (context) {
14280  const next = context.future().text;
14281
14282  if (next in spaceAfterDots) {
14283    return "\\ldots\\,";
14284  } else {
14285    return "\\ldots";
14286  }
14287});
14288defineMacro("\\dotsc", function (context) {
14289  const next = context.future().text; // \dotsc uses \extra@ but not \extrap@, instead specially checking for
14290  // ';' and '.', but doesn't check for ','.
14291
14292  if (next in spaceAfterDots && next !== ',') {
14293    return "\\ldots\\,";
14294  } else {
14295    return "\\ldots";
14296  }
14297});
14298defineMacro("\\cdots", function (context) {
14299  const next = context.future().text;
14300
14301  if (next in spaceAfterDots) {
14302    return "\\@cdots\\,";
14303  } else {
14304    return "\\@cdots";
14305  }
14306});
14307defineMacro("\\dotsb", "\\cdots");
14308defineMacro("\\dotsm", "\\cdots");
14309defineMacro("\\dotsi", "\\!\\cdots"); // amsmath doesn't actually define \dotsx, but \dots followed by a macro
14310// starting with \DOTSX implies \dotso, and then \extra@ detects this case
14311// and forces the added `\,`.
14312
14313defineMacro("\\dotsx", "\\ldots\\,"); // \let\DOTSI\relax
14314// \let\DOTSB\relax
14315// \let\DOTSX\relax
14316
14317defineMacro("\\DOTSI", "\\relax");
14318defineMacro("\\DOTSB", "\\relax");
14319defineMacro("\\DOTSX", "\\relax"); // Spacing, based on amsmath.sty's override of LaTeX defaults
14320// \DeclareRobustCommand{\tmspace}[3]{%
14321//   \ifmmode\mskip#1#2\else\kern#1#3\fi\relax}
14322
14323defineMacro("\\tmspace", "\\TextOrMath{\\kern#1#3}{\\mskip#1#2}\\relax"); // \renewcommand{\,}{\tmspace+\thinmuskip{.1667em}}
14324// TODO: math mode should use \thinmuskip
14325
14326defineMacro("\\,", "\\tmspace+{3mu}{.1667em}"); // \let\thinspace\,
14327
14328defineMacro("\\thinspace", "\\,"); // \def\>{\mskip\medmuskip}
14329// \renewcommand{\:}{\tmspace+\medmuskip{.2222em}}
14330// TODO: \> and math mode of \: should use \medmuskip = 4mu plus 2mu minus 4mu
14331
14332defineMacro("\\>", "\\mskip{4mu}");
14333defineMacro("\\:", "\\tmspace+{4mu}{.2222em}"); // \let\medspace\:
14334
14335defineMacro("\\medspace", "\\:"); // \renewcommand{\;}{\tmspace+\thickmuskip{.2777em}}
14336// TODO: math mode should use \thickmuskip = 5mu plus 5mu
14337
14338defineMacro("\\;", "\\tmspace+{5mu}{.2777em}"); // \let\thickspace\;
14339
14340defineMacro("\\thickspace", "\\;"); // \renewcommand{\!}{\tmspace-\thinmuskip{.1667em}}
14341// TODO: math mode should use \thinmuskip
14342
14343defineMacro("\\!", "\\tmspace-{3mu}{.1667em}"); // \let\negthinspace\!
14344
14345defineMacro("\\negthinspace", "\\!"); // \newcommand{\negmedspace}{\tmspace-\medmuskip{.2222em}}
14346// TODO: math mode should use \medmuskip
14347
14348defineMacro("\\negmedspace", "\\tmspace-{4mu}{.2222em}"); // \newcommand{\negthickspace}{\tmspace-\thickmuskip{.2777em}}
14349// TODO: math mode should use \thickmuskip
14350
14351defineMacro("\\negthickspace", "\\tmspace-{5mu}{.277em}"); // \def\enspace{\kern.5em }
14352
14353defineMacro("\\enspace", "\\kern.5em "); // \def\enskip{\hskip.5em\relax}
14354
14355defineMacro("\\enskip", "\\hskip.5em\\relax"); // \def\quad{\hskip1em\relax}
14356
14357defineMacro("\\quad", "\\hskip1em\\relax"); // \def\qquad{\hskip2em\relax}
14358
14359defineMacro("\\qquad", "\\hskip2em\\relax"); // \tag@in@display form of \tag
14360
14361defineMacro("\\tag", "\\@ifstar\\tag@literal\\tag@paren");
14362defineMacro("\\tag@paren", "\\tag@literal{({#1})}");
14363defineMacro("\\tag@literal", context => {
14364  if (context.macros.get("\\df@tag")) {
14365    throw new ParseError("Multiple \\tag");
14366  }
14367
14368  return "\\gdef\\df@tag{\\text{#1}}";
14369}); // \renewcommand{\bmod}{\nonscript\mskip-\medmuskip\mkern5mu\mathbin
14370//   {\operator@font mod}\penalty900
14371//   \mkern5mu\nonscript\mskip-\medmuskip}
14372// \newcommand{\pod}[1]{\allowbreak
14373//   \if@display\mkern18mu\else\mkern8mu\fi(#1)}
14374// \renewcommand{\pmod}[1]{\pod{{\operator@font mod}\mkern6mu#1}}
14375// \newcommand{\mod}[1]{\allowbreak\if@display\mkern18mu
14376//   \else\mkern12mu\fi{\operator@font mod}\,\,#1}
14377// TODO: math mode should use \medmuskip = 4mu plus 2mu minus 4mu
14378
14379defineMacro("\\bmod", "\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}" + "\\mathbin{\\rm mod}" + "\\mathchoice{\\mskip1mu}{\\mskip1mu}{\\mskip5mu}{\\mskip5mu}");
14380defineMacro("\\pod", "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern8mu}{\\mkern8mu}{\\mkern8mu}(#1)");
14381defineMacro("\\pmod", "\\pod{{\\rm mod}\\mkern6mu#1}");
14382defineMacro("\\mod", "\\allowbreak" + "\\mathchoice{\\mkern18mu}{\\mkern12mu}{\\mkern12mu}{\\mkern12mu}" + "{\\rm mod}\\,\\,#1"); // \pmb    --   A simulation of bold.
14383// The version in ambsy.sty works by typesetting three copies of the argument
14384// with small offsets. We use two copies. We omit the vertical offset because
14385// of rendering problems that makeVList encounters in Safari.
14386
14387defineMacro("\\pmb", "\\html@mathml{" + "\\@binrel{#1}{\\mathrlap{#1}\\kern0.5px#1}}" + "{\\mathbf{#1}}"); //////////////////////////////////////////////////////////////////////
14388// LaTeX source2e
14389// \\ defaults to \newline, but changes to \cr within array environment
14390
14391defineMacro("\\\\", "\\newline"); // \def\TeX{T\kern-.1667em\lower.5ex\hbox{E}\kern-.125emX\@}
14392// TODO: Doesn't normally work in math mode because \@ fails.  KaTeX doesn't
14393// support \@ yet, so that's omitted, and we add \text so that the result
14394// doesn't look funny in math mode.
14395
14396defineMacro("\\TeX", "\\textrm{\\html@mathml{" + "T\\kern-.1667em\\raisebox{-.5ex}{E}\\kern-.125emX" + "}{TeX}}"); // \DeclareRobustCommand{\LaTeX}{L\kern-.36em%
14397//         {\sbox\z@ T%
14398//          \vbox to\ht\z@{\hbox{\check@mathfonts
14399//                               \fontsize\sf@size\z@
14400//                               \math@fontsfalse\selectfont
14401//                               A}%
14402//                         \vss}%
14403//         }%
14404//         \kern-.15em%
14405//         \TeX}
14406// This code aligns the top of the A with the T (from the perspective of TeX's
14407// boxes, though visually the A appears to extend above slightly).
14408// We compute the corresponding \raisebox when A is rendered in \normalsize
14409// \scriptstyle, which has a scale factor of 0.7 (see Options.js).
14410
14411const latexRaiseA = metricMap['Main-Regular']["T".charCodeAt(0)][1] - 0.7 * metricMap['Main-Regular']["A".charCodeAt(0)][1] + "em";
14412defineMacro("\\LaTeX", "\\textrm{\\html@mathml{" + `L\\kern-.36em\\raisebox{${latexRaiseA}}{\\scriptstyle A}` + "\\kern-.15em\\TeX}{LaTeX}}"); // New KaTeX logo based on tweaking LaTeX logo
14413
14414defineMacro("\\KaTeX", "\\textrm{\\html@mathml{" + `K\\kern-.17em\\raisebox{${latexRaiseA}}{\\scriptstyle A}` + "\\kern-.15em\\TeX}{KaTeX}}"); // \DeclareRobustCommand\hspace{\@ifstar\@hspacer\@hspace}
14415// \def\@hspace#1{\hskip  #1\relax}
14416// \def\@hspacer#1{\vrule \@width\z@\nobreak
14417//                 \hskip #1\hskip \z@skip}
14418
14419defineMacro("\\hspace", "\\@ifstar\\@hspacer\\@hspace");
14420defineMacro("\\@hspace", "\\hskip #1\\relax");
14421defineMacro("\\@hspacer", "\\rule{0pt}{0pt}\\hskip #1\\relax"); //////////////////////////////////////////////////////////////////////
14422// mathtools.sty
14423//\providecommand\ordinarycolon{:}
14424
14425defineMacro("\\ordinarycolon", ":"); //\def\vcentcolon{\mathrel{\mathop\ordinarycolon}}
14426//TODO(edemaine): Not yet centered. Fix via \raisebox or #726
14427
14428defineMacro("\\vcentcolon", "\\mathrel{\\mathop\\ordinarycolon}"); // \providecommand*\dblcolon{\vcentcolon\mathrel{\mkern-.9mu}\vcentcolon}
14429
14430defineMacro("\\dblcolon", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-.9mu}\\vcentcolon}}" + "{\\mathop{\\char\"2237}}"); // \providecommand*\coloneqq{\vcentcolon\mathrel{\mkern-1.2mu}=}
14431
14432defineMacro("\\coloneqq", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}=}}" + "{\\mathop{\\char\"2254}}"); // ≔
14433// \providecommand*\Coloneqq{\dblcolon\mathrel{\mkern-1.2mu}=}
14434
14435defineMacro("\\Coloneqq", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}=}}" + "{\\mathop{\\char\"2237\\char\"3d}}"); // \providecommand*\coloneq{\vcentcolon\mathrel{\mkern-1.2mu}\mathrel{-}}
14436
14437defineMacro("\\coloneq", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}" + "{\\mathop{\\char\"3a\\char\"2212}}"); // \providecommand*\Coloneq{\dblcolon\mathrel{\mkern-1.2mu}\mathrel{-}}
14438
14439defineMacro("\\Coloneq", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\mathrel{-}}}" + "{\\mathop{\\char\"2237\\char\"2212}}"); // \providecommand*\eqqcolon{=\mathrel{\mkern-1.2mu}\vcentcolon}
14440
14441defineMacro("\\eqqcolon", "\\html@mathml{" + "\\mathrel{=\\mathrel{\\mkern-1.2mu}\\vcentcolon}}" + "{\\mathop{\\char\"2255}}"); // ≕
14442// \providecommand*\Eqqcolon{=\mathrel{\mkern-1.2mu}\dblcolon}
14443
14444defineMacro("\\Eqqcolon", "\\html@mathml{" + "\\mathrel{=\\mathrel{\\mkern-1.2mu}\\dblcolon}}" + "{\\mathop{\\char\"3d\\char\"2237}}"); // \providecommand*\eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\vcentcolon}
14445
14446defineMacro("\\eqcolon", "\\html@mathml{" + "\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\vcentcolon}}" + "{\\mathop{\\char\"2239}}"); // \providecommand*\Eqcolon{\mathrel{-}\mathrel{\mkern-1.2mu}\dblcolon}
14447
14448defineMacro("\\Eqcolon", "\\html@mathml{" + "\\mathrel{\\mathrel{-}\\mathrel{\\mkern-1.2mu}\\dblcolon}}" + "{\\mathop{\\char\"2212\\char\"2237}}"); // \providecommand*\colonapprox{\vcentcolon\mathrel{\mkern-1.2mu}\approx}
14449
14450defineMacro("\\colonapprox", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\approx}}" + "{\\mathop{\\char\"3a\\char\"2248}}"); // \providecommand*\Colonapprox{\dblcolon\mathrel{\mkern-1.2mu}\approx}
14451
14452defineMacro("\\Colonapprox", "\\html@mathml{" + "\\mathrel{\\dblcolon\\mathrel{\\mkern-1.2mu}\\approx}}" + "{\\mathop{\\char\"2237\\char\"2248}}"); // \providecommand*\colonsim{\vcentcolon\mathrel{\mkern-1.2mu}\sim}
14453
14454defineMacro("\\colonsim", "\\html@mathml{" + "\\mathrel{\\vcentcolon\\mathrel{\\mkern-1.2mu}\\sim}}" + "{\\mathop{\\char\"3a\\char\"223c}}"); // \providecommand*\Colonsim{\dblcolon\mathrel{\mkern-1.2mu}\sim}
14455
14456defineMacro("\\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.
14457
14458defineMacro("\u2237", "\\dblcolon"); // ::
14459
14460defineMacro("\u2239", "\\eqcolon"); // -:
14461
14462defineMacro("\u2254", "\\coloneqq"); // :=
14463
14464defineMacro("\u2255", "\\eqqcolon"); // =:
14465
14466defineMacro("\u2A74", "\\Coloneqq"); // ::=
14467//////////////////////////////////////////////////////////////////////
14468// colonequals.sty
14469// Alternate names for mathtools's macros:
14470
14471defineMacro("\\ratio", "\\vcentcolon");
14472defineMacro("\\coloncolon", "\\dblcolon");
14473defineMacro("\\colonequals", "\\coloneqq");
14474defineMacro("\\coloncolonequals", "\\Coloneqq");
14475defineMacro("\\equalscolon", "\\eqqcolon");
14476defineMacro("\\equalscoloncolon", "\\Eqqcolon");
14477defineMacro("\\colonminus", "\\coloneq");
14478defineMacro("\\coloncolonminus", "\\Coloneq");
14479defineMacro("\\minuscolon", "\\eqcolon");
14480defineMacro("\\minuscoloncolon", "\\Eqcolon"); // \colonapprox name is same in mathtools and colonequals.
14481
14482defineMacro("\\coloncolonapprox", "\\Colonapprox"); // \colonsim name is same in mathtools and colonequals.
14483
14484defineMacro("\\coloncolonsim", "\\Colonsim"); // Additional macros, implemented by analogy with mathtools definitions:
14485
14486defineMacro("\\simcolon", "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\vcentcolon}");
14487defineMacro("\\simcoloncolon", "\\mathrel{\\sim\\mathrel{\\mkern-1.2mu}\\dblcolon}");
14488defineMacro("\\approxcolon", "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\vcentcolon}");
14489defineMacro("\\approxcoloncolon", "\\mathrel{\\approx\\mathrel{\\mkern-1.2mu}\\dblcolon}"); // Present in newtxmath, pxfonts and txfonts
14490
14491defineMacro("\\notni", "\\html@mathml{\\not\\ni}{\\mathrel{\\char`\u220C}}");
14492defineMacro("\\limsup", "\\DOTSB\\operatorname*{lim\\,sup}");
14493defineMacro("\\liminf", "\\DOTSB\\operatorname*{lim\\,inf}"); //////////////////////////////////////////////////////////////////////
14494// MathML alternates for KaTeX glyphs in the Unicode private area
14495
14496defineMacro("\\gvertneqq", "\\html@mathml{\\@gvertneqq}{\u2269}");
14497defineMacro("\\lvertneqq", "\\html@mathml{\\@lvertneqq}{\u2268}");
14498defineMacro("\\ngeqq", "\\html@mathml{\\@ngeqq}{\u2271}");
14499defineMacro("\\ngeqslant", "\\html@mathml{\\@ngeqslant}{\u2271}");
14500defineMacro("\\nleqq", "\\html@mathml{\\@nleqq}{\u2270}");
14501defineMacro("\\nleqslant", "\\html@mathml{\\@nleqslant}{\u2270}");
14502defineMacro("\\nshortmid", "\\html@mathml{\\@nshortmid}{∤}");
14503defineMacro("\\nshortparallel", "\\html@mathml{\\@nshortparallel}{∦}");
14504defineMacro("\\nsubseteqq", "\\html@mathml{\\@nsubseteqq}{\u2288}");
14505defineMacro("\\nsupseteqq", "\\html@mathml{\\@nsupseteqq}{\u2289}");
14506defineMacro("\\varsubsetneq", "\\html@mathml{\\@varsubsetneq}{⊊}");
14507defineMacro("\\varsubsetneqq", "\\html@mathml{\\@varsubsetneqq}{⫋}");
14508defineMacro("\\varsupsetneq", "\\html@mathml{\\@varsupsetneq}{⊋}");
14509defineMacro("\\varsupsetneqq", "\\html@mathml{\\@varsupsetneqq}{⫌}"); //////////////////////////////////////////////////////////////////////
14510// stmaryrd and semantic
14511// The stmaryrd and semantic packages render the next four items by calling a
14512// glyph. Those glyphs do not exist in the KaTeX fonts. Hence the macros.
14513
14514defineMacro("\\llbracket", "\\html@mathml{" + "\\mathopen{[\\mkern-3.2mu[}}" + "{\\mathopen{\\char`\u27e6}}");
14515defineMacro("\\rrbracket", "\\html@mathml{" + "\\mathclose{]\\mkern-3.2mu]}}" + "{\\mathclose{\\char`\u27e7}}");
14516defineMacro("\u27e6", "\\llbracket"); // blackboard bold [
14517
14518defineMacro("\u27e7", "\\rrbracket"); // blackboard bold ]
14519
14520defineMacro("\\lBrace", "\\html@mathml{" + "\\mathopen{\\{\\mkern-3.2mu[}}" + "{\\mathopen{\\char`\u2983}}");
14521defineMacro("\\rBrace", "\\html@mathml{" + "\\mathclose{]\\mkern-3.2mu\\}}}" + "{\\mathclose{\\char`\u2984}}");
14522defineMacro("\u2983", "\\lBrace"); // blackboard bold {
14523
14524defineMacro("\u2984", "\\rBrace"); // blackboard bold }
14525// TODO: Create variable sized versions of the last two items. I believe that
14526// will require new font glyphs.
14527//////////////////////////////////////////////////////////////////////
14528// texvc.sty
14529// The texvc package contains macros available in mediawiki pages.
14530// We omit the functions deprecated at
14531// https://en.wikipedia.org/wiki/Help:Displaying_a_formula#Deprecated_syntax
14532// We also omit texvc's \O, which conflicts with \text{\O}
14533
14534defineMacro("\\darr", "\\downarrow");
14535defineMacro("\\dArr", "\\Downarrow");
14536defineMacro("\\Darr", "\\Downarrow");
14537defineMacro("\\lang", "\\langle");
14538defineMacro("\\rang", "\\rangle");
14539defineMacro("\\uarr", "\\uparrow");
14540defineMacro("\\uArr", "\\Uparrow");
14541defineMacro("\\Uarr", "\\Uparrow");
14542defineMacro("\\N", "\\mathbb{N}");
14543defineMacro("\\R", "\\mathbb{R}");
14544defineMacro("\\Z", "\\mathbb{Z}");
14545defineMacro("\\alef", "\\aleph");
14546defineMacro("\\alefsym", "\\aleph");
14547defineMacro("\\Alpha", "\\mathrm{A}");
14548defineMacro("\\Beta", "\\mathrm{B}");
14549defineMacro("\\bull", "\\bullet");
14550defineMacro("\\Chi", "\\mathrm{X}");
14551defineMacro("\\clubs", "\\clubsuit");
14552defineMacro("\\cnums", "\\mathbb{C}");
14553defineMacro("\\Complex", "\\mathbb{C}");
14554defineMacro("\\Dagger", "\\ddagger");
14555defineMacro("\\diamonds", "\\diamondsuit");
14556defineMacro("\\empty", "\\emptyset");
14557defineMacro("\\Epsilon", "\\mathrm{E}");
14558defineMacro("\\Eta", "\\mathrm{H}");
14559defineMacro("\\exist", "\\exists");
14560defineMacro("\\harr", "\\leftrightarrow");
14561defineMacro("\\hArr", "\\Leftrightarrow");
14562defineMacro("\\Harr", "\\Leftrightarrow");
14563defineMacro("\\hearts", "\\heartsuit");
14564defineMacro("\\image", "\\Im");
14565defineMacro("\\infin", "\\infty");
14566defineMacro("\\Iota", "\\mathrm{I}");
14567defineMacro("\\isin", "\\in");
14568defineMacro("\\Kappa", "\\mathrm{K}");
14569defineMacro("\\larr", "\\leftarrow");
14570defineMacro("\\lArr", "\\Leftarrow");
14571defineMacro("\\Larr", "\\Leftarrow");
14572defineMacro("\\lrarr", "\\leftrightarrow");
14573defineMacro("\\lrArr", "\\Leftrightarrow");
14574defineMacro("\\Lrarr", "\\Leftrightarrow");
14575defineMacro("\\Mu", "\\mathrm{M}");
14576defineMacro("\\natnums", "\\mathbb{N}");
14577defineMacro("\\Nu", "\\mathrm{N}");
14578defineMacro("\\Omicron", "\\mathrm{O}");
14579defineMacro("\\plusmn", "\\pm");
14580defineMacro("\\rarr", "\\rightarrow");
14581defineMacro("\\rArr", "\\Rightarrow");
14582defineMacro("\\Rarr", "\\Rightarrow");
14583defineMacro("\\real", "\\Re");
14584defineMacro("\\reals", "\\mathbb{R}");
14585defineMacro("\\Reals", "\\mathbb{R}");
14586defineMacro("\\Rho", "\\mathrm{P}");
14587defineMacro("\\sdot", "\\cdot");
14588defineMacro("\\sect", "\\S");
14589defineMacro("\\spades", "\\spadesuit");
14590defineMacro("\\sub", "\\subset");
14591defineMacro("\\sube", "\\subseteq");
14592defineMacro("\\supe", "\\supseteq");
14593defineMacro("\\Tau", "\\mathrm{T}");
14594defineMacro("\\thetasym", "\\vartheta"); // TODO: defineMacro("\\varcoppa", "\\\mbox{\\coppa}");
14595
14596defineMacro("\\weierp", "\\wp");
14597defineMacro("\\Zeta", "\\mathrm{Z}"); //////////////////////////////////////////////////////////////////////
14598// statmath.sty
14599// https://ctan.math.illinois.edu/macros/latex/contrib/statmath/statmath.pdf
14600
14601defineMacro("\\argmin", "\\DOTSB\\operatorname*{arg\\,min}");
14602defineMacro("\\argmax", "\\DOTSB\\operatorname*{arg\\,max}");
14603defineMacro("\\plim", "\\DOTSB\\mathop{\\operatorname{plim}}\\limits"); // Custom Khan Academy colors, should be moved to an optional package
14604
14605defineMacro("\\blue", "\\textcolor{##6495ed}{#1}");
14606defineMacro("\\orange", "\\textcolor{##ffa500}{#1}");
14607defineMacro("\\pink", "\\textcolor{##ff00af}{#1}");
14608defineMacro("\\red", "\\textcolor{##df0030}{#1}");
14609defineMacro("\\green", "\\textcolor{##28ae7b}{#1}");
14610defineMacro("\\gray", "\\textcolor{gray}{#1}");
14611defineMacro("\\purple", "\\textcolor{##9d38bd}{#1}");
14612defineMacro("\\blueA", "\\textcolor{##ccfaff}{#1}");
14613defineMacro("\\blueB", "\\textcolor{##80f6ff}{#1}");
14614defineMacro("\\blueC", "\\textcolor{##63d9ea}{#1}");
14615defineMacro("\\blueD", "\\textcolor{##11accd}{#1}");
14616defineMacro("\\blueE", "\\textcolor{##0c7f99}{#1}");
14617defineMacro("\\tealA", "\\textcolor{##94fff5}{#1}");
14618defineMacro("\\tealB", "\\textcolor{##26edd5}{#1}");
14619defineMacro("\\tealC", "\\textcolor{##01d1c1}{#1}");
14620defineMacro("\\tealD", "\\textcolor{##01a995}{#1}");
14621defineMacro("\\tealE", "\\textcolor{##208170}{#1}");
14622defineMacro("\\greenA", "\\textcolor{##b6ffb0}{#1}");
14623defineMacro("\\greenB", "\\textcolor{##8af281}{#1}");
14624defineMacro("\\greenC", "\\textcolor{##74cf70}{#1}");
14625defineMacro("\\greenD", "\\textcolor{##1fab54}{#1}");
14626defineMacro("\\greenE", "\\textcolor{##0d923f}{#1}");
14627defineMacro("\\goldA", "\\textcolor{##ffd0a9}{#1}");
14628defineMacro("\\goldB", "\\textcolor{##ffbb71}{#1}");
14629defineMacro("\\goldC", "\\textcolor{##ff9c39}{#1}");
14630defineMacro("\\goldD", "\\textcolor{##e07d10}{#1}");
14631defineMacro("\\goldE", "\\textcolor{##a75a05}{#1}");
14632defineMacro("\\redA", "\\textcolor{##fca9a9}{#1}");
14633defineMacro("\\redB", "\\textcolor{##ff8482}{#1}");
14634defineMacro("\\redC", "\\textcolor{##f9685d}{#1}");
14635defineMacro("\\redD", "\\textcolor{##e84d39}{#1}");
14636defineMacro("\\redE", "\\textcolor{##bc2612}{#1}");
14637defineMacro("\\maroonA", "\\textcolor{##ffbde0}{#1}");
14638defineMacro("\\maroonB", "\\textcolor{##ff92c6}{#1}");
14639defineMacro("\\maroonC", "\\textcolor{##ed5fa6}{#1}");
14640defineMacro("\\maroonD", "\\textcolor{##ca337c}{#1}");
14641defineMacro("\\maroonE", "\\textcolor{##9e034e}{#1}");
14642defineMacro("\\purpleA", "\\textcolor{##ddd7ff}{#1}");
14643defineMacro("\\purpleB", "\\textcolor{##c6b9fc}{#1}");
14644defineMacro("\\purpleC", "\\textcolor{##aa87ff}{#1}");
14645defineMacro("\\purpleD", "\\textcolor{##7854ab}{#1}");
14646defineMacro("\\purpleE", "\\textcolor{##543b78}{#1}");
14647defineMacro("\\mintA", "\\textcolor{##f5f9e8}{#1}");
14648defineMacro("\\mintB", "\\textcolor{##edf2df}{#1}");
14649defineMacro("\\mintC", "\\textcolor{##e0e5cc}{#1}");
14650defineMacro("\\grayA", "\\textcolor{##f6f7f7}{#1}");
14651defineMacro("\\grayB", "\\textcolor{##f0f1f2}{#1}");
14652defineMacro("\\grayC", "\\textcolor{##e3e5e6}{#1}");
14653defineMacro("\\grayD", "\\textcolor{##d6d8da}{#1}");
14654defineMacro("\\grayE", "\\textcolor{##babec2}{#1}");
14655defineMacro("\\grayF", "\\textcolor{##888d93}{#1}");
14656defineMacro("\\grayG", "\\textcolor{##626569}{#1}");
14657defineMacro("\\grayH", "\\textcolor{##3b3e40}{#1}");
14658defineMacro("\\grayI", "\\textcolor{##21242c}{#1}");
14659defineMacro("\\kaBlue", "\\textcolor{##314453}{#1}");
14660defineMacro("\\kaGreen", "\\textcolor{##71B307}{#1}");
14661
14662/**
14663 * This file contains the “gullet” where macros are expanded
14664 * until only non-macro tokens remain.
14665 */
14666// List of commands that act like macros but aren't defined as a macro,
14667// function, or symbol.  Used in `isDefined`.
14668const implicitCommands = {
14669  "\\relax": true,
14670  // MacroExpander.js
14671  "^": true,
14672  // Parser.js
14673  "_": true,
14674  // Parser.js
14675  "\\limits": true,
14676  // Parser.js
14677  "\\nolimits": true // Parser.js
14678
14679};
14680class MacroExpander {
14681  constructor(input, settings, mode) {
14682    this.settings = void 0;
14683    this.expansionCount = void 0;
14684    this.lexer = void 0;
14685    this.macros = void 0;
14686    this.stack = void 0;
14687    this.mode = void 0;
14688    this.settings = settings;
14689    this.expansionCount = 0;
14690    this.feed(input); // Make new global namespace
14691
14692    this.macros = new Namespace(builtinMacros, settings.macros);
14693    this.mode = mode;
14694    this.stack = []; // contains tokens in REVERSE order
14695  }
14696  /**
14697   * Feed a new input string to the same MacroExpander
14698   * (with existing macros etc.).
14699   */
14700
14701
14702  feed(input) {
14703    this.lexer = new Lexer(input, this.settings);
14704  }
14705  /**
14706   * Switches between "text" and "math" modes.
14707   */
14708
14709
14710  switchMode(newMode) {
14711    this.mode = newMode;
14712  }
14713  /**
14714   * Start a new group nesting within all namespaces.
14715   */
14716
14717
14718  beginGroup() {
14719    this.macros.beginGroup();
14720  }
14721  /**
14722   * End current group nesting within all namespaces.
14723   */
14724
14725
14726  endGroup() {
14727    this.macros.endGroup();
14728  }
14729  /**
14730   * Returns the topmost token on the stack, without expanding it.
14731   * Similar in behavior to TeX's `\futurelet`.
14732   */
14733
14734
14735  future() {
14736    if (this.stack.length === 0) {
14737      this.pushToken(this.lexer.lex());
14738    }
14739
14740    return this.stack[this.stack.length - 1];
14741  }
14742  /**
14743   * Remove and return the next unexpanded token.
14744   */
14745
14746
14747  popToken() {
14748    this.future(); // ensure non-empty stack
14749
14750    return this.stack.pop();
14751  }
14752  /**
14753   * Add a given token to the token stack.  In particular, this get be used
14754   * to put back a token returned from one of the other methods.
14755   */
14756
14757
14758  pushToken(token) {
14759    this.stack.push(token);
14760  }
14761  /**
14762   * Append an array of tokens to the token stack.
14763   */
14764
14765
14766  pushTokens(tokens) {
14767    this.stack.push(...tokens);
14768  }
14769  /**
14770   * Consume all following space tokens, without expansion.
14771   */
14772
14773
14774  consumeSpaces() {
14775    for (;;) {
14776      const token = this.future();
14777
14778      if (token.text === " ") {
14779        this.stack.pop();
14780      } else {
14781        break;
14782      }
14783    }
14784  }
14785  /**
14786   * Consume the specified number of arguments from the token stream,
14787   * and return the resulting array of arguments.
14788   */
14789
14790
14791  consumeArgs(numArgs) {
14792    const args = []; // obtain arguments, either single token or balanced {…} group
14793
14794    for (let i = 0; i < numArgs; ++i) {
14795      this.consumeSpaces(); // ignore spaces before each argument
14796
14797      const startOfArg = this.popToken();
14798
14799      if (startOfArg.text === "{") {
14800        const arg = [];
14801        let depth = 1;
14802
14803        while (depth !== 0) {
14804          const tok = this.popToken();
14805          arg.push(tok);
14806
14807          if (tok.text === "{") {
14808            ++depth;
14809          } else if (tok.text === "}") {
14810            --depth;
14811          } else if (tok.text === "EOF") {
14812            throw new ParseError("End of input in macro argument", startOfArg);
14813          }
14814        }
14815
14816        arg.pop(); // remove last }
14817
14818        arg.reverse(); // like above, to fit in with stack order
14819
14820        args[i] = arg;
14821      } else if (startOfArg.text === "EOF") {
14822        throw new ParseError("End of input expecting macro argument");
14823      } else {
14824        args[i] = [startOfArg];
14825      }
14826    }
14827
14828    return args;
14829  }
14830  /**
14831   * Expand the next token only once if possible.
14832   *
14833   * If the token is expanded, the resulting tokens will be pushed onto
14834   * the stack in reverse order and will be returned as an array,
14835   * also in reverse order.
14836   *
14837   * If not, the next token will be returned without removing it
14838   * from the stack.  This case can be detected by a `Token` return value
14839   * instead of an `Array` return value.
14840   *
14841   * In either case, the next token will be on the top of the stack,
14842   * or the stack will be empty.
14843   *
14844   * Used to implement `expandAfterFuture` and `expandNextToken`.
14845   *
14846   * At the moment, macro expansion doesn't handle delimited macros,
14847   * i.e. things like those defined by \def\foo#1\end{…}.
14848   * See the TeX book page 202ff. for details on how those should behave.
14849   */
14850
14851
14852  expandOnce() {
14853    const topToken = this.popToken();
14854    const name = topToken.text;
14855
14856    const expansion = this._getExpansion(name);
14857
14858    if (expansion == null) {
14859      // mainly checking for undefined here
14860      // Fully expanded
14861      this.pushToken(topToken);
14862      return topToken;
14863    }
14864
14865    this.expansionCount++;
14866
14867    if (this.expansionCount > this.settings.maxExpand) {
14868      throw new ParseError("Too many expansions: infinite loop or " + "need to increase maxExpand setting");
14869    }
14870
14871    let tokens = expansion.tokens;
14872
14873    if (expansion.numArgs) {
14874      const args = this.consumeArgs(expansion.numArgs); // paste arguments in place of the placeholders
14875
14876      tokens = tokens.slice(); // make a shallow copy
14877
14878      for (let i = tokens.length - 1; i >= 0; --i) {
14879        let tok = tokens[i];
14880
14881        if (tok.text === "#") {
14882          if (i === 0) {
14883            throw new ParseError("Incomplete placeholder at end of macro body", tok);
14884          }
14885
14886          tok = tokens[--i]; // next token on stack
14887
14888          if (tok.text === "#") {
14889            // ## → #
14890            tokens.splice(i + 1, 1); // drop first #
14891          } else if (/^[1-9]$/.test(tok.text)) {
14892            // replace the placeholder with the indicated argument
14893            tokens.splice(i, 2, ...args[+tok.text - 1]);
14894          } else {
14895            throw new ParseError("Not a valid argument number", tok);
14896          }
14897        }
14898      }
14899    } // Concatenate expansion onto top of stack.
14900
14901
14902    this.pushTokens(tokens);
14903    return tokens;
14904  }
14905  /**
14906   * Expand the next token only once (if possible), and return the resulting
14907   * top token on the stack (without removing anything from the stack).
14908   * Similar in behavior to TeX's `\expandafter\futurelet`.
14909   * Equivalent to expandOnce() followed by future().
14910   */
14911
14912
14913  expandAfterFuture() {
14914    this.expandOnce();
14915    return this.future();
14916  }
14917  /**
14918   * Recursively expand first token, then return first non-expandable token.
14919   */
14920
14921
14922  expandNextToken() {
14923    for (;;) {
14924      const expanded = this.expandOnce(); // expandOnce returns Token if and only if it's fully expanded.
14925
14926      if (expanded instanceof Token) {
14927        // \relax stops the expansion, but shouldn't get returned (a
14928        // null return value couldn't get implemented as a function).
14929        if (expanded.text === "\\relax") {
14930          this.stack.pop();
14931        } else {
14932          return this.stack.pop(); // === expanded
14933        }
14934      }
14935    } // Flow unable to figure out that this pathway is impossible.
14936    // https://github.com/facebook/flow/issues/4808
14937
14938
14939    throw new Error(); // eslint-disable-line no-unreachable
14940  }
14941  /**
14942   * Fully expand the given macro name and return the resulting list of
14943   * tokens, or return `undefined` if no such macro is defined.
14944   */
14945
14946
14947  expandMacro(name) {
14948    if (!this.macros.get(name)) {
14949      return undefined;
14950    }
14951
14952    const output = [];
14953    const oldStackLength = this.stack.length;
14954    this.pushToken(new Token(name));
14955
14956    while (this.stack.length > oldStackLength) {
14957      const expanded = this.expandOnce(); // expandOnce returns Token if and only if it's fully expanded.
14958
14959      if (expanded instanceof Token) {
14960        output.push(this.stack.pop());
14961      }
14962    }
14963
14964    return output;
14965  }
14966  /**
14967   * Fully expand the given macro name and return the result as a string,
14968   * or return `undefined` if no such macro is defined.
14969   */
14970
14971
14972  expandMacroAsText(name) {
14973    const tokens = this.expandMacro(name);
14974
14975    if (tokens) {
14976      return tokens.map(token => token.text).join("");
14977    } else {
14978      return tokens;
14979    }
14980  }
14981  /**
14982   * Returns the expanded macro as a reversed array of tokens and a macro
14983   * argument count.  Or returns `null` if no such macro.
14984   */
14985
14986
14987  _getExpansion(name) {
14988    const definition = this.macros.get(name);
14989
14990    if (definition == null) {
14991      // mainly checking for undefined here
14992      return definition;
14993    }
14994
14995    const expansion = typeof definition === "function" ? definition(this) : definition;
14996
14997    if (typeof expansion === "string") {
14998      let numArgs = 0;
14999
15000      if (expansion.indexOf("#") !== -1) {
15001        const stripped = expansion.replace(/##/g, "");
15002
15003        while (stripped.indexOf("#" + (numArgs + 1)) !== -1) {
15004          ++numArgs;
15005        }
15006      }
15007
15008      const bodyLexer = new Lexer(expansion, this.settings);
15009      const tokens = [];
15010      let tok = bodyLexer.lex();
15011
15012      while (tok.text !== "EOF") {
15013        tokens.push(tok);
15014        tok = bodyLexer.lex();
15015      }
15016
15017      tokens.reverse(); // to fit in with stack using push and pop
15018
15019      const expanded = {
15020        tokens,
15021        numArgs
15022      };
15023      return expanded;
15024    }
15025
15026    return expansion;
15027  }
15028  /**
15029   * Determine whether a command is currently "defined" (has some
15030   * functionality), meaning that it's a macro (in the current group),
15031   * a function, a symbol, or one of the special commands listed in
15032   * `implicitCommands`.
15033   */
15034
15035
15036  isDefined(name) {
15037    return this.macros.has(name) || functions.hasOwnProperty(name) || symbols.math.hasOwnProperty(name) || symbols.text.hasOwnProperty(name) || implicitCommands.hasOwnProperty(name);
15038  }
15039
15040}
15041
15042// Mapping of Unicode accent characters to their LaTeX equivalent in text and
15043// math mode (when they exist).
15044var unicodeAccents = {
15045  '\u0301': {
15046    text: "\\'",
15047    math: '\\acute'
15048  },
15049  '\u0300': {
15050    text: '\\`',
15051    math: '\\grave'
15052  },
15053  '\u0308': {
15054    text: '\\"',
15055    math: '\\ddot'
15056  },
15057  '\u0303': {
15058    text: '\\~',
15059    math: '\\tilde'
15060  },
15061  '\u0304': {
15062    text: '\\=',
15063    math: '\\bar'
15064  },
15065  '\u0306': {
15066    text: '\\u',
15067    math: '\\breve'
15068  },
15069  '\u030c': {
15070    text: '\\v',
15071    math: '\\check'
15072  },
15073  '\u0302': {
15074    text: '\\^',
15075    math: '\\hat'
15076  },
15077  '\u0307': {
15078    text: '\\.',
15079    math: '\\dot'
15080  },
15081  '\u030a': {
15082    text: '\\r',
15083    math: '\\mathring'
15084  },
15085  '\u030b': {
15086    text: '\\H'
15087  }
15088};
15089
15090// This file is GENERATED by unicodeMake.js. DO NOT MODIFY.
15091var unicodeSymbols = {
15092  "\u00e1": "\u0061\u0301",
15093  // á = \'{a}
15094  "\u00e0": "\u0061\u0300",
15095  // à = \`{a}
15096  "\u00e4": "\u0061\u0308",
15097  // ä = \"{a}
15098  "\u01df": "\u0061\u0308\u0304",
15099  // ǟ = \"\={a}
15100  "\u00e3": "\u0061\u0303",
15101  // ã = \~{a}
15102  "\u0101": "\u0061\u0304",
15103  // ā = \={a}
15104  "\u0103": "\u0061\u0306",
15105  // ă = \u{a}
15106  "\u1eaf": "\u0061\u0306\u0301",
15107  // ắ = \u\'{a}
15108  "\u1eb1": "\u0061\u0306\u0300",
15109  // ằ = \u\`{a}
15110  "\u1eb5": "\u0061\u0306\u0303",
15111  // ẵ = \u\~{a}
15112  "\u01ce": "\u0061\u030c",
15113  // ǎ = \v{a}
15114  "\u00e2": "\u0061\u0302",
15115  // â = \^{a}
15116  "\u1ea5": "\u0061\u0302\u0301",
15117  // ấ = \^\'{a}
15118  "\u1ea7": "\u0061\u0302\u0300",
15119  // ầ = \^\`{a}
15120  "\u1eab": "\u0061\u0302\u0303",
15121  // ẫ = \^\~{a}
15122  "\u0227": "\u0061\u0307",
15123  // ȧ = \.{a}
15124  "\u01e1": "\u0061\u0307\u0304",
15125  // ǡ = \.\={a}
15126  "\u00e5": "\u0061\u030a",
15127  // å = \r{a}
15128  "\u01fb": "\u0061\u030a\u0301",
15129  // ǻ = \r\'{a}
15130  "\u1e03": "\u0062\u0307",
15131  // ḃ = \.{b}
15132  "\u0107": "\u0063\u0301",
15133  // ć = \'{c}
15134  "\u010d": "\u0063\u030c",
15135  // č = \v{c}
15136  "\u0109": "\u0063\u0302",
15137  // ĉ = \^{c}
15138  "\u010b": "\u0063\u0307",
15139  // ċ = \.{c}
15140  "\u010f": "\u0064\u030c",
15141  // ď = \v{d}
15142  "\u1e0b": "\u0064\u0307",
15143  // ḋ = \.{d}
15144  "\u00e9": "\u0065\u0301",
15145  // é = \'{e}
15146  "\u00e8": "\u0065\u0300",
15147  // è = \`{e}
15148  "\u00eb": "\u0065\u0308",
15149  // ë = \"{e}
15150  "\u1ebd": "\u0065\u0303",
15151  // ẽ = \~{e}
15152  "\u0113": "\u0065\u0304",
15153  // ē = \={e}
15154  "\u1e17": "\u0065\u0304\u0301",
15155  // ḗ = \=\'{e}
15156  "\u1e15": "\u0065\u0304\u0300",
15157  // ḕ = \=\`{e}
15158  "\u0115": "\u0065\u0306",
15159  // ĕ = \u{e}
15160  "\u011b": "\u0065\u030c",
15161  // ě = \v{e}
15162  "\u00ea": "\u0065\u0302",
15163  // ê = \^{e}
15164  "\u1ebf": "\u0065\u0302\u0301",
15165  // ế = \^\'{e}
15166  "\u1ec1": "\u0065\u0302\u0300",
15167  // ề = \^\`{e}
15168  "\u1ec5": "\u0065\u0302\u0303",
15169  // ễ = \^\~{e}
15170  "\u0117": "\u0065\u0307",
15171  // ė = \.{e}
15172  "\u1e1f": "\u0066\u0307",
15173  // ḟ = \.{f}
15174  "\u01f5": "\u0067\u0301",
15175  // ǵ = \'{g}
15176  "\u1e21": "\u0067\u0304",
15177  // ḡ = \={g}
15178  "\u011f": "\u0067\u0306",
15179  // ğ = \u{g}
15180  "\u01e7": "\u0067\u030c",
15181  // ǧ = \v{g}
15182  "\u011d": "\u0067\u0302",
15183  // ĝ = \^{g}
15184  "\u0121": "\u0067\u0307",
15185  // ġ = \.{g}
15186  "\u1e27": "\u0068\u0308",
15187  // ḧ = \"{h}
15188  "\u021f": "\u0068\u030c",
15189  // ȟ = \v{h}
15190  "\u0125": "\u0068\u0302",
15191  // ĥ = \^{h}
15192  "\u1e23": "\u0068\u0307",
15193  // ḣ = \.{h}
15194  "\u00ed": "\u0069\u0301",
15195  // í = \'{i}
15196  "\u00ec": "\u0069\u0300",
15197  // ì = \`{i}
15198  "\u00ef": "\u0069\u0308",
15199  // ï = \"{i}
15200  "\u1e2f": "\u0069\u0308\u0301",
15201  // ḯ = \"\'{i}
15202  "\u0129": "\u0069\u0303",
15203  // ĩ = \~{i}
15204  "\u012b": "\u0069\u0304",
15205  // ī = \={i}
15206  "\u012d": "\u0069\u0306",
15207  // ĭ = \u{i}
15208  "\u01d0": "\u0069\u030c",
15209  // ǐ = \v{i}
15210  "\u00ee": "\u0069\u0302",
15211  // î = \^{i}
15212  "\u01f0": "\u006a\u030c",
15213  // ǰ = \v{j}
15214  "\u0135": "\u006a\u0302",
15215  // ĵ = \^{j}
15216  "\u1e31": "\u006b\u0301",
15217  // ḱ = \'{k}
15218  "\u01e9": "\u006b\u030c",
15219  // ǩ = \v{k}
15220  "\u013a": "\u006c\u0301",
15221  // ĺ = \'{l}
15222  "\u013e": "\u006c\u030c",
15223  // ľ = \v{l}
15224  "\u1e3f": "\u006d\u0301",
15225  // ḿ = \'{m}
15226  "\u1e41": "\u006d\u0307",
15227  // ṁ = \.{m}
15228  "\u0144": "\u006e\u0301",
15229  // ń = \'{n}
15230  "\u01f9": "\u006e\u0300",
15231  // ǹ = \`{n}
15232  "\u00f1": "\u006e\u0303",
15233  // ñ = \~{n}
15234  "\u0148": "\u006e\u030c",
15235  // ň = \v{n}
15236  "\u1e45": "\u006e\u0307",
15237  // ṅ = \.{n}
15238  "\u00f3": "\u006f\u0301",
15239  // ó = \'{o}
15240  "\u00f2": "\u006f\u0300",
15241  // ò = \`{o}
15242  "\u00f6": "\u006f\u0308",
15243  // ö = \"{o}
15244  "\u022b": "\u006f\u0308\u0304",
15245  // ȫ = \"\={o}
15246  "\u00f5": "\u006f\u0303",
15247  // õ = \~{o}
15248  "\u1e4d": "\u006f\u0303\u0301",
15249  // ṍ = \~\'{o}
15250  "\u1e4f": "\u006f\u0303\u0308",
15251  // ṏ = \~\"{o}
15252  "\u022d": "\u006f\u0303\u0304",
15253  // ȭ = \~\={o}
15254  "\u014d": "\u006f\u0304",
15255  // ō = \={o}
15256  "\u1e53": "\u006f\u0304\u0301",
15257  // ṓ = \=\'{o}
15258  "\u1e51": "\u006f\u0304\u0300",
15259  // ṑ = \=\`{o}
15260  "\u014f": "\u006f\u0306",
15261  // ŏ = \u{o}
15262  "\u01d2": "\u006f\u030c",
15263  // ǒ = \v{o}
15264  "\u00f4": "\u006f\u0302",
15265  // ô = \^{o}
15266  "\u1ed1": "\u006f\u0302\u0301",
15267  // ố = \^\'{o}
15268  "\u1ed3": "\u006f\u0302\u0300",
15269  // ồ = \^\`{o}
15270  "\u1ed7": "\u006f\u0302\u0303",
15271  // ỗ = \^\~{o}
15272  "\u022f": "\u006f\u0307",
15273  // ȯ = \.{o}
15274  "\u0231": "\u006f\u0307\u0304",
15275  // ȱ = \.\={o}
15276  "\u0151": "\u006f\u030b",
15277  // ő = \H{o}
15278  "\u1e55": "\u0070\u0301",
15279  // ṕ = \'{p}
15280  "\u1e57": "\u0070\u0307",
15281  // ṗ = \.{p}
15282  "\u0155": "\u0072\u0301",
15283  // ŕ = \'{r}
15284  "\u0159": "\u0072\u030c",
15285  // ř = \v{r}
15286  "\u1e59": "\u0072\u0307",
15287  // ṙ = \.{r}
15288  "\u015b": "\u0073\u0301",
15289  // ś = \'{s}
15290  "\u1e65": "\u0073\u0301\u0307",
15291  // ṥ = \'\.{s}
15292  "\u0161": "\u0073\u030c",
15293  // š = \v{s}
15294  "\u1e67": "\u0073\u030c\u0307",
15295  // ṧ = \v\.{s}
15296  "\u015d": "\u0073\u0302",
15297  // ŝ = \^{s}
15298  "\u1e61": "\u0073\u0307",
15299  // ṡ = \.{s}
15300  "\u1e97": "\u0074\u0308",
15301  // ẗ = \"{t}
15302  "\u0165": "\u0074\u030c",
15303  // ť = \v{t}
15304  "\u1e6b": "\u0074\u0307",
15305  // ṫ = \.{t}
15306  "\u00fa": "\u0075\u0301",
15307  // ú = \'{u}
15308  "\u00f9": "\u0075\u0300",
15309  // ù = \`{u}
15310  "\u00fc": "\u0075\u0308",
15311  // ü = \"{u}
15312  "\u01d8": "\u0075\u0308\u0301",
15313  // ǘ = \"\'{u}
15314  "\u01dc": "\u0075\u0308\u0300",
15315  // ǜ = \"\`{u}
15316  "\u01d6": "\u0075\u0308\u0304",
15317  // ǖ = \"\={u}
15318  "\u01da": "\u0075\u0308\u030c",
15319  // ǚ = \"\v{u}
15320  "\u0169": "\u0075\u0303",
15321  // ũ = \~{u}
15322  "\u1e79": "\u0075\u0303\u0301",
15323  // ṹ = \~\'{u}
15324  "\u016b": "\u0075\u0304",
15325  // ū = \={u}
15326  "\u1e7b": "\u0075\u0304\u0308",
15327  // ṻ = \=\"{u}
15328  "\u016d": "\u0075\u0306",
15329  // ŭ = \u{u}
15330  "\u01d4": "\u0075\u030c",
15331  // ǔ = \v{u}
15332  "\u00fb": "\u0075\u0302",
15333  // û = \^{u}
15334  "\u016f": "\u0075\u030a",
15335  // ů = \r{u}
15336  "\u0171": "\u0075\u030b",
15337  // ű = \H{u}
15338  "\u1e7d": "\u0076\u0303",
15339  // ṽ = \~{v}
15340  "\u1e83": "\u0077\u0301",
15341  // ẃ = \'{w}
15342  "\u1e81": "\u0077\u0300",
15343  // ẁ = \`{w}
15344  "\u1e85": "\u0077\u0308",
15345  // ẅ = \"{w}
15346  "\u0175": "\u0077\u0302",
15347  // ŵ = \^{w}
15348  "\u1e87": "\u0077\u0307",
15349  // ẇ = \.{w}
15350  "\u1e98": "\u0077\u030a",
15351  // ẘ = \r{w}
15352  "\u1e8d": "\u0078\u0308",
15353  // ẍ = \"{x}
15354  "\u1e8b": "\u0078\u0307",
15355  // ẋ = \.{x}
15356  "\u00fd": "\u0079\u0301",
15357  // ý = \'{y}
15358  "\u1ef3": "\u0079\u0300",
15359  // ỳ = \`{y}
15360  "\u00ff": "\u0079\u0308",
15361  // ÿ = \"{y}
15362  "\u1ef9": "\u0079\u0303",
15363  // ỹ = \~{y}
15364  "\u0233": "\u0079\u0304",
15365  // ȳ = \={y}
15366  "\u0177": "\u0079\u0302",
15367  // ŷ = \^{y}
15368  "\u1e8f": "\u0079\u0307",
15369  // ẏ = \.{y}
15370  "\u1e99": "\u0079\u030a",
15371  // ẙ = \r{y}
15372  "\u017a": "\u007a\u0301",
15373  // ź = \'{z}
15374  "\u017e": "\u007a\u030c",
15375  // ž = \v{z}
15376  "\u1e91": "\u007a\u0302",
15377  // ẑ = \^{z}
15378  "\u017c": "\u007a\u0307",
15379  // ż = \.{z}
15380  "\u00c1": "\u0041\u0301",
15381  // Á = \'{A}
15382  "\u00c0": "\u0041\u0300",
15383  // À = \`{A}
15384  "\u00c4": "\u0041\u0308",
15385  // Ä = \"{A}
15386  "\u01de": "\u0041\u0308\u0304",
15387  // Ǟ = \"\={A}
15388  "\u00c3": "\u0041\u0303",
15389  // Ã = \~{A}
15390  "\u0100": "\u0041\u0304",
15391  // Ā = \={A}
15392  "\u0102": "\u0041\u0306",
15393  // Ă = \u{A}
15394  "\u1eae": "\u0041\u0306\u0301",
15395  // Ắ = \u\'{A}
15396  "\u1eb0": "\u0041\u0306\u0300",
15397  // Ằ = \u\`{A}
15398  "\u1eb4": "\u0041\u0306\u0303",
15399  // Ẵ = \u\~{A}
15400  "\u01cd": "\u0041\u030c",
15401  // Ǎ = \v{A}
15402  "\u00c2": "\u0041\u0302",
15403  // Â = \^{A}
15404  "\u1ea4": "\u0041\u0302\u0301",
15405  // Ấ = \^\'{A}
15406  "\u1ea6": "\u0041\u0302\u0300",
15407  // Ầ = \^\`{A}
15408  "\u1eaa": "\u0041\u0302\u0303",
15409  // Ẫ = \^\~{A}
15410  "\u0226": "\u0041\u0307",
15411  // Ȧ = \.{A}
15412  "\u01e0": "\u0041\u0307\u0304",
15413  // Ǡ = \.\={A}
15414  "\u00c5": "\u0041\u030a",
15415  // Å = \r{A}
15416  "\u01fa": "\u0041\u030a\u0301",
15417  // Ǻ = \r\'{A}
15418  "\u1e02": "\u0042\u0307",
15419  // Ḃ = \.{B}
15420  "\u0106": "\u0043\u0301",
15421  // Ć = \'{C}
15422  "\u010c": "\u0043\u030c",
15423  // Č = \v{C}
15424  "\u0108": "\u0043\u0302",
15425  // Ĉ = \^{C}
15426  "\u010a": "\u0043\u0307",
15427  // Ċ = \.{C}
15428  "\u010e": "\u0044\u030c",
15429  // Ď = \v{D}
15430  "\u1e0a": "\u0044\u0307",
15431  // Ḋ = \.{D}
15432  "\u00c9": "\u0045\u0301",
15433  // É = \'{E}
15434  "\u00c8": "\u0045\u0300",
15435  // È = \`{E}
15436  "\u00cb": "\u0045\u0308",
15437  // Ë = \"{E}
15438  "\u1ebc": "\u0045\u0303",
15439  // Ẽ = \~{E}
15440  "\u0112": "\u0045\u0304",
15441  // Ē = \={E}
15442  "\u1e16": "\u0045\u0304\u0301",
15443  // Ḗ = \=\'{E}
15444  "\u1e14": "\u0045\u0304\u0300",
15445  // Ḕ = \=\`{E}
15446  "\u0114": "\u0045\u0306",
15447  // Ĕ = \u{E}
15448  "\u011a": "\u0045\u030c",
15449  // Ě = \v{E}
15450  "\u00ca": "\u0045\u0302",
15451  // Ê = \^{E}
15452  "\u1ebe": "\u0045\u0302\u0301",
15453  // Ế = \^\'{E}
15454  "\u1ec0": "\u0045\u0302\u0300",
15455  // Ề = \^\`{E}
15456  "\u1ec4": "\u0045\u0302\u0303",
15457  // Ễ = \^\~{E}
15458  "\u0116": "\u0045\u0307",
15459  // Ė = \.{E}
15460  "\u1e1e": "\u0046\u0307",
15461  // Ḟ = \.{F}
15462  "\u01f4": "\u0047\u0301",
15463  // Ǵ = \'{G}
15464  "\u1e20": "\u0047\u0304",
15465  // Ḡ = \={G}
15466  "\u011e": "\u0047\u0306",
15467  // Ğ = \u{G}
15468  "\u01e6": "\u0047\u030c",
15469  // Ǧ = \v{G}
15470  "\u011c": "\u0047\u0302",
15471  // Ĝ = \^{G}
15472  "\u0120": "\u0047\u0307",
15473  // Ġ = \.{G}
15474  "\u1e26": "\u0048\u0308",
15475  // Ḧ = \"{H}
15476  "\u021e": "\u0048\u030c",
15477  // Ȟ = \v{H}
15478  "\u0124": "\u0048\u0302",
15479  // Ĥ = \^{H}
15480  "\u1e22": "\u0048\u0307",
15481  // Ḣ = \.{H}
15482  "\u00cd": "\u0049\u0301",
15483  // Í = \'{I}
15484  "\u00cc": "\u0049\u0300",
15485  // Ì = \`{I}
15486  "\u00cf": "\u0049\u0308",
15487  // Ï = \"{I}
15488  "\u1e2e": "\u0049\u0308\u0301",
15489  // Ḯ = \"\'{I}
15490  "\u0128": "\u0049\u0303",
15491  // Ĩ = \~{I}
15492  "\u012a": "\u0049\u0304",
15493  // Ī = \={I}
15494  "\u012c": "\u0049\u0306",
15495  // Ĭ = \u{I}
15496  "\u01cf": "\u0049\u030c",
15497  // Ǐ = \v{I}
15498  "\u00ce": "\u0049\u0302",
15499  // Î = \^{I}
15500  "\u0130": "\u0049\u0307",
15501  // İ = \.{I}
15502  "\u0134": "\u004a\u0302",
15503  // Ĵ = \^{J}
15504  "\u1e30": "\u004b\u0301",
15505  // Ḱ = \'{K}
15506  "\u01e8": "\u004b\u030c",
15507  // Ǩ = \v{K}
15508  "\u0139": "\u004c\u0301",
15509  // Ĺ = \'{L}
15510  "\u013d": "\u004c\u030c",
15511  // Ľ = \v{L}
15512  "\u1e3e": "\u004d\u0301",
15513  // Ḿ = \'{M}
15514  "\u1e40": "\u004d\u0307",
15515  // Ṁ = \.{M}
15516  "\u0143": "\u004e\u0301",
15517  // Ń = \'{N}
15518  "\u01f8": "\u004e\u0300",
15519  // Ǹ = \`{N}
15520  "\u00d1": "\u004e\u0303",
15521  // Ñ = \~{N}
15522  "\u0147": "\u004e\u030c",
15523  // Ň = \v{N}
15524  "\u1e44": "\u004e\u0307",
15525  // Ṅ = \.{N}
15526  "\u00d3": "\u004f\u0301",
15527  // Ó = \'{O}
15528  "\u00d2": "\u004f\u0300",
15529  // Ò = \`{O}
15530  "\u00d6": "\u004f\u0308",
15531  // Ö = \"{O}
15532  "\u022a": "\u004f\u0308\u0304",
15533  // Ȫ = \"\={O}
15534  "\u00d5": "\u004f\u0303",
15535  // Õ = \~{O}
15536  "\u1e4c": "\u004f\u0303\u0301",
15537  // Ṍ = \~\'{O}
15538  "\u1e4e": "\u004f\u0303\u0308",
15539  // Ṏ = \~\"{O}
15540  "\u022c": "\u004f\u0303\u0304",
15541  // Ȭ = \~\={O}
15542  "\u014c": "\u004f\u0304",
15543  // Ō = \={O}
15544  "\u1e52": "\u004f\u0304\u0301",
15545  // Ṓ = \=\'{O}
15546  "\u1e50": "\u004f\u0304\u0300",
15547  // Ṑ = \=\`{O}
15548  "\u014e": "\u004f\u0306",
15549  // Ŏ = \u{O}
15550  "\u01d1": "\u004f\u030c",
15551  // Ǒ = \v{O}
15552  "\u00d4": "\u004f\u0302",
15553  // Ô = \^{O}
15554  "\u1ed0": "\u004f\u0302\u0301",
15555  // Ố = \^\'{O}
15556  "\u1ed2": "\u004f\u0302\u0300",
15557  // Ồ = \^\`{O}
15558  "\u1ed6": "\u004f\u0302\u0303",
15559  // Ỗ = \^\~{O}
15560  "\u022e": "\u004f\u0307",
15561  // Ȯ = \.{O}
15562  "\u0230": "\u004f\u0307\u0304",
15563  // Ȱ = \.\={O}
15564  "\u0150": "\u004f\u030b",
15565  // Ő = \H{O}
15566  "\u1e54": "\u0050\u0301",
15567  // Ṕ = \'{P}
15568  "\u1e56": "\u0050\u0307",
15569  // Ṗ = \.{P}
15570  "\u0154": "\u0052\u0301",
15571  // Ŕ = \'{R}
15572  "\u0158": "\u0052\u030c",
15573  // Ř = \v{R}
15574  "\u1e58": "\u0052\u0307",
15575  // Ṙ = \.{R}
15576  "\u015a": "\u0053\u0301",
15577  // Ś = \'{S}
15578  "\u1e64": "\u0053\u0301\u0307",
15579  // Ṥ = \'\.{S}
15580  "\u0160": "\u0053\u030c",
15581  // Š = \v{S}
15582  "\u1e66": "\u0053\u030c\u0307",
15583  // Ṧ = \v\.{S}
15584  "\u015c": "\u0053\u0302",
15585  // Ŝ = \^{S}
15586  "\u1e60": "\u0053\u0307",
15587  // Ṡ = \.{S}
15588  "\u0164": "\u0054\u030c",
15589  // Ť = \v{T}
15590  "\u1e6a": "\u0054\u0307",
15591  // Ṫ = \.{T}
15592  "\u00da": "\u0055\u0301",
15593  // Ú = \'{U}
15594  "\u00d9": "\u0055\u0300",
15595  // Ù = \`{U}
15596  "\u00dc": "\u0055\u0308",
15597  // Ü = \"{U}
15598  "\u01d7": "\u0055\u0308\u0301",
15599  // Ǘ = \"\'{U}
15600  "\u01db": "\u0055\u0308\u0300",
15601  // Ǜ = \"\`{U}
15602  "\u01d5": "\u0055\u0308\u0304",
15603  // Ǖ = \"\={U}
15604  "\u01d9": "\u0055\u0308\u030c",
15605  // Ǚ = \"\v{U}
15606  "\u0168": "\u0055\u0303",
15607  // Ũ = \~{U}
15608  "\u1e78": "\u0055\u0303\u0301",
15609  // Ṹ = \~\'{U}
15610  "\u016a": "\u0055\u0304",
15611  // Ū = \={U}
15612  "\u1e7a": "\u0055\u0304\u0308",
15613  // Ṻ = \=\"{U}
15614  "\u016c": "\u0055\u0306",
15615  // Ŭ = \u{U}
15616  "\u01d3": "\u0055\u030c",
15617  // Ǔ = \v{U}
15618  "\u00db": "\u0055\u0302",
15619  // Û = \^{U}
15620  "\u016e": "\u0055\u030a",
15621  // Ů = \r{U}
15622  "\u0170": "\u0055\u030b",
15623  // Ű = \H{U}
15624  "\u1e7c": "\u0056\u0303",
15625  // Ṽ = \~{V}
15626  "\u1e82": "\u0057\u0301",
15627  // Ẃ = \'{W}
15628  "\u1e80": "\u0057\u0300",
15629  // Ẁ = \`{W}
15630  "\u1e84": "\u0057\u0308",
15631  // Ẅ = \"{W}
15632  "\u0174": "\u0057\u0302",
15633  // Ŵ = \^{W}
15634  "\u1e86": "\u0057\u0307",
15635  // Ẇ = \.{W}
15636  "\u1e8c": "\u0058\u0308",
15637  // Ẍ = \"{X}
15638  "\u1e8a": "\u0058\u0307",
15639  // Ẋ = \.{X}
15640  "\u00dd": "\u0059\u0301",
15641  // Ý = \'{Y}
15642  "\u1ef2": "\u0059\u0300",
15643  // Ỳ = \`{Y}
15644  "\u0178": "\u0059\u0308",
15645  // Ÿ = \"{Y}
15646  "\u1ef8": "\u0059\u0303",
15647  // Ỹ = \~{Y}
15648  "\u0232": "\u0059\u0304",
15649  // Ȳ = \={Y}
15650  "\u0176": "\u0059\u0302",
15651  // Ŷ = \^{Y}
15652  "\u1e8e": "\u0059\u0307",
15653  // Ẏ = \.{Y}
15654  "\u0179": "\u005a\u0301",
15655  // Ź = \'{Z}
15656  "\u017d": "\u005a\u030c",
15657  // Ž = \v{Z}
15658  "\u1e90": "\u005a\u0302",
15659  // Ẑ = \^{Z}
15660  "\u017b": "\u005a\u0307",
15661  // Ż = \.{Z}
15662  "\u03ac": "\u03b1\u0301",
15663  // ά = \'{α}
15664  "\u1f70": "\u03b1\u0300",
15665  // ὰ = \`{α}
15666  "\u1fb1": "\u03b1\u0304",
15667  // ᾱ = \={α}
15668  "\u1fb0": "\u03b1\u0306",
15669  // ᾰ = \u{α}
15670  "\u03ad": "\u03b5\u0301",
15671  // έ = \'{ε}
15672  "\u1f72": "\u03b5\u0300",
15673  // ὲ = \`{ε}
15674  "\u03ae": "\u03b7\u0301",
15675  // ή = \'{η}
15676  "\u1f74": "\u03b7\u0300",
15677  // ὴ = \`{η}
15678  "\u03af": "\u03b9\u0301",
15679  // ί = \'{ι}
15680  "\u1f76": "\u03b9\u0300",
15681  // ὶ = \`{ι}
15682  "\u03ca": "\u03b9\u0308",
15683  // ϊ = \"{ι}
15684  "\u0390": "\u03b9\u0308\u0301",
15685  // ΐ = \"\'{ι}
15686  "\u1fd2": "\u03b9\u0308\u0300",
15687  // ῒ = \"\`{ι}
15688  "\u1fd1": "\u03b9\u0304",
15689  // ῑ = \={ι}
15690  "\u1fd0": "\u03b9\u0306",
15691  // ῐ = \u{ι}
15692  "\u03cc": "\u03bf\u0301",
15693  // ό = \'{ο}
15694  "\u1f78": "\u03bf\u0300",
15695  // ὸ = \`{ο}
15696  "\u03cd": "\u03c5\u0301",
15697  // ύ = \'{υ}
15698  "\u1f7a": "\u03c5\u0300",
15699  // ὺ = \`{υ}
15700  "\u03cb": "\u03c5\u0308",
15701  // ϋ = \"{υ}
15702  "\u03b0": "\u03c5\u0308\u0301",
15703  // ΰ = \"\'{υ}
15704  "\u1fe2": "\u03c5\u0308\u0300",
15705  // ῢ = \"\`{υ}
15706  "\u1fe1": "\u03c5\u0304",
15707  // ῡ = \={υ}
15708  "\u1fe0": "\u03c5\u0306",
15709  // ῠ = \u{υ}
15710  "\u03ce": "\u03c9\u0301",
15711  // ώ = \'{ω}
15712  "\u1f7c": "\u03c9\u0300",
15713  // ὼ = \`{ω}
15714  "\u038e": "\u03a5\u0301",
15715  // Ύ = \'{Υ}
15716  "\u1fea": "\u03a5\u0300",
15717  // Ὺ = \`{Υ}
15718  "\u03ab": "\u03a5\u0308",
15719  // Ϋ = \"{Υ}
15720  "\u1fe9": "\u03a5\u0304",
15721  // Ῡ = \={Υ}
15722  "\u1fe8": "\u03a5\u0306",
15723  // Ῠ = \u{Υ}
15724  "\u038f": "\u03a9\u0301",
15725  // Ώ = \'{Ω}
15726  "\u1ffa": "\u03a9\u0300" // Ὼ = \`{Ω}
15727
15728};
15729
15730/* eslint no-constant-condition:0 */
15731
15732/**
15733 * This file contains the parser used to parse out a TeX expression from the
15734 * input. Since TeX isn't context-free, standard parsers don't work particularly
15735 * well.
15736 *
15737 * The strategy of this parser is as such:
15738 *
15739 * The main functions (the `.parse...` ones) take a position in the current
15740 * parse string to parse tokens from. The lexer (found in Lexer.js, stored at
15741 * this.gullet.lexer) also supports pulling out tokens at arbitrary places. When
15742 * individual tokens are needed at a position, the lexer is called to pull out a
15743 * token, which is then used.
15744 *
15745 * The parser has a property called "mode" indicating the mode that
15746 * the parser is currently in. Currently it has to be one of "math" or
15747 * "text", which denotes whether the current environment is a math-y
15748 * one or a text-y one (e.g. inside \text). Currently, this serves to
15749 * limit the functions which can be used in text mode.
15750 *
15751 * The main functions then return an object which contains the useful data that
15752 * was parsed at its given point, and a new position at the end of the parsed
15753 * data. The main functions can call each other and continue the parsing by
15754 * using the returned position as a new starting point.
15755 *
15756 * There are also extra `.handle...` functions, which pull out some reused
15757 * functionality into self-contained functions.
15758 *
15759 * The functions return ParseNodes.
15760 */
15761class Parser {
15762  constructor(input, settings) {
15763    this.mode = void 0;
15764    this.gullet = void 0;
15765    this.settings = void 0;
15766    this.leftrightDepth = void 0;
15767    this.nextToken = void 0;
15768    // Start in math mode
15769    this.mode = "math"; // Create a new macro expander (gullet) and (indirectly via that) also a
15770    // new lexer (mouth) for this parser (stomach, in the language of TeX)
15771
15772    this.gullet = new MacroExpander(input, settings, this.mode); // Store the settings for use in parsing
15773
15774    this.settings = settings; // Count leftright depth (for \middle errors)
15775
15776    this.leftrightDepth = 0;
15777  }
15778  /**
15779   * Checks a result to make sure it has the right type, and throws an
15780   * appropriate error otherwise.
15781   */
15782
15783
15784  expect(text, consume) {
15785    if (consume === void 0) {
15786      consume = true;
15787    }
15788
15789    if (this.fetch().text !== text) {
15790      throw new ParseError(`Expected '${text}', got '${this.fetch().text}'`, this.fetch());
15791    }
15792
15793    if (consume) {
15794      this.consume();
15795    }
15796  }
15797  /**
15798   * Discards the current lookahead token, considering it consumed.
15799   */
15800
15801
15802  consume() {
15803    this.nextToken = null;
15804  }
15805  /**
15806   * Return the current lookahead token, or if there isn't one (at the
15807   * beginning, or if the previous lookahead token was consume()d),
15808   * fetch the next token as the new lookahead token and return it.
15809   */
15810
15811
15812  fetch() {
15813    if (this.nextToken == null) {
15814      this.nextToken = this.gullet.expandNextToken();
15815    }
15816
15817    return this.nextToken;
15818  }
15819  /**
15820   * Switches between "text" and "math" modes.
15821   */
15822
15823
15824  switchMode(newMode) {
15825    this.mode = newMode;
15826    this.gullet.switchMode(newMode);
15827  }
15828  /**
15829   * Main parsing function, which parses an entire input.
15830   */
15831
15832
15833  parse() {
15834    // Create a group namespace for the math expression.
15835    // (LaTeX creates a new group for every $...$, $$...$$, \[...\].)
15836    this.gullet.beginGroup(); // Use old \color behavior (same as LaTeX's \textcolor) if requested.
15837    // We do this within the group for the math expression, so it doesn't
15838    // pollute settings.macros.
15839
15840    if (this.settings.colorIsTextColor) {
15841      this.gullet.macros.set("\\color", "\\textcolor");
15842    } // Try to parse the input
15843
15844
15845    const parse = this.parseExpression(false); // If we succeeded, make sure there's an EOF at the end
15846
15847    this.expect("EOF"); // End the group namespace for the expression
15848
15849    this.gullet.endGroup();
15850    return parse;
15851  }
15852
15853  parseExpression(breakOnInfix, breakOnTokenText) {
15854    const body = []; // Keep adding atoms to the body until we can't parse any more atoms (either
15855    // we reached the end, a }, or a \right)
15856
15857    while (true) {
15858      // Ignore spaces in math mode
15859      if (this.mode === "math") {
15860        this.consumeSpaces();
15861      }
15862
15863      const lex = this.fetch();
15864
15865      if (Parser.endOfExpression.indexOf(lex.text) !== -1) {
15866        break;
15867      }
15868
15869      if (breakOnTokenText && lex.text === breakOnTokenText) {
15870        break;
15871      }
15872
15873      if (breakOnInfix && functions[lex.text] && functions[lex.text].infix) {
15874        break;
15875      }
15876
15877      const atom = this.parseAtom(breakOnTokenText);
15878
15879      if (!atom) {
15880        break;
15881      }
15882
15883      body.push(atom);
15884    }
15885
15886    if (this.mode === "text") {
15887      this.formLigatures(body);
15888    }
15889
15890    return this.handleInfixNodes(body);
15891  }
15892  /**
15893   * Rewrites infix operators such as \over with corresponding commands such
15894   * as \frac.
15895   *
15896   * There can only be one infix operator per group.  If there's more than one
15897   * then the expression is ambiguous.  This can be resolved by adding {}.
15898   */
15899
15900
15901  handleInfixNodes(body) {
15902    let overIndex = -1;
15903    let funcName;
15904
15905    for (let i = 0; i < body.length; i++) {
15906      const node = checkNodeType(body[i], "infix");
15907
15908      if (node) {
15909        if (overIndex !== -1) {
15910          throw new ParseError("only one infix operator per group", node.token);
15911        }
15912
15913        overIndex = i;
15914        funcName = node.replaceWith;
15915      }
15916    }
15917
15918    if (overIndex !== -1 && funcName) {
15919      let numerNode;
15920      let denomNode;
15921      const numerBody = body.slice(0, overIndex);
15922      const denomBody = body.slice(overIndex + 1);
15923
15924      if (numerBody.length === 1 && numerBody[0].type === "ordgroup") {
15925        numerNode = numerBody[0];
15926      } else {
15927        numerNode = {
15928          type: "ordgroup",
15929          mode: this.mode,
15930          body: numerBody
15931        };
15932      }
15933
15934      if (denomBody.length === 1 && denomBody[0].type === "ordgroup") {
15935        denomNode = denomBody[0];
15936      } else {
15937        denomNode = {
15938          type: "ordgroup",
15939          mode: this.mode,
15940          body: denomBody
15941        };
15942      }
15943
15944      let node;
15945
15946      if (funcName === "\\\\abovefrac") {
15947        node = this.callFunction(funcName, [numerNode, body[overIndex], denomNode], []);
15948      } else {
15949        node = this.callFunction(funcName, [numerNode, denomNode], []);
15950      }
15951
15952      return [node];
15953    } else {
15954      return body;
15955    }
15956  } // The greediness of a superscript or subscript
15957
15958
15959  /**
15960   * Handle a subscript or superscript with nice errors.
15961   */
15962  handleSupSubscript(name) {
15963    const symbolToken = this.fetch();
15964    const symbol = symbolToken.text;
15965    this.consume();
15966    const group = this.parseGroup(name, false, Parser.SUPSUB_GREEDINESS, undefined, undefined, true); // ignore spaces before sup/subscript argument
15967
15968    if (!group) {
15969      throw new ParseError("Expected group after '" + symbol + "'", symbolToken);
15970    }
15971
15972    return group;
15973  }
15974  /**
15975   * Converts the textual input of an unsupported command into a text node
15976   * contained within a color node whose color is determined by errorColor
15977   */
15978
15979
15980  formatUnsupportedCmd(text) {
15981    const textordArray = [];
15982
15983    for (let i = 0; i < text.length; i++) {
15984      textordArray.push({
15985        type: "textord",
15986        mode: "text",
15987        text: text[i]
15988      });
15989    }
15990
15991    const textNode = {
15992      type: "text",
15993      mode: this.mode,
15994      body: textordArray
15995    };
15996    const colorNode = {
15997      type: "color",
15998      mode: this.mode,
15999      color: this.settings.errorColor,
16000      body: [textNode]
16001    };
16002    return colorNode;
16003  }
16004  /**
16005   * Parses a group with optional super/subscripts.
16006   */
16007
16008
16009  parseAtom(breakOnTokenText) {
16010    // The body of an atom is an implicit group, so that things like
16011    // \left(x\right)^2 work correctly.
16012    const base = this.parseGroup("atom", false, null, breakOnTokenText); // In text mode, we don't have superscripts or subscripts
16013
16014    if (this.mode === "text") {
16015      return base;
16016    } // Note that base may be empty (i.e. null) at this point.
16017
16018
16019    let superscript;
16020    let subscript;
16021
16022    while (true) {
16023      // Guaranteed in math mode, so eat any spaces first.
16024      this.consumeSpaces(); // Lex the first token
16025
16026      const lex = this.fetch();
16027
16028      if (lex.text === "\\limits" || lex.text === "\\nolimits") {
16029        // We got a limit control
16030        let opNode = checkNodeType(base, "op");
16031
16032        if (opNode) {
16033          const limits = lex.text === "\\limits";
16034          opNode.limits = limits;
16035          opNode.alwaysHandleSupSub = true;
16036        } else {
16037          opNode = checkNodeType(base, "operatorname");
16038
16039          if (opNode && opNode.alwaysHandleSupSub) {
16040            const limits = lex.text === "\\limits";
16041            opNode.limits = limits;
16042          } else {
16043            throw new ParseError("Limit controls must follow a math operator", lex);
16044          }
16045        }
16046
16047        this.consume();
16048      } else if (lex.text === "^") {
16049        // We got a superscript start
16050        if (superscript) {
16051          throw new ParseError("Double superscript", lex);
16052        }
16053
16054        superscript = this.handleSupSubscript("superscript");
16055      } else if (lex.text === "_") {
16056        // We got a subscript start
16057        if (subscript) {
16058          throw new ParseError("Double subscript", lex);
16059        }
16060
16061        subscript = this.handleSupSubscript("subscript");
16062      } else if (lex.text === "'") {
16063        // We got a prime
16064        if (superscript) {
16065          throw new ParseError("Double superscript", lex);
16066        }
16067
16068        const prime = {
16069          type: "textord",
16070          mode: this.mode,
16071          text: "\\prime"
16072        }; // Many primes can be grouped together, so we handle this here
16073
16074        const primes = [prime];
16075        this.consume(); // Keep lexing tokens until we get something that's not a prime
16076
16077        while (this.fetch().text === "'") {
16078          // For each one, add another prime to the list
16079          primes.push(prime);
16080          this.consume();
16081        } // If there's a superscript following the primes, combine that
16082        // superscript in with the primes.
16083
16084
16085        if (this.fetch().text === "^") {
16086          primes.push(this.handleSupSubscript("superscript"));
16087        } // Put everything into an ordgroup as the superscript
16088
16089
16090        superscript = {
16091          type: "ordgroup",
16092          mode: this.mode,
16093          body: primes
16094        };
16095      } else {
16096        // If it wasn't ^, _, or ', stop parsing super/subscripts
16097        break;
16098      }
16099    } // Base must be set if superscript or subscript are set per logic above,
16100    // but need to check here for type check to pass.
16101
16102
16103    if (superscript || subscript) {
16104      // If we got either a superscript or subscript, create a supsub
16105      return {
16106        type: "supsub",
16107        mode: this.mode,
16108        base: base,
16109        sup: superscript,
16110        sub: subscript
16111      };
16112    } else {
16113      // Otherwise return the original body
16114      return base;
16115    }
16116  }
16117  /**
16118   * Parses an entire function, including its base and all of its arguments.
16119   */
16120
16121
16122  parseFunction(breakOnTokenText, name, // For error reporting.
16123  greediness) {
16124    const token = this.fetch();
16125    const func = token.text;
16126    const funcData = functions[func];
16127
16128    if (!funcData) {
16129      return null;
16130    }
16131
16132    this.consume(); // consume command token
16133
16134    if (greediness != null && funcData.greediness <= greediness) {
16135      throw new ParseError("Got function '" + func + "' with no arguments" + (name ? " as " + name : ""), token);
16136    } else if (this.mode === "text" && !funcData.allowedInText) {
16137      throw new ParseError("Can't use function '" + func + "' in text mode", token);
16138    } else if (this.mode === "math" && funcData.allowedInMath === false) {
16139      throw new ParseError("Can't use function '" + func + "' in math mode", token);
16140    }
16141
16142    const _this$parseArguments = this.parseArguments(func, funcData),
16143          args = _this$parseArguments.args,
16144          optArgs = _this$parseArguments.optArgs;
16145
16146    return this.callFunction(func, args, optArgs, token, breakOnTokenText);
16147  }
16148  /**
16149   * Call a function handler with a suitable context and arguments.
16150   */
16151
16152
16153  callFunction(name, args, optArgs, token, breakOnTokenText) {
16154    const context = {
16155      funcName: name,
16156      parser: this,
16157      token,
16158      breakOnTokenText
16159    };
16160    const func = functions[name];
16161
16162    if (func && func.handler) {
16163      return func.handler(context, args, optArgs);
16164    } else {
16165      throw new ParseError(`No function handler for ${name}`);
16166    }
16167  }
16168  /**
16169   * Parses the arguments of a function or environment
16170   */
16171
16172
16173  parseArguments(func, // Should look like "\name" or "\begin{name}".
16174  funcData) {
16175    const totalArgs = funcData.numArgs + funcData.numOptionalArgs;
16176
16177    if (totalArgs === 0) {
16178      return {
16179        args: [],
16180        optArgs: []
16181      };
16182    }
16183
16184    const baseGreediness = funcData.greediness;
16185    const args = [];
16186    const optArgs = [];
16187
16188    for (let i = 0; i < totalArgs; i++) {
16189      const argType = funcData.argTypes && funcData.argTypes[i];
16190      const isOptional = i < funcData.numOptionalArgs; // Ignore spaces between arguments.  As the TeXbook says:
16191      // "After you have said ‘\def\row#1#2{...}’, you are allowed to
16192      //  put spaces between the arguments (e.g., ‘\row x n’), because
16193      //  TeX doesn’t use single spaces as undelimited arguments."
16194
16195      const consumeSpaces = i > 0 && !isOptional || // Also consume leading spaces in math mode, as parseSymbol
16196      // won't know what to do with them.  This can only happen with
16197      // macros, e.g. \frac\foo\foo where \foo expands to a space symbol.
16198      // In LaTeX, the \foo's get treated as (blank) arguments.
16199      // In KaTeX, for now, both spaces will get consumed.
16200      // TODO(edemaine)
16201      i === 0 && !isOptional && this.mode === "math";
16202      const arg = this.parseGroupOfType(`argument to '${func}'`, argType, isOptional, baseGreediness, consumeSpaces);
16203
16204      if (!arg) {
16205        if (isOptional) {
16206          optArgs.push(null);
16207          continue;
16208        }
16209
16210        throw new ParseError(`Expected group after '${func}'`, this.fetch());
16211      }
16212
16213      (isOptional ? optArgs : args).push(arg);
16214    }
16215
16216    return {
16217      args,
16218      optArgs
16219    };
16220  }
16221  /**
16222   * Parses a group when the mode is changing.
16223   */
16224
16225
16226  parseGroupOfType(name, type, optional, greediness, consumeSpaces) {
16227    switch (type) {
16228      case "color":
16229        if (consumeSpaces) {
16230          this.consumeSpaces();
16231        }
16232
16233        return this.parseColorGroup(optional);
16234
16235      case "size":
16236        if (consumeSpaces) {
16237          this.consumeSpaces();
16238        }
16239
16240        return this.parseSizeGroup(optional);
16241
16242      case "url":
16243        return this.parseUrlGroup(optional, consumeSpaces);
16244
16245      case "math":
16246      case "text":
16247        return this.parseGroup(name, optional, greediness, undefined, type, consumeSpaces);
16248
16249      case "hbox":
16250        {
16251          // hbox argument type wraps the argument in the equivalent of
16252          // \hbox, which is like \text but switching to \textstyle size.
16253          const group = this.parseGroup(name, optional, greediness, undefined, "text", consumeSpaces);
16254
16255          if (!group) {
16256            return group;
16257          }
16258
16259          const styledGroup = {
16260            type: "styling",
16261            mode: group.mode,
16262            body: [group],
16263            style: "text" // simulate \textstyle
16264
16265          };
16266          return styledGroup;
16267        }
16268
16269      case "raw":
16270        {
16271          if (consumeSpaces) {
16272            this.consumeSpaces();
16273          }
16274
16275          if (optional && this.fetch().text === "{") {
16276            return null;
16277          }
16278
16279          const token = this.parseStringGroup("raw", optional, true);
16280
16281          if (token) {
16282            return {
16283              type: "raw",
16284              mode: "text",
16285              string: token.text
16286            };
16287          } else {
16288            throw new ParseError("Expected raw group", this.fetch());
16289          }
16290        }
16291
16292      case "original":
16293      case null:
16294      case undefined:
16295        return this.parseGroup(name, optional, greediness, undefined, undefined, consumeSpaces);
16296
16297      default:
16298        throw new ParseError("Unknown group type as " + name, this.fetch());
16299    }
16300  }
16301  /**
16302   * Discard any space tokens, fetching the next non-space token.
16303   */
16304
16305
16306  consumeSpaces() {
16307    while (this.fetch().text === " ") {
16308      this.consume();
16309    }
16310  }
16311  /**
16312   * Parses a group, essentially returning the string formed by the
16313   * brace-enclosed tokens plus some position information.
16314   */
16315
16316
16317  parseStringGroup(modeName, // Used to describe the mode in error messages.
16318  optional, raw) {
16319    const groupBegin = optional ? "[" : "{";
16320    const groupEnd = optional ? "]" : "}";
16321    const beginToken = this.fetch();
16322
16323    if (beginToken.text !== groupBegin) {
16324      if (optional) {
16325        return null;
16326      } else if (raw && beginToken.text !== "EOF" && /[^{}[\]]/.test(beginToken.text)) {
16327        this.consume();
16328        return beginToken;
16329      }
16330    }
16331
16332    const outerMode = this.mode;
16333    this.mode = "text";
16334    this.expect(groupBegin);
16335    let str = "";
16336    const firstToken = this.fetch();
16337    let nested = 0; // allow nested braces in raw string group
16338
16339    let lastToken = firstToken;
16340    let nextToken;
16341
16342    while ((nextToken = this.fetch()).text !== groupEnd || raw && nested > 0) {
16343      switch (nextToken.text) {
16344        case "EOF":
16345          throw new ParseError("Unexpected end of input in " + modeName, firstToken.range(lastToken, str));
16346
16347        case groupBegin:
16348          nested++;
16349          break;
16350
16351        case groupEnd:
16352          nested--;
16353          break;
16354      }
16355
16356      lastToken = nextToken;
16357      str += lastToken.text;
16358      this.consume();
16359    }
16360
16361    this.expect(groupEnd);
16362    this.mode = outerMode;
16363    return firstToken.range(lastToken, str);
16364  }
16365  /**
16366   * Parses a regex-delimited group: the largest sequence of tokens
16367   * whose concatenated strings match `regex`. Returns the string
16368   * formed by the tokens plus some position information.
16369   */
16370
16371
16372  parseRegexGroup(regex, modeName) {
16373    const outerMode = this.mode;
16374    this.mode = "text";
16375    const firstToken = this.fetch();
16376    let lastToken = firstToken;
16377    let str = "";
16378    let nextToken;
16379
16380    while ((nextToken = this.fetch()).text !== "EOF" && regex.test(str + nextToken.text)) {
16381      lastToken = nextToken;
16382      str += lastToken.text;
16383      this.consume();
16384    }
16385
16386    if (str === "") {
16387      throw new ParseError("Invalid " + modeName + ": '" + firstToken.text + "'", firstToken);
16388    }
16389
16390    this.mode = outerMode;
16391    return firstToken.range(lastToken, str);
16392  }
16393  /**
16394   * Parses a color description.
16395   */
16396
16397
16398  parseColorGroup(optional) {
16399    const res = this.parseStringGroup("color", optional);
16400
16401    if (!res) {
16402      return null;
16403    }
16404
16405    const match = /^(#[a-f0-9]{3}|#?[a-f0-9]{6}|[a-z]+)$/i.exec(res.text);
16406
16407    if (!match) {
16408      throw new ParseError("Invalid color: '" + res.text + "'", res);
16409    }
16410
16411    let color = match[0];
16412
16413    if (/^[0-9a-f]{6}$/i.test(color)) {
16414      // We allow a 6-digit HTML color spec without a leading "#".
16415      // This follows the xcolor package's HTML color model.
16416      // Predefined color names are all missed by this RegEx pattern.
16417      color = "#" + color;
16418    }
16419
16420    return {
16421      type: "color-token",
16422      mode: this.mode,
16423      color
16424    };
16425  }
16426  /**
16427   * Parses a size specification, consisting of magnitude and unit.
16428   */
16429
16430
16431  parseSizeGroup(optional) {
16432    let res;
16433    let isBlank = false;
16434
16435    if (!optional && this.fetch().text !== "{") {
16436      res = this.parseRegexGroup(/^[-+]? *(?:$|\d+|\d+\.\d*|\.\d*) *[a-z]{0,2} *$/, "size");
16437    } else {
16438      res = this.parseStringGroup("size", optional);
16439    }
16440
16441    if (!res) {
16442      return null;
16443    }
16444
16445    if (!optional && res.text.length === 0) {
16446      // Because we've tested for what is !optional, this block won't
16447      // affect \kern, \hspace, etc. It will capture the mandatory arguments
16448      // to \genfrac and \above.
16449      res.text = "0pt"; // Enable \above{}
16450
16451      isBlank = true; // This is here specifically for \genfrac
16452    }
16453
16454    const match = /([-+]?) *(\d+(?:\.\d*)?|\.\d+) *([a-z]{2})/.exec(res.text);
16455
16456    if (!match) {
16457      throw new ParseError("Invalid size: '" + res.text + "'", res);
16458    }
16459
16460    const data = {
16461      number: +(match[1] + match[2]),
16462      // sign + magnitude, cast to number
16463      unit: match[3]
16464    };
16465
16466    if (!validUnit(data)) {
16467      throw new ParseError("Invalid unit: '" + data.unit + "'", res);
16468    }
16469
16470    return {
16471      type: "size",
16472      mode: this.mode,
16473      value: data,
16474      isBlank
16475    };
16476  }
16477  /**
16478   * Parses an URL, checking escaped letters and allowed protocols,
16479   * and setting the catcode of % as an active character (as in \hyperref).
16480   */
16481
16482
16483  parseUrlGroup(optional, consumeSpaces) {
16484    this.gullet.lexer.setCatcode("%", 13); // active character
16485
16486    const res = this.parseStringGroup("url", optional, true); // get raw string
16487
16488    this.gullet.lexer.setCatcode("%", 14); // comment character
16489
16490    if (!res) {
16491      return null;
16492    } // hyperref package allows backslashes alone in href, but doesn't
16493    // generate valid links in such cases; we interpret this as
16494    // "undefined" behaviour, and keep them as-is. Some browser will
16495    // replace backslashes with forward slashes.
16496
16497
16498    const url = res.text.replace(/\\([#$%&~_^{}])/g, '$1');
16499    return {
16500      type: "url",
16501      mode: this.mode,
16502      url
16503    };
16504  }
16505  /**
16506   * If `optional` is false or absent, this parses an ordinary group,
16507   * which is either a single nucleus (like "x") or an expression
16508   * in braces (like "{x+y}") or an implicit group, a group that starts
16509   * at the current position, and ends right before a higher explicit
16510   * group ends, or at EOF.
16511   * If `optional` is true, it parses either a bracket-delimited expression
16512   * (like "[x+y]") or returns null to indicate the absence of a
16513   * bracket-enclosed group.
16514   * If `mode` is present, switches to that mode while parsing the group,
16515   * and switches back after.
16516   */
16517
16518
16519  parseGroup(name, // For error reporting.
16520  optional, greediness, breakOnTokenText, mode, consumeSpaces) {
16521    // Switch to specified mode
16522    const outerMode = this.mode;
16523
16524    if (mode) {
16525      this.switchMode(mode);
16526    } // Consume spaces if requested, crucially *after* we switch modes,
16527    // so that the next non-space token is parsed in the correct mode.
16528
16529
16530    if (consumeSpaces) {
16531      this.consumeSpaces();
16532    } // Get first token
16533
16534
16535    const firstToken = this.fetch();
16536    const text = firstToken.text;
16537    let result; // Try to parse an open brace or \begingroup
16538
16539    if (optional ? text === "[" : text === "{" || text === "\\begingroup") {
16540      this.consume();
16541      const groupEnd = Parser.endOfGroup[text]; // Start a new group namespace
16542
16543      this.gullet.beginGroup(); // If we get a brace, parse an expression
16544
16545      const expression = this.parseExpression(false, groupEnd);
16546      const lastToken = this.fetch(); // Check that we got a matching closing brace
16547
16548      this.expect(groupEnd); // End group namespace
16549
16550      this.gullet.endGroup();
16551      result = {
16552        type: "ordgroup",
16553        mode: this.mode,
16554        loc: SourceLocation.range(firstToken, lastToken),
16555        body: expression,
16556        // A group formed by \begingroup...\endgroup is a semi-simple group
16557        // which doesn't affect spacing in math mode, i.e., is transparent.
16558        // https://tex.stackexchange.com/questions/1930/when-should-one-
16559        // use-begingroup-instead-of-bgroup
16560        semisimple: text === "\\begingroup" || undefined
16561      };
16562    } else if (optional) {
16563      // Return nothing for an optional group
16564      result = null;
16565    } else {
16566      // If there exists a function with this name, parse the function.
16567      // Otherwise, just return a nucleus
16568      result = this.parseFunction(breakOnTokenText, name, greediness) || this.parseSymbol();
16569
16570      if (result == null && text[0] === "\\" && !implicitCommands.hasOwnProperty(text)) {
16571        if (this.settings.throwOnError) {
16572          throw new ParseError("Undefined control sequence: " + text, firstToken);
16573        }
16574
16575        result = this.formatUnsupportedCmd(text);
16576        this.consume();
16577      }
16578    } // Switch mode back
16579
16580
16581    if (mode) {
16582      this.switchMode(outerMode);
16583    }
16584
16585    return result;
16586  }
16587  /**
16588   * Form ligature-like combinations of characters for text mode.
16589   * This includes inputs like "--", "---", "``" and "''".
16590   * The result will simply replace multiple textord nodes with a single
16591   * character in each value by a single textord node having multiple
16592   * characters in its value.  The representation is still ASCII source.
16593   * The group will be modified in place.
16594   */
16595
16596
16597  formLigatures(group) {
16598    let n = group.length - 1;
16599
16600    for (let i = 0; i < n; ++i) {
16601      const a = group[i]; // $FlowFixMe: Not every node type has a `text` property.
16602
16603      const v = a.text;
16604
16605      if (v === "-" && group[i + 1].text === "-") {
16606        if (i + 1 < n && group[i + 2].text === "-") {
16607          group.splice(i, 3, {
16608            type: "textord",
16609            mode: "text",
16610            loc: SourceLocation.range(a, group[i + 2]),
16611            text: "---"
16612          });
16613          n -= 2;
16614        } else {
16615          group.splice(i, 2, {
16616            type: "textord",
16617            mode: "text",
16618            loc: SourceLocation.range(a, group[i + 1]),
16619            text: "--"
16620          });
16621          n -= 1;
16622        }
16623      }
16624
16625      if ((v === "'" || v === "`") && group[i + 1].text === v) {
16626        group.splice(i, 2, {
16627          type: "textord",
16628          mode: "text",
16629          loc: SourceLocation.range(a, group[i + 1]),
16630          text: v + v
16631        });
16632        n -= 1;
16633      }
16634    }
16635  }
16636  /**
16637   * Parse a single symbol out of the string. Here, we handle single character
16638   * symbols and special functions like \verb.
16639   */
16640
16641
16642  parseSymbol() {
16643    const nucleus = this.fetch();
16644    let text = nucleus.text;
16645
16646    if (/^\\verb[^a-zA-Z]/.test(text)) {
16647      this.consume();
16648      let arg = text.slice(5);
16649      const star = arg.charAt(0) === "*";
16650
16651      if (star) {
16652        arg = arg.slice(1);
16653      } // Lexer's tokenRegex is constructed to always have matching
16654      // first/last characters.
16655
16656
16657      if (arg.length < 2 || arg.charAt(0) !== arg.slice(-1)) {
16658        throw new ParseError(`\\verb assertion failed --
16659                    please report what input caused this bug`);
16660      }
16661
16662      arg = arg.slice(1, -1); // remove first and last char
16663
16664      return {
16665        type: "verb",
16666        mode: "text",
16667        body: arg,
16668        star
16669      };
16670    } // At this point, we should have a symbol, possibly with accents.
16671    // First expand any accented base symbol according to unicodeSymbols.
16672
16673
16674    if (unicodeSymbols.hasOwnProperty(text[0]) && !symbols[this.mode][text[0]]) {
16675      // This behavior is not strict (XeTeX-compatible) in math mode.
16676      if (this.settings.strict && this.mode === "math") {
16677        this.settings.reportNonstrict("unicodeTextInMathMode", `Accented Unicode text character "${text[0]}" used in ` + `math mode`, nucleus);
16678      }
16679
16680      text = unicodeSymbols[text[0]] + text.substr(1);
16681    } // Strip off any combining characters
16682
16683
16684    const match = combiningDiacriticalMarksEndRegex.exec(text);
16685
16686    if (match) {
16687      text = text.substring(0, match.index);
16688
16689      if (text === 'i') {
16690        text = '\u0131'; // dotless i, in math and text mode
16691      } else if (text === 'j') {
16692        text = '\u0237'; // dotless j, in math and text mode
16693      }
16694    } // Recognize base symbol
16695
16696
16697    let symbol;
16698
16699    if (symbols[this.mode][text]) {
16700      if (this.settings.strict && this.mode === 'math' && extraLatin.indexOf(text) >= 0) {
16701        this.settings.reportNonstrict("unicodeTextInMathMode", `Latin-1/Unicode text character "${text[0]}" used in ` + `math mode`, nucleus);
16702      }
16703
16704      const group = symbols[this.mode][text].group;
16705      const loc = SourceLocation.range(nucleus);
16706      let s;
16707
16708      if (ATOMS.hasOwnProperty(group)) {
16709        // $FlowFixMe
16710        const family = group;
16711        s = {
16712          type: "atom",
16713          mode: this.mode,
16714          family,
16715          loc,
16716          text
16717        };
16718      } else {
16719        // $FlowFixMe
16720        s = {
16721          type: group,
16722          mode: this.mode,
16723          loc,
16724          text
16725        };
16726      }
16727
16728      symbol = s;
16729    } else if (text.charCodeAt(0) >= 0x80) {
16730      // no symbol for e.g. ^
16731      if (this.settings.strict) {
16732        if (!supportedCodepoint(text.charCodeAt(0))) {
16733          this.settings.reportNonstrict("unknownSymbol", `Unrecognized Unicode character "${text[0]}"` + ` (${text.charCodeAt(0)})`, nucleus);
16734        } else if (this.mode === "math") {
16735          this.settings.reportNonstrict("unicodeTextInMathMode", `Unicode text character "${text[0]}" used in math mode`, nucleus);
16736        }
16737      } // All nonmathematical Unicode characters are rendered as if they
16738      // are in text mode (wrapped in \text) because that's what it
16739      // takes to render them in LaTeX.  Setting `mode: this.mode` is
16740      // another natural choice (the user requested math mode), but
16741      // this makes it more difficult for getCharacterMetrics() to
16742      // distinguish Unicode characters without metrics and those for
16743      // which we want to simulate the letter M.
16744
16745
16746      symbol = {
16747        type: "textord",
16748        mode: "text",
16749        loc: SourceLocation.range(nucleus),
16750        text
16751      };
16752    } else {
16753      return null; // EOF, ^, _, {, }, etc.
16754    }
16755
16756    this.consume(); // Transform combining characters into accents
16757
16758    if (match) {
16759      for (let i = 0; i < match[0].length; i++) {
16760        const accent = match[0][i];
16761
16762        if (!unicodeAccents[accent]) {
16763          throw new ParseError(`Unknown accent ' ${accent}'`, nucleus);
16764        }
16765
16766        const command = unicodeAccents[accent][this.mode];
16767
16768        if (!command) {
16769          throw new ParseError(`Accent ${accent} unsupported in ${this.mode} mode`, nucleus);
16770        }
16771
16772        symbol = {
16773          type: "accent",
16774          mode: this.mode,
16775          loc: SourceLocation.range(nucleus),
16776          label: command,
16777          isStretchy: false,
16778          isShifty: true,
16779          base: symbol
16780        };
16781      }
16782    }
16783
16784    return symbol;
16785  }
16786
16787}
16788Parser.endOfExpression = ["}", "\\endgroup", "\\end", "\\right", "&"];
16789Parser.endOfGroup = {
16790  "[": "]",
16791  "{": "}",
16792  "\\begingroup": "\\endgroup"
16793  /**
16794   * Parses an "expression", which is a list of atoms.
16795   *
16796   * `breakOnInfix`: Should the parsing stop when we hit infix nodes? This
16797   *                 happens when functions have higher precendence han infix
16798   *                 nodes in implicit parses.
16799   *
16800   * `breakOnTokenText`: The text of the token that the expression should end
16801   *                     with, or `null` if something else should end the
16802   *                     expression.
16803   */
16804
16805};
16806Parser.SUPSUB_GREEDINESS = 1;
16807
16808/**
16809 * Provides a single function for parsing an expression using a Parser
16810 * TODO(emily): Remove this
16811 */
16812
16813/**
16814 * Parses an expression using a Parser, then returns the parsed result.
16815 */
16816const parseTree = function parseTree(toParse, settings) {
16817  if (!(typeof toParse === 'string' || toParse instanceof String)) {
16818    throw new TypeError('KaTeX can only parse string typed expression');
16819  }
16820
16821  const parser = new Parser(toParse, settings); // Blank out any \df@tag to avoid spurious "Duplicate \tag" errors
16822
16823  delete parser.gullet.macros.current["\\df@tag"];
16824  let tree = parser.parse(); // If the input used \tag, it will set the \df@tag macro to the tag.
16825  // In this case, we separately parse the tag and wrap the tree.
16826
16827  if (parser.gullet.macros.get("\\df@tag")) {
16828    if (!settings.displayMode) {
16829      throw new ParseError("\\tag works only in display equations");
16830    }
16831
16832    parser.gullet.feed("\\df@tag");
16833    tree = [{
16834      type: "tag",
16835      mode: "text",
16836      body: tree,
16837      tag: parser.parse()
16838    }];
16839  }
16840
16841  return tree;
16842};
16843
16844/* eslint no-console:0 */
16845
16846/**
16847 * Parse and build an expression, and place that expression in the DOM node
16848 * given.
16849 */
16850let render = function render(expression, baseNode, options) {
16851  baseNode.textContent = "";
16852  const node = renderToDomTree(expression, options).toNode();
16853  baseNode.appendChild(node);
16854}; // KaTeX's styles don't work properly in quirks mode. Print out an error, and
16855// disable rendering.
16856
16857
16858if (typeof document !== "undefined") {
16859  if (document.compatMode !== "CSS1Compat") {
16860    typeof console !== "undefined" && console.warn("Warning: KaTeX doesn't work in quirks mode. Make sure your " + "website has a suitable doctype.");
16861
16862    render = function render() {
16863      throw new ParseError("KaTeX doesn't work in quirks mode.");
16864    };
16865  }
16866}
16867/**
16868 * Parse and build an expression, and return the markup for that.
16869 */
16870
16871
16872const renderToString = function renderToString(expression, options) {
16873  const markup = renderToDomTree(expression, options).toMarkup();
16874  return markup;
16875};
16876/**
16877 * Parse an expression and return the parse tree.
16878 */
16879
16880
16881const generateParseTree = function generateParseTree(expression, options) {
16882  const settings = new Settings(options);
16883  return parseTree(expression, settings);
16884};
16885/**
16886 * If the given error is a KaTeX ParseError and options.throwOnError is false,
16887 * renders the invalid LaTeX as a span with hover title giving the KaTeX
16888 * error message.  Otherwise, simply throws the error.
16889 */
16890
16891
16892const renderError = function renderError(error, expression, options) {
16893  if (options.throwOnError || !(error instanceof ParseError)) {
16894    throw error;
16895  }
16896
16897  const node = buildCommon.makeSpan(["katex-error"], [new SymbolNode(expression)]);
16898  node.setAttribute("title", error.toString());
16899  node.setAttribute("style", `color:${options.errorColor}`);
16900  return node;
16901};
16902/**
16903 * Generates and returns the katex build tree. This is used for advanced
16904 * use cases (like rendering to custom output).
16905 */
16906
16907
16908const renderToDomTree = function renderToDomTree(expression, options) {
16909  const settings = new Settings(options);
16910
16911  try {
16912    const tree = parseTree(expression, settings);
16913    return buildTree(tree, expression, settings);
16914  } catch (error) {
16915    return renderError(error, expression, settings);
16916  }
16917};
16918/**
16919 * Generates and returns the katex build tree, with just HTML (no MathML).
16920 * This is used for advanced use cases (like rendering to custom output).
16921 */
16922
16923
16924const renderToHTMLTree = function renderToHTMLTree(expression, options) {
16925  const settings = new Settings(options);
16926
16927  try {
16928    const tree = parseTree(expression, settings);
16929    return buildHTMLTree(tree, expression, settings);
16930  } catch (error) {
16931    return renderError(error, expression, settings);
16932  }
16933};
16934
16935var katex = {
16936  /**
16937   * Current KaTeX version
16938   */
16939  version: "0.11.1",
16940
16941  /**
16942   * Renders the given LaTeX into an HTML+MathML combination, and adds
16943   * it as a child to the specified DOM node.
16944   */
16945  render,
16946
16947  /**
16948   * Renders the given LaTeX into an HTML+MathML combination string,
16949   * for sending to the client.
16950   */
16951  renderToString,
16952
16953  /**
16954   * KaTeX error, usually during parsing.
16955   */
16956  ParseError,
16957
16958  /**
16959   * Parses the given LaTeX into KaTeX's internal parse tree structure,
16960   * without rendering to HTML or MathML.
16961   *
16962   * NOTE: This method is not currently recommended for public use.
16963   * The internal tree representation is unstable and is very likely
16964   * to change. Use at your own risk.
16965   */
16966  __parse: generateParseTree,
16967
16968  /**
16969   * Renders the given LaTeX into an HTML+MathML internal DOM tree
16970   * representation, without flattening that representation to a string.
16971   *
16972   * NOTE: This method is not currently recommended for public use.
16973   * The internal tree representation is unstable and is very likely
16974   * to change. Use at your own risk.
16975   */
16976  __renderToDomTree: renderToDomTree,
16977
16978  /**
16979   * Renders the given LaTeX into an HTML internal DOM tree representation,
16980   * without MathML and without flattening that representation to a string.
16981   *
16982   * NOTE: This method is not currently recommended for public use.
16983   * The internal tree representation is unstable and is very likely
16984   * to change. Use at your own risk.
16985   */
16986  __renderToHTMLTree: renderToHTMLTree,
16987
16988  /**
16989   * extends internal font metrics object with a new object
16990   * each key in the new object represents a font name
16991  */
16992  __setFontMetrics: setFontMetrics,
16993
16994  /**
16995   * adds a new symbol to builtin symbols table
16996   */
16997  __defineSymbol: defineSymbol,
16998
16999  /**
17000   * adds a new macro to builtin macro list
17001   */
17002  __defineMacro: defineMacro,
17003
17004  /**
17005   * Expose the dom tree node types, which can be useful for type checking nodes.
17006   *
17007   * NOTE: This method is not currently recommended for public use.
17008   * The internal tree representation is unstable and is very likely
17009   * to change. Use at your own risk.
17010   */
17011  __domTree: {
17012    Span,
17013    Anchor,
17014    SymbolNode,
17015    SvgNode,
17016    PathNode,
17017    LineNode
17018  }
17019};
17020
17021export default katex;
17022